diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index f930a3a73f..f83310d862 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) { @@ -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) { @@ -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,10 +557,10 @@ 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); + 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; @@ -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); @@ -700,19 +700,19 @@ 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); } } void FramebufferManagerDX9::CopyDisplayToOutput() { DownloadFramebufferOnSwitch(currentRenderVfb_); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; if (displayFramebufPtr_ == 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; @@ -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) { @@ -843,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); } } /* @@ -931,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; @@ -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; } @@ -975,31 +978,22 @@ 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); - 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); - // 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 +1052,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; } @@ -1069,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); @@ -1108,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; @@ -1206,7 +1200,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 +1259,7 @@ namespace DX9 { } void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) { - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1326,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; @@ -1337,12 +1330,9 @@ 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))) { - renderTarget = fbo_get_color_for_read(tempFBO); + 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); } } @@ -1359,7 +1349,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); @@ -1421,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; @@ -1465,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/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index c2f56547a1..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_color_as_texture(depalFBO, 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 bd59e5c01f..b39b4749c0 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 @@ -64,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); @@ -100,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; } @@ -115,7 +116,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(); @@ -132,30 +133,47 @@ 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) { return fbo->surf; } -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, int binding, FBOChannel channelBit, int color) { + switch (channelBit) { + case FB_DEPTH_BIT: + if (fbo->depthstenciltex) { + pD3Ddevice->SetTexture(binding, fbo->depthstenciltex); + } + break; + case FB_COLOR_BIT: + default: + if (fbo->tex) { + pD3Ddevice->SetTexture(binding, fbo->tex); + } + break; } } @@ -164,10 +182,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..f75e3fcd96 100644 --- a/GPU/Directx9/helper/dx_fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -32,6 +32,27 @@ enum FBOColorDepth { FBO_5551, }; +enum FBOChannel { + FB_COLOR_BIT = 1, + FB_DEPTH_BIT = 2, + FB_STENCIL_BIT = 4, + + FB_SURFACE_BIT = 32, +}; + +enum FBBlitFilter { + FB_BLIT_NEAREST = 0, + 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. @@ -39,23 +60,21 @@ enum FBOColorDepth { // 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); // 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); -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); +// color must be 0. +void fbo_bind_as_texture(FBO_DX9 *fbo, int binding, FBOChannel channelBit, int color); +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); +// 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 47ff42a06b..05fd8f3835 100644 --- a/GPU/GLES/FBO.cpp +++ b/GPU/GLES/FBO.cpp @@ -37,11 +37,8 @@ struct FBO { int width; int height; FBOColorDepth colorDepth; - bool native_fbo; }; -static FBO *g_overriddenBackbuffer; - static GLuint currentDrawHandle_ = 0; static GLuint currentReadHandle_ = 0; @@ -49,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); @@ -68,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; } @@ -93,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 @@ -127,23 +123,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) { @@ -155,12 +135,12 @@ int fbo_standard_z_depth() { } } -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; } @@ -168,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); @@ -185,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; } @@ -207,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); @@ -222,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); @@ -248,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); @@ -258,7 +237,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; @@ -281,24 +260,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) { @@ -323,7 +284,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); @@ -336,13 +296,7 @@ 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(); +static void fbo_unbind() { #ifndef USING_GLES2 if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { glBindFramebuffer(GL_FRAMEBUFFER, 0); @@ -361,10 +315,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. @@ -373,7 +323,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(); } @@ -382,22 +332,70 @@ 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 + glCopyImageSubDataOES( + 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( + 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( + 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 } -void fbo_bind_color_as_texture(FBO *fbo, int color) { - if (fbo) { - glBindTexture(GL_TEXTURE_2D, fbo->color_texture); +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__) + } +} + +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) { + case FB_COLOR_BIT: + default: + if (fbo) { + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + } + break; } } 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); @@ -429,15 +427,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 5548923f35..1d21798dd0 100644 --- a/GPU/GLES/FBO.h +++ b/GPU/GLES/FBO.h @@ -33,6 +33,25 @@ 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, +}; + +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. @@ -41,28 +60,21 @@ enum FBOColorDepth { // 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); -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); +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); -// 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_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, int binding, FBOChannel channelBit, int attachment); 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_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); - -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..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. @@ -130,7 +130,7 @@ void FramebufferManagerGLES::SetNumExtraFBOs(int num) { } currentRenderVfb_ = 0; - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); } void FramebufferManagerGLES::CompileDraw2DProgram() { @@ -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, @@ -551,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(); @@ -601,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) { @@ -611,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) { @@ -634,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; } @@ -664,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) { @@ -673,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) { @@ -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(); } } @@ -812,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); @@ -873,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, 0, FB_COLOR_BIT, 0); } else { - fbo_bind_color_as_texture(framebuffer->fbo, 0); + fbo_bind_as_texture(framebuffer->fbo, 0, FB_COLOR_BIT, 0); } } else { - fbo_bind_color_as_texture(framebuffer->fbo, 0); + fbo_bind_as_texture(framebuffer->fbo, 0, FB_COLOR_BIT, 0); } if (stage != GL_TEXTURE0) { @@ -916,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) { @@ -1025,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_as_texture(vfb->fbo, 0, FB_COLOR_BIT, 0); int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; @@ -1047,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. @@ -1066,17 +1055,17 @@ 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(); + 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; } - colorTexture = fbo_get_color_texture(extraFBOs_[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. @@ -1085,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) { @@ -1112,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); } } @@ -1222,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; } @@ -1251,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; } @@ -1296,49 +1285,17 @@ 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_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_unbind_read(); + fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST); } else { - fbo_bind_color_as_texture(src->fbo, 0); + fbo_bind_as_render_target(dst->fbo); + 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(); @@ -1621,16 +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; - } - - GLenum fbStatus; - fbStatus = (GLenum)fbo_check_framebuffer_status(vfb->fbo); - - if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { - ERROR_LOG(SCEGE, "Incomplete source framebuffer, aborting read"); - fbo_unbind_read(); return; } @@ -1652,7 +1599,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; @@ -1675,7 +1621,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; } @@ -1735,8 +1680,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) { @@ -1778,8 +1721,6 @@ void FramebufferManagerGLES::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int depth[i] = (int)scaled; } } - - fbo_unbind_read(); } void FramebufferManagerGLES::EndFrame() { @@ -1850,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(); } } @@ -1880,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) { @@ -1927,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; @@ -1951,7 +1892,7 @@ void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) { } tempFBOs_.clear(); - fbo_unbind(); + fbo_bind_backbuffer_as_render_target(); DisableState(); } @@ -2011,14 +1952,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; 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/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/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 6f4bbef660..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_color_as_texture(depalFBO, 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/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; 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); } } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 882d9bbc48..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" @@ -1028,9 +1027,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();