diff --git a/CMakeLists.txt b/CMakeLists.txt index 515761f6d..08c83a569 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -923,8 +923,6 @@ add_library(native STATIC native/gfx_es2/draw_buffer.h native/gfx_es2/draw_text.cpp native/gfx_es2/draw_text.h - native/gfx_es2/fbo.cpp - native/gfx_es2/fbo.h native/gfx_es2/gl_state.cpp native/gfx_es2/gl_state.h native/gfx_es2/gpu_features.cpp @@ -1485,6 +1483,8 @@ add_library(GPU OBJECT GPU/Debugger/Stepping.h GPU/GLES/DepalettizeShader.cpp GPU/GLES/DepalettizeShader.h + GPU/GLES/FBO.cpp + GPU/GLES/FBO.h GPU/GLES/GLES_GPU.cpp GPU/GLES/GLES_GPU.h GPU/GLES/FragmentShaderGenerator.cpp diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 8d1349f74..89d7b930b 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -28,7 +28,7 @@ #include "GPU/Debugger/Stepping.h" #include "helper/dx_state.h" -#include "helper/fbo.h" +#include "helper/dx_fbo.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Common/TextureDecoder.h" diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index cf4199173..f57734083 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -23,7 +23,7 @@ #include "d3d9.h" -#include "GPU/Directx9/helper/fbo.h" +#include "GPU/Directx9/helper/dx_fbo.h" // Keeps track of allocated FBOs. // Also provides facilities for drawing and later converting raw // pixel data. diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 0fc3fb929..bdf5384b9 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -25,7 +25,7 @@ #include "GPU/Directx9/TransformPipelineDX9.h" #include "GPU/Directx9/TextureCacheDX9.h" #include "GPU/Directx9/DepalettizeShaderDX9.h" -#include "GPU/Directx9/helper/fbo.h" +#include "GPU/Directx9/helper/dx_fbo.h" #include "GPU/Common/VertexDecoderCommon.h" namespace DX9 { diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 22e512ef3..11cfa7206 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -18,7 +18,7 @@ #include "base/logging.h" #include "helper/dx_state.h" -#include "helper/fbo.h" +#include "helper/dx_fbo.h" #include "Core/Reporting.h" #include "GPU/Directx9/FramebufferDX9.h" #include "GPU/Directx9/PixelShaderGeneratorDX9.h" diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index eb2563271..f24399de6 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -21,7 +21,7 @@ #include "../Globals.h" #include "helper/global.h" -#include "helper/fbo.h" +#include "helper/dx_fbo.h" #include "GPU/GPU.h" #include "GPU/GPUInterface.h" #include "GPU/Directx9/TextureScalerDX9.h" diff --git a/GPU/Directx9/helper/fbo.cpp b/GPU/Directx9/helper/dx_fbo.cpp similarity index 83% rename from GPU/Directx9/helper/fbo.cpp rename to GPU/Directx9/helper/dx_fbo.cpp index 1edff95ba..87e17c069 100644 --- a/GPU/Directx9/helper/fbo.cpp +++ b/GPU/Directx9/helper/dx_fbo.cpp @@ -1,9 +1,26 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + #include "global.h" #include #include #include #include "base/logging.h" -#include "fbo.h" +#include "dx_fbo.h" #include "dx_state.h" struct FBO { diff --git a/GPU/Directx9/helper/fbo.h b/GPU/Directx9/helper/dx_fbo.h similarity index 66% rename from GPU/Directx9/helper/fbo.h rename to GPU/Directx9/helper/dx_fbo.h index c19d3de1f..4ce156138 100644 --- a/GPU/Directx9/helper/fbo.h +++ b/GPU/Directx9/helper/dx_fbo.h @@ -1,3 +1,20 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + #pragma once // Simple wrapper around FBO functionality. diff --git a/GPU/Directx9/helper/global.cpp b/GPU/Directx9/helper/global.cpp index 1864b31f4..d814cb321 100644 --- a/GPU/Directx9/helper/global.cpp +++ b/GPU/Directx9/helper/global.cpp @@ -1,5 +1,7 @@ -#include "global.h" -#include "fbo.h" + + +#include "GPU/Directx9/helper/global.h" +#include "GPU/Directx9/helper/dx_fbo.h" #include "thin3d/d3dx9_loader.h" #include "Common/CommonFuncs.h" diff --git a/GPU/GLES/FBO.cpp b/GPU/GLES/FBO.cpp new file mode 100644 index 000000000..546572313 --- /dev/null +++ b/GPU/GLES/FBO.cpp @@ -0,0 +1,430 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include + +#include "base/logging.h" +#include "gfx/gl_common.h" +#include "gfx_es2/gl_state.h" + +#include "GPU/GLES/FBO.h" + +#ifdef IOS +extern void bindDefaultFBO(); +#endif + +struct FBO { + GLuint handle; + GLuint color_texture; + GLuint z_stencil_buffer; // Either this is set, or the two below. + GLuint z_buffer; + GLuint stencil_buffer; + + int width; + int height; + FBOColorDepth colorDepth; + bool native_fbo; +}; + +static FBO *g_overriddenBackbuffer; + +static GLuint currentDrawHandle_ = 0; +static GLuint currentReadHandle_ = 0; + +// On PC, we always use GL_DEPTH24_STENCIL8. +// 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 = new FBO(); + fbo->native_fbo = false; + fbo->width = width; + fbo->height = height; + fbo->colorDepth = colorDepth; + + // Color texture is same everywhere + glGenFramebuffersEXT(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + 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) { + case FBO_8888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 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); + break; + case FBO_5551: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 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); + break; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 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_DEPTH24_STENCIL8, width, height); + + // Bind it all together + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->z_stencil_buffer); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE_EXT: + // ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; + return fbo; +} +#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; +} + +FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { + 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); + } else if (!gl_extensions.ARB_framebuffer_object) { + return nullptr; + } + // If GLES2, we have basic FBO support and can just proceed. +#endif + + FBO *fbo = new FBO(); + fbo->native_fbo = false; + fbo->width = width; + fbo->height = height; + fbo->colorDepth = colorDepth; + + // Color texture is same everywhere + glGenFramebuffers(1, &fbo->handle); + glGenTextures(1, &fbo->color_texture); + + // Create the surfaces. + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + 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) { + case FBO_8888: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 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); + break; + case FBO_5551: + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 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); + break; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + if (gl_extensions.IsGLES) { + if (gl_extensions.OES_packed_depth_stencil) { + ILOG("Creating %i x %i FBO using DEPTH24_STENCIL8", width, 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); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + 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); + // 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); + glRenderbufferStorage(GL_RENDERBUFFER, gl_extensions.OES_depth24 ? GL_DEPTH_COMPONENT24 : GL_DEPTH_COMPONENT16, width, height); + + // 8-bit stencil buffer + glGenRenderbuffers(1, &fbo->stencil_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, fbo->stencil_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->stencil_buffer); + } + } else { + fbo->stencil_buffer = 0; + fbo->z_buffer = 0; + // 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); + + // Bind it all together + glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo->color_texture, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbo->z_stencil_buffer); + } + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + switch(status) { + case GL_FRAMEBUFFER_COMPLETE: + // ILOG("Framebuffer verified complete."); + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + ELOG("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + ELOG("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT "); + break; + default: + FLOG("Other framebuffer error: %i", status); + break; + } + // Unbind state we don't need + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + + currentDrawHandle_ = fbo->handle; + currentReadHandle_ = fbo->handle; + 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) { + supportsBlit = (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); + } + + // Note: GL_FRAMEBUFFER_EXT and GL_FRAMEBUFFER have the same value, same with _NV. + if (supportsBlit) { + if (read) { + *cached = ¤tReadHandle_; + return GL_READ_FRAMEBUFFER; + } else { + *cached = ¤tDrawHandle_; + return GL_DRAW_FRAMEBUFFER; + } + } else { + *cached = ¤tDrawHandle_; + return GL_FRAMEBUFFER; + } +} + +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); + } else { +#ifndef USING_GLES2 + glBindFramebufferEXT(target, name); +#endif + } + *cached = 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); + } else if (gl_extensions.EXT_framebuffer_object) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + +#ifdef IOS + bindDefaultFBO(); +#endif + + currentDrawHandle_ = 0; + 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. + fbo_bind_fb_target(false, fbo->handle); + // Always restore viewport after render target binding + glstate.viewport.restore(); +} + +void fbo_unbind_render_target() { + fbo_unbind(); +} + +// For GL_EXT_FRAMEBUFFER_BLIT and similar. +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_bind_color_as_texture(FBO *fbo, int color) { + if (fbo) { + glBindTexture(GL_TEXTURE_2D, fbo->color_texture); + } +} + +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); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &fbo->handle); + glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); + glDeleteRenderbuffers(1, &fbo->z_buffer); + glDeleteRenderbuffers(1, &fbo->stencil_buffer); + } else if (gl_extensions.EXT_framebuffer_object) { +#ifndef USING_GLES2 + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->handle); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER_EXT, 0); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &fbo->handle); + glDeleteRenderbuffersEXT(1, &fbo->z_stencil_buffer); +#endif + } + + currentDrawHandle_ = 0; + currentReadHandle_ = 0; + + glDeleteTextures(1, &fbo->color_texture); + delete fbo; +} + +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 new file mode 100644 index 000000000..24c06cb13 --- /dev/null +++ b/GPU/GLES/FBO.h @@ -0,0 +1,66 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +// Simple wrapper around FBO functionality. +// Very C-ish API because that's what I felt like, and it's cool to completely +// hide the data from callers... + +#include "gfx/gl_common.h" + +struct FBO; + + +enum FBOColorDepth { + FBO_8888, + FBO_565, + FBO_4444, + FBO_5551, +}; + + +// Creates a simple FBO with a RGBA32 color buffer stored in a texture, and +// optionally an accompanying Z/stencil buffer. +// No mipmap support. +// num_color_textures must be 1 for now. +// 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); + +// 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); + +// 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_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); + +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/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 8164547c5..4f2b4fe84 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -22,7 +22,6 @@ #include "gfx_es2/glsl_program.h" #include "gfx_es2/gl_state.h" -#include "gfx_es2/fbo.h" #include "base/timeutil.h" #include "math/lin/matrix4x4.h" @@ -41,6 +40,7 @@ #include "GPU/Common/TextureDecoder.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Debugger/Stepping.h" +#include "GPU/GLES/FBO.h" #include "GPU/GLES/Framebuffer.h" #include "GPU/GLES/TextureCache.h" #include "GPU/GLES/TransformPipeline.h" diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 341f4b19b..1b39d0e20 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -22,14 +22,14 @@ #include #include "gfx/gl_common.h" -#include "gfx_es2/fbo.h" // Keeps track of allocated FBOs. // Also provides facilities for drawing and later converting raw // pixel data. -#include "../Globals.h" +#include "Globals.h" #include "GPU/GPUCommon.h" +#include "GPU/GLES/FBO.h" #include "GPU/Common/FramebufferCommon.h" #include "Core/Config.h" diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index a40090e85..f71df08d8 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -20,9 +20,8 @@ #include #include -#include "gfx_es2/fbo.h" - #include "GPU/GPUCommon.h" +#include "GPU/GLES/FBO.h" #include "GPU/GLES/Framebuffer.h" #include "GPU/GLES/TransformPipeline.h" #include "GPU/GLES/TextureCache.h" diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 9b7a9593a..bc9cd034f 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -19,12 +19,12 @@ #include -#include "gfx_es2/fbo.h" #include "gfx_es2/gpu_features.h" #include "Globals.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" +#include "GPU/GLES/FBO.h" #include "GPU/GLES/TextureScaler.h" #include "GPU/Common/TextureCacheCommon.h" diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 0117fc450..cd8ef72cf 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -204,7 +204,7 @@ - + @@ -217,6 +217,7 @@ + @@ -278,7 +279,7 @@ - + @@ -291,6 +292,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index bc8fa1fb2..493bf2545 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -126,9 +126,6 @@ DirectX9\helper - - DirectX9\helper - DirectX9\helper @@ -186,6 +183,12 @@ Common + + GLES + + + DirectX9\helper + @@ -284,9 +287,6 @@ DirectX9\helper - - DirectX9\helper - DirectX9\helper @@ -359,5 +359,11 @@ Common + + GLES + + + DirectX9\helper + \ No newline at end of file diff --git a/Qt/Debugger/debugger_displaylist.h b/Qt/Debugger/debugger_displaylist.h index f2ccf6b2c..ce68d1079 100644 --- a/Qt/Debugger/debugger_displaylist.h +++ b/Qt/Debugger/debugger_displaylist.h @@ -2,10 +2,12 @@ #define DEBUGGER_DISPLAYLIST_H #include "Core/Debugger/DebugInterface.h" + #include #include + #include "GPU/GPUState.h" -#include "native/gfx_es2/fbo.h" +#include "GPU/GLES/FBO.h" class MainWindow; namespace Ui { diff --git a/Qt/GPU.pro b/Qt/GPU.pro index f8a1a307d..a5d720677 100644 --- a/Qt/GPU.pro +++ b/Qt/GPU.pro @@ -27,6 +27,7 @@ SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU $$P/GPU/GPUState.cpp \ $$P/GPU/Math3D.cpp \ $$P/GPU/Null/NullGpu.cpp \ + $$P/GPU/GLES/FBO.cpp \ $$P/GPU/GLES/DepalettizeShader.cpp \ $$P/GPU/GLES/FragmentShaderGenerator.cpp \ $$P/GPU/GLES/FragmentTestCache.cpp \ diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 213a21036..c2aeb4927 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -25,7 +25,6 @@ #include "gfx_es2/gpu_features.h" #include "gfx_es2/draw_text.h" -#include "gfx_es2/fbo.h" #include "input/input_state.h" #include "ui/ui.h" @@ -43,6 +42,7 @@ #include "Core/System.h" #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" +#include "GPU/GLES/FBO.h" #include "GPU/GLES/Framebuffer.h" #include "Core/HLE/sceCtrl.h" #include "Core/HLE/sceDisplay.h" diff --git a/Windows/D3D9Base.cpp b/Windows/D3D9Base.cpp index 7363ebfd7..9733f9fa1 100644 --- a/Windows/D3D9Base.cpp +++ b/Windows/D3D9Base.cpp @@ -3,7 +3,7 @@ #include #include "GPU/Directx9/helper/global.h" -#include "GPU/Directx9/helper/fbo.h" +#include "GPU/Directx9/helper/dx_fbo.h" #include "base/logging.h" #include "util/text/utf8.h" diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 1f81df812..ef9ad6d65 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -170,6 +170,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/GLES/Framebuffer.cpp \ $(SRC)/GPU/GLES/DepalettizeShader.cpp \ $(SRC)/GPU/GLES/GLES_GPU.cpp.arm \ + $(SRC)/GPU/GLES/FBO.cpp \ $(SRC)/GPU/GLES/StencilBuffer.cpp.arm \ $(SRC)/GPU/GLES/TextureCache.cpp.arm \ $(SRC)/GPU/GLES/TransformPipeline.cpp.arm \ diff --git a/headless/WindowsHeadlessHostDx9.cpp b/headless/WindowsHeadlessHostDx9.cpp index da9260c89..4fbb57021 100644 --- a/headless/WindowsHeadlessHostDx9.cpp +++ b/headless/WindowsHeadlessHostDx9.cpp @@ -25,7 +25,7 @@ #include "base/logging.h" #include "thin3d/d3dx9_loader.h" #include "GPU/Directx9/helper/global.h" -#include "GPU/Directx9/helper/fbo.h" +#include "GPU/Directx9/helper/dx_fbo.h" #include "file/vfs.h" #include "file/zip_read.h" diff --git a/ios/ViewController.mm b/ios/ViewController.mm index ee1682aa6..944f6ad03 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -18,7 +18,7 @@ #include "input/keycodes.h" #include "Core/Config.h" -#include "gfx_es2/fbo.h" +#include "GPU/GLES/FBO.h" #define IS_IPAD() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) #define IS_IPHONE() ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) diff --git a/native b/native index 3f05c8d99..f78c4f6f8 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 3f05c8d99031931149a072c64cae51eb5635202b +Subproject commit f78c4f6f84a5beea8c82040a1c169512bc857242