Implement glGenerateMipmapEXT
This commit is contained in:
parent
c6ba127bc9
commit
5c190c1095
165
GL/framebuffer.c
165
GL/framebuffer.c
|
@ -86,8 +86,171 @@ void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum
|
||||||
ACTIVE_FRAMEBUFFER->texture_id = texture;
|
ACTIVE_FRAMEBUFFER->texture_id = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APIENTRY glGenerateMipmapEXT(GLenum target) {
|
static inline GLuint A1555(GLuint v) {
|
||||||
|
const GLuint MASK = (1 << 15);
|
||||||
|
return (v & MASK) >> 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint R1555(GLuint v) {
|
||||||
|
const GLuint MASK = (31 << 10);
|
||||||
|
return (v & MASK) >> 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint G1555(GLuint v) {
|
||||||
|
const GLuint MASK = (31 << 5);
|
||||||
|
return (v & MASK) >> 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint B1555(GLuint v) {
|
||||||
|
const GLuint MASK = (31 << 0);
|
||||||
|
return (v & MASK) >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint A4444(GLuint v) {
|
||||||
|
const GLuint MASK = (0xF << 12);
|
||||||
|
return (v & MASK) >> 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint R4444(GLuint v) {
|
||||||
|
const GLuint MASK = (0xF << 8);
|
||||||
|
return (v & MASK) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint G4444(GLuint v) {
|
||||||
|
const GLuint MASK = (0xF << 4);
|
||||||
|
return (v & MASK) >> 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint B4444(GLuint v) {
|
||||||
|
const GLuint MASK = (0xF << 0);
|
||||||
|
return (v & MASK) >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint R565(GLuint v) {
|
||||||
|
const GLuint MASK = (31 << 11);
|
||||||
|
return (v & MASK) >> 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint G565(GLuint v) {
|
||||||
|
const GLuint MASK = (63 << 5);
|
||||||
|
return (v & MASK) >> 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline GLuint B565(GLuint v) {
|
||||||
|
const GLuint MASK = (31 << 0);
|
||||||
|
return (v & MASK) >> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLboolean _glCalculateAverageTexel(const GLubyte* src, const GLuint srcWidth, const GLuint pvrFormat, GLubyte* dest) {
|
||||||
|
GLushort* s1 = ((GLushort*) src);
|
||||||
|
GLushort* s2 = ((GLushort*) src) + 1;
|
||||||
|
GLushort* s3 = ((GLushort*) src) + srcWidth;
|
||||||
|
GLushort* s4 = ((GLushort*) src) + srcWidth + 1;
|
||||||
|
GLushort* d1 = ((GLushort*) dest);
|
||||||
|
|
||||||
|
GLuint a, r, g, b;
|
||||||
|
|
||||||
|
if((pvrFormat & PVR_TXRFMT_ARGB1555) == PVR_TXRFMT_ARGB1555) {
|
||||||
|
a = A1555(*s1) + A1555(*s2) + A1555(*s3) + A1555(*s4);
|
||||||
|
r = R1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||||
|
g = G1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||||
|
b = B1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||||
|
|
||||||
|
a /= 4;
|
||||||
|
r /= 4;
|
||||||
|
g /= 4;
|
||||||
|
b /= 4;
|
||||||
|
|
||||||
|
*d1 = (a << 15 | r << 10 | g << 5 | b);
|
||||||
|
} else if((pvrFormat & PVR_TXRFMT_ARGB4444) == PVR_TXRFMT_ARGB4444) {
|
||||||
|
a = A4444(*s1) + A4444(*s2) + A4444(*s3) + A4444(*s4);
|
||||||
|
r = R4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||||
|
g = G4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||||
|
b = B4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||||
|
|
||||||
|
a /= 4;
|
||||||
|
r /= 4;
|
||||||
|
g /= 4;
|
||||||
|
b /= 4;
|
||||||
|
|
||||||
|
*d1 = (a << 12 | r << 8 | g << 4 | b);
|
||||||
|
} else if((pvrFormat & PVR_TXRFMT_RGB565) == PVR_TXRFMT_ARGB4444) {
|
||||||
|
r = R565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||||
|
g = G565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||||
|
b = B565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||||
|
|
||||||
|
r /= 4;
|
||||||
|
g /= 4;
|
||||||
|
b /= 4;
|
||||||
|
|
||||||
|
*d1 = (r << 11 | g << 5 | b);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "ERROR: Unsupported PVR format for mipmap generation");
|
||||||
|
_glKosThrowError(GL_INVALID_OPERATION, "glGenerateMipmapEXT");
|
||||||
|
_glKosPrintError();
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void APIENTRY glGenerateMipmapEXT(GLenum target) {
|
||||||
|
if(target != GL_TEXTURE_2D) {
|
||||||
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
|
_glKosPrintError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureObject* tex = getBoundTexture();
|
||||||
|
|
||||||
|
if(!tex || !tex->data || !tex->mipmapCount) {
|
||||||
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
|
_glKosPrintError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_glIsMipmapComplete(tex)) {
|
||||||
|
/* Nothing to do */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint i = 1;
|
||||||
|
GLuint sx, sy, dx, dy;
|
||||||
|
GLuint prevWidth = tex->width;
|
||||||
|
GLuint prevHeight = tex->height;
|
||||||
|
|
||||||
|
for(; i < _glGetMipmapLevelCount(tex); ++i) {
|
||||||
|
GLubyte* prevData = _glGetMipmapLocation(tex, i - 1);
|
||||||
|
GLubyte* thisData = _glGetMipmapLocation(tex, i);
|
||||||
|
|
||||||
|
GLuint thisWidth = (prevWidth > 1) ? prevWidth / 2 : 1;
|
||||||
|
GLuint thisHeight = (prevHeight > 1) ? prevHeight / 2 : 1;
|
||||||
|
|
||||||
|
/* Do the minification */
|
||||||
|
for(sx = 0, dx = 0; sx < prevWidth; sx += 2, dx += 1) {
|
||||||
|
for(sy = 0, sy = 0; sy < prevHeight; sy += 2, dy += 1) {
|
||||||
|
GLubyte* srcTexel = &prevData[
|
||||||
|
((sy * prevWidth) + sx) * tex->dataStride
|
||||||
|
];
|
||||||
|
|
||||||
|
GLubyte* destTexel = &thisData[
|
||||||
|
((dy * thisWidth) + dx) * tex->dataStride
|
||||||
|
];
|
||||||
|
|
||||||
|
if(!_glCalculateAverageTexel(
|
||||||
|
srcTexel,
|
||||||
|
prevWidth,
|
||||||
|
tex->color,
|
||||||
|
destTexel
|
||||||
|
)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prevWidth = thisWidth;
|
||||||
|
prevHeight = thisHeight;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
|
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
|
||||||
|
|
|
@ -92,6 +92,8 @@ TextureObject* getTexture1();
|
||||||
TextureObject* getBoundTexture();
|
TextureObject* getBoundTexture();
|
||||||
GLboolean isBlendingEnabled();
|
GLboolean isBlendingEnabled();
|
||||||
GLboolean _glIsMipmapComplete(TextureObject* obj);
|
GLboolean _glIsMipmapComplete(TextureObject* obj);
|
||||||
|
GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level);
|
||||||
|
GLuint _glGetMipmapLevelCount(TextureObject* obj);
|
||||||
|
|
||||||
GLboolean isLightingEnabled();
|
GLboolean isLightingEnabled();
|
||||||
GLboolean isLightEnabled(GLubyte light);
|
GLboolean isLightEnabled(GLubyte light);
|
||||||
|
|
19
GL/texture.c
19
GL/texture.c
|
@ -605,12 +605,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the required mipmap count */
|
|
||||||
active->mipmapCount = _glGetMipmapLevelCount(active);
|
|
||||||
|
|
||||||
/* Mark this level as set in the mipmap bitmask */
|
|
||||||
active->mipmap |= (1 << level);
|
|
||||||
|
|
||||||
GLuint bytes = (width * height * sizeof(GLushort));
|
GLuint bytes = (width * height * sizeof(GLushort));
|
||||||
|
|
||||||
if(!active->data) {
|
if(!active->data) {
|
||||||
|
@ -618,10 +612,15 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
active->width = width;
|
active->width = width;
|
||||||
active->height = height;
|
active->height = height;
|
||||||
active->color = pvr_format;
|
active->color = pvr_format;
|
||||||
|
/* Set the required mipmap count */
|
||||||
|
active->mipmapCount = _glGetMipmapLevelCount(active);
|
||||||
active->data = pvr_mem_malloc(_glGetMipmapDataSize(active));
|
active->data = pvr_mem_malloc(_glGetMipmapDataSize(active));
|
||||||
active->dataStride = _determineStride(format, type);
|
active->dataStride = sizeof(GLshort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark this level as set in the mipmap bitmask */
|
||||||
|
active->mipmap |= (1 << level);
|
||||||
|
|
||||||
/* Let's assume we need to convert */
|
/* Let's assume we need to convert */
|
||||||
GLboolean needsConversion = GL_TRUE;
|
GLboolean needsConversion = GL_TRUE;
|
||||||
|
|
||||||
|
@ -667,7 +666,9 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
GLushort* dest = (GLushort*) targetData;
|
GLushort* dest = (GLushort*) targetData;
|
||||||
const GLubyte* source = data;
|
const GLubyte* source = data;
|
||||||
|
|
||||||
if(active->dataStride == -1) {
|
GLint stride = _determineStride(format, type);
|
||||||
|
|
||||||
|
if(stride == -1) {
|
||||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -678,7 +679,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||||
convert(source, dest);
|
convert(source, dest);
|
||||||
|
|
||||||
dest++;
|
dest++;
|
||||||
source += active->dataStride;
|
source += stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,8 @@ void LoadGLTextures() {
|
||||||
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
|
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
|
||||||
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
|
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||||
|
|
||||||
|
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user