Add support for mipmapped compressed textures
This commit is contained in:
parent
b06f6116c8
commit
4c99dd740a
|
@ -35,7 +35,8 @@ typedef struct {
|
||||||
GLuint color; /* This is the PVR texture format */
|
GLuint color; /* This is the PVR texture format */
|
||||||
GLubyte env;
|
GLubyte env;
|
||||||
GLubyte filter;
|
GLubyte filter;
|
||||||
GLubyte mip_map;
|
GLushort mipmap; /* Bitmask of supplied mipmap levels */
|
||||||
|
GLubyte mipmapCount; /* The number of mipmap levels */
|
||||||
GLubyte uv_clamp;
|
GLubyte uv_clamp;
|
||||||
GLuint index;
|
GLuint index;
|
||||||
GLvoid *data;
|
GLvoid *data;
|
||||||
|
@ -89,6 +90,7 @@ TextureObject* getTexture0();
|
||||||
TextureObject* getTexture1();
|
TextureObject* getTexture1();
|
||||||
TextureObject* getBoundTexture();
|
TextureObject* getBoundTexture();
|
||||||
GLboolean isBlendingEnabled();
|
GLboolean isBlendingEnabled();
|
||||||
|
GLboolean _glIsMipmapComplete(TextureObject* obj);
|
||||||
|
|
||||||
GLboolean isLightingEnabled();
|
GLboolean isLightingEnabled();
|
||||||
GLboolean isLightEnabled(GLubyte light);
|
GLboolean isLightEnabled(GLubyte light);
|
||||||
|
|
|
@ -129,6 +129,7 @@ void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject *tx1) {
|
||||||
if(tx1) {
|
if(tx1) {
|
||||||
context->txr.enable = PVR_TEXTURE_ENABLE;
|
context->txr.enable = PVR_TEXTURE_ENABLE;
|
||||||
context->txr.filter = tx1->filter;
|
context->txr.filter = tx1->filter;
|
||||||
|
context->txr.mipmap = (_glIsMipmapComplete(tx1)) ? PVR_MIPMAP_ENABLE : PVR_MIPMAP_DISABLE;
|
||||||
context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
|
context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
|
||||||
context->txr.width = tx1->width;
|
context->txr.width = tx1->width;
|
||||||
context->txr.height = tx1->height;
|
context->txr.height = tx1->height;
|
||||||
|
|
69
GL/texture.c
69
GL/texture.c
|
@ -8,6 +8,8 @@
|
||||||
#define CLAMP_U (1<<1)
|
#define CLAMP_U (1<<1)
|
||||||
#define CLAMP_V (1<<0)
|
#define CLAMP_V (1<<0)
|
||||||
|
|
||||||
|
#define MAX(x, y) ((x > y) ? x : y)
|
||||||
|
|
||||||
static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL};
|
static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL};
|
||||||
static NamedArray TEXTURE_OBJECTS;
|
static NamedArray TEXTURE_OBJECTS;
|
||||||
static GLubyte ACTIVE_TEXTURE = 0;
|
static GLubyte ACTIVE_TEXTURE = 0;
|
||||||
|
@ -77,11 +79,12 @@ void APIENTRY glGenTextures(GLsizei n, GLuint *textures) {
|
||||||
TextureObject* txr = (TextureObject*) named_array_alloc(&TEXTURE_OBJECTS, &id);
|
TextureObject* txr = (TextureObject*) named_array_alloc(&TEXTURE_OBJECTS, &id);
|
||||||
txr->index = id;
|
txr->index = id;
|
||||||
txr->width = txr->height = 0;
|
txr->width = txr->height = 0;
|
||||||
txr->mip_map = 0;
|
txr->mipmap = 0;
|
||||||
txr->uv_clamp = 0;
|
txr->uv_clamp = 0;
|
||||||
txr->env = PVR_TXRENV_MODULATEALPHA;
|
txr->env = PVR_TXRENV_MODULATEALPHA;
|
||||||
txr->filter = PVR_FILTER_NONE;
|
txr->filter = PVR_FILTER_NONE;
|
||||||
txr->data = NULL;
|
txr->data = NULL;
|
||||||
|
txr->mipmapCount = 0;
|
||||||
|
|
||||||
*textures = id;
|
*textures = id;
|
||||||
|
|
||||||
|
@ -181,8 +184,13 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||||
if(target != GL_TEXTURE_2D)
|
if(target != GL_TEXTURE_2D)
|
||||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||||
|
|
||||||
if(level < 0 || border)
|
if(level || border) {
|
||||||
|
/* We don't support setting mipmap levels manually with compressed textures
|
||||||
|
maybe one day */
|
||||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLboolean mipmapped = GL_FALSE;
|
||||||
|
|
||||||
switch(internalFormat) {
|
switch(internalFormat) {
|
||||||
case GL_COMPRESSED_ARGB_1555_VQ_KOS:
|
case GL_COMPRESSED_ARGB_1555_VQ_KOS:
|
||||||
|
@ -192,6 +200,14 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||||
case GL_COMPRESSED_RGB_565_VQ_KOS:
|
case GL_COMPRESSED_RGB_565_VQ_KOS:
|
||||||
case GL_COMPRESSED_RGB_565_VQ_TWID_KOS:
|
case GL_COMPRESSED_RGB_565_VQ_TWID_KOS:
|
||||||
break;
|
break;
|
||||||
|
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS:
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS:
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS:
|
||||||
|
mipmapped = GL_TRUE;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +224,7 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||||
/* The ratio is the uncompressed vs compressed data size */
|
/* The ratio is the uncompressed vs compressed data size */
|
||||||
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) imageSize));
|
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) imageSize));
|
||||||
|
|
||||||
if(ratio < 7) {
|
if(ratio < 7 && !mipmapped) {
|
||||||
/* If the ratio is less than 1:7 then we assume that the reason for that
|
/* If the ratio is less than 1:7 then we assume that the reason for that
|
||||||
is the extra data used for mipmaps. Testing shows that a single VQ compressed
|
is the extra data used for mipmaps. Testing shows that a single VQ compressed
|
||||||
image is around 1:7 or 1:8. We may need to tweak this if it detects false positives */
|
image is around 1:7 or 1:8. We may need to tweak this if it detects false positives */
|
||||||
|
@ -223,9 +239,11 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||||
|
|
||||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||||
|
|
||||||
|
/* Set the required mipmap count */
|
||||||
|
active->mipmapCount = 1 + floor(log2(MAX(width, height)));
|
||||||
|
active->mipmap = (mipmapped) ? ~0 : (1 << level); /* Set only a single bit if this wasn't mipmapped otherwise set all */
|
||||||
active->width = width;
|
active->width = width;
|
||||||
active->height = height;
|
active->height = height;
|
||||||
active->mip_map = level;
|
|
||||||
active->color = _determinePVRFormat(
|
active->color = _determinePVRFormat(
|
||||||
internalFormat,
|
internalFormat,
|
||||||
internalFormat /* Doesn't matter (see determinePVRFormat) */
|
internalFormat /* Doesn't matter (see determinePVRFormat) */
|
||||||
|
@ -333,21 +351,27 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
|
||||||
/* Compressed and twiddled versions */
|
/* Compressed and twiddled versions */
|
||||||
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
|
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
|
||||||
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED;
|
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED;
|
||||||
case GL_COMPRESSED_RGB_565_VQ_KOS:
|
|
||||||
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
|
||||||
case GL_COMPRESSED_RGB_565_VQ_TWID_KOS:
|
|
||||||
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
|
||||||
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
|
case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS:
|
||||||
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED;
|
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED;
|
||||||
case GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS:
|
|
||||||
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
|
||||||
case GL_COMPRESSED_ARGB_4444_VQ_KOS:
|
|
||||||
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
|
||||||
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
|
case GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS:
|
||||||
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED;
|
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED;
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_KOS:
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS:
|
||||||
|
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_TWID_KOS:
|
||||||
|
case GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS:
|
||||||
|
return PVR_TXRFMT_RGB565 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS:
|
||||||
|
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS:
|
||||||
|
return PVR_TXRFMT_ARGB4444 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
case GL_COMPRESSED_ARGB_1555_VQ_KOS:
|
case GL_COMPRESSED_ARGB_1555_VQ_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS:
|
||||||
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_NONTWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
case GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS:
|
case GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS:
|
||||||
|
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS:
|
||||||
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -445,6 +469,20 @@ static GLboolean _isSupportedFormat(GLenum format) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLboolean _glIsMipmapComplete(TextureObject* obj) {
|
||||||
|
if(!obj->mipmap || !obj->mipmapCount) {
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLsizei i = 0;
|
||||||
|
for(; i < obj->mipmapCount; ++i) {
|
||||||
|
if((obj->mipmap & (1 << i)) == 0) {
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
GLsizei width, GLsizei height, GLint border,
|
GLsizei width, GLsizei height, GLint border,
|
||||||
|
@ -509,21 +547,24 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
/* pre-existing texture - check if changed */
|
/* pre-existing texture - check if changed */
|
||||||
if(active->width != width ||
|
if(active->width != width ||
|
||||||
active->height != height ||
|
active->height != height ||
|
||||||
active->mip_map != level ||
|
|
||||||
active->color != pvr_format) {
|
active->color != pvr_format) {
|
||||||
/* changed - free old texture memory */
|
/* changed - free old texture memory */
|
||||||
pvr_mem_free(active->data);
|
pvr_mem_free(active->data);
|
||||||
active->data = NULL;
|
active->data = NULL;
|
||||||
|
active->mipmap = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the required mipmap count */
|
||||||
|
active->mipmapCount = 1 + floor(log2(MAX(width, height)));
|
||||||
|
|
||||||
GLuint bytes = (width * height * sizeof(GLushort));
|
GLuint bytes = (width * height * sizeof(GLushort));
|
||||||
|
|
||||||
if(!active->data) {
|
if(!active->data) {
|
||||||
/* need texture memory */
|
/* need texture memory */
|
||||||
active->width = width;
|
active->width = width;
|
||||||
active->height = height;
|
active->height = height;
|
||||||
active->mip_map = level;
|
active->mipmap |= (1 << level); /* Mark this level as set in the mipmap bitmask */
|
||||||
active->color = pvr_format;
|
active->color = pvr_format;
|
||||||
active->data = pvr_mem_malloc(bytes);
|
active->data = pvr_mem_malloc(bytes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,14 @@ __BEGIN_DECLS
|
||||||
#define GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS 0xEEEA
|
#define GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS 0xEEEA
|
||||||
#define GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS 0xEEEB
|
#define GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS 0xEEEB
|
||||||
|
|
||||||
|
#define GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS 0xEEEC
|
||||||
|
#define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS 0xEEED
|
||||||
|
#define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS 0xEEEE
|
||||||
|
|
||||||
|
#define GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS 0xEEEF
|
||||||
|
#define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS 0xEEF0
|
||||||
|
#define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS 0xEEF1
|
||||||
|
|
||||||
#define GL_NEARZ_CLIPPING_KOS 0xEEFA
|
#define GL_NEARZ_CLIPPING_KOS 0xEEFA
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,10 @@ int ImageLoad(char *filename, Image *image) {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
char id[4]; // 'DTEX'
|
char id[4]; // 'DTEX'
|
||||||
short width;
|
GLushort width;
|
||||||
short height;
|
GLushort height;
|
||||||
int type;
|
GLuint type;
|
||||||
int size;
|
GLuint size;
|
||||||
} header;
|
} header;
|
||||||
|
|
||||||
fread(&header, sizeof(header), 1, file);
|
fread(&header, sizeof(header), 1, file);
|
||||||
|
@ -66,14 +66,27 @@ int ImageLoad(char *filename, Image *image) {
|
||||||
if(compressed) {
|
if(compressed) {
|
||||||
if(twiddled) {
|
if(twiddled) {
|
||||||
switch(format) {
|
switch(format) {
|
||||||
case 0:
|
case 0: {
|
||||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
if(mipmapped) {
|
||||||
break;
|
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
|
||||||
case 1:
|
} else {
|
||||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||||
break;
|
}
|
||||||
case 2:
|
} break;
|
||||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
case 1: {
|
||||||
|
if(mipmapped) {
|
||||||
|
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS;
|
||||||
|
} else {
|
||||||
|
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
if(mipmapped) {
|
||||||
|
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS;
|
||||||
|
} else {
|
||||||
|
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Invalid texture format");
|
fprintf(stderr, "Invalid texture format");
|
||||||
|
@ -81,14 +94,27 @@ int ImageLoad(char *filename, Image *image) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(format) {
|
switch(format) {
|
||||||
case 0:
|
case 0: {
|
||||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
if(mipmapped) {
|
||||||
break;
|
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
|
||||||
case 1:
|
} else {
|
||||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
|
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||||
break;
|
}
|
||||||
case 2:
|
} break;
|
||||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
case 1: {
|
||||||
|
if(mipmapped) {
|
||||||
|
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS;
|
||||||
|
} else {
|
||||||
|
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 2: {
|
||||||
|
if(mipmapped) {
|
||||||
|
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS;
|
||||||
|
} else {
|
||||||
|
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Invalid texture format");
|
fprintf(stderr, "Invalid texture format");
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 23 KiB |
Binary file not shown.
Loading…
Reference in New Issue
Block a user