diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 6967bab74..7c77c27ea 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -131,7 +131,6 @@ static const GLfloat byte2float[256] = { // -----------------+ // GL_DBG_Printf : Output debug messages to debug log if DEBUG_TO_FILE is defined, // : else do nothing -// Returns : // -----------------+ #ifdef DEBUG_TO_FILE @@ -159,8 +158,6 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) // -----------------+ // GL_MSG_Warning : Raises a warning. -// : -// Returns : // -----------------+ static void GL_MSG_Warning(const char *format, ...) @@ -184,8 +181,6 @@ static void GL_MSG_Warning(const char *format, ...) // -----------------+ // GL_MSG_Error : Raises an error. -// : -// Returns : // -----------------+ static void GL_MSG_Error(const char *format, ...) @@ -207,6 +202,32 @@ static void GL_MSG_Error(const char *format, ...) #endif } +// ----------------------+ +// GetTextureFormatName : Returns the corresponding texture format string from the texture format enumeration. +// ----------------------+ +static const char *GetTextureFormatName(INT32 format) +{ + static char num[12]; + + switch (format) + { + case GL_TEXFMT_P_8: return "GL_TEXFMT_P_8"; + case GL_TEXFMT_AP_88: return "GL_TEXFMT_AP_88"; + case GL_TEXFMT_RGBA: return "GL_TEXFMT_RGBA"; + case GL_TEXFMT_ALPHA_8: return "GL_TEXFMT_ALPHA_8"; + case GL_TEXFMT_INTENSITY_8: return "GL_TEXFMT_INTENSITY_8"; + case GL_TEXFMT_ALPHA_INTENSITY_88: return "GL_TEXFMT_ALPHA_INTENSITY_88"; + default: break; + } + + // If the texture format is not known (due to it being invalid), + // return a string containing the format index instead. + format = INT32_MIN; + snprintf(num, sizeof(num), "%d", format); + + return num; +} + #ifdef STATIC_OPENGL /* 1.0 functions */ /* Miscellaneous */ @@ -1375,7 +1396,6 @@ INT32 isExtAvailable(const char *extension, const GLubyte *start) // -----------------+ // Init : Initialise the OpenGL interface API -// Returns : // -----------------+ EXPORT boolean HWRAPI(Init) (void) { @@ -1737,37 +1757,59 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } +// -------------------+ +// AllocTextureBuffer : Allocates memory for converting a non-RGBA texture into an RGBA texture. +// -------------------+ +static RGBA_t *AllocTextureBuffer(GLMipmap_t *pTexInfo) +{ + size_t len = (pTexInfo->width * pTexInfo->height); + RGBA_t *tex = calloc(len, sizeof(RGBA_t)); + + if (tex == NULL) + I_Error("AllocTextureBuffer: out of memory allocating %s bytes for texture %d, format %s", + sizeu1(len * sizeof(RGBA_t)), pTexInfo->downloaded, GetTextureFormatName(pTexInfo->format)); + + return tex; +} + +// ------------------+ +// FreeTextureBuffer : Frees memory allocated by AllocTextureBuffer. +// ------------------+ +static void FreeTextureBuffer(RGBA_t *tex) +{ + if (tex) + free(tex); +} + // -----------------+ -// UpdateTexture : Updates the texture data. +// UpdateTexture : Updates texture data. // -----------------+ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) { - // Download a mipmap - boolean updatemipmap = true; - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; + // Upload a texture + GLuint num = pTexInfo->downloaded; + boolean update = true; - if (!pTexInfo->downloaded) + INT32 w = pTexInfo->width, h = pTexInfo->height; + INT32 i, j; + + const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; + const GLvoid *ptex = NULL; + RGBA_t *tex = NULL; + + // Generate a new texture name. + if (!num) { - pglGenTextures(1, &texnum); - pTexInfo->downloaded = texnum; - updatemipmap = false; + pglGenTextures(1, &num); + pTexInfo->downloaded = num; + update = false; } - else - texnum = pTexInfo->downloaded; - //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->data); + //GL_DBG_Printf("UpdateTexture %d %x\n", (INT32)num, pImgData); - w = pTexInfo->width; - h = pTexInfo->height; - - if ((pTexInfo->format == GL_TEXFMT_P_8) || - (pTexInfo->format == GL_TEXFMT_AP_88)) + if ((pTexInfo->format == GL_TEXFMT_P_8) || (pTexInfo->format == GL_TEXFMT_AP_88)) { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1798,20 +1840,17 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) tex[w*j+i].s.alpha = *pImgData; pImgData++; } - } } } else if (pTexInfo->format == GL_TEXFMT_RGBA) { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->data; + // Directly upload the texture data without any kind of conversion. + ptex = pImgData; } else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1828,8 +1867,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; - INT32 i, j; + ptex = tex = AllocTextureBuffer(pTexInfo); for (j = 0; j < h; j++) { @@ -1844,11 +1882,10 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } } else - GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->format); + GL_MSG_Warning("UpdateTexture: bad format %d\n", pTexInfo->format); - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - tex_downloaded = texnum; + pglBindTexture(GL_TEXTURE_2D, num); + tex_downloaded = num; // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues if (pTexInfo->flags & TF_TRANSPARENT) @@ -1877,7 +1914,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1898,7 +1935,7 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); @@ -1918,13 +1955,16 @@ EXPORT void HWRAPI(UpdateTexture) (GLMipmap_t *pTexInfo) } else { - if (updatemipmap) + if (update) pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); else pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); } } + // Free the texture buffer + FreeTextureBuffer(tex); + if (pTexInfo->flags & TF_WRAPX) pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); else