diff --git a/core/rend/gl4/abuffer.cpp b/core/rend/gl4/abuffer.cpp index 5adb584b7..f13b8b64c 100644 --- a/core/rend/gl4/abuffer.cpp +++ b/core/rend/gl4/abuffer.cpp @@ -431,7 +431,7 @@ void DrawTranslucentModVols(int first, int count) u32 mv_mode = param.isp.DepthMode; - verify(param.first >= 0 && param.first + param.count <= pvrrc.modtrig.used()); + verify(param.first >= 0 && param.first + param.count <= (u32)pvrrc.modtrig.used()); if (mod_base == -1) mod_base = param.first; diff --git a/core/rend/gl4/gl4.h b/core/rend/gl4/gl4.h index 7b1f0ef6f..d93b57ea1 100755 --- a/core/rend/gl4/gl4.h +++ b/core/rend/gl4/gl4.h @@ -10,22 +10,30 @@ struct gl4PipelineShader { GLuint program; - GLuint pp_ClipTest,cp_AlphaTestValue; - GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY; - GLuint shade_scale_factor; - GLuint pp_Number; - GLuint blend_mode; - GLuint use_alpha; - GLuint ignore_tex_alpha; - GLuint shading_instr; - GLuint fog_control; - GLuint trilinear_alpha; - GLuint fog_clamp_min, fog_clamp_max; - GLuint normal_matrix; + GLint pp_ClipTest; + GLint cp_AlphaTestValue; + GLint sp_FOG_COL_RAM; + GLint sp_FOG_COL_VERT; + GLint sp_FOG_DENSITY; + GLint shade_scale_factor; + GLint pp_Number; + GLint blend_mode; + GLint use_alpha; + GLint ignore_tex_alpha; + GLint shading_instr; + GLint fog_control; + GLint trilinear_alpha; + GLint fog_clamp_min, fog_clamp_max; + GLint normal_matrix; - u32 cp_AlphaTest; - s32 pp_ClipTestMode; - u32 pp_Texture, pp_UseAlpha, pp_IgnoreTexA, pp_ShadInstr, pp_Offset, pp_FogCtrl; + bool cp_AlphaTest; + bool pp_InsideClipping; + bool pp_Texture; + bool pp_UseAlpha; + bool pp_IgnoreTexA; + u32 pp_ShadInstr; + bool pp_Offset; + u32 pp_FogCtrl; Pass pass; bool pp_TwoVolumes; bool pp_Gouraud; @@ -240,8 +248,15 @@ extern struct gl4ShaderUniforms_t float fog_clamp_min[4]; float fog_clamp_max[4]; glm::mat4 normal_mat; + struct { + bool enabled; + int x; + int y; + int width; + int height; + } base_clipping; - void setUniformArray(GLuint location, int v0, int v1) + void setUniformArray(GLint location, int v0, int v1) { int array[] = { v0, v1 }; glUniform1iv(location, 2, array); diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index aac1a98ae..bd45a664c 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -1,5 +1,6 @@ #include "gl4.h" #include "rend/gles/glcache.h" +#include "rend/tileclip.h" /* @@ -21,22 +22,22 @@ GLuint texSamplers[2]; GLuint depth_fbo; GLuint depthSaveTexId; -static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, s32 pp_ClipTestMode, - u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, +static gl4PipelineShader *gl4GetProgram(bool cp_AlphaTest, bool pp_InsideClipping, + bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset, u32 pp_FogCtrl, bool pp_TwoVolumes, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, Pass pass) { u32 rv=0; - rv |= (pp_ClipTestMode + 1); - rv<<=1; rv|=cp_AlphaTest; - rv<<=1; rv|=pp_Texture; - rv<<=1; rv|=pp_UseAlpha; - rv<<=1; rv|=pp_IgnoreTexA; - rv<<=2; rv|=pp_ShadInstr; - rv<<=1; rv|=pp_Offset; - rv<<=2; rv|=pp_FogCtrl; - rv <<= 1; rv |= (int)pp_TwoVolumes; - rv <<= 1; rv |= (int)pp_Gouraud; + rv |= pp_InsideClipping; + rv <<= 1; rv |= cp_AlphaTest; + rv <<= 1; rv |= pp_Texture; + rv <<= 1; rv |= pp_UseAlpha; + rv <<= 1; rv |= pp_IgnoreTexA; + rv <<= 2; rv |= pp_ShadInstr; + rv <<= 1; rv |= pp_Offset; + rv <<= 2; rv |= pp_FogCtrl; + rv <<= 1; rv |= pp_TwoVolumes; + rv <<= 1; rv |= pp_Gouraud; rv <<= 1; rv |= pp_BumpMap; rv <<= 1; rv |= fog_clamping; rv <<= 2; rv |= (int)pass; @@ -45,7 +46,7 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, s32 pp_ClipTestMode, if (shader->program == 0) { shader->cp_AlphaTest = cp_AlphaTest; - shader->pp_ClipTestMode = pp_ClipTestMode; + shader->pp_InsideClipping = pp_InsideClipping; shader->pp_Texture = pp_Texture; shader->pp_UseAlpha = pp_UseAlpha; shader->pp_IgnoreTexA = pp_IgnoreTexA; @@ -71,6 +72,17 @@ static void SetTextureRepeatMode(int index, GLuint dir, u32 clamp, u32 mirror) glSamplerParameteri(texSamplers[index], dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT); } +static void SetBaseClipping() +{ + if (gl4ShaderUniforms.base_clipping.enabled) + { + glcache.Enable(GL_SCISSOR_TEST); + glcache.Scissor(gl4ShaderUniforms.base_clipping.x, gl4ShaderUniforms.base_clipping.y, gl4ShaderUniforms.base_clipping.width, gl4ShaderUniforms.base_clipping.height); + } + else + glcache.Disable(GL_SCISSOR_TEST); +} + template static void SetGPState(const PolyParam* gp) { @@ -85,12 +97,13 @@ static void SetGPState(const PolyParam* gp) else gl4ShaderUniforms.trilinear_alpha = 1.0; - s32 clipping = SetTileClip(gp->tileclip, -1); + int clip_rect[4] = {}; + TileClipping clipmode = GetTileClip(gp->tileclip, ViewportMatrix, clip_rect); if (pass == Pass::Depth) { CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0, - clipping, + clipmode == TileClipping::Inside, Type == ListType_Punch_Through ? gp->pcw.Texture : 0, 1, gp->tsp.IgnoreTexA, @@ -106,13 +119,13 @@ static void SetGPState(const PolyParam* gp) else { // Two volumes mode only supported for OP and PT - bool two_volumes_mode = (gp->tsp1.full != -1) && Type != ListType_Translucent; + bool two_volumes_mode = (gp->tsp1.full != (u32)-1) && Type != ListType_Translucent; bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff); int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2; CurrentShader = gl4GetProgram(Type == ListType_Punch_Through ? 1 : 0, - clipping, + clipmode == TileClipping::Inside, gp->pcw.Texture, gp->tsp.UseAlpha, gp->tsp.IgnoreTexA, @@ -141,7 +154,15 @@ static void SetGPState(const PolyParam* gp) else glcache.Disable(GL_BLEND); - SetTileClip(gp->tileclip, CurrentShader->pp_ClipTest); + if (clipmode == TileClipping::Inside) + glUniform4f(CurrentShader->pp_ClipTest, clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3]); + if (clipmode == TileClipping::Outside) + { + glcache.Enable(GL_SCISSOR_TEST); + glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]); + } + else + SetBaseClipping(); // This bit controls which pixels are affected by modvols const u32 stencil = gp->pcw.Shadow != 0 ? 0x80 : 0x0; @@ -155,12 +176,11 @@ static void SetGPState(const PolyParam* gp) glActiveTexture(GL_TEXTURE0 + i); GLuint texid = (GLuint)(i == 0 ? gp->texid : gp->texid1); - glBindTexture(GL_TEXTURE_2D, texid == -1 ? 0 : texid); + glBindTexture(GL_TEXTURE_2D, texid == (GLuint)-1 ? 0 : texid); - if (texid != -1) + if (texid != (GLuint)-1) { TSP tsp = i == 0 ? gp->tsp : gp->tsp1; - TCW tcw = i == 0 ? gp->tcw : gp->tcw1; glBindSampler(i, texSamplers[i]); SetTextureRepeatMode(i, GL_TEXTURE_WRAP_S, tsp.ClampU, tsp.FlipU); @@ -298,6 +318,7 @@ static void DrawModVols(int first, int count) glBindVertexArray(gl4.vbo.modvol_vao); glcache.Disable(GL_BLEND); + SetBaseClipping(); glcache.UseProgram(gl4.modvol_shader.program); @@ -639,7 +660,7 @@ static void gl4_draw_quad_texture(GLuint texture, float w, float h) gl4ShaderUniforms.trilinear_alpha = 1.0; CurrentShader = gl4GetProgram(0, - 0, + false, 1, 0, 1, diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 1ed4bb3eb..db12ad55f 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -51,7 +51,7 @@ void main() const char* gl4PixelPipelineShader = SHADER_HEADER R"( #define cp_AlphaTest %d -#define pp_ClipTestMode %d +#define pp_ClipInside %d #define pp_UseAlpha %d #define pp_Texture %d #define pp_IgnoreTexA %d @@ -146,14 +146,8 @@ void main() discard; #endif - // Clip outside the box - #if pp_ClipTestMode==1 - if (gl_FragCoord.x < pp_ClipTest.x || gl_FragCoord.x > pp_ClipTest.z - || gl_FragCoord.y < pp_ClipTest.y || gl_FragCoord.y > pp_ClipTest.w) - discard; - #endif // Clip inside the box - #if pp_ClipTestMode==-1 + #if pp_ClipInside == 1 if (gl_FragCoord.x >= pp_ClipTest.x && gl_FragCoord.x <= pp_ClipTest.z && gl_FragCoord.y >= pp_ClipTest.y && gl_FragCoord.y <= pp_ClipTest.w) discard; @@ -374,8 +368,9 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *pixel_source /* char pshader[16384]; sprintf(pshader, pixel_source, - s->cp_AlphaTest,s->pp_ClipTestMode,s->pp_UseAlpha, - s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_TwoVolumes, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, (int)s->pass); + s->cp_AlphaTest, s->pp_InsideClipping, s->pp_UseAlpha, + s->pp_Texture, s->pp_IgnoreTexA, s->pp_ShadInstr, s->pp_Offset, s->pp_FogCtrl, + s->pp_TwoVolumes, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, (int)s->pass); s->program = gl_CompileAndLink(vshader, pshader); @@ -705,7 +700,7 @@ static bool RenderFrame() case 7: //7 invalid die("7 is not valid"); - break; + return false; } DEBUG_LOG(RENDERER, "RTT packmode=%d stride=%d - %d,%d -> %d,%d", FB_W_CTRL.fb_packmode, FB_W_LINESTRIDE.stride * 8, FB_X_CLIP.min, FB_Y_CLIP.min, FB_X_CLIP.max, FB_Y_CLIP.max); @@ -785,9 +780,9 @@ static bool RenderFrame() glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glcache.Enable(GL_SCISSOR_TEST); - glScissor(0, 0, (GLsizei)lroundf(scaled_offs_x), rendering_height); + glcache.Scissor(0, 0, (GLsizei)lroundf(scaled_offs_x), rendering_height); glClear(GL_COLOR_BUFFER_BIT); - glScissor((GLint)lroundf(screen_width * screen_scaling - scaled_offs_x), 0, (GLsizei)lroundf(scaled_offs_x) + 1, rendering_height); + glcache.Scissor((GLint)lroundf(screen_width * screen_scaling - scaled_offs_x), 0, (GLsizei)lroundf(scaled_offs_x) + 1, rendering_height); glClear(GL_COLOR_BUFFER_BIT); } } @@ -805,9 +800,19 @@ static bool RenderFrame() height *= settings.rend.RenderToTextureUpscale; } } - glScissor((GLint)lroundf(min_x), (GLint)lroundf(min_y), (GLsizei)lroundf(width), (GLsizei)lroundf(height)); + gl4ShaderUniforms.base_clipping.enabled = true; + gl4ShaderUniforms.base_clipping.x = (int)lroundf(min_x); + gl4ShaderUniforms.base_clipping.y = (int)lroundf(min_y); + gl4ShaderUniforms.base_clipping.width = (int)lroundf(width); + gl4ShaderUniforms.base_clipping.height = (int)lroundf(height); + glcache.Scissor(gl4ShaderUniforms.base_clipping.x, gl4ShaderUniforms.base_clipping.y, + gl4ShaderUniforms.base_clipping.width, gl4ShaderUniforms.base_clipping.height); glcache.Enable(GL_SCISSOR_TEST); } + else + { + gl4ShaderUniforms.base_clipping.enabled = false; + } gl4DrawStrips(output_fbo, rendering_width, rendering_height); } @@ -822,8 +827,6 @@ static bool RenderFrame() gl4DrawFramebuffer(640.f, 480.f); } - eglCheck(); - if (is_rtt) ReadRTTBuffer(); else if (settings.rend.ScreenScaling != 100 || !theGLContext.IsSwapBufferPreserved()) diff --git a/core/rend/gl4/gltex.cpp b/core/rend/gl4/gltex.cpp index 1bb7ac707..9201d64b4 100644 --- a/core/rend/gl4/gltex.cpp +++ b/core/rend/gl4/gltex.cpp @@ -9,10 +9,10 @@ GLuint gl4BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) gl.rtt.TexAddr=addy>>3; // Find the smallest power of two texture that fits the viewport - int fbh2 = 8; + u32 fbh2 = 8; while (fbh2 < fbh) fbh2 *= 2; - int fbw2 = 8; + u32 fbw2 = 8; while (fbw2 < fbw) fbw2 *= 2; diff --git a/core/rend/gles/glcache.h b/core/rend/gles/glcache.h index 3227a2fd3..b06f181e0 100644 --- a/core/rend/gles/glcache.h +++ b/core/rend/gles/glcache.h @@ -110,6 +110,18 @@ public: } } + void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) + { + if (x != _scissor.x || y != _scissor.y || width != _scissor.width || height != _scissor.height || _disable_cache) + { + _scissor.x = x; + _scissor.y = y; + _scissor.width = width; + _scissor.height = height; + glScissor(x, y, width, height); + } + } + void TexParameteri(GLenum target, GLenum pname, GLint param) { if (target == GL_TEXTURE_2D && !_disable_cache) @@ -117,22 +129,22 @@ public: TextureParameters &cur_params = _texture_params[_texture]; switch (pname) { case GL_TEXTURE_MIN_FILTER: - if (cur_params._min_filter == param) + if (cur_params._min_filter == (GLenum)param) return; cur_params._min_filter = param; break; case GL_TEXTURE_MAG_FILTER: - if (cur_params._mag_filter == param) + if (cur_params._mag_filter == (GLenum)param) return; cur_params._mag_filter = param; break; case GL_TEXTURE_WRAP_S: - if (cur_params._wrap_s == param) + if (cur_params._wrap_s == (GLenum)param) return; cur_params._wrap_s = param; break; case GL_TEXTURE_WRAP_T: - if (cur_params._wrap_t == param) + if (cur_params._wrap_t == (GLenum)param) return; cur_params._wrap_t = param; break; @@ -190,6 +202,10 @@ public: _stencil_dpfail = 0xFFFFFFFFu; _stencil_dppass = 0xFFFFFFFFu; _stencil_mask = 0; + _scissor.x = -1; + _scissor.y = -1; + _scissor.width = -1; + _scissor.height = -1; if (_texture_cache_size > 0) { glDeleteTextures(_texture_cache_size, _texture_ids); @@ -274,6 +290,12 @@ private: GLenum _stencil_dpfail; GLenum _stencil_dppass; GLuint _stencil_mask; + struct { + GLint x; + GLint y; + GLsizei width; + GLsizei height; + } _scissor; GLuint _texture_ids[TEXTURE_ID_CACHE_SIZE]; GLuint _texture_cache_size; std::map _texture_params; diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 97979429e..64bad9a20 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -1,6 +1,7 @@ #include "glcache.h" #include "gles.h" #include "rend/sorter.h" +#include "rend/tileclip.h" /* @@ -70,59 +71,6 @@ extern int screen_height; PipelineShader* CurrentShader; u32 gcflip; -s32 SetTileClip(u32 val, GLint uniform) -{ - if (!settings.rend.Clipping) - return 0; - - u32 clipmode = val >> 28; - s32 clip_mode; - if (clipmode < 2) - clip_mode = 0; //always passes - else if (clipmode & 1) - clip_mode = -1; //render stuff outside the region - else - clip_mode = 1; //render stuff inside the region - - float csx = val & 63; - float cex = (val >> 6) & 63; - float csy = (val >> 12) & 31; - float cey = (val >> 17) & 31; - csx = csx * 32; - cex = cex * 32 + 32; - csy = csy * 32; - cey = cey * 32 + 32; - - if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480) - return 0; - - if (uniform >= 0 && clip_mode) - { - if (!pvrrc.isRTT) - { - glm::vec4 clip_start(csx, csy, 0, 1); - glm::vec4 clip_end(cex, cey, 0, 1); - clip_start = ViewportMatrix * clip_start; - clip_end = ViewportMatrix * clip_end; - - csx = clip_start[0]; - csy = clip_start[1]; - cey = clip_end[1]; - cex = clip_end[0]; - } - else if (!settings.rend.RenderToTextureBuffer) - { - csx *= settings.rend.RenderToTextureUpscale; - csy *= settings.rend.RenderToTextureUpscale; - cex *= settings.rend.RenderToTextureUpscale; - cey *= settings.rend.RenderToTextureUpscale; - } - glUniform4f(uniform, std::min(csx, cex), std::min(csy, cey), std::max(csx, cex), std::max(csy, cey)); - } - - return clip_mode; -} - void SetCull(u32 CulliMode) { if (CullMode[CulliMode]==GL_NONE) @@ -142,6 +90,17 @@ static void SetTextureRepeatMode(GLuint dir, u32 clamp, u32 mirror) glcache.TexParameteri(GL_TEXTURE_2D, dir, mirror ? GL_MIRRORED_REPEAT : GL_REPEAT); } +static void SetBaseClipping() +{ + if (ShaderUniforms.base_clipping.enabled) + { + glcache.Enable(GL_SCISSOR_TEST); + glcache.Scissor(ShaderUniforms.base_clipping.x, ShaderUniforms.base_clipping.y, ShaderUniforms.base_clipping.width, ShaderUniforms.base_clipping.height); + } + else + glcache.Disable(GL_SCISSOR_TEST); +} + template __forceinline void SetGPState(const PolyParam* gp,u32 cflip=0) @@ -159,8 +118,11 @@ __forceinline bool color_clamp = gp->tsp.ColorClamp && (pvrrc.fog_clamp_min != 0 || pvrrc.fog_clamp_max != 0xffffffff); int fog_ctrl = settings.rend.Fog ? gp->tsp.FogCtrl : 2; + int clip_rect[4] = {}; + TileClipping clipmode = GetTileClip(gp->tileclip, ViewportMatrix, clip_rect); + CurrentShader = GetProgram(Type == ListType_Punch_Through ? 1 : 0, - SetTileClip(gp->tileclip, -1) + 1, + clipmode == TileClipping::Inside, gp->pcw.Texture, gp->tsp.UseAlpha, gp->tsp.IgnoreTexA, @@ -176,7 +138,15 @@ __forceinline if (CurrentShader->trilinear_alpha != -1) glUniform1f(CurrentShader->trilinear_alpha, ShaderUniforms.trilinear_alpha); - SetTileClip(gp->tileclip, CurrentShader->pp_ClipTest); + if (clipmode == TileClipping::Inside) + glUniform4f(CurrentShader->pp_ClipTest, clip_rect[0], clip_rect[1], clip_rect[0] + clip_rect[2], clip_rect[1] + clip_rect[3]); + if (clipmode == TileClipping::Outside) + { + glcache.Enable(GL_SCISSOR_TEST); + glcache.Scissor(clip_rect[0], clip_rect[1], clip_rect[2], clip_rect[3]); + } + else + SetBaseClipping(); //This bit control which pixels are affected //by modvols @@ -184,7 +154,7 @@ __forceinline glcache.StencilFunc(GL_ALWAYS,stencil,stencil); - glcache.BindTexture(GL_TEXTURE_2D, gp->texid == -1 ? 0 : (GLuint)gp->texid); + glcache.BindTexture(GL_TEXTURE_2D, gp->texid == (u64)-1 ? 0 : (GLuint)gp->texid); SetTextureRepeatMode(GL_TEXTURE_WRAP_S, gp->tsp.ClampU, gp->tsp.FlipU); SetTextureRepeatMode(GL_TEXTURE_WRAP_T, gp->tsp.ClampV, gp->tsp.FlipV); @@ -533,6 +503,7 @@ void DrawModVols(int first, int count) SetupModvolVBO(); glcache.Disable(GL_BLEND); + SetBaseClipping(); glcache.UseProgram(gl.modvol_shader.program); glUniform1f(gl.modvol_shader.sp_ShaderColor, 1 - FPU_SHAD_SCALE.scale_factor / 256.f); @@ -672,7 +643,7 @@ static void DrawQuad(GLuint texId, float x, float y, float w, float h, float u0, ShaderUniforms.trilinear_alpha = 1.0; - PipelineShader *shader = GetProgram(0, 1, 1, 0, 1, 0, 0, 2, false, false, false, false); + PipelineShader *shader = GetProgram(0, false, 1, 0, 1, 0, 0, 2, false, false, false, false); glcache.UseProgram(shader->program); glActiveTexture(GL_TEXTURE0); diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 91d9e5e8d..9c6f66011 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -95,7 +95,7 @@ R"(%s #define TARGET_GL %s #define cp_AlphaTest %d -#define pp_ClipTestMode %d +#define pp_ClipInside %d #define pp_UseAlpha %d #define pp_Texture %d #define pp_IgnoreTexA %d @@ -185,14 +185,8 @@ highp vec4 fog_clamp(lowp vec4 col) void main() { - // Clip outside the box - #if pp_ClipTestMode==1 - if (gl_FragCoord.x < pp_ClipTest.x || gl_FragCoord.x > pp_ClipTest.z - || gl_FragCoord.y < pp_ClipTest.y || gl_FragCoord.y > pp_ClipTest.w) - discard; - #endif // Clip inside the box - #if pp_ClipTestMode==-1 + #if pp_ClipInside == 1 if (gl_FragCoord.x >= pp_ClipTest.x && gl_FragCoord.x <= pp_ClipTest.z && gl_FragCoord.y >= pp_ClipTest.y && gl_FragCoord.y <= pp_ClipTest.w) discard; @@ -599,13 +593,13 @@ GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader) return program; } -PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, - u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, - u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear) +PipelineShader *GetProgram(bool cp_AlphaTest, bool pp_InsideClipping, + bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset, + u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear) { u32 rv=0; - rv|=pp_ClipTestMode; + rv |= pp_InsideClipping; rv<<=1; rv|=cp_AlphaTest; rv<<=1; rv|=pp_Texture; rv<<=1; rv|=pp_UseAlpha; @@ -622,7 +616,7 @@ PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, if (shader->program == 0) { shader->cp_AlphaTest = cp_AlphaTest; - shader->pp_ClipTestMode = pp_ClipTestMode-1; + shader->pp_InsideClipping = pp_InsideClipping; shader->pp_Texture = pp_Texture; shader->pp_UseAlpha = pp_UseAlpha; shader->pp_IgnoreTexA = pp_IgnoreTexA; @@ -644,21 +638,21 @@ bool CompilePipelineShader( PipelineShader* s) char vshader[8192]; int rc = sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud); - verify(rc + 1 <= sizeof(vshader)); + verify(rc + 1 <= (int)sizeof(vshader)); char pshader[8192]; rc = sprintf(pshader,PixelPipelineShader, gl.glsl_version_header, gl.gl_version, - s->cp_AlphaTest,s->pp_ClipTestMode,s->pp_UseAlpha, + s->cp_AlphaTest,s->pp_InsideClipping,s->pp_UseAlpha, s->pp_Texture,s->pp_IgnoreTexA,s->pp_ShadInstr,s->pp_Offset,s->pp_FogCtrl, s->pp_Gouraud, s->pp_BumpMap, s->fog_clamping, s->trilinear); - verify(rc + 1 <= sizeof(pshader)); + verify(rc + 1 <= (int)sizeof(pshader)); s->program=gl_CompileAndLink(vshader, pshader); //setup texture 0 as the input for the shader - GLuint gu=glGetUniformLocation(s->program, "tex"); + GLint gu = glGetUniformLocation(s->program, "tex"); if (s->pp_Texture==1) glUniform1i(gu,0); @@ -1118,7 +1112,7 @@ bool RenderFrame() case 7: //7 invalid die("7 is not valid"); - break; + return false; } DEBUG_LOG(RENDERER, "RTT packmode=%d stride=%d - %d,%d -> %d,%d", FB_W_CTRL.fb_packmode, FB_W_LINESTRIDE.stride * 8, FB_X_CLIP.min, FB_Y_CLIP.min, FB_X_CLIP.max, FB_Y_CLIP.max); @@ -1205,9 +1199,9 @@ bool RenderFrame() glcache.ClearColor(0.f, 0.f, 0.f, 0.f); glcache.Enable(GL_SCISSOR_TEST); - glScissor(0, 0, (GLsizei)lroundf(scaled_offs_x), (GLsizei)lroundf(screen_height * screen_scaling)); + glcache.Scissor(0, 0, (GLsizei)lroundf(scaled_offs_x), (GLsizei)lroundf(screen_height * screen_scaling)); glClear(GL_COLOR_BUFFER_BIT); - glScissor(screen_width * screen_scaling - scaled_offs_x, 0, (GLsizei)lroundf(scaled_offs_x + 1.f), (GLsizei)lroundf(screen_height * screen_scaling)); + glcache.Scissor(screen_width * screen_scaling - scaled_offs_x, 0, (GLsizei)lroundf(scaled_offs_x + 1.f), (GLsizei)lroundf(screen_height * screen_scaling)); glClear(GL_COLOR_BUFFER_BIT); } } @@ -1225,9 +1219,18 @@ bool RenderFrame() height *= settings.rend.RenderToTextureUpscale; } } - glScissor((GLint)lroundf(min_x), (GLint)lroundf(min_y), (GLsizei)lroundf(width), (GLsizei)lroundf(height)); + ShaderUniforms.base_clipping.enabled = true; + ShaderUniforms.base_clipping.x = (int)lroundf(min_x); + ShaderUniforms.base_clipping.y = (int)lroundf(min_y); + ShaderUniforms.base_clipping.width = (int)lroundf(width); + ShaderUniforms.base_clipping.height = (int)lroundf(height); + glcache.Scissor(ShaderUniforms.base_clipping.x, ShaderUniforms.base_clipping.y, ShaderUniforms.base_clipping.width, ShaderUniforms.base_clipping.height); glcache.Enable(GL_SCISSOR_TEST); } + else + { + ShaderUniforms.base_clipping.enabled = false; + } DrawStrips(); } @@ -1238,8 +1241,6 @@ bool RenderFrame() DrawFramebuffer(); } - eglCheck(); - if (is_rtt) ReadRTTBuffer(); else if (settings.rend.ScreenScaling != 100 || !theGLContext.IsSwapBufferPreserved()) diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index d84a0ca3a..48d59887d 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -8,7 +8,6 @@ #include #define glCheck() do { if (unlikely(settings.validate.OpenGlChecks)) { verify(glGetError()==GL_NO_ERROR); } } while(0) -#define eglCheck() false #define VERTEX_POS_ARRAY 0 #define VERTEX_COL_BASE_ARRAY 1 @@ -30,17 +29,27 @@ struct PipelineShader { GLuint program; - GLuint depth_scale; - GLuint pp_ClipTest,cp_AlphaTestValue; - GLuint sp_FOG_COL_RAM,sp_FOG_COL_VERT,sp_FOG_DENSITY; - GLuint trilinear_alpha; - GLuint fog_clamp_min, fog_clamp_max; - GLuint normal_matrix; + GLint depth_scale; + GLint pp_ClipTest; + GLint cp_AlphaTestValue; + GLint sp_FOG_COL_RAM; + GLint sp_FOG_COL_VERT; + GLint sp_FOG_DENSITY; + GLint trilinear_alpha; + GLint fog_clamp_min, fog_clamp_max; + GLint normal_matrix; // - u32 cp_AlphaTest; s32 pp_ClipTestMode; - u32 pp_Texture, pp_UseAlpha, pp_IgnoreTexA, pp_ShadInstr, pp_Offset, pp_FogCtrl; - bool pp_Gouraud, pp_BumpMap; + bool cp_AlphaTest; + bool pp_InsideClipping; + bool pp_Texture; + bool pp_UseAlpha; + bool pp_IgnoreTexA; + u32 pp_ShadInstr; + bool pp_Offset; + u32 pp_FogCtrl; + bool pp_Gouraud; + bool pp_BumpMap; bool fog_clamping; bool trilinear; }; @@ -52,9 +61,9 @@ struct gl_ctx { GLuint program; - GLuint depth_scale; - GLuint sp_ShaderColor; - GLuint normal_matrix; + GLint depth_scale; + GLint sp_ShaderColor; + GLint normal_matrix; } modvol_shader; @@ -63,7 +72,7 @@ struct gl_ctx struct { GLuint program; - GLuint scale; + GLint scale; GLuint vao; GLuint geometry; GLuint osd_tex; @@ -146,9 +155,9 @@ void free_output_framebuffer(); void HideOSD(); void OSD_DRAW(bool clear_screen); -PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, - u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, - u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear); +PipelineShader *GetProgram(bool cp_AlphaTest, bool pp_InsideClipping, + bool pp_Texture, bool pp_UseAlpha, bool pp_IgnoreTexA, u32 pp_ShadInstr, bool pp_Offset, + u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear); GLuint gl_CompileShader(const char* shader, GLuint type); GLuint gl_CompileAndLink(const char* VertexShader, const char* FragmentShader); @@ -165,6 +174,13 @@ extern struct ShaderUniforms_t float fog_clamp_min[4]; float fog_clamp_max[4]; glm::mat4 normal_mat; + struct { + bool enabled; + int x; + int y; + int width; + int height; + } base_clipping; void Set(const PipelineShader* s) { diff --git a/core/rend/gles/imgui_impl_opengl3.cpp b/core/rend/gles/imgui_impl_opengl3.cpp index 236ad58fc..8a8635b24 100644 --- a/core/rend/gles/imgui_impl_opengl3.cpp +++ b/core/rend/gles/imgui_impl_opengl3.cpp @@ -241,9 +241,9 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr { // Apply scissor/clipping rectangle if (clip_origin_lower_left) - glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); + glcache.Scissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); else - glScissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) + glcache.Scissor((int)clip_rect.x, (int)clip_rect.y, (int)clip_rect.z, (int)clip_rect.w); // Support for GL 4.5's glClipControl(GL_UPPER_LEFT) // Bind texture, Draw glcache.BindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); diff --git a/core/rend/tileclip.h b/core/rend/tileclip.h new file mode 100644 index 000000000..07255ee29 --- /dev/null +++ b/core/rend/tileclip.h @@ -0,0 +1,84 @@ +/* + Copyright 2020 flyinghead + + This file is part of Flycast. + + Flycast is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Flycast is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Flycast. If not, see . +*/ +#pragma once +#include + +#include "types.h" +#include "hw/pvr/Renderer_if.h" + +enum class TileClipping { + Inside, // Render stuff outside the region + Off, // Always passes + Outside // Render stuff inside the region +}; + +// clip_rect[] will contain x, y, width, height +static inline TileClipping GetTileClip(u32 val, const glm::mat4& viewport, int *clip_rect) +{ + if (!settings.rend.Clipping) + return TileClipping::Off; + + u32 clipmode = val >> 28; + if (clipmode < 2) + return TileClipping::Off; //always passes + + TileClipping tileClippingMode; + if (clipmode & 1) + tileClippingMode = TileClipping::Inside; //render stuff outside the region + else + tileClippingMode = TileClipping::Outside; //render stuff inside the region + + float csx = (float)(val & 63); + float cex = (float)((val >> 6) & 63); + float csy = (float)((val >> 12) & 31); + float cey = (float)((val >> 17) & 31); + csx = csx * 32; + cex = cex * 32 + 32; + csy = csy * 32; + cey = cey * 32 + 32; + + if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480) + return TileClipping::Off; + + if (!pvrrc.isRTT) + { + glm::vec4 clip_start(csx, csy, 0, 1); + glm::vec4 clip_end(cex, cey, 0, 1); + clip_start = viewport * clip_start; + clip_end = viewport * clip_end; + + csx = clip_start[0]; + csy = clip_start[1]; + cey = clip_end[1]; + cex = clip_end[0]; + } + else if (!settings.rend.RenderToTextureBuffer) + { + csx *= settings.rend.RenderToTextureUpscale; + csy *= settings.rend.RenderToTextureUpscale; + cex *= settings.rend.RenderToTextureUpscale; + cey *= settings.rend.RenderToTextureUpscale; + } + clip_rect[0] = std::max(0, (int)lroundf(csx)); + clip_rect[1] = std::max(0, (int)lroundf(std::min(csy, cey))); + clip_rect[2] = std::max(0, (int)lroundf(cex - csx)); + clip_rect[3] = std::max(0, (int)lroundf(std::abs(cey - csy))); + + return tileClippingMode; +} diff --git a/core/rend/vulkan/drawer.cpp b/core/rend/vulkan/drawer.cpp index 2f52d4ca0..af574ddca 100644 --- a/core/rend/vulkan/drawer.cpp +++ b/core/rend/vulkan/drawer.cpp @@ -45,57 +45,16 @@ void Drawer::SortTriangles() } } -// FIXME Code dup TileClipping BaseDrawer::SetTileClip(u32 val, vk::Rect2D& clipRect) { - if (!settings.rend.Clipping) - return TileClipping::Off; + int rect[4] = {}; + TileClipping clipmode = ::GetTileClip(val, matrices.GetViewportMatrix(), rect); + clipRect.offset.x = rect[0]; + clipRect.offset.y = rect[1]; + clipRect.extent.width = rect[2]; + clipRect.extent.height = rect[3]; - u32 clipmode = val >> 28; - if (clipmode < 2) - return TileClipping::Off; //always passes - - TileClipping tileClippingMode; - if (clipmode & 1) - tileClippingMode = TileClipping::Inside; //render stuff outside the region - else - tileClippingMode = TileClipping::Outside; //render stuff inside the region - - float csx = (float)(val & 63); - float cex = (float)((val >> 6) & 63); - float csy = (float)((val >> 12) & 31); - float cey = (float)((val >> 17) & 31); - csx = csx * 32; - cex = cex * 32 + 32; - csy = csy * 32; - cey = cey * 32 + 32; - - if (csx <= 0 && csy <= 0 && cex >= 640 && cey >= 480) - return TileClipping::Off; - - if (!pvrrc.isRTT) - { - glm::vec4 clip_start(csx, csy, 0, 1); - glm::vec4 clip_end(cex, cey, 0, 1); - clip_start = matrices.GetViewportMatrix() * clip_start; - clip_end = matrices.GetViewportMatrix() * clip_end; - - csx = clip_start[0]; - csy = clip_start[1]; - cey = clip_end[1]; - cex = clip_end[0]; - } - else if (!settings.rend.RenderToTextureBuffer) - { - csx *= settings.rend.RenderToTextureUpscale; - csy *= settings.rend.RenderToTextureUpscale; - cex *= settings.rend.RenderToTextureUpscale; - cey *= settings.rend.RenderToTextureUpscale; - } - clipRect = vk::Rect2D(vk::Offset2D(std::max(0, (int)lroundf(csx)), std::max(0, (int)lroundf(csy))), - vk::Extent2D(std::max(0, (int)lroundf(cex - csx)), std::max(0, (int)lroundf(cey - csy)))); - - return tileClippingMode; + return clipmode; } void BaseDrawer::SetBaseScissor() @@ -432,10 +391,10 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass() u32 origHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; u32 upscaledWidth = origWidth; u32 upscaledHeight = origHeight; - int heightPow2 = 8; + u32 heightPow2 = 8; while (heightPow2 < upscaledHeight) heightPow2 *= 2; - int widthPow2 = 8; + u32 widthPow2 = 8; while (widthPow2 < upscaledWidth) widthPow2 *= 2; @@ -486,8 +445,8 @@ vk::CommandBuffer TextureDrawer::BeginRenderPass() } TSP tsp = { 0 }; - for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < origWidth; tsp.TexU++); - for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < origHeight; tsp.TexV++); + for (tsp.TexU = 0; tsp.TexU <= 7 && (8u << tsp.TexU) < origWidth; tsp.TexU++); + for (tsp.TexV = 0; tsp.TexV <= 7 && (8u << tsp.TexV) < origHeight; tsp.TexV++); texture = textureCache->getTextureCacheData(tsp, tcw); if (texture->IsNew()) diff --git a/core/rend/vulkan/drawer.h b/core/rend/vulkan/drawer.h index e94a9f940..dabc9e4ee 100644 --- a/core/rend/vulkan/drawer.h +++ b/core/rend/vulkan/drawer.h @@ -20,6 +20,7 @@ */ #pragma once #include "rend/sorter.h" +#include "rend/tileclip.h" #include "rend/transform_matrix.h" #include "vulkan.h" #include "buffer.h" diff --git a/core/rend/vulkan/oit/oit_drawer.cpp b/core/rend/vulkan/oit/oit_drawer.cpp index 06aca35d7..8fffdf1cf 100644 --- a/core/rend/vulkan/oit/oit_drawer.cpp +++ b/core/rend/vulkan/oit/oit_drawer.cpp @@ -42,7 +42,7 @@ void OITDrawer::DrawPoly(const vk::CommandBuffer& cmdBuffer, u32 listType, bool trilinearAlpha = 1.0 - trilinearAlpha; } - bool twoVolumes = poly.tsp1.full != -1 || poly.tcw1.full != -1; + bool twoVolumes = poly.tsp1.full != (u32)-1 || poly.tcw1.full != (u32)-1; OITDescriptorSets::PushConstants pushConstants = { { @@ -114,7 +114,7 @@ void OITDrawer::DrawModifierVolumes(const vk::CommandBuffer& cmdBuffer, int firs u32 mv_mode = param.isp.DepthMode; - verify(param.first >= 0 && param.first + param.count <= pvrrc.modtrig.used()); + verify(param.first >= 0 && param.first + param.count <= (u32)pvrrc.modtrig.used()); if (mod_base == -1) mod_base = param.first; @@ -469,10 +469,10 @@ vk::CommandBuffer OITTextureDrawer::NewFrame() u32 origHeight = pvrrc.fb_Y_CLIP.max - pvrrc.fb_Y_CLIP.min + 1; u32 upscaledWidth = origWidth; u32 upscaledHeight = origHeight; - int heightPow2 = 8; + u32 heightPow2 = 8; while (heightPow2 < upscaledHeight) heightPow2 *= 2; - int widthPow2 = 8; + u32 widthPow2 = 8; while (widthPow2 < upscaledWidth) widthPow2 *= 2; @@ -514,8 +514,8 @@ vk::CommandBuffer OITTextureDrawer::NewFrame() } TSP tsp = {}; - for (tsp.TexU = 0; tsp.TexU <= 7 && (8 << tsp.TexU) < origWidth; tsp.TexU++); - for (tsp.TexV = 0; tsp.TexV <= 7 && (8 << tsp.TexV) < origHeight; tsp.TexV++); + for (tsp.TexU = 0; tsp.TexU <= 7 && (8u << tsp.TexU) < origWidth; tsp.TexU++); + for (tsp.TexV = 0; tsp.TexV <= 7 && (8u << tsp.TexV) < origHeight; tsp.TexV++); texture = textureCache->getTextureCacheData(tsp, tcw); if (texture->IsNew()) diff --git a/core/rend/vulkan/utils.h b/core/rend/vulkan/utils.h index 0336e0415..0caa16178 100644 --- a/core/rend/vulkan/utils.h +++ b/core/rend/vulkan/utils.h @@ -23,12 +23,6 @@ enum class ModVolMode { Xor, Or, Inclusion, Exclusion, Final }; -enum class TileClipping { - Inside, // render stuff outside the region - Off, - Outside // render stuff inside the region -}; - static const vk::CompareOp depthOps[] = { vk::CompareOp::eNever, //0 Never @@ -41,7 +35,7 @@ static const vk::CompareOp depthOps[] = vk::CompareOp::eAlways, //7 Always }; -static vk::BlendFactor getBlendFactor(u32 instr, bool src) +static inline vk::BlendFactor getBlendFactor(u32 instr, bool src) { switch (instr) { case 0: // zero @@ -78,6 +72,6 @@ static inline u32 findMemoryType(vk::PhysicalDeviceMemoryProperties const& memor } typeBits >>= 1; } - verify(typeIndex != ~0); + verify(typeIndex != u32(~0)); return typeIndex; }