diff options
author | Denton Woods <denton.woods@gmail.com> | 2017-01-21 22:39:42 -0600 |
---|---|---|
committer | Denton Woods <denton.woods@gmail.com> | 2017-01-21 22:39:42 -0600 |
commit | e7cd401ec8859a788f5847cff793b59e2f929168 (patch) | |
tree | 19848c2ff0ecaea2c969199e4f1c6f8a10c8bd91 | |
parent | d7a5c33776635e92548c8d5494d1c8060318144c (diff) | |
download | devil-e7cd401ec8859a788f5847cff793b59e2f929168.tar.gz |
- Added support for uncompressed KTX mipmaps
-rw-r--r-- | DevIL/src-IL/src/il_dds.cpp | 24 | ||||
-rw-r--r-- | DevIL/src-IL/src/il_ktx.cpp | 104 | ||||
-rw-r--r-- | DevIL/src-IL/src/il_states.cpp | 3 |
3 files changed, 109 insertions, 22 deletions
diff --git a/DevIL/src-IL/src/il_dds.cpp b/DevIL/src-IL/src/il_dds.cpp index daaec723..46e64344 100644 --- a/DevIL/src-IL/src/il_dds.cpp +++ b/DevIL/src-IL/src/il_dds.cpp @@ -409,33 +409,40 @@ ILboolean iLoadDdsInternal() CompData = NULL; Image = NULL; - if (iCurImage == NULL) { + if (iCurImage == NULL) + { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } - if (!iGetDdsHead(&Head)) { + if (!iGetDdsHead(&Head)) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } - if (!iCheckDds(&Head)) { + if (!iCheckDds(&Head)) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } BlockSize = DecodePixelFormat(&CompFormat); - if (CompFormat == PF_UNKNOWN) { + if (CompFormat == PF_UNKNOWN) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } - if (CompFormat == PF_DX10) { + if (CompFormat == PF_DX10) + { IsDXT10 = IL_TRUE; - if (!iGetDXT10Head(&HeadDXT10)) { + if (!iGetDXT10Head(&HeadDXT10)) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } - if (!iCheckDxt10(&HeadDXT10)) { + if (!iCheckDxt10(&HeadDXT10)) + { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } @@ -1121,7 +1128,8 @@ ILboolean ReadMipmaps(ILuint CompFormat, ILboolean IsDXT10) } LastLinear = Head.LinearSize; - for (i = 0; i < Head.MipMapCount - 1; i++) { + for (i = 0; i < Head.MipMapCount - 1; i++) + { Depth = Depth / 2; Width = Width / 2; Height = Height / 2; diff --git a/DevIL/src-IL/src/il_ktx.cpp b/DevIL/src-IL/src/il_ktx.cpp index c424810a..7871ac7c 100644 --- a/DevIL/src-IL/src/il_ktx.cpp +++ b/DevIL/src-IL/src/il_ktx.cpp @@ -19,6 +19,7 @@ ILboolean iIsValidKtx(void); ILboolean iLoadKtxInternal(); +ILboolean iKtxReadMipmaps(ILboolean Compressed, ILuint NumMips); #ifdef _MSC_VER @@ -217,7 +218,6 @@ ILboolean iLoadKtxInternal() Header.numberOfFaces = GetLittleUInt(); Header.numberOfMipmapLevels = GetLittleUInt(); Header.bytesOfKeyValueData = GetLittleUInt(); - imageSize = GetLittleUInt(); if (memcmp(Header.identifier, FileIdentifier, 12) || Header.endianness != 0x04030201) { ilSetError(IL_ILLEGAL_FILE_VALUE); @@ -229,13 +229,15 @@ ILboolean iLoadKtxInternal() return IL_FALSE; } //@TODO: Really needed? - /*if (Header.glInternalFormat != Header.glFormat || Header.glBaseInternalFormat != Header.glFormat) { + /*if (Header.glInternalFormat != Header.glFormat || Header.glBaseInternalFormat != Header.glFormat) + { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; }*/ //@TODO: Mipmaps, etc. - if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 || Header.numberOfMipmapLevels != 1) { + if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 /*|| Header.numberOfMipmapLevels != 1*/) + { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } @@ -289,11 +291,6 @@ ILboolean iLoadKtxInternal() } } - if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, Type, NULL)) { - return IL_FALSE; - } - iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; - if (!Compressed) { //@TODO: Additional types @@ -312,15 +309,28 @@ ILboolean iLoadKtxInternal() return IL_FALSE; } - if (imageSize != Header.pixelWidth * Header.pixelHeight * Bpp * Bpc) { + if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, Type, NULL)) + return IL_FALSE; + + if (!iKtxReadMipmaps(Compressed, Header.numberOfMipmapLevels)) + return IL_FALSE; + + //iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; //@TODO: Correct for all? + } + else // Compressed formats require different handling + { + //@TODO: Add support for compressed mipmaps + if (Header.numberOfMipmapLevels != 1) + { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } - if (iread(iCurImage->Data, Bpp*Bpc, Header.pixelWidth * Header.pixelHeight) != Header.pixelWidth * Header.pixelHeight) + imageSize = GetLittleUInt(); + + if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, Type, NULL)) return IL_FALSE; - } - else { // Compressed formats require different handling + switch (Header.glInternalFormat) { case I_GL_ETC1_RGB8_OES: @@ -359,11 +369,79 @@ ILboolean iLoadKtxInternal() ifree(FullBuffer); break; } - //return IL_FALSE; + + iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; //@TODO: Correct for all? } return ilFixImage(); } +ILboolean iKtxReadMipmaps(ILboolean Compressed, ILuint NumMips) +{ + ILimage *Image = iCurImage; + ILuint Width = iCurImage->Width, Height = iCurImage->Height; + ILuint imageSize, Padding, Pos; + + for (ILuint Mip = 0; Mip < NumMips; Mip++) + { + imageSize = GetLittleUInt(); + Padding = 3 - ((Image->Bps + 3) % 4); + + if (imageSize != Image->SizeOfData + Padding*Image->Height) + { + ilSetError(IL_ILLEGAL_FILE_VALUE); + goto mip_fail; + } + + // Note: The KTX spec at https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ + // seems to imply dword-alignment of the entire image. + if (Image->Bps % 4 == 0) // Required to be dword-aligned + { + if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) + return IL_FALSE; + } + else // Since not dword-aligned, have to read each line separately. + { + Pos = 0; + for (ILuint h = 0; h < Height; h++) + { + if (iread(&Image->Data[Pos], 1, Image->Bps) != Image->Bps) + return IL_FALSE; + iseek(Padding, IL_SEEK_CUR); + Pos += Image->Bps; + } + + } + + Image->Origin = IL_ORIGIN_LOWER_LEFT; //@TODO: Correct for all? + Width = Width / 2; + Height = Height / 2; + + if (Mip < NumMips - 1) + { + Image->Mipmaps = ilNewImage(Width, Height, 1, Image->Bpp, Image->Bpc); + if (Image->Mipmaps == NULL) + goto mip_fail; + Image->Mipmaps->Format = Image->Format; + Image->Mipmaps->Type = Image->Type; + Image = Image->Mipmaps; + } + } + + return IL_TRUE; + +mip_fail: + Image = iCurImage; + ILimage *StartImage = Image->Mipmaps, *TempImage; + while (StartImage) { + TempImage = StartImage; + StartImage = StartImage->Mipmaps; + ifree(TempImage); + } + + Image->Mipmaps = NULL; + return IL_FALSE; +} + #endif//IL_NO_KTX diff --git a/DevIL/src-IL/src/il_states.cpp b/DevIL/src-IL/src/il_states.cpp index 974ebe02..752624bd 100644 --- a/DevIL/src-IL/src/il_states.cpp +++ b/DevIL/src-IL/src/il_states.cpp @@ -419,7 +419,8 @@ void ILAPIENTRY ilGetIntegerv(ILenum Mode, ILint *Param) *Param = 0; - switch (Mode) { + switch (Mode) + { // Integer values case IL_COMPRESS_MODE: *Param = ilStates[ilCurrentPos].ilCompression; |