From af7b4795b73f1ccd3310def7adc202c14c9dc55f Mon Sep 17 00:00:00 2001 From: Jaime Passos Date: Tue, 28 Jan 2020 00:16:38 -0300 Subject: [PATCH] port pfnUpdateTexture --- src/hardware/hw_drv.h | 2 + src/hardware/r_opengl/r_opengl.c | 379 +++++++++++++++++-------------- src/sdl/hwsym_sdl.c | 1 + src/sdl/i_video.c | 1 + src/win32/win_dll.c | 2 + 5 files changed, 212 insertions(+), 173 deletions(-) diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index 99687ccf5..a09f3f224 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -40,6 +40,7 @@ EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -92,6 +93,7 @@ struct hwdriver_s SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; + UpdateTexture pfnUpdateTexture; ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 1547ead99..d0a07d262 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -267,6 +267,7 @@ static void GL_MSG_Error(const char *format, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D +#define pglTexSubImage2D glTexSubImage2D /* Fog */ #define pglFogf glFogf @@ -381,6 +382,8 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint static PFNglTexParameteri pglTexParameteri; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; +typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexSubImage2D pglTexSubImage2D; /* Fog */ typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); @@ -518,6 +521,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi, glTexEnvi) GETOPENGLFUNC(pglTexParameteri, glTexParameteri) GETOPENGLFUNC(pglTexImage2D, glTexImage2D) + GETOPENGLFUNC(pglTexSubImage2D , glTexSubImage2D) GETOPENGLFUNC(pglFogf, glFogf) GETOPENGLFUNC(pglFogfv, glFogfv) @@ -1633,6 +1637,207 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) CurrentPolyFlags = PolyFlags; } +// -----------------+ +// UpdateTexture : Updates the texture data. +// -----------------+ +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) +{ + // Download a mipmap + boolean updatemipmap = true; + static RGBA_t tex[2048*2048]; + const GLvoid *ptex = tex; + INT32 w, h; + GLuint texnum = 0; + + if (!pTexInfo->downloaded) + { + pglGenTextures(1, &texnum); + pTexInfo->downloaded = texnum; + updatemipmap = false; + } + else + texnum = pTexInfo->downloaded; + + //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); + + w = pTexInfo->width; + h = pTexInfo->height; + + if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || + (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && + (pTexInfo->flags & TF_CHROMAKEYED)) + { + tex[w*j+i].s.red = 0; + tex[w*j+i].s.green = 0; + tex[w*j+i].s.blue = 0; + tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it + } + else + { + tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; + tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; + tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; + tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; + } + + pImgData++; + + if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) + { + if (!(pTexInfo->flags & TF_CHROMAKEYED)) + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + + } + } + } + else if (pTexInfo->grInfo.format == GR_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->grInfo.data; + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = *pImgData; + tex[w*j+i].s.green = *pImgData; + tex[w*j+i].s.blue = *pImgData; + pImgData++; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else + GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); + + // the texture number was already generated by pglGenTextures + pglBindTexture(GL_TEXTURE_2D, texnum); + tex_downloaded = texnum; + + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } + + if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + 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); + } + } + else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + 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); + } + } + else + { + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + // Control the mipmap level of detail + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); + } + else + { + if (updatemipmap) + 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); + } + } + + if (pTexInfo->flags & TF_WRAPX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_S); + + if (pTexInfo->flags & TF_WRAPY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_T); + + if (maximumAnisotropy) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); +} // -----------------+ // SetTexture : The mipmap becomes the current texture source @@ -1654,179 +1859,7 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) } else { - // Download a mipmap - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; - - pglGenTextures(1, &texnum); - //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data); - - w = pTexInfo->width; - h = pTexInfo->height; - - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i].s.red = 0; - tex[w*j+i].s.green = 0; - tex[w*j+i].s.blue = 0; - tex[w*j+i].s.alpha = 0; - pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it - } - else - { - tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; - tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; - tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; - tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; - } - - pImgData++; - - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - - } - } - } - else if (pTexInfo->grInfo.format == GR_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->grInfo.data; - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = *pImgData; - tex[w*j+i].s.green = *pImgData; - tex[w*j+i].s.blue = *pImgData; - pImgData++; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't - tex[w*j+i].s.green = 255; - tex[w*j+i].s.blue = 255; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else - GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - pTexInfo->downloaded = texnum; - tex_downloaded = texnum; - - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (pTexInfo->flags & TF_TRANSPARENT) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - else - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - } - - if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else - { - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - // Control the mipmap level of detail - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - - if (pTexInfo->flags & TF_WRAPX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_S); - - if (pTexInfo->flags & TF_WRAPY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_T); - - if (maximumAnisotropy) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); - + UpdateTexture(pTexInfo); pTexInfo->nextmipmap = NULL; if (gr_cachetail) { // insertion at the tail diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 9c4e5a22b..974ac5edd 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -84,6 +84,7 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); + GETFUNC(UpdateTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e4f4790fd..747f37f1a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1769,6 +1769,7 @@ void I_StartupHardwareGraphics(void) HWD.pfnSetBlend = hwSym("SetBlend",NULL); HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); HWD.pfnReadRect = hwSym("ReadRect",NULL); HWD.pfnGClipRect = hwSym("GClipRect",NULL); HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 986eb32dc..1fd7e4a98 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -106,6 +106,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend@4", &hwdriver.pfnSetBlend}, {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, {"SetTexture@4", &hwdriver.pfnSetTexture}, + {"UpdateTexture@4", &hwdriver.pfnUpdateTexture}, {"ReadRect@24", &hwdriver.pfnReadRect}, {"GClipRect@20", &hwdriver.pfnGClipRect}, {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, @@ -137,6 +138,7 @@ static loadfunc_t hwdFuncTable[] = { {"SetBlend", &hwdriver.pfnSetBlend}, {"ClearBuffer", &hwdriver.pfnClearBuffer}, {"SetTexture", &hwdriver.pfnSetTexture}, + {"UpdateTexture", &hwdriver.pfnUpdateTexture}, {"ReadRect", &hwdriver.pfnReadRect}, {"GClipRect", &hwdriver.pfnGClipRect}, {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache},