Created
February 25, 2016 09:04
-
-
Save rotoglup/9a6340752a2629496d4b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* rtgu_ktx.h - Version -1 WIP untested | |
* No endianness swap support | |
int ktx_load(ktx_image* i, ktx__context* k); | |
*/ | |
// TODO(nico) public typedefs | |
typedef unsigned char ktx_uc; | |
#ifdef _MSC_VER | |
typedef unsigned short ktx__uint16; | |
typedef signed short ktx__int16; | |
typedef unsigned int ktx__uint32; | |
typedef signed int ktx__int32; | |
typedef unsigned __int64 ktx_uint64; | |
#else | |
#include <stdint.h> | |
typedef uint16_t ktx__uint16; | |
typedef int16_t ktx__int16; | |
typedef uint32_t ktx__uint32; | |
typedef int32_t ktx__int32; | |
#endif | |
typedef struct { | |
ktx_uc identifier[12]; | |
ktx__uint32 endianness; | |
ktx__uint32 glType; | |
ktx__uint32 glTypeSize; | |
ktx__uint32 glFormat; | |
ktx__uint32 glInternalFormat; | |
ktx__uint32 glBaseInternalFormat; | |
ktx__uint32 pixelWidth; | |
ktx__uint32 pixelHeight; | |
ktx__uint32 pixelDepth; | |
ktx__uint32 numberOfArrayElements; | |
ktx__uint32 numberOfFaces; | |
ktx__uint32 numberOfMipmapLevels; | |
ktx__uint32 bytesOfKeyValueData; | |
} ktx__header; | |
#define KTX__MAX_NUM_FACES 6 | |
#define KTX__MAX_NUM_MIPMAPS 16 | |
typedef struct { | |
int w, h, d; // width, height, depth | |
int dimensions; // 1, 2 or 3 | |
int is_compressed; // bool | |
int requests_generate_mipmaps; // bool | |
int is_array; // bool | |
int num_mipmaps; | |
int num_array_elements; | |
int num_faces; | |
int gl_target; // GL_TEXTURE_1D ... GL_TEXTURE_CUBE_MAP | |
int gl_internal_format; | |
int gl_format; | |
int gl_type; | |
ktx_uint64 images_offsets[KTX__MAX_NUM_FACES * KTX__MAX_NUM_MIPMAPS]; | |
} ktx_image; | |
// should produce compiler error if sizes are wrong | |
typedef unsigned char ktx__validate_uint32[sizeof(ktx__uint32)== 4 ? 1 : -1]; | |
typedef unsigned char ktx__validate_header[sizeof(ktx__header)==64 ? 1 : -1]; | |
// | |
typedef struct { | |
ktx_uc *buffer, *buffer_end; | |
} ktx__context; | |
// | |
#define KTXDEF // TODO | |
#define KTX__IDENTIFIER_REF { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A } // TODO | |
#define KTX__ENDIAN_REF 0x04030201 | |
#define KTX__ENDIAN_REF_REV 0x01020304 | |
#define KTX__GL_TEXTURE_1D 0x0 // TODO | |
#define KTX__GL_TEXTURE_2D 0x0 | |
#define KTX__GL_TEXTURE_3D 0x0 | |
#define KTX__GL_TEXTURE_CUBE_MAP 0x0 | |
#define KTX__MAX(x, y) (((y)<(x)) ? (x) : (y)) | |
// | |
static int ktx__getn(ktx__context *k, ktx_uc *buffer, int n) | |
{ | |
if (k->buffer+n <= k->buffer_end) { | |
memcpy(buffer, k->buffer, n); | |
k->buffer += n; | |
return 1; | |
} else | |
return 0; | |
} | |
static ktx__uint32 ktx__get32(ktx__context *k) | |
{ | |
ktx__uint32 res; | |
if (!ktx__getn(k, (ktx_uc*)&res, sizeof(res))) return 0; | |
return res; | |
} | |
// | |
// this is not threadsafe | |
static const char *ktx__g_failure_reason; | |
KTXDEF const char *ktx_failure_reason(void) | |
{ | |
return ktx__g_failure_reason; | |
} | |
static int ktx__err(const char *str) | |
{ | |
ktx__g_failure_reason = str; | |
return 0; | |
} | |
#ifdef STBI_NO_FAILURE_STRINGS | |
#define ktx__err(x,y) 0 | |
#elif defined(STBI_FAILURE_USERMSG) | |
#define ktx__err(x,y) ktx__err(y) | |
#else | |
#define ktx__err(x,y) ktx__err(x) | |
#endif | |
// | |
static int ktx__check_ktx_header(ktx__header *h, ktx_image *i) { | |
ktx__uint32 max_dim; | |
if (h->endianness == KTX__ENDIAN_REF_REV) return ktx__err("header", "Wrong endianness for this plaftorm"); | |
if (h->endianness != KTX__ENDIAN_REF) return ktx__err("header", "Invalid signature"); | |
i->is_compressed = (h->glType == 0 || h->glFormat == 0); | |
if (i->is_compressed && (h->glType == h->glFormat)) return ktx__err("header", "Invalid glType or glFormat"); | |
if (h->pixelWidth == 0) return ktx__err("header", "Image without width"); | |
if (h->pixelDepth > 0 && h->pixelHeight == 0) return ktx__err("header", "Image without height"); | |
i->dimensions = 1; | |
i->gl_target = KTX__GL_TEXTURE_1D; | |
if (h->pixelHeight > 0) { | |
i->dimensions = 2; | |
i->gl_target = KTX__GL_TEXTURE_2D; | |
} | |
if (h->pixelDepth > 0) { | |
i->dimensions = 3; | |
i->gl_target = KTX__GL_TEXTURE_3D; | |
} | |
if (h->numberOfFaces == 6) { | |
if (i->dimensions != 2) return ktx__err("header", "Invalid cubemap faces"); | |
i->gl_target = KTX__GL_TEXTURE_CUBE_MAP; | |
} | |
else { | |
if (h->numberOfFaces != 1) return ktx__err("header", "Invalid number of faces"); | |
} | |
i->requests_generate_mipmaps = (h->numberOfMipmapLevels == 0); | |
h->numberOfMipmapLevels = KTX__MAX(1, h->numberOfMipmapLevels); | |
if (h->numberOfMipmapLevels > KTX__MAX_NUM_MIPMAPS) return ktx__err("header", "Unsupported number of mipmaps"); | |
i->is_array = (h->numberOfArrayElements != 0); | |
h->numberOfArrayElements = KTX__MAX(1, h->numberOfArrayElements); | |
max_dim = KTX__MAX( KTX__MAX(h->pixelWidth, h->pixelHeight), h->pixelDepth ); | |
if (max_dim < (1u << (h->numberOfMipmapLevels-1)) ) return ktx__err("header", "Too many mipmaps"); | |
i->w = h->pixelWidth; | |
i->h = h->pixelHeight; | |
i->d = h->pixelDepth; | |
return 1; | |
} | |
static int ktx__load_ktx_key_value_data(ktx__context *k, ktx__header *h) { | |
return 0; // TODO(nico) | |
} | |
int ktx_load(ktx_image* i, ktx__context* k) { | |
ktx__header header; | |
int level, array_elem, face; | |
int res = 0; | |
if (!ktx__getn(k, (ktx_uc*)&header, sizeof(header))) return ktx__err("outofdata", "Corrupt KTX header"); | |
if (!ktx__check_ktx_header(&header, i)) return 0; | |
if (!ktx__load_ktx_key_value_data(k, &header)) return 0; | |
for (level = 0; level < header.numberOfMipmapLevels; ++level) | |
{ | |
ktx__int32 w = KTX__MAX(1, header.pixelWidth >> level); | |
ktx__int32 h = KTX__MAX(1, header.pixelHeight >> level); | |
ktx__int32 d = KTX__MAX(1, header.pixelDepth >> level); | |
ktx__uint32 face_lod_size = ktx__get32(k); | |
ktx__uint32 face_lod_size_padded = (face_lod_size + 3u) & (ktx__uint32)(~3); | |
if (face_lod_size == 0) return ktx__err("outofdata", "Invalid imageSize"); | |
// TODO(nico) allocate memory ? | |
for (face = 0; face < header.numberOfFaces; ++face) | |
{ | |
//if (!stbi__getn(k, some_buffer, face_lod_size_padded)) goto errorEnd; // TODO(nico) some error info | |
} | |
} | |
res = 1; | |
errorEnd: | |
return res; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "rtgu_ktx.h" | |
#define GLenum int // TODO(nico) | |
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0 // TODO | |
#define GL_TEXTURE_CUBE_MAP 0 // TODO | |
#define GL_UNPACK_ALIGNMENT 0 // TODO | |
int main() | |
{ | |
ktx_image c; | |
ktx__context k; | |
int face, level; | |
if (ktx_load(&c, &k)) { | |
void **image_data = c.images_data; | |
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | |
for (level=0; level<c.num_mipmaps; ++level) { | |
int w = c.w, h = c.h, d = c.d; | |
int dim = c.dimensions; | |
if (c.is_array) { | |
// adjust dimensions to upload the whole array in one batch | |
if (dim == 1) h = c.num_array_elements; | |
if (dim == 2) d = c.num_array_elements; | |
else return 0; // TODO(nico) err("Arrays of 3D textures unsupported") | |
if (c.gl_target == GL_TEXTURE_CUBE_MAP) return 0; // TODO(nico) err("Arrays of cubemap textures unsupported") | |
++dim; | |
} | |
for (face=0; face<c.num_faces; ++face) { | |
GLenum gl_target = | |
(c.gl_target == GL_TEXTURE_CUBE_MAP) | |
? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face | |
: c.gl_target | |
; | |
if (c.is_compressed) { | |
// TODO(nico) | |
} | |
else { | |
if (dim == 1) { | |
glTexImage1D( | |
gl_target, | |
level, | |
c.gl_internal_format, | |
w, | |
0, | |
c.gl_format, c.gl_type, image_data | |
); | |
} | |
else if (dim == 2) { | |
glTexImage2D( | |
gl_target, | |
level, | |
c.gl_internal_format, | |
w, h, | |
0, | |
c.gl_format, c.gl_type, image_data | |
); | |
} | |
else if (dim == 3) { | |
// TODO(nico) | |
} | |
} | |
++image_data; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment