1322 lines
45 KiB
C++
1322 lines
45 KiB
C++
//=====================================================================
|
|
// Copyright 2016 (c), Advanced Micro Devices, Inc. All rights reserved.
|
|
//=====================================================================
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files(the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions :
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
|
|
// Windows Header Files:
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "cKTX.h"
|
|
|
|
#include "TC_PluginAPI.h"
|
|
#include "TC_PluginInternal.h"
|
|
#include "Common.h"
|
|
|
|
#include "softfloat.h"
|
|
|
|
#include <algorithm>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#pragma comment(lib, "opengl32.lib") // Open GL
|
|
#pragma comment(lib, "Glu32.lib") // Glu
|
|
#pragma comment(lib, "glew32.lib") // glew 1.13.0
|
|
|
|
CMIPS *KTX_CMips;
|
|
|
|
#ifdef BUILD_AS_PLUGIN_DLL
|
|
DECLARE_PLUGIN(Plugin_KTX)
|
|
SET_PLUGIN_TYPE("IMAGE")
|
|
SET_PLUGIN_NAME("KTX")
|
|
#else
|
|
void *make_Plugin_KTX() { return new Plugin_KTX; }
|
|
#endif
|
|
|
|
uint32_t Endian_Conversion(uint32_t dword)
|
|
{
|
|
return (((dword>>24)&0x000000FF) | ((dword>>8)&0x0000FF00) | ((dword<<8)&0x00FF0000) | ((dword<<24)&0xFF000000));
|
|
}
|
|
|
|
Plugin_KTX::Plugin_KTX()
|
|
{
|
|
}
|
|
|
|
Plugin_KTX::~Plugin_KTX()
|
|
{
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginSetSharedIO(void* Shared)
|
|
{
|
|
if (Shared)
|
|
{
|
|
KTX_CMips = static_cast<CMIPS *>(Shared);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginGetVersion(TC_PluginVersion* pPluginVersion)
|
|
{
|
|
#ifdef _WIN32
|
|
pPluginVersion->guid = g_GUID;
|
|
#endif
|
|
pPluginVersion->dwAPIVersionMajor = TC_API_VERSION_MAJOR;
|
|
pPluginVersion->dwAPIVersionMinor = TC_API_VERSION_MINOR;
|
|
pPluginVersion->dwPluginVersionMajor = TC_PLUGIN_VERSION_MAJOR;
|
|
pPluginVersion->dwPluginVersionMinor = TC_PLUGIN_VERSION_MINOR;
|
|
return 0;
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginFileLoadTexture(const char* pszFilename, CMP_Texture *srcTexture)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginFileSaveTexture(const char* pszFilename, CMP_Texture *srcTexture)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
uint32_t ktx_u32_byterev(uint32_t v)
|
|
{
|
|
return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24);
|
|
}
|
|
|
|
// perform endianness switch on raw data
|
|
static void switch_endianness2(void *dataptr, int bytes)
|
|
{
|
|
int i;
|
|
uint8_t *data = (uint8_t *) dataptr;
|
|
|
|
for (i = 0; i < bytes / 2; i++)
|
|
{
|
|
uint8_t d0 = data[0];
|
|
uint8_t d1 = data[1];
|
|
data[0] = d1;
|
|
data[1] = d0;
|
|
data += 2;
|
|
}
|
|
}
|
|
|
|
static void switch_endianness4(void *dataptr, int bytes)
|
|
{
|
|
int i;
|
|
uint8_t *data = (uint8_t *) dataptr;
|
|
|
|
for (i = 0; i < bytes / 4; i++)
|
|
{
|
|
uint8_t d0 = data[0];
|
|
uint8_t d1 = data[1];
|
|
uint8_t d2 = data[2];
|
|
uint8_t d3 = data[3];
|
|
data[0] = d3;
|
|
data[1] = d2;
|
|
data[2] = d1;
|
|
data[3] = d0;
|
|
data += 4;
|
|
}
|
|
}
|
|
|
|
static void copy_scanline(void *dst, const void *src, int pixels, int method)
|
|
{
|
|
|
|
#define id(x) (x)
|
|
#define u16_sf16(x) float_to_sf16( x * (1.0f/65535.0f), SF_NEARESTEVEN )
|
|
#define f32_sf16(x) sf32_to_sf16( x, SF_NEARESTEVEN )
|
|
|
|
#define COPY_R( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[i]); \
|
|
d[4*i+1] = 0; \
|
|
d[4*i+2] = 0; \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_RG( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[2*i]); \
|
|
d[4*i+1] = convfunc(s[2*i+1]); \
|
|
d[4*i+2] = 0; \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_RGB( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[3*i]); \
|
|
d[4*i+1] = convfunc(s[3*i+1]); \
|
|
d[4*i+2] = convfunc(s[3*i+2]); \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_BGR( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[3*i+2]); \
|
|
d[4*i+1] = convfunc(s[3*i+1]); \
|
|
d[4*i+2] = convfunc(s[3*i]); \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_RGBX( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[4*i]); \
|
|
d[4*i+1] = convfunc(s[4*i+1]); \
|
|
d[4*i+2] = convfunc(s[4*i+2]); \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_BGRX( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[4*i+2]); \
|
|
d[4*i+1] = convfunc(s[4*i+1]); \
|
|
d[4*i+2] = convfunc(s[4*i]); \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_RGBA( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[4*i]); \
|
|
d[4*i+1] = convfunc(s[4*i+1]); \
|
|
d[4*i+2] = convfunc(s[4*i+2]); \
|
|
d[4*i+3] = convfunc(s[4*i+3]); \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_BGRA( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[4*i+2]); \
|
|
d[4*i+1] = convfunc(s[4*i+1]); \
|
|
d[4*i+2] = convfunc(s[4*i]); \
|
|
d[4*i+3] = convfunc(s[4*i+3]); \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_L( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[i]); \
|
|
d[4*i+1] = convfunc(s[i]); \
|
|
d[4*i+2] = convfunc(s[i]); \
|
|
d[4*i+3] = oneval; \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
#define COPY_LA( dsttype, srctype, convfunc, oneval ) \
|
|
do { \
|
|
srctype *s = (srctype *)src; \
|
|
dsttype *d = (dsttype *)dst; \
|
|
for(i=0;i<pixels;i++)\
|
|
{\
|
|
d[4*i] = convfunc(s[2*i]); \
|
|
d[4*i+1] = convfunc(s[2*i]); \
|
|
d[4*i+2] = convfunc(s[2*i]); \
|
|
d[4*i+3] = convfunc(s[2*i+1]); \
|
|
} \
|
|
} while(0); \
|
|
break;
|
|
|
|
int i;
|
|
switch (method)
|
|
{
|
|
case R8_TO_RGBA8:
|
|
COPY_R(uint8_t, uint8_t, id, 0xFF);
|
|
case RG8_TO_RGBA8:
|
|
COPY_RG(uint8_t, uint8_t, id, 0xFF);
|
|
case RGB8_TO_RGBA8:
|
|
COPY_RGB(uint8_t, uint8_t, id, 0xFF);
|
|
case RGBA8_TO_RGBA8:
|
|
COPY_RGBA(uint8_t, uint8_t, id, 0xFF);
|
|
case BGR8_TO_RGBA8:
|
|
COPY_BGR(uint8_t, uint8_t, id, 0xFF);
|
|
case BGRA8_TO_RGBA8:
|
|
COPY_BGRA(uint8_t, uint8_t, id, 0xFF);
|
|
case RGBX8_TO_RGBA8:
|
|
COPY_RGBX(uint8_t, uint8_t, id, 0xFF);
|
|
case BGRX8_TO_RGBA8:
|
|
COPY_BGRX(uint8_t, uint8_t, id, 0xFF);
|
|
case L8_TO_RGBA8:
|
|
COPY_L(uint8_t, uint8_t, id, 0xFF);
|
|
case LA8_TO_RGBA8:
|
|
COPY_LA(uint8_t, uint8_t, id, 0xFF);
|
|
|
|
case R16F_TO_RGBA16F:
|
|
COPY_R(uint16_t, uint16_t, id, 0x3C00);
|
|
case RG16F_TO_RGBA16F:
|
|
COPY_RG(uint16_t, uint16_t, id, 0x3C00);
|
|
case RGB16F_TO_RGBA16F:
|
|
COPY_RGB(uint16_t, uint16_t, id, 0x3C00);
|
|
case RGBA16F_TO_RGBA16F:
|
|
COPY_RGBA(uint16_t, uint16_t, id, 0x3C00);
|
|
case BGR16F_TO_RGBA16F:
|
|
COPY_BGR(uint16_t, uint16_t, id, 0x3C00);
|
|
case BGRA16F_TO_RGBA16F:
|
|
COPY_BGRA(uint16_t, uint16_t, id, 0x3C00);
|
|
case L16F_TO_RGBA16F:
|
|
COPY_L(uint16_t, uint16_t, id, 0x3C00);
|
|
case LA16F_TO_RGBA16F:
|
|
COPY_LA(uint16_t, uint16_t, id, 0x3C00);
|
|
|
|
case R16_TO_RGBA16F:
|
|
COPY_R(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case RG16_TO_RGBA16F:
|
|
COPY_RG(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case RGB16_TO_RGBA16F:
|
|
COPY_RGB(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case RGBA16_TO_RGBA16F:
|
|
COPY_RGBA(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case BGR16_TO_RGBA16F:
|
|
COPY_BGR(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case BGRA16_TO_RGBA16F:
|
|
COPY_BGRA(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case L16_TO_RGBA16F:
|
|
COPY_L(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
case LA16_TO_RGBA16F:
|
|
COPY_LA(uint16_t, uint16_t, u16_sf16, 0x3C00);
|
|
|
|
case R32F_TO_RGBA16F:
|
|
COPY_R(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case RG32F_TO_RGBA16F:
|
|
COPY_RG(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case RGB32F_TO_RGBA16F:
|
|
COPY_RGB(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case RGBA32F_TO_RGBA16F:
|
|
COPY_RGBA(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case BGR32F_TO_RGBA16F:
|
|
COPY_BGR(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case BGRA32F_TO_RGBA16F:
|
|
COPY_BGRA(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case L32F_TO_RGBA16F:
|
|
COPY_L(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
case LA32F_TO_RGBA16F:
|
|
COPY_LA(uint16_t, uint32_t, f32_sf16, 0x3C00);
|
|
};
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginFileLoadTexture(const char* pszFilename, MipSet* pMipSet)
|
|
{
|
|
FILE* pFile = NULL;
|
|
pFile = fopen(pszFilename, ("rb"));
|
|
if (pFile == NULL)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) opening file = %s \n"), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
//using libktx
|
|
KTX_header fheader;
|
|
KTX_texinfo texinfo;
|
|
if (fread(&fheader, sizeof(KTX_header), 1, pFile) != 1)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) invalid KTX header. Filename = %s \n"), EL_Error, IDS_ERROR_NOT_KTX, pszFilename);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
if (_ktxCheckHeader(&fheader, &texinfo) != KTX_SUCCESS)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) invalid KTX header. Filename = %s \n"), EL_Error, IDS_ERROR_NOT_KTX, pszFilename);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
if (texinfo.compressed)
|
|
{
|
|
pMipSet->m_compressed = true;
|
|
pMipSet->m_nBlockHeight = 4;
|
|
pMipSet->m_nBlockWidth = 4;
|
|
pMipSet->m_nBlockDepth = 1;
|
|
pMipSet->m_ChannelFormat = CF_Compressed;
|
|
|
|
switch (fheader.glInternalFormat)
|
|
{
|
|
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
|
pMipSet->m_format = CMP_FORMAT_BC1;
|
|
pMipSet->m_TextureDataType = TDT_XRGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
|
pMipSet->m_format = CMP_FORMAT_BC1;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
|
pMipSet->m_format = CMP_FORMAT_BC2;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
|
pMipSet->m_format = CMP_FORMAT_BC3;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case RGB_BP_UNorm:
|
|
pMipSet->m_format = CMP_FORMAT_BC7;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case R_ATI1N_UNorm:
|
|
pMipSet->m_format = CMP_FORMAT_ATI1N;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case R_ATI1N_SNorm:
|
|
pMipSet->m_format = CMP_FORMAT_ATI2N;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case RG_ATI2N_UNorm:
|
|
pMipSet->m_format = CMP_FORMAT_ATI2N_XY;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case RG_ATI2N_SNorm:
|
|
pMipSet->m_format = CMP_FORMAT_ATI2N_DXT5;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case RGB_BP_UNSIGNED_FLOAT:
|
|
pMipSet->m_format = CMP_FORMAT_BC6H;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case RGB_BP_SIGNED_FLOAT:
|
|
pMipSet->m_format = CMP_FORMAT_BC6H_SF;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case ATC_RGB_AMD:
|
|
pMipSet->m_format = CMP_FORMAT_ATC_RGB;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case ATC_RGBA_EXPLICIT_ALPHA_AMD:
|
|
pMipSet->m_format = CMP_FORMAT_ATC_RGBA_Explicit;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case ATC_RGBA_INTERPOLATED_ALPHA_AMD:
|
|
pMipSet->m_format = CMP_FORMAT_ATC_RGBA_Interpolated;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 4;
|
|
pMipSet->m_nBlockHeight = 4;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 5;
|
|
pMipSet->m_nBlockHeight = 4;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 5;
|
|
pMipSet->m_nBlockHeight = 5;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 6;
|
|
pMipSet->m_nBlockHeight = 5;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 6;
|
|
pMipSet->m_nBlockHeight = 6;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 8;
|
|
pMipSet->m_nBlockHeight = 5;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 8;
|
|
pMipSet->m_nBlockHeight = 6;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 10;
|
|
pMipSet->m_nBlockHeight = 5;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 10;
|
|
pMipSet->m_nBlockHeight = 6;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 8;
|
|
pMipSet->m_nBlockHeight = 8;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 10;
|
|
pMipSet->m_nBlockHeight = 8;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 10;
|
|
pMipSet->m_nBlockHeight = 10;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 12;
|
|
pMipSet->m_nBlockHeight = 10;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
|
|
pMipSet->m_format = CMP_FORMAT_ASTC;
|
|
pMipSet->m_nBlockWidth = 12;
|
|
pMipSet->m_nBlockHeight = 12;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case ETC1_RGB8_OES:
|
|
pMipSet->m_format = CMP_FORMAT_ETC_RGB;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGB8_ETC2:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_RGB;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_SRGB8_ETC2:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_SRGB;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGBA8_ETC2_EAC:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_RGBA;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_RGBA1;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_SRGBA;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
|
pMipSet->m_format = CMP_FORMAT_ETC2_SRGBA1;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case COMPRESSED_FORMAT_DXT5_RxBG :
|
|
pMipSet->m_format = CMP_FORMAT_DXT5_RxBG;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case COMPRESSED_FORMAT_DXT5_RBxG :
|
|
pMipSet->m_format = CMP_FORMAT_DXT5_RBxG;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case COMPRESSED_FORMAT_DXT5_xRBG :
|
|
pMipSet->m_format = CMP_FORMAT_DXT5_xRBG;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case COMPRESSED_FORMAT_DXT5_RGxB :
|
|
pMipSet->m_format = CMP_FORMAT_DXT5_RGxB;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case COMPRESSED_FORMAT_DXT5_xGxR :
|
|
pMipSet->m_format = CMP_FORMAT_DXT5_xGxR;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
default:
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) unsupported GL format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pMipSet->m_compressed = false;
|
|
switch (fheader.glType)
|
|
{
|
|
case GL_UNSIGNED_BYTE:
|
|
pMipSet->m_ChannelFormat = CF_8bit;
|
|
switch (fheader.glFormat)
|
|
{
|
|
case GL_RED:
|
|
pMipSet->m_format = CMP_FORMAT_R_8;
|
|
pMipSet->m_TextureDataType = TDT_R;
|
|
break;
|
|
case GL_RG:
|
|
pMipSet->m_format = CMP_FORMAT_RG_8;
|
|
pMipSet->m_TextureDataType = TDT_RG;
|
|
break;
|
|
case GL_RGB:
|
|
pMipSet->m_format = CMP_FORMAT_RGB_888;
|
|
pMipSet->m_TextureDataType = TDT_XRGB;
|
|
break;
|
|
case GL_RGBA:
|
|
case GL_RGBA8:
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_BGR:
|
|
pMipSet->m_swizzle = true;
|
|
pMipSet->m_format = CMP_FORMAT_RGB_888;
|
|
pMipSet->m_TextureDataType = TDT_XRGB;
|
|
break;
|
|
case GL_BGRA:
|
|
pMipSet->m_swizzle = true;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_8888;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
}
|
|
break;
|
|
case GL_UNSIGNED_SHORT:
|
|
pMipSet->m_ChannelFormat = CF_16bit;
|
|
switch (fheader.glFormat)
|
|
{
|
|
case GL_RED:
|
|
pMipSet->m_format = CMP_FORMAT_R_16;
|
|
pMipSet->m_TextureDataType = TDT_R;
|
|
break;
|
|
case GL_RG:
|
|
pMipSet->m_format = CMP_FORMAT_RG_16;
|
|
pMipSet->m_TextureDataType = TDT_RG;
|
|
break;
|
|
case GL_RGBA:
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_16;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_BGRA:
|
|
pMipSet->m_swizzle = true;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_16;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
}
|
|
break;
|
|
case GL_HALF_FLOAT:
|
|
pMipSet->m_ChannelFormat = CF_Float16;
|
|
switch (fheader.glFormat)
|
|
{
|
|
case GL_RED:
|
|
pMipSet->m_format = CMP_FORMAT_R_16F;
|
|
pMipSet->m_TextureDataType = TDT_R;
|
|
break;
|
|
case GL_RG:
|
|
pMipSet->m_format = CMP_FORMAT_RG_16F;
|
|
pMipSet->m_TextureDataType = TDT_RG;
|
|
break;
|
|
case GL_RGBA:
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_16F;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_BGRA:
|
|
pMipSet->m_swizzle = true;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_16F;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
}
|
|
break;
|
|
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_2101010;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
pMipSet->m_ChannelFormat = CF_2101010;
|
|
break;
|
|
case GL_FLOAT:
|
|
pMipSet->m_ChannelFormat = CF_Float32;
|
|
switch (fheader.glFormat)
|
|
{
|
|
case GL_RED:
|
|
pMipSet->m_format = CMP_FORMAT_R_32F;
|
|
pMipSet->m_TextureDataType = TDT_R;
|
|
break;
|
|
case GL_RG:
|
|
pMipSet->m_format = CMP_FORMAT_RG_32F;
|
|
pMipSet->m_TextureDataType = TDT_RG;
|
|
break;
|
|
case GL_RGBA:
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_32F;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
case GL_BGRA:
|
|
pMipSet->m_swizzle = true;
|
|
pMipSet->m_format = CMP_FORMAT_ARGB_32F;
|
|
pMipSet->m_TextureDataType = TDT_ARGB;
|
|
break;
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) unsupported GL format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
switch (texinfo.glTarget)
|
|
{
|
|
case GL_TEXTURE_2D:
|
|
pMipSet->m_TextureType = TT_2D;
|
|
break;
|
|
case GL_TEXTURE_3D:
|
|
pMipSet->m_TextureType = TT_VolumeTexture;
|
|
break;
|
|
case GL_TEXTURE_CUBE_MAP:
|
|
pMipSet->m_TextureType = TT_CubeMap;
|
|
break;
|
|
default:
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) unsupported texture format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, texinfo.glTarget);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
if (fheader.numberOfMipmapLevels == 0) fheader.numberOfMipmapLevels = 1;
|
|
if (fheader.numberOfArrayElements != 0)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) array textures not supported %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.numberOfArrayElements);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
|
|
pMipSet->m_nMipLevels = fheader.numberOfMipmapLevels;
|
|
if (fheader.numberOfFaces < 1) fheader.numberOfFaces = 1; // depthsupport
|
|
pMipSet->m_nDepth = fheader.numberOfFaces;
|
|
pMipSet->dwWidth = fheader.pixelWidth;
|
|
pMipSet->dwHeight = fheader.pixelHeight;
|
|
|
|
// Allocate MipSet header
|
|
KTX_CMips->AllocateMipSet(pMipSet,
|
|
pMipSet->m_ChannelFormat,
|
|
pMipSet->m_TextureDataType,
|
|
pMipSet->m_TextureType,
|
|
fheader.pixelWidth,
|
|
fheader.pixelHeight,
|
|
pMipSet->m_nDepth // depthsupport
|
|
);
|
|
|
|
if (pMipSet->m_nMipLevels > pMipSet->m_nMaxMipLevels)
|
|
{
|
|
pMipSet->m_nMipLevels = pMipSet->m_nMaxMipLevels;
|
|
}
|
|
|
|
fclose(pFile);
|
|
pFile = NULL;
|
|
pFile = fopen(pszFilename, "rb");
|
|
if (pFile == NULL)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) loading file = %s "), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
//skip key value data
|
|
int imageSizeOffset = sizeof(KTX_header) + fheader.bytesOfKeyValueData;
|
|
if (fseek(pFile, imageSizeOffset, SEEK_SET))
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) Seek past key/vals in KTX compressed bitmap file failed. Format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
|
|
int w = pMipSet->m_nWidth;
|
|
int h = pMipSet->m_nHeight;
|
|
|
|
unsigned int totalByteRead=0;
|
|
|
|
unsigned int faceSize = 0;
|
|
unsigned int faceSizeRounded = 0;
|
|
unsigned int numArrayElement = fheader.numberOfArrayElements;
|
|
|
|
for (int nMipLevel = 0; nMipLevel < fheader.numberOfMipmapLevels; nMipLevel++)
|
|
{
|
|
if ((w <= 0) || (h <= 0)) break;
|
|
|
|
totalByteRead = fread(&faceSize, 1, sizeof(khronos_uint32_t), pFile);
|
|
if (totalByteRead == 0) {
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) Read image data size failed. Format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
if (fheader.endianness == KTX_ENDIAN_REF_REV) {
|
|
_ktxSwapEndian32(&faceSize, 1);
|
|
}
|
|
faceSizeRounded = (faceSize + 3) & ~(khronos_uint32_t)3;
|
|
|
|
for (int face = 0; face < fheader.numberOfFaces; ++face)
|
|
{
|
|
// Determine buffer size and set Mip Set Levels
|
|
MipLevel *pMipLevel = KTX_CMips->GetMipLevel(pMipSet, nMipLevel, face);
|
|
if (pMipSet->m_compressed)
|
|
KTX_CMips->AllocateCompressedMipLevelData(pMipLevel, w, h, faceSizeRounded);
|
|
else
|
|
KTX_CMips->AllocateMipLevelData(pMipLevel, w, h, pMipSet->m_ChannelFormat, pMipSet->m_TextureDataType);
|
|
|
|
// handle padded KTX data
|
|
// store size to be read at this miplevel to check with face size in KTX file
|
|
|
|
int sizeTobeRead = 0;
|
|
int numChannel = 0;
|
|
int bytesPerChannel = 0;
|
|
|
|
if (pMipSet->m_compressed)
|
|
{
|
|
sizeTobeRead = faceSizeRounded;
|
|
}
|
|
else
|
|
{
|
|
switch (pMipSet->m_TextureDataType)
|
|
{
|
|
case TDT_XRGB:
|
|
numChannel = 3;
|
|
break;
|
|
case TDT_ARGB:
|
|
case TDT_NORMAL_MAP:
|
|
numChannel = 4;
|
|
break;
|
|
|
|
case TDT_R:
|
|
numChannel = 1;
|
|
break;
|
|
|
|
case TDT_RG:
|
|
numChannel = 2;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
switch (pMipSet->m_ChannelFormat)
|
|
{
|
|
case CF_8bit:
|
|
case CF_2101010:
|
|
case CF_Float9995E:
|
|
bytesPerChannel = 1;
|
|
break;
|
|
|
|
case CF_16bit:
|
|
case CF_Float16:
|
|
bytesPerChannel = 2;
|
|
break;
|
|
|
|
case CF_32bit:
|
|
case CF_Float32:
|
|
bytesPerChannel = 4;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
sizeTobeRead = w * h * numChannel * bytesPerChannel;
|
|
}
|
|
CMP_BYTE* pData = (CMP_BYTE*)(pMipLevel->m_pbData);
|
|
|
|
if (!pData)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) Read image data failed, Out of Memory. Format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
//read image data
|
|
unsigned int bytesRead = 0;
|
|
//size to be read has to be same as face size, else padding is done in the KTX file
|
|
if (sizeTobeRead == faceSizeRounded)
|
|
{
|
|
bytesRead = fread(pData, 1, faceSizeRounded, pFile);
|
|
}
|
|
else if(faceSizeRounded > sizeTobeRead) // padding in KTX file
|
|
{
|
|
std::vector<CMP_BYTE> pTempData;
|
|
pTempData.resize(faceSizeRounded);
|
|
bytesRead = fread(pTempData.data(), 1, faceSizeRounded, pFile);
|
|
int paddedBytes = faceSizeRounded - sizeTobeRead;
|
|
|
|
int n = 0;
|
|
for (int i = 0; i < pTempData.size(); i++)
|
|
{
|
|
for (int w_i = 0; w_i < w; w_i++)
|
|
{
|
|
for (int j = 0; j < numChannel*bytesPerChannel; j++)
|
|
{
|
|
pData[n++] = pTempData[i++];
|
|
}
|
|
}
|
|
//skip padded bytes
|
|
i += (paddedBytes / h)-1;
|
|
}
|
|
}
|
|
|
|
if (bytesRead != faceSizeRounded)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) Read image data failed. Unexpectec EOF. Format %x\n"), EL_Error, IDS_ERROR_UNSUPPORTED_TYPE, fheader.glFormat);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
}
|
|
// next miplevel width and height
|
|
w = ((std::max))(0, (w >> 1));
|
|
h = ((std::max))(0, (h >> 1));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Plugin_KTX::TC_PluginFileSaveTexture(const char* pszFilename, MipSet* pMipSet)
|
|
{
|
|
assert(pszFilename);
|
|
assert(pMipSet);
|
|
|
|
FILE* pFile = NULL;
|
|
pFile = fopen(pszFilename, "wb");
|
|
if (pFile == NULL)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) saving file = %s "), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
//using libktx
|
|
KTX_texture_info textureinfo;
|
|
KTX_image_info* inputMip = new KTX_image_info[pMipSet->m_nMipLevels];
|
|
|
|
unsigned pDataLen = 0;
|
|
CMP_BYTE* pData = NULL;
|
|
bool isCompressed = false;
|
|
|
|
if (pMipSet->m_TextureType == TT_CubeMap)
|
|
textureinfo.numberOfFaces = 6;
|
|
else
|
|
textureinfo.numberOfFaces = 1;
|
|
|
|
//todo: handle array textures
|
|
textureinfo.numberOfArrayElements = 0;
|
|
|
|
if (pMipSet->m_pMipLevelTable == NULL)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) saving file = %s "), EL_Error, IDS_ERROR_ALLOCATEMIPSET, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
if (KTX_CMips->GetMipLevel(pMipSet, 0) == NULL)
|
|
{
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) saving file = %s "), EL_Error, IDS_ERROR_ALLOCATEMIPSET, pszFilename);
|
|
return -1;
|
|
}
|
|
|
|
int nSlices = (pMipSet->m_TextureType == TT_2D) ? 1 : CMP_MaxFacesOrSlices(pMipSet, 0);
|
|
|
|
for (int nSlice = 0; nSlice < nSlices; nSlice++)
|
|
{
|
|
for (int nMipLevel = 0; nMipLevel < pMipSet->m_nMipLevels; nMipLevel++)
|
|
{
|
|
inputMip[nMipLevel].size = KTX_CMips->GetMipLevel(pMipSet, nMipLevel)->m_dwLinearSize;
|
|
inputMip[nMipLevel].data = KTX_CMips->GetMipLevel(pMipSet, nMipLevel, nSlice)->m_pbData;
|
|
}
|
|
}
|
|
|
|
switch (pMipSet->m_format)
|
|
{
|
|
//uncompressed format case
|
|
case CMP_FORMAT_ARGB_8888 :
|
|
case CMP_FORMAT_RGB_888 :
|
|
case CMP_FORMAT_RG_8 :
|
|
case CMP_FORMAT_R_8 :
|
|
isCompressed = false;
|
|
textureinfo.glType = GL_UNSIGNED_BYTE;
|
|
textureinfo.glTypeSize = 1;
|
|
break;
|
|
case CMP_FORMAT_ARGB_2101010 :
|
|
textureinfo.glType = GL_UNSIGNED_INT_2_10_10_10_REV;
|
|
textureinfo.glTypeSize = 1;
|
|
break;
|
|
case CMP_FORMAT_ARGB_16 :
|
|
textureinfo.glType = GL_UNSIGNED_SHORT;
|
|
textureinfo.glTypeSize = 2;
|
|
break;
|
|
case CMP_FORMAT_RG_16 :
|
|
textureinfo.glType = GL_UNSIGNED_SHORT;
|
|
textureinfo.glTypeSize = 2;
|
|
break;
|
|
case CMP_FORMAT_R_16 :
|
|
textureinfo.glType = GL_UNSIGNED_SHORT;
|
|
textureinfo.glTypeSize = 2;
|
|
break;
|
|
case CMP_FORMAT_ARGB_16F :
|
|
case CMP_FORMAT_RG_16F :
|
|
case CMP_FORMAT_R_16F :
|
|
textureinfo.glType = GL_HALF_FLOAT;
|
|
textureinfo.glTypeSize = 2;
|
|
break;
|
|
case CMP_FORMAT_ARGB_32F :
|
|
case CMP_FORMAT_RGB_32F :
|
|
case CMP_FORMAT_RG_32F :
|
|
case CMP_FORMAT_R_32F :
|
|
textureinfo.glType = GL_FLOAT;
|
|
textureinfo.glTypeSize = 4;
|
|
break;
|
|
//compressed format case
|
|
case CMP_FORMAT_ATI1N :
|
|
case CMP_FORMAT_ATI2N :
|
|
case CMP_FORMAT_ATI2N_XY :
|
|
case CMP_FORMAT_ATI2N_DXT5 :
|
|
case CMP_FORMAT_ATC_RGB :
|
|
case CMP_FORMAT_ATC_RGBA_Explicit :
|
|
case CMP_FORMAT_ATC_RGBA_Interpolated :
|
|
case CMP_FORMAT_BC1 :
|
|
case CMP_FORMAT_BC2 :
|
|
case CMP_FORMAT_BC3 :
|
|
case CMP_FORMAT_BC4 :
|
|
case CMP_FORMAT_BC5 :
|
|
case CMP_FORMAT_BC6H :
|
|
case CMP_FORMAT_BC6H_SF:
|
|
case CMP_FORMAT_BC7 :
|
|
case CMP_FORMAT_DXT1 :
|
|
case CMP_FORMAT_DXT3 :
|
|
case CMP_FORMAT_DXT5 :
|
|
case CMP_FORMAT_DXT5_xGBR :
|
|
case CMP_FORMAT_DXT5_RxBG :
|
|
case CMP_FORMAT_DXT5_RBxG :
|
|
case CMP_FORMAT_DXT5_xRBG :
|
|
case CMP_FORMAT_DXT5_RGxB :
|
|
case CMP_FORMAT_DXT5_xGxR :
|
|
case CMP_FORMAT_ETC_RGB :
|
|
case CMP_FORMAT_ETC2_RGB:
|
|
case CMP_FORMAT_ETC2_SRGB:
|
|
case CMP_FORMAT_ETC2_RGBA:
|
|
case CMP_FORMAT_ETC2_RGBA1:
|
|
case CMP_FORMAT_ETC2_SRGBA:
|
|
case CMP_FORMAT_ETC2_SRGBA1:
|
|
case CMP_FORMAT_ASTC :
|
|
#ifdef USE_GTC
|
|
case CMP_FORMAT_GTC:
|
|
#endif
|
|
#ifdef USE_BASIS
|
|
case CMP_FORMAT_BASIS:
|
|
#endif
|
|
isCompressed = true;
|
|
textureinfo.glType = 0;
|
|
textureinfo.glTypeSize = 1;
|
|
textureinfo.glFormat = 0;
|
|
break;
|
|
//default case
|
|
default:
|
|
isCompressed = false;
|
|
textureinfo.glType = GL_UNSIGNED_BYTE;
|
|
textureinfo.glTypeSize = 1;
|
|
break;
|
|
}
|
|
|
|
switch (pMipSet->m_TextureDataType)
|
|
{
|
|
case TDT_R: //single component-- can be Luminance and Alpha case, here only cover R
|
|
{
|
|
if (!isCompressed)
|
|
{
|
|
textureinfo.glFormat = textureinfo.glBaseInternalFormat = GL_RED;
|
|
textureinfo.glInternalFormat = GL_RED;
|
|
}
|
|
else
|
|
{
|
|
textureinfo.glBaseInternalFormat = GL_RED;
|
|
textureinfo.glInternalFormat = GL_RED;
|
|
}
|
|
}
|
|
break;
|
|
case TDT_RG: //two component
|
|
{
|
|
if (!isCompressed)
|
|
{
|
|
textureinfo.glFormat = textureinfo.glBaseInternalFormat = GL_RG;
|
|
textureinfo.glInternalFormat = GL_RG;
|
|
}
|
|
else
|
|
{
|
|
textureinfo.glBaseInternalFormat = GL_RG;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RG;
|
|
}
|
|
}
|
|
break;
|
|
case TDT_XRGB: //normally 3 component
|
|
{
|
|
if (!isCompressed)
|
|
{
|
|
textureinfo.glFormat = textureinfo.glBaseInternalFormat = GL_RGB;
|
|
textureinfo.glInternalFormat = GL_RGB;
|
|
}
|
|
else
|
|
{
|
|
|
|
switch (pMipSet->m_format)
|
|
{
|
|
case CMP_FORMAT_BC1 :
|
|
case CMP_FORMAT_DXT1:
|
|
textureinfo.glBaseInternalFormat = GL_RGB;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
|
break;
|
|
case CMP_FORMAT_ETC_RGB:
|
|
textureinfo.glBaseInternalFormat = GL_RGB;
|
|
textureinfo.glInternalFormat = ETC1_RGB8_OES;
|
|
break;
|
|
case CMP_FORMAT_ETC2_RGB:
|
|
textureinfo.glBaseInternalFormat = GL_RGB;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB8_ETC2;
|
|
break;
|
|
case CMP_FORMAT_ETC2_SRGB:
|
|
textureinfo.glBaseInternalFormat = GL_SRGB;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_SRGB8_ETC2;
|
|
break;
|
|
default:
|
|
textureinfo.glBaseInternalFormat = GL_RGB;
|
|
textureinfo.glInternalFormat = GL_RGB; //other compressed format not found in qtangle header
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case TDT_ARGB: //4 component
|
|
{
|
|
if (!isCompressed)
|
|
{
|
|
textureinfo.glFormat = textureinfo.glBaseInternalFormat = GL_RGBA;
|
|
textureinfo.glInternalFormat = GL_RGBA8;
|
|
}
|
|
else
|
|
{
|
|
textureinfo.glBaseInternalFormat = GL_RGBA;
|
|
switch (pMipSet->m_format)
|
|
{
|
|
case CMP_FORMAT_BC1:
|
|
case CMP_FORMAT_DXT1:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
|
break;
|
|
case CMP_FORMAT_BC2:
|
|
case CMP_FORMAT_DXT3:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
|
break;
|
|
case CMP_FORMAT_BC3:
|
|
case CMP_FORMAT_DXT5:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
|
break;
|
|
case CMP_FORMAT_BC7:
|
|
textureinfo.glInternalFormat = RGB_BP_UNorm;
|
|
break;
|
|
case CMP_FORMAT_ATI1N:
|
|
textureinfo.glInternalFormat = R_ATI1N_UNorm;
|
|
break;
|
|
case CMP_FORMAT_ATI2N:
|
|
textureinfo.glInternalFormat = R_ATI1N_SNorm;
|
|
break;
|
|
case CMP_FORMAT_ATI2N_XY:
|
|
textureinfo.glInternalFormat = RG_ATI2N_UNorm;
|
|
break;
|
|
case CMP_FORMAT_ATI2N_DXT5:
|
|
textureinfo.glInternalFormat = RG_ATI2N_SNorm;
|
|
break;
|
|
case CMP_FORMAT_ATC_RGB:
|
|
textureinfo.glInternalFormat = ATC_RGB_AMD;
|
|
break;
|
|
case CMP_FORMAT_ATC_RGBA_Explicit:
|
|
textureinfo.glInternalFormat = ATC_RGBA_EXPLICIT_ALPHA_AMD;
|
|
break;
|
|
case CMP_FORMAT_ATC_RGBA_Interpolated:
|
|
textureinfo.glInternalFormat = ATC_RGBA_INTERPOLATED_ALPHA_AMD;
|
|
break;
|
|
case CMP_FORMAT_BC4:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RED_RGTC1;
|
|
break;
|
|
case CMP_FORMAT_BC5:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RG_RGTC2;
|
|
break;
|
|
case CMP_FORMAT_BC6H:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
|
|
break;
|
|
case CMP_FORMAT_BC6H_SF:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
|
|
break;
|
|
case CMP_FORMAT_ASTC:
|
|
if ((pMipSet->m_nBlockWidth == 4) && (pMipSet->m_nBlockHeight == 4))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 5) && (pMipSet->m_nBlockHeight == 4))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_5x4_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 5) && (pMipSet->m_nBlockHeight == 5))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_5x5_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 6) && (pMipSet->m_nBlockHeight == 5))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_6x5_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 6) && (pMipSet->m_nBlockHeight == 6))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_6x6_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 8) && (pMipSet->m_nBlockHeight == 5))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x5_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 8) && (pMipSet->m_nBlockHeight == 6))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x6_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 8) && (pMipSet->m_nBlockHeight == 8))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_8x8_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 10) && (pMipSet->m_nBlockHeight == 5))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_10x5_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 10) && (pMipSet->m_nBlockHeight == 6))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_10x6_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 10) && (pMipSet->m_nBlockHeight == 8))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_10x8_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 10) && (pMipSet->m_nBlockHeight == 10))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_10x10_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 12) && (pMipSet->m_nBlockHeight == 10))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_12x10_KHR;
|
|
else if ((pMipSet->m_nBlockWidth == 12) && (pMipSet->m_nBlockHeight == 12))
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_12x12_KHR;
|
|
else
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
|
break;
|
|
case CMP_FORMAT_ETC_RGB:
|
|
textureinfo.glInternalFormat = ETC1_RGB8_OES;
|
|
break;
|
|
case CMP_FORMAT_ETC2_RGB:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB8_ETC2;
|
|
break;
|
|
case CMP_FORMAT_ETC2_SRGB:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_SRGB8_ETC2;
|
|
break;
|
|
case CMP_FORMAT_ETC2_RGBA:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
|
|
break;
|
|
case CMP_FORMAT_ETC2_RGBA1:
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
|
break;
|
|
case CMP_FORMAT_ETC2_SRGBA:
|
|
textureinfo.glBaseInternalFormat = GL_SRGB8_ALPHA8;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
|
|
break;
|
|
case CMP_FORMAT_ETC2_SRGBA1:
|
|
textureinfo.glBaseInternalFormat = GL_SRGB8_ALPHA8;
|
|
textureinfo.glInternalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
|
break;
|
|
case CMP_FORMAT_DXT5_xGBR:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_xGBR;
|
|
break;
|
|
case CMP_FORMAT_DXT5_RxBG:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_RxBG;
|
|
break;
|
|
case CMP_FORMAT_DXT5_RBxG:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_RBxG;
|
|
break;
|
|
case CMP_FORMAT_DXT5_xRBG:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_xRBG;
|
|
break;
|
|
case CMP_FORMAT_DXT5_RGxB:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_RGxB;
|
|
break;
|
|
case CMP_FORMAT_DXT5_xGxR:
|
|
textureinfo.glInternalFormat = COMPRESSED_FORMAT_DXT5_xGxR;
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
textureinfo.pixelWidth = pMipSet->m_nWidth;
|
|
textureinfo.pixelHeight = pMipSet->m_nHeight;
|
|
textureinfo.pixelDepth = 0; //for 1D, 2D and cube texture , depth =0;
|
|
|
|
//1D
|
|
if (pMipSet->m_nHeight == 1 && pData != NULL) {
|
|
delete(pData);
|
|
pData = NULL;
|
|
pDataLen = 0;
|
|
}
|
|
|
|
textureinfo.numberOfMipmapLevels = pMipSet->m_nMipLevels;
|
|
|
|
KTX_error_code save = ktxWriteKTXF(pFile, &textureinfo, pDataLen, pData, pMipSet->m_nMipLevels, inputMip);
|
|
if (save == KTX_SUCCESS) {
|
|
fclose(pFile);
|
|
}
|
|
else {
|
|
if (KTX_CMips)
|
|
KTX_CMips->PrintError(("Error(%d): KTX Plugin ID(%d) saving file = %s "), EL_Error, IDS_ERROR_FILE_OPEN, pszFilename);
|
|
fclose(pFile);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|