diff --git a/core/hw/pvr/ta_ctx.cpp b/core/hw/pvr/ta_ctx.cpp index f7a3b736c..fdf3fd9eb 100644 --- a/core/hw/pvr/ta_ctx.cpp +++ b/core/hw/pvr/ta_ctx.cpp @@ -146,14 +146,15 @@ bool QueueRender(TA_context* ctx) bool too_fast = (cycle_span / time_span) > (SH4_MAIN_CLOCK * 1.2); - if (rqueue && too_fast && settings.pvr.SynchronousRender) { + if ((rqueue && too_fast && settings.pvr.SynchronousRender) || + (rqueue && ctx->rend.isRTT)) { //wait for a frame if // we have another one queue'd and // sh4 run at > 120% on the last slice // and SynchronousRendering is enabled frame_finished.Wait(); verify(!rqueue); - } + } if (rqueue) { tactx_Recycle(ctx); diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index ded55e1d4..f2a37fecd 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -146,15 +146,18 @@ s32 SetTileClip(u32 val, bool set) return 0; if (set && clip_mode) { - csy = 480 - csy; - cey = 480 - cey; - float dc2s_scale_h = screen_height / 480.0f; - float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2; - csx = csx * dc2s_scale_h + ds2s_offs_x; - cex = cex * dc2s_scale_h + ds2s_offs_x; - csy = csy * dc2s_scale_h; - cey = cey * dc2s_scale_h; - glUniform4f(CurrentShader->pp_ClipTest, csx, cey, cex, csy); + if (!pvrrc.isRTT) { + float t = cey; + cey = 480 - csy; + csy = 480 - t; + float dc2s_scale_h = screen_height / 480.0f; + float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2; + csx = csx * dc2s_scale_h + ds2s_offs_x; + cex = cex * dc2s_scale_h + ds2s_offs_x; + csy = csy * dc2s_scale_h; + cey = cey * dc2s_scale_h; + } + glUniform4f(CurrentShader->pp_ClipTest, csx, csy, cex, cey); } return clip_mode; diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index d8ec2823f..e7bb861c4 100755 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -172,10 +172,10 @@ const char* VertexShaderSource = #endif - - - - +//0 - not in use +//1 - in use since the last frame +//2 - not anymore in use (e.g. exit to menu) +u8 rttInUse = 0; /* @@ -1447,10 +1447,6 @@ void OSD_DRAW() bool ProcessFrame(TA_context* ctx) { - //disable RTTs for now .. - if (ctx->rend.isRTT) - return false; - ctx->rend_inuse.Lock(); ctx->MarkRend(); @@ -1580,14 +1576,10 @@ bool RenderFrame() //For some reason this produces wrong results //so for now its hacked based like on the d3d code - /* - dc_width=FB_X_CLIP.max-FB_X_CLIP.min+1; - dc_height=FB_Y_CLIP.max-FB_Y_CLIP.min+1; - u32 pvr_stride=(FB_W_LINESTRIDE.stride)*8; - */ - dc_width=640; - dc_height=480; + dc_width = FB_X_CLIP.max - FB_X_CLIP.min + 1; + dc_height = FB_Y_CLIP.max - FB_Y_CLIP.min + 1; + //u32 pvr_stride=(FB_W_LINESTRIDE.stride)*8; } float scale_x=1, scale_y=1; @@ -1646,8 +1638,9 @@ bool RenderFrame() /* Handle Dc to screen scaling */ - float dc2s_scale_h=screen_height/480.0f; - float ds2s_offs_x=(screen_width-dc2s_scale_h*640)/2; + + float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0); + float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0) / 2); //-1 -> too much to left ShaderUniforms.scale_coefs[0]=2.0f/(screen_width/dc2s_scale_h*scale_x); @@ -1703,7 +1696,6 @@ bool RenderFrame() glUniform4fv( gl.modvol_shader.scale, 1, ShaderUniforms.scale_coefs); glUniform4fv( gl.modvol_shader.depth_scale, 1, ShaderUniforms.depth_coefs); - GLfloat td[4]={0.5,0,0,0}; glUseProgram(gl.OSD_SHADER.program); @@ -1768,12 +1760,22 @@ bool RenderFrame() break; } BindRTT(FB_W_SOF1&VRAM_MASK,FB_X_CLIP.max-FB_X_CLIP.min+1,FB_Y_CLIP.max-FB_Y_CLIP.min+1,channels,format); + rttInUse = 1; } else { #if HOST_OS != OS_DARWIN - //Fix this in a proper way + if (rttInUse == 1) { + ReadRTT(); + rttInUse = 2; + } + else if (rttInUse == 2) { + FreeRTTBuffers(); + rttInUse = 0; + } + glBindFramebuffer(GL_FRAMEBUFFER,0); + glViewport(0, 0, screen_width, screen_height); #endif } diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index c77e67f5b..63b841d6a 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -117,6 +117,8 @@ void DoCleanup(); void SortPParams(); void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt); +void ReadRTT(); +void FreeRTTBuffers(); int GetProgramID(u32 cp_AlphaTest, u32 pp_ClipTestMode, u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, u32 pp_FogCtrl); diff --git a/core/rend/gles/gltex.cpp b/core/rend/gles/gltex.cpp index 171c6897b..6399ce1aa 100644 --- a/core/rend/gles/gltex.cpp +++ b/core/rend/gles/gltex.cpp @@ -20,6 +20,8 @@ Compression look into it, but afaik PVRC is not realtime doable */ +u16 buf[1024*1024]; + #if FEAT_HAS_SOFTREND #include #endif @@ -384,11 +386,6 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) { FBT& rv=fb_rtt; - if (rv.fbo) glDeleteFramebuffers(1,&rv.fbo); - if (rv.tex) glDeleteTextures(1,&rv.tex); - if (rv.depthb) glDeleteRenderbuffers(1,&rv.depthb); - if (rv.stencilb) glDeleteRenderbuffers(1,&rv.stencilb); - rv.TexAddr=addy>>3; // Find the largest square power of two texture that fits into the viewport @@ -397,7 +394,8 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) //glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_i32OriginalFbo); // Generate and bind a render buffer which will become a depth buffer shared between our two FBOs - glGenRenderbuffers(1, &rv.depthb); + if (!rv.depthb) + glGenRenderbuffers(1, &rv.depthb); glBindRenderbuffer(GL_RENDERBUFFER, rv.depthb); /* @@ -412,23 +410,25 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, fbw, fbh); #endif - glGenRenderbuffers(1, &rv.stencilb); + if (!rv.stencilb) + glGenRenderbuffers(1, &rv.stencilb); glBindRenderbuffer(GL_RENDERBUFFER, rv.stencilb); glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbw, fbh); // Create a texture for rendering to - glGenTextures(1, &rv.tex); + if (!rv.tex) + glGenTextures(1, &rv.tex); glBindTexture(GL_TEXTURE_2D, rv.tex); - glTexImage2D(GL_TEXTURE_2D, 0, channels, fbw, fbh, 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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_OES); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_OES); // Create the object that will allow us to render to the aforementioned texture - glGenFramebuffers(1, &rv.fbo); + if (!rv.fbo) + glGenFramebuffers(1, &rv.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rv.fbo); // Attach the texture to the FBO @@ -441,6 +441,51 @@ void BindRTT(u32 addy, u32 fbw, u32 fbh, u32 channels, u32 fmt) GLuint uStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER); verify(uStatus == GL_FRAMEBUFFER_COMPLETE); + + glViewport(0, 0, fbw, fbh); +} + +void ReadRTT() { + FBT& rv=fb_rtt; + + //get viewport width and height from rtt framebuffer + GLint dimensions[4] = {0}; + glGetIntegerv(GL_VIEWPORT, dimensions); + GLint w = dimensions[2]; + GLint h = dimensions[3]; + + //bind texture to which we have rendered in the last rtt pass + glBindTexture(GL_TEXTURE_2D, rv.tex); + + switch(FB_W_CTRL.fb_packmode) + { + //currently RGB 565 is supported only + case 1: //0x1 565 RGB 16 bit + { + u16 *dataPointer = temp_tex_buffer; + glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, temp_tex_buffer); + for (u32 i = 0; i < w * h; i++) { + buf[i] = ((*dataPointer & 0xF000) >> 12) | ((*dataPointer & 0x0FFF) << 4); + *dataPointer++; + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buf); + + break; + } + default: + //clear unsupported texture to avoid artifacts + memset(buf, '\0', w * h); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, buf); + + break; + } +} + +void FreeRTTBuffers() { + if (fb_rtt.fbo) { glDeleteFramebuffers(1,&fb_rtt.fbo); fb_rtt.fbo = 0; } + if (fb_rtt.tex) { glDeleteTextures(1,&fb_rtt.tex); fb_rtt.tex = 0; } + if (fb_rtt.depthb) { glDeleteRenderbuffers(1,&fb_rtt.depthb); fb_rtt.depthb = 0; } + if (fb_rtt.stencilb) { glDeleteRenderbuffers(1,&fb_rtt.stencilb); fb_rtt.stencilb = 0; } } GLuint gl_GetTexture(TSP tsp, TCW tcw) @@ -523,12 +568,12 @@ text_info raw_GetTexture(TSP tsp, TCW tcw) //return gl texture rv.height = tf->h; - rv.width = tf->w; - rv.pdata = tf->pData; - rv.textype = tf->tex_type; - - - return rv; + rv.width = tf->w; + rv.pdata = tf->pData; + rv.textype = tf->tex_type; + + + return rv; } void CollectCleanup() {