Work towards unifying the GL and DX FBO APIs

This commit is contained in:
Henrik Rydgard 2017-02-04 16:19:54 +01:00 committed by Henrik Rydgård
parent 089fa4f5a7
commit daee5c24e5
10 changed files with 117 additions and 135 deletions

View File

@ -298,7 +298,7 @@ namespace DX9 {
if (currentRenderVfb_ && currentRenderVfb_->fbo_dx9) { if (currentRenderVfb_ && currentRenderVfb_->fbo_dx9) {
fbo_bind_as_render_target(currentRenderVfb_->fbo_dx9); fbo_bind_as_render_target(currentRenderVfb_->fbo_dx9);
} else { } else {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
} }
@ -346,7 +346,7 @@ namespace DX9 {
} }
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
if (!useBufferedRendering_) { if (!useBufferedRendering_) {
if (vfb->fbo_dx9) { if (vfb->fbo_dx9) {
@ -379,7 +379,7 @@ namespace DX9 {
void FramebufferManagerDX9::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { void FramebufferManagerDX9::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) { if (!useBufferedRendering_) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
// Let's ignore rendering to targets that have not (yet) been displayed. // Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
} }
@ -411,7 +411,7 @@ namespace DX9 {
fbo_bind_as_render_target(vfb->fbo_dx9); fbo_bind_as_render_target(vfb->fbo_dx9);
} else { } else {
// wtf? This should only happen very briefly when toggling bBufferedRendering // wtf? This should only happen very briefly when toggling bBufferedRendering
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
} else { } else {
if (vfb->fbo_dx9) { if (vfb->fbo_dx9) {
@ -420,7 +420,7 @@ namespace DX9 {
fbo_destroy(vfb->fbo_dx9); fbo_destroy(vfb->fbo_dx9);
vfb->fbo_dx9 = nullptr; vfb->fbo_dx9 = nullptr;
} }
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
// Let's ignore rendering to targets that have not (yet) been displayed. // Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
@ -557,7 +557,7 @@ namespace DX9 {
bool matchingSize = src->width == dst->width && src->height == dst->height; bool matchingSize = src->width == dst->width && src->height == dst->height;
if (matchingDepthBuffer && matchingSize) { if (matchingDepthBuffer && matchingSize) {
// Doesn't work. Use a shader maybe? // 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 srcTex = fbo_get_depth_texture(src->fbo_dx9);
LPDIRECT3DTEXTURE9 dstTex = fbo_get_depth_texture(dst->fbo_dx9); LPDIRECT3DTEXTURE9 dstTex = fbo_get_depth_texture(dst->fbo_dx9);
@ -712,7 +712,7 @@ namespace DX9 {
void FramebufferManagerDX9::CopyDisplayToOutput() { void FramebufferManagerDX9::CopyDisplayToOutput() {
DownloadFramebufferOnSwitch(currentRenderVfb_); DownloadFramebufferOnSwitch(currentRenderVfb_);
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
if (displayFramebufPtr_ == 0) { if (displayFramebufPtr_ == 0) {
@ -827,11 +827,14 @@ namespace DX9 {
if (1) { if (1) {
const u32 rw = PSP_CoreParameter().pixelWidth; const u32 rw = PSP_CoreParameter().pixelWidth;
const u32 rh = PSP_CoreParameter().pixelHeight; 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)}; bool result = fbo_blit(vfb->fbo_dx9,
const RECT dstRect = {(LONG)(x * rw / w), (LONG)(y * rh / h), (LONG)((x + w) * rw / w), (LONG)((y + h) * rh / h)}; (LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight),
HRESULT hr = fbo_blit_color(vfb->fbo_dx9, &srcRect, nullptr, &dstRect, g_Config.iBufFilter == SCALE_LINEAR ? D3DTEXF_LINEAR : D3DTEXF_POINT); nullptr,
if (FAILED(hr)) { (LONG)(x * rw / w), (LONG)(y * rh / h), (LONG)((x + w) * rw / w), (LONG)((y + h) * rh / h),
ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display: %08x", hr); 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); DXSetViewport(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
// These are in the output display coordinates // These are in the output display coordinates
if (g_Config.iBufFilter == SCALE_LINEAR) { 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) { 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_) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
// This can happen if they recently switched from non-buffered. // This can happen if they recently switched from non-buffered.
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
return; return;
} }
@ -977,29 +980,31 @@ namespace DX9 {
LPDIRECT3DSURFACE9 srcSurf = fbo_get_color_for_read(src->fbo_dx9); LPDIRECT3DSURFACE9 srcSurf = fbo_get_color_for_read(src->fbo_dx9);
LPDIRECT3DSURFACE9 dstSurf = fbo_get_color_for_write(dst->fbo_dx9); LPDIRECT3DSURFACE9 dstSurf = fbo_get_color_for_write(dst->fbo_dx9);
RECT srcRect = {srcX1, srcY1, srcX2, srcY2}; D3DSURFACE_DESC srcDesc;
RECT dstRect = {dstX1, dstY1, dstX2, dstY2}; D3DSURFACE_DESC dstDesc;
srcSurf->GetDesc(&srcDesc);
D3DSURFACE_DESC desc; dstSurf->GetDesc(&dstDesc);
srcSurf->GetDesc(&desc); srcX2 = std::min(srcX2, (int)srcDesc.Width);
srcRect.right = std::min(srcRect.right, (LONG)desc.Width); srcY2 = std::min(srcY2, (int)srcDesc.Height);
srcRect.bottom = std::min(srcRect.bottom, (LONG)desc.Height); dstX2 = std::min(dstX2, (int)dstDesc.Width);
dstY2 = std::min(dstY2, (int)dstDesc.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. // Direct3D 9 doesn't support rect -> self.
FBO_DX9 *srcFBO = src->fbo_dx9; FBO_DX9 *srcFBO = src->fbo_dx9;
if (src == dst) { if (src == dst) {
FBO_DX9 *tempFBO = GetTempFBO(src->renderWidth, src->renderHeight, (FBOColorDepth)src->colorDepth); 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)) { if (SUCCEEDED(hr)) {
srcFBO = tempFBO; srcFBO = tempFBO;
} }
} }
HRESULT hr = fbo_blit(
HRESULT hr = fbo_blit_color(srcFBO, &srcRect, dst->fbo_dx9, &dstRect, D3DTEXF_POINT); srcFBO, srcX1, srcY1, srcX2, srcY2,
dst->fbo_dx9, dstX1, dstY1, dstX2, dstY2,
FB_COLOR_BIT, FB_BLIT_NEAREST);
if (FAILED(hr)) { if (FAILED(hr)) {
ERROR_LOG_REPORT(G3D, "fbo_blit_color failed in blit: %08x (%08x -> %08x)", hr, src->fb_address, dst->fb_address); 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) { void FramebufferManagerDX9::PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
if (!vfb->fbo) { if (!vfb->fbo) {
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferDirectx9_: vfb->fbo == 0"); ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferDirectx9_: vfb->fbo == 0");
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
return; return;
} }
@ -1206,7 +1211,7 @@ namespace DX9 {
void FramebufferManagerDX9::DecimateFBOs() { void FramebufferManagerDX9::DecimateFBOs() {
if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) { if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
bool updateVram = !(g_Config.iRenderingMode == FB_NON_BUFFERED_MODE || g_Config.iRenderingMode == FB_BUFFERED_MODE); 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) { void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
displayFramebuf_ = 0; displayFramebuf_ = 0;
prevDisplayFramebuf_ = 0; prevDisplayFramebuf_ = 0;
@ -1337,11 +1342,8 @@ namespace DX9 {
// Let's resize. We must stretch to a render target first. // Let's resize. We must stretch to a render target first.
w = vfb->width * maxRes; w = vfb->width * maxRes;
h = vfb->height * maxRes; h = vfb->height * maxRes;
tempFBO = fbo_create(w, h, 1, false); tempFBO = fbo_create(w, h, 1, false);
RECT srcRect = {0, 0, vfb->renderWidth, vfb->renderHeight}; 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))) {
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); renderTarget = fbo_get_color_for_read(tempFBO);
} }
} }
@ -1359,7 +1361,7 @@ namespace DX9 {
} }
bool FramebufferManagerDX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { bool FramebufferManagerDX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
LPDIRECT3DSURFACE9 renderTarget = nullptr; LPDIRECT3DSURFACE9 renderTarget = nullptr;
HRESULT hr = pD3Ddevice->GetRenderTarget(0, &renderTarget); HRESULT hr = pD3Ddevice->GetRenderTarget(0, &renderTarget);

View File

@ -787,7 +787,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
shaderApply.Shade(); 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 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;

View File

@ -115,7 +115,7 @@ void fbo_destroy(FBO_DX9 *fbo) {
delete fbo; delete fbo;
} }
void fbo_unbind() { void fbo_bind_backbuffer_as_render_target() {
pD3Ddevice->SetRenderTarget(0, deviceRTsurf); pD3Ddevice->SetRenderTarget(0, deviceRTsurf);
pD3Ddevice->SetDepthStencilSurface(deviceDSsurf); pD3Ddevice->SetDepthStencilSurface(deviceDSsurf);
dxstate.scissorRect.restore(); dxstate.scissorRect.restore();
@ -149,13 +149,19 @@ LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo) {
return fbo->surf; return fbo->surf;
} }
void fbo_bind_color_as_texture(FBO_DX9 *fbo, int color) { void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, int color) {
pD3Ddevice->SetTexture(0, fbo->tex); switch (channelBit) {
} case FB_DEPTH_BIT:
if (fbo->depthstenciltex) {
void fbo_bind_depth_as_texture(FBO_DX9 *fbo) { pD3Ddevice->SetTexture(0, fbo->depthstenciltex);
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; *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 srcSurf = src ? src->surf : deviceRTsurf;
LPDIRECT3DSURFACE9 dstSurf = dst ? dst->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

View File

@ -32,6 +32,17 @@ enum FBOColorDepth {
FBO_5551, 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 // Creates a simple FBO with a RGBA32 color buffer stored in a texture, and
// optionally an accompanying Z/stencil buffer. // optionally an accompanying Z/stencil buffer.
// No mipmap support. // 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. // 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(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. // These functions should be self explanatory.
void fbo_bind_as_render_target(FBO_DX9 *fbo); void fbo_bind_as_render_target(FBO_DX9 *fbo);
// color must be 0, for now. // color must be 0.
void fbo_bind_color_as_texture(FBO_DX9 *fbo, int color); void fbo_bind_as_texture(FBO_DX9 *fbo, FBOChannel channelBit, 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_read(FBO_DX9 *fbo);
LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo); LPDIRECT3DSURFACE9 fbo_get_color_for_write(FBO_DX9 *fbo);
void fbo_unbind(); void fbo_bind_backbuffer_as_render_target();
void fbo_destroy(FBO_DX9 *fbo);
void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h); void fbo_get_dimensions(FBO_DX9 *fbo, int *w, int *h);
void fbo_resolve(FBO_DX9 *fbo); 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_color_texture(FBO_DX9 *fbo);
LPDIRECT3DTEXTURE9 fbo_get_depth_texture(FBO_DX9 *fbo); LPDIRECT3DTEXTURE9 fbo_get_depth_texture(FBO_DX9 *fbo);

View File

@ -125,23 +125,7 @@ FBO *fbo_ext_create(int width, int height, int num_color_textures, bool z_stenci
} }
#endif #endif
int fbo_check_framebuffer_status(FBO *fbo) { int fbo_preferred_z_bitdepth() {
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() {
// This matches the fbo_create() logic. // This matches the fbo_create() logic.
if (gl_extensions.IsGLES) { if (gl_extensions.IsGLES) {
if (gl_extensions.OES_packed_depth_stencil) { 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); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) { switch (status) {
case GL_FRAMEBUFFER_COMPLETE: case GL_FRAMEBUFFER_COMPLETE:
// ILOG("Framebuffer verified complete."); // ILOG("Framebuffer verified complete.");
break; break;
@ -279,24 +263,6 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F
return fbo; 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) { static GLenum fbo_get_fb_target(bool read, GLuint **cached) {
bool supportsBlit = gl_extensions.ARB_framebuffer_object; bool supportsBlit = gl_extensions.ARB_framebuffer_object;
if (gl_extensions.IsGLES) { 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 #ifndef USING_GLES2
if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) { if (gl_extensions.ARB_framebuffer_object || gl_extensions.IsGLES) {
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
@ -360,7 +326,7 @@ void fbo_bind_as_render_target(FBO *fbo) {
glstate.viewport.restore(); glstate.viewport.restore();
} }
void fbo_unbind_render_target() { void fbo_bind_backbuffer_as_render_target() {
fbo_unbind(); 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) { void fbo_bind_as_texture(FBO *fbo, FBOChannel channelBit, int color) {
if (fbo) { switch (channelBit) {
glBindTexture(GL_TEXTURE_2D, fbo->color_texture); case FB_COLOR_BIT:
default:
if (fbo) {
glBindTexture(GL_TEXTURE_2D, fbo->color_texture);
}
break;
} }
} }

View File

@ -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. // 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(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_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); 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_preferred_z_bitdepth();
int fbo_check_framebuffer_status(FBO *fbo);
// These functions should be self explanatory. // These functions should be self explanatory.
void fbo_bind_as_render_target(FBO *fbo); void fbo_bind_as_render_target(FBO *fbo);
// color must be 0, for now. // 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_bind_for_read(FBO *fbo);
void fbo_unbind();
void fbo_unbind_render_target(); void fbo_bind_backbuffer_as_render_target();
void fbo_destroy(FBO *fbo);
void fbo_get_dimensions(FBO *fbo, int *w, int *h); void fbo_get_dimensions(FBO *fbo, int *w, int *h);

View File

@ -130,7 +130,7 @@ void FramebufferManagerGLES::SetNumExtraFBOs(int num) {
} }
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
void FramebufferManagerGLES::CompileDraw2DProgram() { void FramebufferManagerGLES::CompileDraw2DProgram() {
@ -552,7 +552,7 @@ void FramebufferManagerGLES::RebindFramebuffer() {
if (currentRenderVfb_ && currentRenderVfb_->fbo) { if (currentRenderVfb_ && currentRenderVfb_->fbo) {
fbo_bind_as_render_target(currentRenderVfb_->fbo); fbo_bind_as_render_target(currentRenderVfb_->fbo);
} else { } else {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE)
glstate.viewport.restore(); glstate.viewport.restore();
@ -602,7 +602,7 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u
} }
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
if (!useBufferedRendering_) { if (!useBufferedRendering_) {
if (vfb->fbo) { if (vfb->fbo) {
@ -635,7 +635,7 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u
void FramebufferManagerGLES::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { void FramebufferManagerGLES::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
if (!useBufferedRendering_) { if (!useBufferedRendering_) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
// Let's ignore rendering to targets that have not (yet) been displayed. // Let's ignore rendering to targets that have not (yet) been displayed.
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
} }
@ -665,7 +665,7 @@ void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer
fbo_bind_as_render_target(vfb->fbo); fbo_bind_as_render_target(vfb->fbo);
} else { } else {
// wtf? This should only happen very briefly when toggling bBufferedRendering // wtf? This should only happen very briefly when toggling bBufferedRendering
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
} else { } else {
if (vfb->fbo) { if (vfb->fbo) {
@ -674,7 +674,7 @@ void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer
fbo_destroy(vfb->fbo); fbo_destroy(vfb->fbo);
vfb->fbo = 0; vfb->fbo = 0;
} }
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
// Let's ignore rendering to targets that have not (yet) been displayed. // Let's ignore rendering to targets that have not (yet) been displayed.
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
@ -862,12 +862,12 @@ void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, V
BlitFramebuffer(&copyInfo, x, y, framebuffer, x, y, w, h, 0); BlitFramebuffer(&copyInfo, 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 { } else {
fbo_bind_color_as_texture(framebuffer->fbo, 0); fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0);
} }
} else { } else {
fbo_bind_color_as_texture(framebuffer->fbo, 0); fbo_bind_as_texture(framebuffer->fbo, FB_COLOR_BIT, 0);
} }
if (stage != GL_TEXTURE0) { if (stage != GL_TEXTURE0) {
@ -905,7 +905,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
DownloadFramebufferOnSwitch(currentRenderVfb_); DownloadFramebufferOnSwitch(currentRenderVfb_);
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
if (displayFramebufPtr_ == 0) { if (displayFramebufPtr_ == 0) {
@ -1014,7 +1014,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() {
DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address);
DisableState(); 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; 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_); 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); 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. // 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) { if (extraFBOs_.size() == 0) {
ERROR_LOG(G3D, "WTF?"); ERROR_LOG(G3D, "WTF?");
return; 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 // We are doing the DrawActiveTexture call directly to the backbuffer after here. Hence, we must
// flip V. // 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) { 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_) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
// This can happen if they recently switched from non-buffered. // This can happen if they recently switched from non-buffered.
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
return; 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); fbo_blit(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, FB_COLOR_BIT, FB_BLIT_NEAREST);
} else { } else {
fbo_bind_as_render_target(dst->fbo); 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. // Make sure our 2D drawing program is ready. Compiles only if not already compiled.
CompileDraw2DProgram(); CompileDraw2DProgram();
@ -1581,14 +1581,6 @@ void FramebufferManagerGLES::PackFramebufferAsync_(VirtualFramebuffer *vfb) {
return; 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); glBindBuffer(GL_PIXEL_PACK_BUFFER, pixelBufObj_[currentPBO_].handle);
if (pixelBufObj_[currentPBO_].maxSize < bufSize) { if (pixelBufObj_[currentPBO_].maxSize < bufSize) {
@ -1799,7 +1791,7 @@ void FramebufferManagerGLES::EndFrame() {
GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT };
glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments);
} }
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
} }
} }
@ -1829,7 +1821,7 @@ std::vector<FramebufferInfo> FramebufferManagerGLES::GetFramebufferList() {
} }
void FramebufferManagerGLES::DecimateFBOs() { void FramebufferManagerGLES::DecimateFBOs() {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
for (size_t i = 0; i < vfbs_.size(); ++i) { for (size_t i = 0; i < vfbs_.size(); ++i) {
@ -1876,7 +1868,7 @@ void FramebufferManagerGLES::DecimateFBOs() {
} }
void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) { void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) {
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
displayFramebuf_ = 0; displayFramebuf_ = 0;
prevDisplayFramebuf_ = 0; prevDisplayFramebuf_ = 0;
@ -1900,7 +1892,7 @@ void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) {
} }
tempFBOs_.clear(); tempFBOs_.clear();
fbo_unbind(); fbo_bind_backbuffer_as_render_target();
DisableState(); DisableState();
} }

View File

@ -605,14 +605,14 @@ void GPU_GLES::CheckGPUFeatures() {
features |= GPU_SUPPORTS_TEXTURE_FLOAT; features |= GPU_SUPPORTS_TEXTURE_FLOAT;
// If we already have a 16-bit depth buffer, we don't need to round. // 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) { if (!g_Config.bHighQualityDepth && (features & GPU_SUPPORTS_ACCURATE_DEPTH) != 0) {
features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;
} else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) {
if (!gl_extensions.IsGLES || gl_extensions.GLES3) { if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
// Use fragment rounding on desktop and GLES3, most accurate. // Use fragment rounding on desktop and GLES3, most accurate.
features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; 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. // 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. // 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; features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT;

View File

@ -862,7 +862,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram
shaderApply.Shade(); 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 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor; const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;

View File

@ -1028,9 +1028,6 @@ void EmuScreen::render() {
if (invalid_) if (invalid_)
return; 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) { 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(); DrawContext *thin3d = screenManager()->getDrawContext();