From d14a38844191913dbcf0077d7d2649c3bae404e3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 14:51:21 +0100 Subject: [PATCH 1/9] Hide glCopyImageSubData behind the FBO interface --- GPU/GLES/FBO.cpp | 40 +++++++++++++++++++---------- GPU/GLES/FBO.h | 8 ++---- GPU/GLES/FramebufferManagerGLES.cpp | 28 +++----------------- 3 files changed, 32 insertions(+), 44 deletions(-) diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index 47ff42a06b..00c8ee952c 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -40,8 +40,6 @@ struct FBO { bool native_fbo; }; -static FBO *g_overriddenBackbuffer; - static GLuint currentDrawHandle_ = 0; static GLuint currentReadHandle_ = 0; @@ -323,7 +321,6 @@ static GLenum fbo_get_fb_target(bool read, GLuint **cached) { static void fbo_bind_fb_target(bool read, GLuint name) { GLuint *cached; GLenum target = fbo_get_fb_target(read, &cached); - if (*cached != name) { if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(target, name); @@ -337,12 +334,6 @@ static void fbo_bind_fb_target(bool read, GLuint name) { } void fbo_unbind() { - if (g_overriddenBackbuffer) { - fbo_bind_as_render_target(g_overriddenBackbuffer); - return; - } - - CheckGLExtensions(); #ifndef USING_GLES2 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -361,10 +352,6 @@ void fbo_unbind() { currentReadHandle_ = 0; } -void fbo_override_backbuffer(FBO *fbo) { - g_overriddenBackbuffer = fbo; -} - void fbo_bind_as_render_target(FBO *fbo) { // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing // in ES 2.0 that actually separate them anyway of course, so doesn't matter. @@ -386,6 +373,33 @@ void fbo_unbind_read() { fbo_bind_fb_target(true, 0); } +void fbo_copy_image(FBO *src, int srcLevel, int srcX, int srcY, int srcZ, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) { +#if defined(USING_GLES2) +#ifndef IOS + glCopyImageSubDataOES( + fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + width, height, depth); + return; +#endif +#else + if (gl_extensions.ARB_copy_image) { + glCopyImageSubData( + fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + width, height, depth); + return; + } else if (gl_extensions.NV_copy_image) { + // Older, pre GL 4.x NVIDIA cards. + glCopyImageSubDataNV( + fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + width, height, depth); + return; + } +#endif +} + void fbo_bind_color_as_texture(FBO *fbo, int color) { if (fbo) { glBindTexture(GL_TEXTURE_2D, fbo->color_texture); diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index 5548923f35..0b308a8b4b 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -43,11 +43,9 @@ enum FBOColorDepth { // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); -int fbo_standard_z_depth(); +void fbo_copy_image(FBO *src, int level, int x, int y, int z, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth); -// Create an opaque FBO from a native GL FBO, optionally reusing an existing FBO structure. -// Useful for overriding the backbuffer FBO that is generated outside of this wrapper. -FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo = NULL); +int fbo_standard_z_depth(); int fbo_check_framebuffer_status(FBO *fbo); // These functions should be self explanatory. @@ -64,5 +62,3 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h); int fbo_get_color_texture(FBO *fbo); int fbo_get_depth_buffer(FBO *fbo); int fbo_get_stencil_buffer(FBO *fbo); - -void fbo_override_backbuffer(FBO *fbo); // Makes unbind bind this instead of the real backbuffer. diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index dc669fa661..b445ded9fa 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1296,37 +1296,14 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2; const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2; if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) { -#if defined(USING_GLES2) -#ifndef IOS - glCopyImageSubDataOES( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); + fbo_copy_image(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1); return; -#endif -#else - if (gl_extensions.ARB_copy_image) { - glCopyImageSubData( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); - return; - } else if (gl_extensions.NV_copy_image) { - // Older, pre GL 4.x NVIDIA cards. - glCopyImageSubDataNV( - fbo_get_color_texture(src->fbo), GL_TEXTURE_2D, 0, srcX1, srcY1, 0, - fbo_get_color_texture(dst->fbo), GL_TEXTURE_2D, 0, dstX1, dstY1, 0, - dstX2 - dstX1, dstY2 - dstY1, 1); - return; - } -#endif } } - fbo_bind_as_render_target(dst->fbo); glstate.scissorTest.force(false); - if (useBlit) { + fbo_bind_as_render_target(dst->fbo); fbo_bind_for_read(src->fbo); if (!useNV) { glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); @@ -1338,6 +1315,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, fbo_unbind_read(); } else { + fbo_bind_as_render_target(dst->fbo); fbo_bind_color_as_texture(src->fbo, 0); // Make sure our 2D drawing program is ready. Compiles only if not already compiled. From 8f00dd3f30871ded8aa3f3ecbf8e5e1cc9e10339 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 15:30:59 +0100 Subject: [PATCH 2/9] Hide glBlitFramebuffer behind fbo_blit --- GPU/GLES/FBO.cpp | 19 +++++++++++++++++++ GPU/GLES/FBO.h | 12 ++++++++++++ GPU/GLES/FramebufferManagerGLES.cpp | 28 ++++------------------------ GPU/GLES/StencilBufferGLES.cpp | 11 +---------- GPU/Vulkan/FramebufferVulkan.cpp | 1 - 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index 00c8ee952c..586f89f8ee 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -400,6 +400,25 @@ void fbo_copy_image(FBO *src, int srcLevel, int srcX, int srcY, int srcZ, FBO *d #endif } +void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter) { + GLuint bits = 0; + if (channels & FB_COLOR_BIT) + bits |= GL_COLOR_BUFFER_BIT; + if (channels & FB_DEPTH_BIT) + bits |= GL_DEPTH_BUFFER_BIT; + if (channels & FB_STENCIL_BIT) + bits |= GL_STENCIL_BUFFER_BIT; + fbo_bind_as_render_target(dst); + fbo_bind_for_read(src); + if (gl_extensions.GLES3 || gl_extensions.ARB_framebuffer_object) { + glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); +#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. + } else if (gl_extensions.NV_framebuffer_blit) { + glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, bits, linearFilter == FB_BLIT_LINEAR ? GL_LINEAR : GL_NEAREST); +#endif // defined(USING_GLES2) && defined(__ANDROID__) + } +} + void fbo_bind_color_as_texture(FBO *fbo, int color) { if (fbo) { glBindTexture(GL_TEXTURE_2D, fbo->color_texture); diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index 0b308a8b4b..1243c7b5da 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -33,6 +33,16 @@ enum FBOColorDepth { FBO_5551, }; +enum FBOChannel { + FB_COLOR_BIT = 1, + FB_DEPTH_BIT = 2, + FB_STENCIL_BIT = 4, +}; + +enum FBBlitFilter { + FB_BLIT_NEAREST = 0, + FB_BLIT_LINEAR = 1, +}; // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and // optionally an accompanying Z/stencil buffer. @@ -45,6 +55,8 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F void fbo_copy_image(FBO *src, int level, int x, int y, int z, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth); +void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter); + int fbo_standard_z_depth(); int fbo_check_framebuffer_status(FBO *fbo); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index b445ded9fa..eb54827afc 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -440,6 +440,7 @@ void FramebufferManagerGLES::DrawFramebufferToOutput(const u8 *srcPixels, GEBuff } // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. +// TODO: This could totally use fbo_blit. void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation) { float texCoords[8] = { u0,v0, @@ -782,22 +783,10 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu int h = std::min(src->renderHeight, dst->renderHeight); if (gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT)) { - // Only use NV if ARB isn't supported. - bool useNV = !gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT); - // Let's only do this if not clearing depth. - fbo_bind_for_read(src->fbo); glstate.scissorTest.force(false); - - if (useNV) { -#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. - glBlitFramebufferNV(0, 0, w, h, 0, 0, w, h, GL_DEPTH_BUFFER_BIT, GL_NEAREST); -#endif // defined(USING_GLES2) && defined(__ANDROID__) - } else { - glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } - // If we set dst->depthUpdated here, our optimization above would be pointless. - + fbo_blit(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, FB_DEPTH_BIT, FB_BLIT_NEAREST); + // WARNING: If we set dst->depthUpdated here, our optimization above would be pointless. glstate.scissorTest.restore(); } } @@ -1303,16 +1292,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, glstate.scissorTest.force(false); if (useBlit) { - fbo_bind_as_render_target(dst->fbo); - fbo_bind_for_read(src->fbo); - if (!useNV) { - glBlitFramebuffer(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } else { -#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. - glBlitFramebufferNV(srcX1, srcY1, srcX2, srcY2, dstX1, dstY1, dstX2, dstY2, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#endif // defined(USING_GLES2) && defined(__ANDROID__) - } - + fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST); fbo_unbind_read(); } else { fbo_bind_as_render_target(dst->fbo); diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 3209c360b1..e7866bfca3 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -171,7 +171,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE); bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT); - bool useNV = useBlit && !gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT); // Our fragment shader (and discard) is slow. Since the source is 1x, we can stencil to 1x. // Then after we're done, we'll just blit it across and stretch it there. @@ -221,15 +220,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe glstate.stencilMask.set(0xFF); if (useBlit) { - fbo_bind_as_render_target(dstBuffer->fbo); - fbo_bind_for_read(blitFBO); - if (!useNV) { - glBlitFramebuffer(0, 0, w, h, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, GL_STENCIL_BUFFER_BIT, GL_NEAREST); - } else { -#if defined(USING_GLES2) && defined(__ANDROID__) // We only support this extension on Android, it's not even available on PC. - glBlitFramebufferNV(0, 0, w, h, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, GL_STENCIL_BUFFER_BIT, GL_NEAREST); -#endif // defined(USING_GLES2) && defined(__ANDROID__) - } + fbo_blit(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, FB_STENCIL_BIT, FB_BLIT_NEAREST); } RebindFramebuffer(); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 1b26cecadc..7aa1c00dae 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -1201,7 +1201,6 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX return; } - // glBlitFramebuffer can clip, but glCopyImageSubData is more restricted. // In case the src goes outside, we just skip the optimization in that case. const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1; const bool sameDepth = dst->colorDepth == src->colorDepth; From 16dda97dfaf5df3b3c3dfd465415575e41fdd1d5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 15:35:45 +0100 Subject: [PATCH 3/9] Get rid of fbo_unbind_read --- GPU/GLES/FBO.cpp | 4 ---- GPU/GLES/FBO.h | 1 - GPU/GLES/FramebufferManagerGLES.cpp | 12 ------------ 3 files changed, 17 deletions(-) diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index 586f89f8ee..d9890fa68a 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -369,10 +369,6 @@ void fbo_bind_for_read(FBO *fbo) { fbo_bind_fb_target(true, fbo->handle); } -void fbo_unbind_read() { - fbo_bind_fb_target(true, 0); -} - void fbo_copy_image(FBO *src, int srcLevel, int srcX, int srcY, int srcZ, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) { #if defined(USING_GLES2) #ifndef IOS diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index 1243c7b5da..a45607f367 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -67,7 +67,6 @@ void fbo_bind_color_as_texture(FBO *fbo, int color); void fbo_bind_for_read(FBO *fbo); void fbo_unbind(); void fbo_unbind_render_target(); -void fbo_unbind_read(); void fbo_destroy(FBO *fbo); void fbo_get_dimensions(FBO *fbo, int *w, int *h); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index eb54827afc..1fdf6d4037 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1293,7 +1293,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, glstate.scissorTest.force(false); if (useBlit) { fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST); - fbo_unbind_read(); } else { fbo_bind_as_render_target(dst->fbo); fbo_bind_color_as_texture(src->fbo, 0); @@ -1579,7 +1578,6 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { fbo_bind_for_read(vfb->fbo); } else { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferAsync_: vfb->fbo == 0"); - fbo_unbind_read(); return; } @@ -1588,7 +1586,6 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { ERROR_LOG(SCEGE, "Incomplete source framebuffer, aborting read"); - fbo_unbind_read(); return; } @@ -1610,7 +1607,6 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { SafeGLReadPixels(0, 0, vfb->fb_stride, vfb->height, pixelFormat, pixelType, 0); } - fbo_unbind_read(); unbind = true; pixelBufObj_[currentPBO_].fb_address = fb_address; @@ -1633,7 +1629,6 @@ void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x fbo_bind_for_read(vfb->fbo); } else { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferSync_: vfb->fbo == 0"); - fbo_unbind_read(); return; } @@ -1693,8 +1688,6 @@ void FramebufferManagerGLES::PackFramebufferSync_(VirtualFramebuffer *vfb, int x GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; glInvalidateFramebuffer(target, 3, attachments); } - - fbo_unbind_read(); } void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { @@ -1736,8 +1729,6 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int depth[i] = (int)scaled; } } - - fbo_unbind_read(); } void FramebufferManagerGLES::EndFrame() { @@ -1969,14 +1960,11 @@ bool FramebufferManagerGLES::GetFramebuffer(u32 fb_address, int fb_stride, GEBuf SafeGLReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData()); // We may have clitted to a temp FBO. - fbo_unbind_read(); RebindFramebuffer(); return true; } bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - fbo_unbind_read(); - int pw = PSP_CoreParameter().pixelWidth; int ph = PSP_CoreParameter().pixelHeight; From 089fa4f5a7c93cdafe183f3f2b53a3d8d455f304 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 15:39:50 +0100 Subject: [PATCH 4/9] Delete more unused fbo functions --- GPU/GLES/FBO.cpp | 24 ++++++------------------ GPU/GLES/FBO.h | 4 ---- GPU/GLES/FramebufferManagerGLES.cpp | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 34 deletions(-) diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index d9890fa68a..49ed9ee3ba 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -373,23 +373,23 @@ void fbo_copy_image(FBO *src, int srcLevel, int srcX, int srcY, int srcZ, FBO *d #if defined(USING_GLES2) #ifndef IOS glCopyImageSubDataOES( - fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; #endif #else if (gl_extensions.ARB_copy_image) { glCopyImageSubData( - fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; } else if (gl_extensions.NV_copy_image) { // Older, pre GL 4.x NVIDIA cards. glCopyImageSubDataNV( - fbo_get_color_texture(src), GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - fbo_get_color_texture(dst), GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; } @@ -458,15 +458,3 @@ void fbo_get_dimensions(FBO *fbo, int *w, int *h) { *w = fbo->width; *h = fbo->height; } - -int fbo_get_color_texture(FBO *fbo) { - return fbo->color_texture; -} - -int fbo_get_depth_buffer(FBO *fbo) { - return fbo->z_buffer; -} - -int fbo_get_stencil_buffer(FBO *fbo) { - return fbo->stencil_buffer; -} diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index a45607f367..f652dcb212 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -69,7 +69,3 @@ void fbo_unbind(); void fbo_unbind_render_target(); void fbo_destroy(FBO *fbo); void fbo_get_dimensions(FBO *fbo, int *w, int *h); - -int fbo_get_color_texture(FBO *fbo); -int fbo_get_depth_buffer(FBO *fbo); -int fbo_get_stencil_buffer(FBO *fbo); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 1fdf6d4037..2b4c5139f4 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1014,7 +1014,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); DisableState(); - GLuint colorTexture = fbo_get_color_texture(vfb->fbo); + fbo_bind_color_as_texture(vfb->fbo, 0); int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; @@ -1036,15 +1036,15 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { if (cardboardSettings.enabled) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); } } else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. @@ -1055,7 +1055,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { shaderManager_->DirtyLastShader(); // dirty lastShader_ glsl_bind(postShaderProgram_); UpdatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_); - DrawActiveTexture(colorTexture, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); fbo_unbind(); @@ -1065,7 +1065,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { ERROR_LOG(G3D, "WTF?"); return; } - colorTexture = fbo_get_color_texture(extraFBOs_[0]); + fbo_bind_color_as_texture(extraFBOs_[0], 0); // We are doing the DrawActiveTexture call directly to the backbuffer after here. Hence, we must // flip V. @@ -1074,15 +1074,15 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { if (g_Config.bEnableCardboard) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); } if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { @@ -1101,15 +1101,15 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { if (g_Config.bEnableCardboard) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(colorTexture, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); + DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); } } From daee5c24e5dc0cc6c85e8e6d9dd0ee01a8ab3762 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 16:19:54 +0100 Subject: [PATCH 5/9] Work towards unifying the GL and DX FBO APIs --- GPU/Directx9/FramebufferDX9.cpp | 72 +++++++++++++++-------------- GPU/Directx9/TextureCacheDX9.cpp | 2 +- GPU/Directx9/helper/dx_fbo.cpp | 32 ++++++++----- GPU/Directx9/helper/dx_fbo.h | 23 ++++++--- GPU/GLES/FBO.cpp | 53 +++++---------------- GPU/GLES/FBO.h | 13 +++--- GPU/GLES/FramebufferManagerGLES.cpp | 48 ++++++++----------- GPU/GLES/GPU_GLES.cpp | 4 +- GPU/GLES/TextureCacheGLES.cpp | 2 +- UI/EmuScreen.cpp | 3 -- 10 files changed, 117 insertions(+), 135 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index f930a3a73f..786847066f 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -298,7 +298,7 @@ namespace DX9 { if (currentRenderVfb_ && currentRenderVfb_->fbo_dx9) { fbo_bind_as_render_target(currentRenderVfb_->fbo_dx9); } else { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } } @@ -346,7 +346,7 @@ namespace DX9 { } textureCache_->ForgetLastTexture(); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); if (!useBufferedRendering_) { if (vfb->fbo_dx9) { @@ -379,7 +379,7 @@ namespace DX9 { void FramebufferManagerDX9::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { if (!useBufferedRendering_) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); // Let's ignore rendering to targets that have not (yet) been displayed. gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; } @@ -411,7 +411,7 @@ namespace DX9 { fbo_bind_as_render_target(vfb->fbo_dx9); } else { // wtf? This should only happen very briefly when toggling bBufferedRendering - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } } else { if (vfb->fbo_dx9) { @@ -420,7 +420,7 @@ namespace DX9 { fbo_destroy(vfb->fbo_dx9); vfb->fbo_dx9 = nullptr; } - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); // Let's ignore rendering to targets that have not (yet) been displayed. if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { @@ -557,7 +557,7 @@ namespace DX9 { bool matchingSize = src->width == dst->width && src->height == dst->height; if (matchingDepthBuffer && matchingSize) { // Doesn't work. Use a shader maybe? - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); LPDIRECT3DTEXTURE9 srcTex = fbo_get_depth_texture(src->fbo_dx9); LPDIRECT3DTEXTURE9 dstTex = fbo_get_depth_texture(dst->fbo_dx9); @@ -712,7 +712,7 @@ namespace DX9 { void FramebufferManagerDX9::CopyDisplayToOutput() { DownloadFramebufferOnSwitch(currentRenderVfb_); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; if (displayFramebufPtr_ == 0) { @@ -827,11 +827,14 @@ namespace DX9 { if (1) { const u32 rw = PSP_CoreParameter().pixelWidth; const u32 rh = PSP_CoreParameter().pixelHeight; - const RECT srcRect = {(LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight)}; - const RECT dstRect = {(LONG)(x * rw / w), (LONG)(y * rh / h), (LONG)((x + w) * rw / w), (LONG)((y + h) * rh / h)}; - HRESULT hr = fbo_blit_color(vfb->fbo_dx9, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT); - if (FAILED(hr)) { - ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr); + bool result = fbo_blit(vfb->fbo_dx9, + (LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight), + nullptr, + (LONG)(x * rw / w), (LONG)(y * rh / h), (LONG)((x + w) * rw / w), (LONG)((y + h) * rh / h), + FB_COLOR_BIT, + g_Config.iBufFilter == SCALE_LINEAR ? FB_BLIT_LINEAR : FB_BLIT_NEAREST); + if (!result) { + ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display"); DXSetViewport(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); // These are in the output display coordinates if (g_Config.iBufFilter == SCALE_LINEAR) { @@ -949,7 +952,7 @@ namespace DX9 { void FramebufferManagerDX9::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if they recently switched from non-buffered. - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); return; } @@ -977,29 +980,31 @@ namespace DX9 { LPDIRECT3DSURFACE9 srcSurf = fbo_get_color_for_read(src->fbo_dx9); LPDIRECT3DSURFACE9 dstSurf = fbo_get_color_for_write(dst->fbo_dx9); - RECT srcRect = {srcX1, srcY1, srcX2, srcY2}; - RECT dstRect = {dstX1, dstY1, dstX2, dstY2}; - - D3DSURFACE_DESC desc; - srcSurf->GetDesc(&desc); - srcRect.right = std::min(srcRect.right, (LONG)desc.Width); - srcRect.bottom = std::min(srcRect.bottom, (LONG)desc.Height); - - dstSurf->GetDesc(&desc); - dstRect.right = std::min(dstRect.right, (LONG)desc.Width); - dstRect.bottom = std::min(dstRect.bottom, (LONG)desc.Height); + D3DSURFACE_DESC srcDesc; + D3DSURFACE_DESC dstDesc; + srcSurf->GetDesc(&srcDesc); + dstSurf->GetDesc(&dstDesc); + srcX2 = std::min(srcX2, (int)srcDesc.Width); + srcY2 = std::min(srcY2, (int)srcDesc.Height); + dstX2 = std::min(dstX2, (int)dstDesc.Width); + dstY2 = std::min(dstY2, (int)dstDesc.Height); // Direct3D 9 doesn't support rect -> self. FBO_DX9 *srcFBO = src->fbo_dx9; if (src == dst) { FBO_DX9 *tempFBO = GetTempFBO(src->renderWidth, src->renderHeight, (FBOColorDepth)src->colorDepth); - HRESULT hr = fbo_blit_color(src->fbo_dx9, &srcRect, tempFBO, &srcRect, D3DTEXF_POINT); + HRESULT hr = fbo_blit( + src->fbo_dx9, srcX1, srcY1, srcX2, srcY2, + tempFBO, dstX1, dstY1, dstX2, dstY2, + FB_COLOR_BIT, FB_BLIT_NEAREST); if (SUCCEEDED(hr)) { srcFBO = tempFBO; } } - - HRESULT hr = fbo_blit_color(srcFBO, &srcRect, dst->fbo_dx9, &dstRect, D3DTEXF_POINT); + HRESULT hr = fbo_blit( + srcFBO, srcX1, srcY1, srcX2, srcY2, + dst->fbo_dx9, dstX1, dstY1, dstX2, dstY2, + FB_COLOR_BIT, FB_BLIT_NEAREST); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "fbo_blit_color failed in blit: %08x (%08x -> %08x)", hr, src->fb_address, dst->fb_address); } @@ -1058,7 +1063,7 @@ namespace DX9 { void FramebufferManagerDX9::PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferDirectx9_: vfb->fbo == 0"); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); return; } @@ -1206,7 +1211,7 @@ namespace DX9 { void FramebufferManagerDX9::DecimateFBOs() { if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } currentRenderVfb_ = 0; bool updateVram = !(g_Config.iRenderingMode == FB_NON_BUFFERED_MODE || g_Config.iRenderingMode == FB_BUFFERED_MODE); @@ -1265,7 +1270,7 @@ namespace DX9 { } void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1337,11 +1342,8 @@ namespace DX9 { // Let's resize. We must stretch to a render target first. w = vfb->width * maxRes; h = vfb->height * maxRes; - tempFBO = fbo_create(w, h, 1, false); - RECT srcRect = {0, 0, vfb->renderWidth, vfb->renderHeight}; - D3DTEXTUREFILTERTYPE filt = g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT; - if (SUCCEEDED(fbo_blit_color(vfb->fbo_dx9, &srcRect, tempFBO, nullptr, filt))) { + if (SUCCEEDED(fbo_blit(vfb->fbo_dx9, 0, 0, vfb->renderWidth, vfb->renderHeight, tempFBO, 0, 0, w, h, FB_COLOR_BIT, g_Config.iBufFilter == SCALE_LINEAR ? FB_BLIT_LINEAR : FB_BLIT_NEAREST))) { renderTarget = fbo_get_color_for_read(tempFBO); } } @@ -1359,7 +1361,7 @@ namespace DX9 { } bool FramebufferManagerDX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); LPDIRECT3DSURFACE9 renderTarget = nullptr; HRESULT hr = pD3Ddevice->GetRenderTarget(0, &renderTarget); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index c2f56547a1..525528756b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -787,7 +787,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame shaderApply.Shade(); - fbo_bind_color_as_texture(depalFBO, 0); + fbo_bind_as_texture(depalFBO, FB_COLOR_BIT, 0); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; diff --git a/GPU/Directx9/helper/dx_fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp index bd59e5c01f..c8b0d7943a 100644 --- a/GPU/Directx9/helper/dx_fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -115,7 +115,7 @@ void fbo_destroy(FBO_DX9 *fbo) { delete fbo; } -void fbo_unbind() { +void fbo_bind_backbuffer_as_render_target() { pD3Ddevice->SetRenderTarget(0, deviceRTsurf); pD3Ddevice->SetDepthStencilSurface(deviceDSsurf); dxstate.scissorRect.restore(); @@ -149,13 +149,19 @@ LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo) { return fbo->surf; } -void fbo_bind_color_as_texture(FBO_DX9 *fbo, int color) { - pD3Ddevice->SetTexture(0, fbo->tex); -} - -void fbo_bind_depth_as_texture(FBO_DX9 *fbo) { - if (fbo->depthstenciltex) { - pD3Ddevice->SetTexture(0, fbo->depthstenciltex); +void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, int color) { + switch (channelBit) { + case FB_DEPTH_BIT: + if (fbo->depthstenciltex) { + pD3Ddevice->SetTexture(0, fbo->depthstenciltex); + } + break; + case FB_COLOR_BIT: + default: + if (fbo->tex) { + pD3Ddevice->SetTexture(0, fbo->tex); + } + break; } } @@ -164,10 +170,14 @@ void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h) { *h = fbo->height; } -HRESULT fbo_blit_color(FBO_DX9 *src, const RECT *srcRect, FBO_DX9 *dst, const RECT *dstRect, D3DTEXTUREFILTERTYPE filter) { +bool fbo_blit(FBO_DX9 *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO_DX9 *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) { + if (channelBits != FB_COLOR_BIT) + return false; + RECT srcRect{ (LONG)srcX1, (LONG)srcY1, (LONG)srcX2, (LONG)srcY2 }; + RECT dstRect{ (LONG)dstX1, (LONG)dstY1, (LONG)dstX2, (LONG)dstY2 }; LPDIRECT3DSURFACE9 srcSurf = src ? src->surf : deviceRTsurf; LPDIRECT3DSURFACE9 dstSurf = dst ? dst->surf : deviceRTsurf; - return pD3Ddevice->StretchRect(srcSurf, srcRect, dstSurf, dstRect, filter); + return SUCCEEDED(pD3Ddevice->StretchRect(srcSurf, &srcRect, dstSurf, &dstRect, filter == FB_BLIT_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT)); } -} +} // namespace diff --git a/GPU/Directx9/helper/dx_fbo.h b/GPU/Directx9/helper/dx_fbo.h index d8260b0a2b..7eb0de4b45 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -32,6 +32,17 @@ enum FBOColorDepth { FBO_5551, }; +enum FBOChannel { + FB_COLOR_BIT = 1, + FB_DEPTH_BIT = 2, + FB_STENCIL_BIT = 4, +}; + +enum FBBlitFilter { + FB_BLIT_NEAREST = 0, + FB_BLIT_LINEAR = 1, +}; + // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and // optionally an accompanying Z/stencil buffer. // No mipmap support. @@ -40,19 +51,19 @@ enum FBOColorDepth { // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO_DX9 *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); +void fbo_destroy(FBO_DX9 *fbo); + +bool fbo_blit(FBO_DX9 *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO_DX9 *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter); // These functions should be self explanatory. void fbo_bind_as_render_target(FBO_DX9 *fbo); -// color must be 0, for now. -void fbo_bind_color_as_texture(FBO_DX9 *fbo, int color); -void fbo_bind_depth_as_texture(FBO_DX9 *fbo); +// color must be 0. +void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, int color); LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo); LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo); -void fbo_unbind(); -void fbo_destroy(FBO_DX9 *fbo); +void fbo_bind_backbuffer_as_render_target(); void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h); void fbo_resolve(FBO_DX9 *fbo); -HRESULT fbo_blit_color(FBO_DX9 *src, const RECT *srcRect, FBO_DX9 *dst, const RECT *dstRect, D3DTEXTUREFILTERTYPE filter); LPDIRECT3DTEXTURE9 fbo_get_color_texture(FBO_DX9 *fbo); LPDIRECT3DTEXTURE9 fbo_get_depth_texture(FBO_DX9 *fbo); diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index 49ed9ee3ba..6944dd7568 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -125,23 +125,7 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci } #endif -int fbo_check_framebuffer_status(FBO *fbo) { - GLenum fbStatus; -#ifndef USING_GLES2 - if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { - fbStatus = glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER); - } else if (gl_extensions.ARB_framebuffer_object) { - fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); - } else { - fbStatus = 0; - } -#else - fbStatus = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); -#endif - return (int)fbStatus; -} - -int fbo_standard_z_depth() { +int fbo_preferred_z_bitdepth() { // This matches the fbo_create() logic. if (gl_extensions.IsGLES) { if (gl_extensions.OES_packed_depth_stencil) { @@ -256,7 +240,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F } GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - switch(status) { + switch (status) { case GL_FRAMEBUFFER_COMPLETE: // ILOG("Framebuffer verified complete."); break; @@ -279,24 +263,6 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F return fbo; } -FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) -{ - if (!fbo) - fbo = new FBO(); - - fbo->native_fbo = true; - fbo->handle = native_fbo; - fbo->color_texture = 0; - fbo->z_stencil_buffer = 0; - fbo->z_buffer = 0; - fbo->stencil_buffer = 0; - fbo->width = 0; - fbo->height = 0; - fbo->colorDepth = FBO_8888; - - return fbo; -} - static GLenum fbo_get_fb_target(bool read, GLuint **cached) { bool supportsBlit = gl_extensions.ARB_framebuffer_object; if (gl_extensions.IsGLES) { @@ -333,7 +299,7 @@ static void fbo_bind_fb_target(bool read, GLuint name) { } } -void fbo_unbind() { +static void fbo_unbind() { #ifndef USING_GLES2 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -360,7 +326,7 @@ void fbo_bind_as_render_target(FBO *fbo) { glstate.viewport.restore(); } -void fbo_unbind_render_target() { +void fbo_bind_backbuffer_as_render_target() { fbo_unbind(); } @@ -415,9 +381,14 @@ void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, in } } -void fbo_bind_color_as_texture(FBO *fbo, int color) { - if (fbo) { - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); +void fbo_bind_as_texture(FBO *fbo, FBOChannel channelBit, int color) { + switch (channelBit) { + case FB_COLOR_BIT: + default: + if (fbo) { + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + } + break; } } diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index f652dcb212..b3f8b959eb 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -52,20 +52,19 @@ enum FBBlitFilter { // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); +void fbo_destroy(FBO *fbo); void fbo_copy_image(FBO *src, int level, int x, int y, int z, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth); - void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter); -int fbo_standard_z_depth(); -int fbo_check_framebuffer_status(FBO *fbo); +int fbo_preferred_z_bitdepth(); // These functions should be self explanatory. void fbo_bind_as_render_target(FBO *fbo); // color must be 0, for now. -void fbo_bind_color_as_texture(FBO *fbo, int color); +void fbo_bind_as_texture(FBO *fbo, FBOChannel channelBit, int attachment); void fbo_bind_for_read(FBO *fbo); -void fbo_unbind(); -void fbo_unbind_render_target(); -void fbo_destroy(FBO *fbo); + +void fbo_bind_backbuffer_as_render_target(); + void fbo_get_dimensions(FBO *fbo, int *w, int *h); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 2b4c5139f4..9321c56214 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -130,7 +130,7 @@ void FramebufferManagerGLES::SetNumExtraFBOs(int num) { } currentRenderVfb_ = 0; - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } void FramebufferManagerGLES::CompileDraw2DProgram() { @@ -552,7 +552,7 @@ void FramebufferManagerGLES::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { fbo_bind_as_render_target(currentRenderVfb_->fbo); } else { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) glstate.viewport.restore(); @@ -602,7 +602,7 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u } textureCache_->ForgetLastTexture(); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); if (!useBufferedRendering_) { if (vfb->fbo) { @@ -635,7 +635,7 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u void FramebufferManagerGLES::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { if (!useBufferedRendering_) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); // Let's ignore rendering to targets that have not (yet) been displayed. gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; } @@ -665,7 +665,7 @@ void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer fbo_bind_as_render_target(vfb->fbo); } else { // wtf? This should only happen very briefly when toggling bBufferedRendering - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } } else { if (vfb->fbo) { @@ -674,7 +674,7 @@ void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer fbo_destroy(vfb->fbo); vfb->fbo = 0; } - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); // Let's ignore rendering to targets that have not (yet) been displayed. if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { @@ -862,12 +862,12 @@ void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, V BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); - fbo_bind_color_as_texture(renderCopy, 0); + fbo_bind_as_texture(renderCopy, FB_COLOR_BIT, 0); } else { - fbo_bind_color_as_texture(framebuffer->fbo, 0); + fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0); } } else { - fbo_bind_color_as_texture(framebuffer->fbo, 0); + fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0); } if (stage != GL_TEXTURE0) { @@ -905,7 +905,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { DownloadFramebufferOnSwitch(currentRenderVfb_); glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; if (displayFramebufPtr_ == 0) { @@ -1014,7 +1014,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); DisableState(); - fbo_bind_color_as_texture(vfb->fbo, 0); + fbo_bind_as_texture(vfb->fbo, FB_COLOR_BIT, 0); int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; @@ -1057,15 +1057,15 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { UpdatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_); DrawActiveTexture(0, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); // Use the extra FBO, with applied post-processing shader, as a texture. - // fbo_bind_color_as_texture(extraFBOs_[0], 0); + // fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); if (extraFBOs_.size() == 0) { ERROR_LOG(G3D, "WTF?"); return; } - fbo_bind_color_as_texture(extraFBOs_[0], 0); + fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); // We are doing the DrawActiveTexture call directly to the backbuffer after here. Hence, we must // flip V. @@ -1240,7 +1240,7 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if they recently switched from non-buffered. - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); return; } @@ -1295,7 +1295,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST); } else { fbo_bind_as_render_target(dst->fbo); - fbo_bind_color_as_texture(src->fbo, 0); + fbo_bind_as_texture(src->fbo, FB_COLOR_BIT, 0); // Make sure our 2D drawing program is ready. Compiles only if not already compiled. CompileDraw2DProgram(); @@ -1581,14 +1581,6 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) { return; } - GLenum fbStatus; - fbStatus = (GLenum)fbo_check_framebuffer_status(vfb->fbo); - - if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { - ERROR_LOG(SCEGE, "Incomplete source framebuffer, aborting read"); - return; - } - glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufObj_[currentPBO_].handle); if (pixelBufObj_[currentPBO_].maxSize < bufSize) { @@ -1799,7 +1791,7 @@ void FramebufferManagerGLES::EndFrame() { GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); } - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } } @@ -1829,7 +1821,7 @@ std::vector FramebufferManagerGLES::GetFramebufferList() { } void FramebufferManagerGLES::DecimateFBOs() { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; for (size_t i = 0; i < vfbs_.size(); ++i) { @@ -1876,7 +1868,7 @@ void FramebufferManagerGLES::DecimateFBOs() { } void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1900,7 +1892,7 @@ void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) { } tempFBOs_.clear(); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); DisableState(); } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index e522fb90d0..340ae6e499 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -605,14 +605,14 @@ void GPU_GLES::CheckGPUFeatures() { features |= GPU_SUPPORTS_TEXTURE_FLOAT; // If we already have a 16-bit depth buffer, we don't need to round. - if (fbo_standard_z_depth() > 16) { + if (fbo_preferred_z_bitdepth() > 16) { if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { if (!gl_extensions.IsGLES || gl_extensions.GLES3) { // Use fragment rounding on desktop and GLES3, most accurate. features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; - } else if (fbo_standard_z_depth() == 24 && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { + } else if (fbo_preferred_z_bitdepth() == 24 && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) { // Here we can simulate a 16 bit depth buffer by scaling. // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6f4bbef660..e1933d2e50 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -862,7 +862,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram shaderApply.Shade(); - fbo_bind_color_as_texture(depalFBO, 0); + fbo_bind_as_texture(depalFBO, FB_COLOR_BIT, 0); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 882d9bbc48..6bcca81d2b 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1028,9 +1028,6 @@ void EmuScreen::render() { if (invalid_) return; - if (useBufferedRendering && GetGPUBackend() == GPUBackend::OPENGL) - fbo_unbind(); - if (!osm.IsEmpty() || g_Config.bShowDebugStats || g_Config.iShowFPSCounter || g_Config.bShowTouchControls || g_Config.bShowDeveloperMenu || g_Config.bShowAudioDebug || saveStatePreview_->GetVisibility() != UI::V_GONE || g_Config.bShowFrameProfiler) { DrawContext *thin3d = screenManager()->getDrawContext(); From 0b7f3720aed13386f8dae821d0e645b6f1db881e Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 16:32:40 +0100 Subject: [PATCH 6/9] More FBO api cleanup --- GPU/Directx9/FramebufferDX9.cpp | 11 ----------- GPU/Directx9/TextureCacheDX9.cpp | 2 +- GPU/Directx9/helper/dx_fbo.cpp | 8 +++++--- GPU/Directx9/helper/dx_fbo.h | 2 +- GPU/GLES/FBO.cpp | 3 ++- GPU/GLES/FBO.h | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 12 ++++++------ GPU/GLES/TextureCacheGLES.cpp | 2 +- UI/EmuScreen.cpp | 1 - 9 files changed, 17 insertions(+), 26 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 786847066f..70b03e874d 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -978,17 +978,6 @@ namespace DX9 { int dstY1 = dstY * dstYFactor; int dstY2 = (dstY + h) * dstYFactor; - LPDIRECT3DSURFACE9 srcSurf = fbo_get_color_for_read(src->fbo_dx9); - LPDIRECT3DSURFACE9 dstSurf = fbo_get_color_for_write(dst->fbo_dx9); - D3DSURFACE_DESC srcDesc; - D3DSURFACE_DESC dstDesc; - srcSurf->GetDesc(&srcDesc); - dstSurf->GetDesc(&dstDesc); - srcX2 = std::min(srcX2, (int)srcDesc.Width); - srcY2 = std::min(srcY2, (int)srcDesc.Height); - dstX2 = std::min(dstX2, (int)dstDesc.Width); - dstY2 = std::min(dstY2, (int)dstDesc.Height); - // Direct3D 9 doesn't support rect -> self. FBO_DX9 *srcFBO = src->fbo_dx9; if (src == dst) { diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 525528756b..317f3e8e39 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -787,7 +787,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame shaderApply.Shade(); - fbo_bind_as_texture(depalFBO, FB_COLOR_BIT, 0); + fbo_bind_as_texture(depalFBO, 0, FB_COLOR_BIT, 0); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; diff --git a/GPU/Directx9/helper/dx_fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp index c8b0d7943a..d24ae05611 100644 --- a/GPU/Directx9/helper/dx_fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -15,6 +15,8 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include + #include "global.h" #include #include @@ -149,17 +151,17 @@ LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo) { return fbo->surf; } -void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, int color) { +void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color) { switch (channelBit) { case FB_DEPTH_BIT: if (fbo->depthstenciltex) { - pD3Ddevice->SetTexture(0, fbo->depthstenciltex); + pD3Ddevice->SetTexture(binding, fbo->depthstenciltex); } break; case FB_COLOR_BIT: default: if (fbo->tex) { - pD3Ddevice->SetTexture(0, fbo->tex); + pD3Ddevice->SetTexture(binding, fbo->tex); } break; } diff --git a/GPU/Directx9/helper/dx_fbo.h b/GPU/Directx9/helper/dx_fbo.h index 7eb0de4b45..9939150df6 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -58,7 +58,7 @@ bool fbo_blit(FBO_DX9 *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO_DX9 // These functions should be self explanatory. void fbo_bind_as_render_target(FBO_DX9 *fbo); // color must be 0. -void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, int color); +void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color); LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo); LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo); void fbo_bind_backbuffer_as_render_target(); diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index 6944dd7568..f31700be38 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -381,7 +381,8 @@ void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, in } } -void fbo_bind_as_texture(FBO *fbo, FBOChannel channelBit, int color) { +void fbo_bind_as_texture(FBO *fbo, int binding, FBOChannel channelBit, int color) { + // glActiveTexture(GL_TEXTURE0 + binding); switch (channelBit) { case FB_COLOR_BIT: default: diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index b3f8b959eb..25bb83a924 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -62,7 +62,7 @@ int fbo_preferred_z_bitdepth(); // These functions should be self explanatory. void fbo_bind_as_render_target(FBO *fbo); // color must be 0, for now. -void fbo_bind_as_texture(FBO *fbo, FBOChannel channelBit, int attachment); +void fbo_bind_as_texture(FBO *fbo, int binding, FBOChannel channelBit, int attachment); void fbo_bind_for_read(FBO *fbo); void fbo_bind_backbuffer_as_render_target(); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 9321c56214..770d06150b 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -862,12 +862,12 @@ void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, V BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); - fbo_bind_as_texture(renderCopy, FB_COLOR_BIT, 0); + fbo_bind_as_texture(renderCopy, 0, FB_COLOR_BIT, 0); } else { - fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0); + fbo_bind_as_texture(framebuffer->fbo, 0, FB_COLOR_BIT, 0); } } else { - fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0); + fbo_bind_as_texture(framebuffer->fbo, 0, FB_COLOR_BIT, 0); } if (stage != GL_TEXTURE0) { @@ -1014,7 +1014,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); DisableState(); - fbo_bind_as_texture(vfb->fbo, FB_COLOR_BIT, 0); + fbo_bind_as_texture(vfb->fbo, 0, FB_COLOR_BIT, 0); int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; @@ -1065,7 +1065,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { ERROR_LOG(G3D, "WTF?"); return; } - fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); + fbo_bind_as_texture(extraFBOs_[0], 0, FB_COLOR_BIT, 0); // We are doing the DrawActiveTexture call directly to the backbuffer after here. Hence, we must // flip V. @@ -1295,7 +1295,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST); } else { fbo_bind_as_render_target(dst->fbo); - fbo_bind_as_texture(src->fbo, FB_COLOR_BIT, 0); + fbo_bind_as_texture(src->fbo, 0, FB_COLOR_BIT, 0); // Make sure our 2D drawing program is ready. Compiles only if not already compiled. CompileDraw2DProgram(); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index e1933d2e50..9c53eb6d64 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -862,7 +862,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram shaderApply.Shade(); - fbo_bind_as_texture(depalFBO, FB_COLOR_BIT, 0); + fbo_bind_as_texture(depalFBO, 0, FB_COLOR_BIT, 0); const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16); const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 6bcca81d2b..cbe83fddf4 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -44,7 +44,6 @@ #include "Core/System.h" #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" -#include "GPU/GLES/FBO.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceDisplay.h" From f4c3f884e9dde8e9a13f3f5943e598ebd01653a5 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 16:50:00 +0100 Subject: [PATCH 7/9] DX: Remove further fbo functions to get the interfaces closer --- GPU/Directx9/FramebufferDX9.cpp | 10 +++++----- GPU/Directx9/helper/dx_fbo.cpp | 4 ---- GPU/Directx9/helper/dx_fbo.h | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 70b03e874d..0781cacadb 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -700,12 +700,12 @@ namespace DX9 { BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0); RebindFramebuffer(); - pD3Ddevice->SetTexture(stage, fbo_get_color_texture(renderCopy)); + fbo_bind_as_texture(renderCopy, stage, FB_COLOR_BIT, 0); } else { - pD3Ddevice->SetTexture(stage, fbo_get_color_texture(framebuffer->fbo_dx9)); + fbo_bind_as_texture(framebuffer->fbo_dx9, stage, FB_COLOR_BIT, 0); } } else { - pD3Ddevice->SetTexture(stage, fbo_get_color_texture(framebuffer->fbo_dx9)); + fbo_bind_as_texture(framebuffer->fbo_dx9, stage, FB_COLOR_BIT, 0); } } @@ -812,7 +812,7 @@ namespace DX9 { if (vfb->fbo) { DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); DisableState(); - LPDIRECT3DTEXTURE9 colorTexture = fbo_get_color_texture(vfb->fbo_dx9); + fbo_bind_as_texture(vfb->fbo_dx9, 0, FB_COLOR_BIT, 0); // Output coordinates float x, y, w, h; @@ -846,7 +846,7 @@ namespace DX9 { } dxstate.texMipFilter.set(D3DTEXF_NONE); dxstate.texMipLodBias.set(0); - DrawActiveTexture(colorTexture, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation); + DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation); } } /* diff --git a/GPU/Directx9/helper/dx_fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp index d24ae05611..a633810473 100644 --- a/GPU/Directx9/helper/dx_fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -147,10 +147,6 @@ LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo) { return fbo->surf; } -LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo) { - return fbo->surf; -} - void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color) { switch (channelBit) { case FB_DEPTH_BIT: diff --git a/GPU/Directx9/helper/dx_fbo.h b/GPU/Directx9/helper/dx_fbo.h index 9939150df6..8772495e84 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -60,7 +60,6 @@ void fbo_bind_as_render_target(FBO_DX9 *fbo); // color must be 0. void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color); LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo); -LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo); void fbo_bind_backbuffer_as_render_target(); void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h); void fbo_resolve(FBO_DX9 *fbo); From bec2921aca00cea5ee4dde75bc139fc1c741994d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 17:20:20 +0100 Subject: [PATCH 8/9] Add escape route for some more esoteric FBO functionality --- GPU/Directx9/FramebufferDX9.cpp | 17 ++++++++--------- GPU/Directx9/helper/dx_fbo.cpp | 29 ++++++++++++++++++++++------- GPU/Directx9/helper/dx_fbo.h | 7 ++++--- GPU/GLES/FBO.cpp | 5 +++++ GPU/GLES/FBO.h | 1 + 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 0781cacadb..6260021d65 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -559,8 +559,8 @@ namespace DX9 { // Doesn't work. Use a shader maybe? fbo_bind_backbuffer_as_render_target(); - LPDIRECT3DTEXTURE9 srcTex = fbo_get_depth_texture(src->fbo_dx9); - LPDIRECT3DTEXTURE9 dstTex = fbo_get_depth_texture(dst->fbo_dx9); + LPDIRECT3DTEXTURE9 srcTex = (LPDIRECT3DTEXTURE9)fbo_get_api_texture(src->fbo_dx9, FB_DEPTH_BIT, 0); + LPDIRECT3DTEXTURE9 dstTex = (LPDIRECT3DTEXTURE9)fbo_get_api_texture(dst->fbo_dx9, FB_DEPTH_BIT, 0); if (srcTex && dstTex) { D3DSURFACE_DESC srcDesc; @@ -1063,7 +1063,7 @@ namespace DX9 { // Right now that's always 8888. DEBUG_LOG(HLE, "Reading framebuffer to mem, fb_address = %08x", fb_address); - LPDIRECT3DSURFACE9 renderTarget = fbo_get_color_for_read(vfb->fbo_dx9); + LPDIRECT3DSURFACE9 renderTarget = (LPDIRECT3DSURFACE9)fbo_get_api_texture(vfb->fbo_dx9, FB_COLOR_BIT | FB_SURFACE_BIT, 0); D3DSURFACE_DESC desc; renderTarget->GetDesc(&desc); @@ -1102,7 +1102,7 @@ namespace DX9 { DEBUG_LOG(SCEGE, "Reading depthbuffer to mem at %08x for vfb=%08x", z_address, vfb->fb_address); - LPDIRECT3DTEXTURE9 tex = fbo_get_depth_texture(vfb->fbo_dx9); + LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)fbo_get_api_texture(vfb->fbo_dx9, FB_DEPTH_BIT, 0); if (tex) { D3DSURFACE_DESC desc; D3DLOCKED_RECT locked; @@ -1320,8 +1320,7 @@ namespace DX9 { buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, fb_format); return true; } - - LPDIRECT3DSURFACE9 renderTarget = vfb->fbo_dx9 ? fbo_get_color_for_read(vfb->fbo_dx9) : nullptr; + LPDIRECT3DSURFACE9 renderTarget = vfb->fbo_dx9 ? (LPDIRECT3DSURFACE9)fbo_get_api_texture(vfb->fbo_dx9, FB_COLOR_BIT | FB_SURFACE_BIT, 0) : nullptr; bool success = false; if (renderTarget) { FBO_DX9 *tempFBO = nullptr; @@ -1333,7 +1332,7 @@ namespace DX9 { h = vfb->height * maxRes; tempFBO = fbo_create(w, h, 1, false); if (SUCCEEDED(fbo_blit(vfb->fbo_dx9, 0, 0, vfb->renderWidth, vfb->renderHeight, tempFBO, 0, 0, w, h, FB_COLOR_BIT, g_Config.iBufFilter == SCALE_LINEAR ? FB_BLIT_LINEAR : FB_BLIT_NEAREST))) { - renderTarget = fbo_get_color_for_read(tempFBO); + renderTarget = (LPDIRECT3DSURFACE9)fbo_get_api_texture(tempFBO, FB_COLOR_BIT | FB_SURFACE_BIT, 0); } } @@ -1412,7 +1411,7 @@ namespace DX9 { } bool success = false; - LPDIRECT3DTEXTURE9 tex = fbo_get_depth_texture(vfb->fbo_dx9); + LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)fbo_get_api_texture(vfb->fbo_dx9, FB_DEPTH_BIT, 0); if (tex) { D3DSURFACE_DESC desc; D3DLOCKED_RECT locked; @@ -1456,7 +1455,7 @@ namespace DX9 { } bool success = false; - LPDIRECT3DTEXTURE9 tex = fbo_get_depth_texture(vfb->fbo_dx9); + LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)fbo_get_api_texture(vfb->fbo_dx9, FB_DEPTH_BIT, 0); if (tex) { D3DSURFACE_DESC desc; D3DLOCKED_RECT locked; diff --git a/GPU/Directx9/helper/dx_fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp index a633810473..4407c97a05 100644 --- a/GPU/Directx9/helper/dx_fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -134,13 +134,28 @@ void fbo_bind_as_render_target(FBO_DX9 *fbo) { dxstate.viewport.restore(); } - -LPDIRECT3DTEXTURE9 fbo_get_color_texture(FBO_DX9 *fbo) { - return fbo->tex; -} - -LPDIRECT3DTEXTURE9 fbo_get_depth_texture(FBO_DX9 *fbo) { - return fbo->depthstenciltex; +uintptr_t fbo_get_api_texture(FBO_DX9 *fbo, int channelBits, int attachment) { + if (channelBits & FB_SURFACE_BIT) { + switch (channelBits & 7) { + case FB_DEPTH_BIT: + return (uintptr_t)fbo->depthstencil; + case FB_STENCIL_BIT: + return (uintptr_t)fbo->depthstencil; + case FB_COLOR_BIT: + default: + return (uintptr_t)fbo->surf; + } + } else { + switch (channelBits & 7) { + case FB_DEPTH_BIT: + return (uintptr_t)fbo->depthstenciltex; + case FB_STENCIL_BIT: + return 0; // Can't texture from stencil + case FB_COLOR_BIT: + default: + return (uintptr_t)fbo->tex; + } + } } LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo) { diff --git a/GPU/Directx9/helper/dx_fbo.h b/GPU/Directx9/helper/dx_fbo.h index 8772495e84..3abf73d814 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -36,6 +36,8 @@ enum FBOChannel { FB_COLOR_BIT = 1, FB_DEPTH_BIT = 2, FB_STENCIL_BIT = 4, + + FB_SURFACE_BIT = 32, }; enum FBBlitFilter { @@ -59,13 +61,12 @@ bool fbo_blit(FBO_DX9 *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO_DX9 void fbo_bind_as_render_target(FBO_DX9 *fbo); // color must be 0. void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color); -LPDIRECT3DSURFACE9 fbo_get_color_for_read(FBO_DX9 *fbo); void fbo_bind_backbuffer_as_render_target(); void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h); void fbo_resolve(FBO_DX9 *fbo); -LPDIRECT3DTEXTURE9 fbo_get_color_texture(FBO_DX9 *fbo); -LPDIRECT3DTEXTURE9 fbo_get_depth_texture(FBO_DX9 *fbo); +// Escape route until we complete the API +uintptr_t fbo_get_api_texture(FBO_DX9 *fbo, int channelBits, int attachment); // To get default depth and rt surface void fbo_init(LPDIRECT3D9 d3d); diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index f31700be38..f96592eff2 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -381,6 +381,11 @@ void fbo_blit(FBO *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO *dst, in } } +uintptr_t fbo_get_api_texture(FBO *fbo, FBOChannel channelBit, int attachment) { + // Unimplemented + return 0; +} + void fbo_bind_as_texture(FBO *fbo, int binding, FBOChannel channelBit, int color) { // glActiveTexture(GL_TEXTURE0 + binding); switch (channelBit) { diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index 25bb83a924..b339c6798b 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -66,5 +66,6 @@ void fbo_bind_as_texture(FBO *fbo, int binding, FBOChannel channelBit, int attac void fbo_bind_for_read(FBO *fbo); void fbo_bind_backbuffer_as_render_target(); +uintptr_t fbo_get_api_texture(FBO *fbo, FBOChannel channelBit, int attachment); void fbo_get_dimensions(FBO *fbo, int *w, int *h); From 1a149ba02da3f9db803b4a7f6c48d9d47f9dee16 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 4 Feb 2017 17:44:31 +0100 Subject: [PATCH 9/9] Final tweak to the cleaned up FBO api before moving it to thin3d. Buildfixes. --- GPU/Directx9/FramebufferDX9.cpp | 10 ++--- GPU/Directx9/helper/dx_fbo.cpp | 9 ++--- GPU/Directx9/helper/dx_fbo.h | 10 ++++- GPU/GLES/FBO.cpp | 60 ++++++++++++---------------- GPU/GLES/FBO.h | 11 ++++- GPU/GLES/FramebufferManagerGLES.cpp | 10 ++--- Qt/Debugger/debugger_displaylist.cpp | 2 +- 7 files changed, 60 insertions(+), 52 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 6260021d65..f83310d862 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -356,7 +356,7 @@ namespace DX9 { return; } - vfb->fbo_dx9 = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, (FBOColorDepth)vfb->colorDepth); + vfb->fbo_dx9 = fbo_create({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (FBOColorDepth)vfb->colorDepth }); if (old.fbo_dx9) { INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); if (vfb->fbo) { @@ -610,7 +610,7 @@ namespace DX9 { } textureCache_->ForgetLastTexture(); - FBO_DX9 *fbo = fbo_create(w, h, 1, false, depth); + FBO_DX9 *fbo = fbo_create({ w, h, 1, 1, false, depth }); if (!fbo) return fbo; fbo_bind_as_render_target(fbo); @@ -934,7 +934,7 @@ namespace DX9 { bool FramebufferManagerDX9::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) { nvfb->colorDepth = FBO_8888; - nvfb->fbo_dx9 = fbo_create(nvfb->width, nvfb->height, 1, true, (FBOColorDepth)nvfb->colorDepth); + nvfb->fbo_dx9 = fbo_create({ nvfb->width, nvfb->height, 1, 1, true, (FBOColorDepth)nvfb->colorDepth }); if (!(nvfb->fbo_dx9)) { ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", nvfb->renderWidth, nvfb->renderHeight); return false; @@ -1330,8 +1330,8 @@ namespace DX9 { // Let's resize. We must stretch to a render target first. w = vfb->width * maxRes; h = vfb->height * maxRes; - tempFBO = fbo_create(w, h, 1, false); - if (SUCCEEDED(fbo_blit(vfb->fbo_dx9, 0, 0, vfb->renderWidth, vfb->renderHeight, tempFBO, 0, 0, w, h, FB_COLOR_BIT, g_Config.iBufFilter == SCALE_LINEAR ? FB_BLIT_LINEAR : FB_BLIT_NEAREST))) { + tempFBO = fbo_create({ w, h, 1, 1, false, FBO_8888 }); + if (fbo_blit(vfb->fbo_dx9, 0, 0, vfb->renderWidth, vfb->renderHeight, tempFBO, 0, 0, w, h, FB_COLOR_BIT, g_Config.iBufFilter == SCALE_LINEAR ? FB_BLIT_LINEAR : FB_BLIT_NEAREST)) { renderTarget = (LPDIRECT3DSURFACE9)fbo_get_api_texture(tempFBO, FB_COLOR_BIT | FB_SURFACE_BIT, 0); } } diff --git a/GPU/Directx9/helper/dx_fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp index 4407c97a05..b39b4749c0 100644 --- a/GPU/Directx9/helper/dx_fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -66,13 +66,13 @@ void fbo_shutdown() { deviceDSsurf->Release(); } -FBO_DX9 *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { +FBO_DX9 *fbo_create(const FramebufferDesc &desc) { static uint32_t id = 0; FBO_DX9 *fbo = new FBO_DX9(); - fbo->width = width; - fbo->height = height; - fbo->colorDepth = colorDepth; + fbo->width = desc.width; + fbo->height = desc.height; + fbo->colorDepth = desc.colorDepth; fbo->depthstenciltex = nullptr; HRESULT rtResult = pD3Ddevice->CreateTexture(fbo->width, fbo->height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, NULL); @@ -102,7 +102,6 @@ FBO_DX9 *fbo_create(int width, int height, int num_color_textures, bool z_stenci delete fbo; return NULL; } - fbo->id = id++; return fbo; } diff --git a/GPU/Directx9/helper/dx_fbo.h b/GPU/Directx9/helper/dx_fbo.h index 3abf73d814..f75e3fcd96 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -45,6 +45,14 @@ enum FBBlitFilter { FB_BLIT_LINEAR = 1, }; +struct FramebufferDesc { + int width; + int height; + int depth; + int numColorAttachments; + bool z_stencil; + FBOColorDepth colorDepth; +}; // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and // optionally an accompanying Z/stencil buffer. // No mipmap support. @@ -52,7 +60,7 @@ enum FBBlitFilter { // you lose bound texture state. // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. -FBO_DX9 *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); +FBO_DX9 *fbo_create(const FramebufferDesc &desc); void fbo_destroy(FBO_DX9 *fbo); bool fbo_blit(FBO_DX9 *src, int srcX1, int srcY1, int srcX2, int srcY2, FBO_DX9 *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter); diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp index f96592eff2..05fd8f3835 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -37,7 +37,6 @@ struct FBO { int width; int height; FBOColorDepth colorDepth; - bool native_fbo; }; static GLuint currentDrawHandle_ = 0; @@ -47,12 +46,11 @@ static GLuint currentReadHandle_ = 0; // On Android, we try to use what's available. #ifndef USING_GLES2 -FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { +FBO *fbo_ext_create(const FramebufferDesc &desc) { FBO *fbo = new FBO(); - fbo->native_fbo = false; - fbo->width = width; - fbo->height = height; - fbo->colorDepth = colorDepth; + fbo->width = desc.width; + fbo->height = desc.height; + fbo->colorDepth = desc.colorDepth; // Color texture is same everywhere glGenFramebuffersEXT(1, &fbo->handle); @@ -66,18 +64,18 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (colorDepth) { + switch (fbo->colorDepth) { case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); break; case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); break; case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); break; case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->width, fbo->height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); break; } @@ -91,7 +89,7 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci // 24-bit Z, 8-bit stencil glGenRenderbuffersEXT(1, &fbo->z_stencil_buffer); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, width, height); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, fbo->width, fbo->height); //glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8, width, height); // Bind it all together @@ -137,12 +135,12 @@ int fbo_preferred_z_bitdepth() { } } -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { +FBO *fbo_create(const FramebufferDesc &desc) { CheckGLExtensions(); #ifndef USING_GLES2 if (!gl_extensions.ARB_framebuffer_object && gl_extensions.EXT_framebuffer_object) { - return fbo_ext_create(width, height, num_color_textures, z_stencil, colorDepth); + return fbo_ext_create(desc); } else if (!gl_extensions.ARB_framebuffer_object) { return nullptr; } @@ -150,10 +148,9 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F #endif FBO *fbo = new FBO(); - fbo->native_fbo = false; - fbo->width = width; - fbo->height = height; - fbo->colorDepth = colorDepth; + fbo->width = desc.width; + fbo->height = desc.height; + fbo->colorDepth = desc.colorDepth; // Color texture is same everywhere glGenFramebuffers(1, &fbo->handle); @@ -167,18 +164,18 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // TODO: We could opt to only create 16-bit render targets on slow devices. For later. - switch (colorDepth) { + switch (fbo->colorDepth) { case FBO_8888: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); break; case FBO_4444: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, NULL); break; case FBO_5551: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fbo->width, fbo->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, NULL); break; case FBO_565: - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->width, fbo->height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); break; } @@ -189,14 +186,14 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F if (gl_extensions.IsGLES) { if (gl_extensions.OES_packed_depth_stencil) { - ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, height); + ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", fbo->width, fbo->height); // Standard method fbo->stencil_buffer = 0; fbo->z_buffer = 0; // 24-bit Z, 8-bit stencil combined glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, fbo->width, fbo->height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); @@ -204,19 +201,19 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); } else { - ILOG("Creating %i x %i FBO using separate stencil", width, height); + ILOG("Creating %i x %i FBO using separate stencil", fbo->width, fbo->height); // TEGRA fbo->z_stencil_buffer = 0; // 16/24-bit Z, separate 8-bit stencil glGenRenderbuffers(1, &fbo->z_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_buffer); // Don't forget to make sure fbo_standard_z_depth() matches. - glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, fbo->width, fbo->height); // 8-bit stencil buffer glGenRenderbuffers(1, &fbo->stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, fbo->width, fbo->height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); @@ -230,7 +227,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // 24-bit Z, 8-bit stencil glGenRenderbuffers(1, &fbo->z_stencil_buffer); glBindRenderbuffer(GL_RENDERBUFFER, fbo->z_stencil_buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, fbo->width, fbo->height); // Bind it all together glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); @@ -399,11 +396,6 @@ void fbo_bind_as_texture(FBO *fbo, int binding, FBOChannel channelBit, int color } void fbo_destroy(FBO *fbo) { - if (fbo->native_fbo) { - delete fbo; - return; - } - if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); diff --git a/GPU/GLES/FBO.h b/GPU/GLES/FBO.h index b339c6798b..1d21798dd0 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -44,6 +44,15 @@ enum FBBlitFilter { FB_BLIT_LINEAR = 1, }; +struct FramebufferDesc { + int width; + int height; + int depth; + int numColorAttachments; + bool z_stencil; + FBOColorDepth colorDepth; +}; + // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and // optionally an accompanying Z/stencil buffer. // No mipmap support. @@ -51,7 +60,7 @@ enum FBBlitFilter { // you lose bound texture state. // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. -FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth = FBO_8888); +FBO *fbo_create(const FramebufferDesc &desc); void fbo_destroy(FBO *fbo); void fbo_copy_image(FBO *src, int level, int x, int y, int z, FBO *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 770d06150b..1ff719e6ec 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -121,7 +121,7 @@ void FramebufferManagerGLES::SetNumExtraFBOs(int num) { extraFBOs_.clear(); for (int i = 0; i < num; i++) { // No depth/stencil for post processing - FBO *fbo = fbo_create(renderWidth_, renderHeight_, 1, false, FBO_8888); + FBO *fbo = fbo_create({ (int)renderWidth_, (int)renderHeight_, 1, 1, false, FBO_8888 }); extraFBOs_.push_back(fbo); // The new FBO is still bound after creation, but let's bind it anyway. @@ -612,7 +612,7 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u return; } - vfb->fbo = fbo_create(vfb->renderWidth, vfb->renderHeight, 1, true, (FBOColorDepth)vfb->colorDepth); + vfb->fbo = fbo_create({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (FBOColorDepth)vfb->colorDepth }); if (old.fbo) { INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); if (vfb->fbo) { @@ -801,7 +801,7 @@ FBO *FramebufferManagerGLES::GetTempFBO(u16 w, u16 h, FBOColorDepth depth) { } textureCache_->ForgetLastTexture(); - FBO *fbo = fbo_create(w, h, 1, false, depth); + FBO *fbo = fbo_create({ w, h, 1, 1, false, depth }); if (!fbo) return fbo; fbo_bind_as_render_target(fbo); @@ -1211,8 +1211,8 @@ bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) } } - nvfb->fbo = fbo_create(nvfb->width, nvfb->height, 1, false, (FBOColorDepth)nvfb->colorDepth); - if (!(nvfb->fbo)) { + nvfb->fbo = fbo_create({ nvfb->width, nvfb->height, 1, 1, false, (FBOColorDepth)nvfb->colorDepth }); + if (!nvfb->fbo) { ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", nvfb->renderWidth, nvfb->renderHeight); return false; } diff --git a/Qt/Debugger/debugger_displaylist.cpp b/Qt/Debugger/debugger_displaylist.cpp index 6dfb9847aa..36fc859c3b 100644 --- a/Qt/Debugger/debugger_displaylist.cpp +++ b/Qt/Debugger/debugger_displaylist.cpp @@ -1353,7 +1353,7 @@ void Debugger_DisplayList::UpdateRenderBufferGUI() memset(data,0,FRAME_WIDTH * FRAME_HEIGHT * 4); if(currentRenderFrameDisplay == 0) { - fbo_bind_color_as_texture(currentTextureDisplay,0); + fbo_bind_as_texture(currentTextureDisplay, 0, FB_COLOR_BIT, 0); glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); } }