diff --git a/core/rend/gles/glcache.h b/core/rend/gles/glcache.h index f6b5526ad..b72bd61fa 100644 --- a/core/rend/gles/glcache.h +++ b/core/rend/gles/glcache.h @@ -1,4 +1,5 @@ #pragma once +#include #include "gles.h" #define TEXTURE_ID_CACHE_SIZE 32 @@ -43,10 +44,9 @@ public: void DeleteTextures(GLsizei n, const GLuint *textures) { for (int i = 0; i < n; i++) { - if (textures[i] == _texture) { + _texture_params.erase(textures[i]); + if (textures[i] == _texture) _texture = 0; - break; - } } glDeleteTextures(n, textures); } @@ -105,6 +105,36 @@ public: } } + void TexParameteri(GLenum target, GLenum pname, GLint param) { + if (target == GL_TEXTURE_2D) + { + TextureParameters &cur_params = _texture_params[_texture]; + switch (pname) { + case GL_TEXTURE_MIN_FILTER: + if (cur_params._min_filter == param) + return; + cur_params._min_filter = param; + break; + case GL_TEXTURE_MAG_FILTER: + if (cur_params._mag_filter == param) + return; + cur_params._mag_filter = param; + break; + case GL_TEXTURE_WRAP_S: + if (cur_params._wrap_s == param) + return; + cur_params._wrap_s = param; + break; + case GL_TEXTURE_WRAP_T: + if (cur_params._wrap_t == param) + return; + cur_params._wrap_t = param; + break; + } + } + glTexParameteri(target, pname, param); + } + GLuint GenTexture() { if (_texture_cache_size == 0) { _texture_cache_size = TEXTURE_ID_CACHE_SIZE; @@ -141,6 +171,16 @@ public: } private: + class TextureParameters { + public: + TextureParameters() : _min_filter(GL_NEAREST_MIPMAP_LINEAR), _mag_filter(GL_LINEAR), _wrap_s(GL_REPEAT), _wrap_t(GL_REPEAT) {} + + GLenum _min_filter; + GLenum _mag_filter; + GLenum _wrap_s; + GLenum _wrap_t; + }; + void setCapability(GLenum cap, bool value) { bool *pCap = NULL; switch (cap) { @@ -196,6 +236,7 @@ private: GLuint _stencil_mask; GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE]; GLuint _texture_cache_size; + std::map _texture_params; }; extern GLCache glcache; diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 5345da8ad..01483b2c1 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -74,18 +74,6 @@ extern int screen_height; PipelineShader* CurrentShader; u32 gcflip; -static struct -{ - TSP tsp; - GLuint texture; - - void Reset(const PolyParam* gp) - { - texture=~0; - tsp.full = ~gp->tsp.full; - } -} cache; - s32 SetTileClip(u32 val, bool set) { u32 clipmode=val>>28; @@ -149,6 +137,14 @@ void SetCull(u32 CulliMode) } } +static void SetTextureRepeatMode(GLuint dir, u32 clamp, u32 mirror) +{ + if (clamp) + glcache.TexParameteri(GL_TEXTURE_2D, dir, GL_CLAMP_TO_EDGE); + else + glcache.TexParameteri(GL_TEXTURE_2D, dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT); +} + template __forceinline void SetGPState(const PolyParam* gp,u32 cflip=0) @@ -174,17 +170,24 @@ __forceinline glcache.StencilFunc(GL_ALWAYS,stencil,stencil); - bool texture_changed = false; + glcache.BindTexture(GL_TEXTURE_2D, gp->texid == -1 ? 0 : gp->texid); - // FIXME the same gl texture id can be used with different parameters (filtering, clamping, etc.) This is not handled here - if (gp->texid != cache.texture) + SetTextureRepeatMode(GL_TEXTURE_WRAP_S, gp->tsp.ClampU, gp->tsp.FlipU); + SetTextureRepeatMode(GL_TEXTURE_WRAP_T, gp->tsp.ClampV, gp->tsp.FlipV); + + //set texture filter mode + if (gp->tsp.FilterMode == 0) { - cache.texture=gp->texid; - if (gp->texid != -1) { - //verify(glIsTexture(gp->texid)); - glcache.BindTexture(GL_TEXTURE_2D, gp->texid); - texture_changed = true; - } + //disable filtering, mipmaps + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else + { + //bilinear filtering + //PowerVR supports also trilinear via two passes, but we ignore that for now + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gp->tcw.MipMapped && settings.rend.UseMipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (Type==ListType_Translucent) @@ -195,29 +198,6 @@ __forceinline else glcache.Disable(GL_BLEND); - if (gp->tsp.full != cache.tsp.full || texture_changed) - { - cache.tsp=gp->tsp; - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (gp->tsp.ClampU ? GL_CLAMP_TO_EDGE : (gp->tsp.FlipU ? GL_MIRRORED_REPEAT : GL_REPEAT))) ; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (gp->tsp.ClampV ? GL_CLAMP_TO_EDGE : (gp->tsp.FlipV ? GL_MIRRORED_REPEAT : GL_REPEAT))) ; - - //set texture filter mode - if (gp->tsp.FilterMode == 0) - { - //disable filtering, mipmaps - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else - { - //bilinear filtering - //PowerVR supports also trilinear via two passes, but we ignore that for now - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gp->tcw.MipMapped && settings.rend.UseMipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - } - //set cull mode ! //cflip is required when exploding triangles for triangle sorting //gcflip is global clip flip, needed for when rendering to texture due to mirrored Y direction @@ -819,48 +799,39 @@ void SetMVS_Mode(u32 mv_mode,ISP_Modvol ispc) //no depth test glcache.Disable(GL_DEPTH_TEST); + //write bits 1:0 + glcache.StencilMask(3); if (mv_mode==1) { + // Inclusion volume //res : old : final //0 : 0 : 00 //0 : 1 : 01 //1 : 0 : 01 //1 : 1 : 01 - //write bits 1:0 - glcache.StencilMask(3); //if (1<=st) st=1; else st=0; glcache.StencilFunc(GL_LEQUAL,1,3); glcache.StencilOp(GL_ZERO,GL_ZERO,GL_REPLACE); - - /* - //if !=0 -> set to 10 - verifyc(dev->SetRenderState(D3DRS_STENCILFUNC,D3DCMP_LESSEQUAL)); - verifyc(dev->SetRenderState(D3DRS_STENCILREF,1)); - verifyc(dev->SetRenderState(D3DRS_STENCILPASS,D3DSTENCILOP_REPLACE)); - verifyc(dev->SetRenderState(D3DRS_STENCILFAIL,D3DSTENCILOP_ZERO)); - */ } else { + // Exclusion volume /* - this is bugged. a lot. I've only seen a single game use it, so i guess it doesn't matter ? (Zombie revenge) (actually, i think there was also another, racing game) */ - + // The initial value for exclusion volumes is 1 so we need to invert the result before and'ing. //res : old : final //0 : 0 : 00 - //0 : 1 : 00 + //0 : 1 : 01 //1 : 0 : 00 - //1 : 1 : 01 + //1 : 1 : 00 - // Write to bit 0 - glcache.StencilMask(1); // FIXME bit 1 is not reset. Need other pass - //if (3==st) st=1; else st=0; //can't be done with a single pass - glcache.StencilFunc(GL_EQUAL, 3, 3); - glcache.StencilOp(GL_ZERO,GL_KEEP,GL_REPLACE); + // if (1 == st) st = 1; else st = 0; + glcache.StencilFunc(GL_EQUAL, 1, 3); + glcache.StencilOp(GL_ZERO, GL_ZERO, GL_REPLACE); } } } @@ -921,7 +892,7 @@ void DrawModVols(int first, int count) glcache.DepthMask(GL_FALSE); glcache.DepthFunc(GL_GREATER); - if(0 /*|| GetAsyncKeyState(VK_F5)*/ ) + if(0) { //simply draw the volumes -- for debugging SetCull(0); @@ -948,7 +919,7 @@ void DrawModVols(int first, int count) glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); - if ( 0 /* || GetAsyncKeyState(VK_F6)*/ ) + if (0) { //simple single level stencil glcache.Enable(GL_STENCIL_TEST); diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 3709f3f2c..c7817896e 100755 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -2039,7 +2039,7 @@ GLuint loadPNG(const string& fname, int &width, int &height) glcache.BindTexture(GL_TEXTURE_2D, texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //clean up memory and close stuff png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index af1af49fc..92ee52c5d 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -163,14 +163,6 @@ struct TextureCacheData printf("\n"); } - void SetRepeatMode(GLuint dir,u32 clamp,u32 mirror) - { - if (clamp) - glTexParameteri (GL_TEXTURE_2D, dir, GL_CLAMP_TO_EDGE); - else - glTexParameteri (GL_TEXTURE_2D, dir, mirror?GL_MIRRORED_REPEAT : GL_REPEAT); - } - //Create GL texture from tsp/tcw void Create(bool isGL) { @@ -199,30 +191,6 @@ struct TextureCacheData w=8<bpp==4) { @@ -467,11 +435,6 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw2, fbh2, 0, channels, fmt, 0); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - // Create the object that will allow us to render to the aforementioned texture glGenFramebuffers(1, &rv.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo);