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 */
|
||||
GLubyte env;
|
||||
GLubyte filter;
|
||||
GLubyte mip_map;
|
||||
GLushort mipmap; /* Bitmask of supplied mipmap levels */
|
||||
GLubyte mipmapCount; /* The number of mipmap levels */
|
||||
GLubyte uv_clamp;
|
||||
GLuint index;
|
||||
GLvoid *data;
|
||||
|
@ -89,6 +90,7 @@ TextureObject* getTexture0();
|
|||
TextureObject* getTexture1();
|
||||
TextureObject* getBoundTexture();
|
||||
GLboolean isBlendingEnabled();
|
||||
GLboolean _glIsMipmapComplete(TextureObject* obj);
|
||||
|
||||
GLboolean isLightingEnabled();
|
||||
GLboolean isLightEnabled(GLubyte light);
|
||||
|
|
|
@ -129,6 +129,7 @@ void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject *tx1) {
|
|||
if(tx1) {
|
||||
context->txr.enable = PVR_TEXTURE_ENABLE;
|
||||
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.width = tx1->width;
|
||||
context->txr.height = tx1->height;
|
||||
|
|
69
GL/texture.c
69
GL/texture.c
|
@ -8,6 +8,8 @@
|
|||
#define CLAMP_U (1<<1)
|
||||
#define CLAMP_V (1<<0)
|
||||
|
||||
#define MAX(x, y) ((x > y) ? x : y)
|
||||
|
||||
static TextureObject* TEXTURE_UNITS[MAX_TEXTURE_UNITS] = {NULL, NULL};
|
||||
static NamedArray TEXTURE_OBJECTS;
|
||||
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);
|
||||
txr->index = id;
|
||||
txr->width = txr->height = 0;
|
||||
txr->mip_map = 0;
|
||||
txr->mipmap = 0;
|
||||
txr->uv_clamp = 0;
|
||||
txr->env = PVR_TXRENV_MODULATEALPHA;
|
||||
txr->filter = PVR_FILTER_NONE;
|
||||
txr->data = NULL;
|
||||
txr->mipmapCount = 0;
|
||||
|
||||
*textures = id;
|
||||
|
||||
|
@ -181,8 +184,13 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
|||
if(target != GL_TEXTURE_2D)
|
||||
_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__);
|
||||
}
|
||||
|
||||
GLboolean mipmapped = GL_FALSE;
|
||||
|
||||
switch(internalFormat) {
|
||||
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_TWID_KOS:
|
||||
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:
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
}
|
||||
|
@ -208,7 +224,7 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
|||
/* The ratio is the uncompressed vs compressed data size */
|
||||
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
|
||||
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 */
|
||||
|
@ -223,9 +239,11 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
|||
|
||||
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->height = height;
|
||||
active->mip_map = level;
|
||||
active->color = _determinePVRFormat(
|
||||
internalFormat,
|
||||
internalFormat /* Doesn't matter (see determinePVRFormat) */
|
||||
|
@ -333,21 +351,27 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
|
|||
/* Compressed and twiddled versions */
|
||||
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
|
||||
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:
|
||||
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:
|
||||
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_MIPMAP_KOS:
|
||||
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_MIPMAP_TWID_KOS:
|
||||
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
|
||||
default:
|
||||
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,
|
||||
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 */
|
||||
if(active->width != width ||
|
||||
active->height != height ||
|
||||
active->mip_map != level ||
|
||||
active->color != pvr_format) {
|
||||
/* changed - free old texture memory */
|
||||
pvr_mem_free(active->data);
|
||||
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));
|
||||
|
||||
if(!active->data) {
|
||||
/* need texture memory */
|
||||
active->width = width;
|
||||
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->data = pvr_mem_malloc(bytes);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,14 @@ __BEGIN_DECLS
|
|||
#define GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS 0xEEEA
|
||||
#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
|
||||
|
||||
|
||||
|
|
|
@ -38,10 +38,10 @@ int ImageLoad(char *filename, Image *image) {
|
|||
|
||||
struct {
|
||||
char id[4]; // 'DTEX'
|
||||
short width;
|
||||
short height;
|
||||
int type;
|
||||
int size;
|
||||
GLushort width;
|
||||
GLushort height;
|
||||
GLuint type;
|
||||
GLuint size;
|
||||
} header;
|
||||
|
||||
fread(&header, sizeof(header), 1, file);
|
||||
|
@ -66,14 +66,27 @@ int ImageLoad(char *filename, Image *image) {
|
|||
if(compressed) {
|
||||
if(twiddled) {
|
||||
switch(format) {
|
||||
case 0:
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||
break;
|
||||
case 1:
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||
break;
|
||||
case 2:
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||
case 0: {
|
||||
if(mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||
}
|
||||
} break;
|
||||
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;
|
||||
default:
|
||||
fprintf(stderr, "Invalid texture format");
|
||||
|
@ -81,14 +94,27 @@ int ImageLoad(char *filename, Image *image) {
|
|||
}
|
||||
} else {
|
||||
switch(format) {
|
||||
case 0:
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||
break;
|
||||
case 1:
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||
break;
|
||||
case 2:
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||
case 0: {
|
||||
if(mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||
}
|
||||
} break;
|
||||
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;
|
||||
default:
|
||||
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