diff --git a/gfx/texture.cpp b/gfx/texture.cpp index 6cc617a241..168a55adea 100644 --- a/gfx/texture.cpp +++ b/gfx/texture.cpp @@ -157,7 +157,7 @@ bool Texture::LoadPNG(const char *filename, bool genMips) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -188,7 +188,7 @@ bool Texture::LoadJPEG(const char *filename, bool genMips) { SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -213,7 +213,7 @@ bool Texture::LoadPNG(const uint8_t *data, size_t size, bool genMips) { SetTextureParameters(genMips ? ZIM_GEN_MIPS : ZIM_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data); if (genMips) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); } else { #ifndef USING_GLES2 @@ -243,7 +243,7 @@ bool Texture::LoadXOR() { SetTextureParameters(ZIM_GEN_MIPS); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); - if(gl_extensions.FBO_ARB){ + if(gl_extensions.ARB_framebuffer_object){ glGenerateMipmap(GL_TEXTURE_2D); }else{ #ifndef USING_GLES2 @@ -342,7 +342,7 @@ bool Texture::LoadZIM(const char *filename) { colors, data_type, image_data[l]); } if (num_levels == 1 && (flags & ZIM_GEN_MIPS)) { - if(gl_extensions.FBO_ARB) { + if(gl_extensions.ARB_framebuffer_object) { glGenerateMipmap(GL_TEXTURE_2D); }else{ #ifndef USING_GLES2 diff --git a/gfx_es2/fbo.cpp b/gfx_es2/fbo.cpp index 35cd3c0ee8..0d96f18cdd 100644 --- a/gfx_es2/fbo.cpp +++ b/gfx_es2/fbo.cpp @@ -6,25 +6,6 @@ #include "gfx/gl_common.h" #include "gfx_es2/gl_state.h" -#if defined(USING_GLES2) && !defined(BLACKBERRY) - -#ifndef GL_READ_FRAMEBUFFER -// Careful - our ES3 header defines these. Means that we must make sure -// to only use them if ES3 support is detected to be available and otherwise -// use GL_FRAMEBUFFER only. -#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER -#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER -#endif - -#ifndef GL_DEPTH_COMPONENT24 -#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES -#endif -#endif - -#ifndef GL_DEPTH24_STENCIL8_OES -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif - #ifdef IOS extern void bindDefaultFBO(); #endif @@ -129,12 +110,32 @@ 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; +} + FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, FBOColorDepth colorDepth) { CheckGLExtensions(); #ifndef USING_GLES2 - if(!gl_extensions.FBO_ARB) + 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(); @@ -269,7 +270,7 @@ FBO *fbo_create_from_native_fbo(GLuint native_fbo, FBO *fbo) } static GLenum fbo_get_fb_target(bool read, GLuint **cached) { - bool supportsBlit = gl_extensions.FBO_ARB; + bool supportsBlit = gl_extensions.ARB_framebuffer_object; if (gl_extensions.IsGLES) { supportsBlit = supportsBlit && (gl_extensions.GLES3 || gl_extensions.NV_framebuffer_blit); } @@ -294,7 +295,7 @@ static void fbo_bind_fb_target(bool read, GLuint name) { GLenum target = fbo_get_fb_target(read, &cached); if (*cached != name) { - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { glBindFramebuffer(target, name); } else { #ifndef USING_GLES2 @@ -312,13 +313,16 @@ void fbo_unbind() { } CheckGLExtensions(); - if (gl_extensions.FBO_ARB) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } else { #ifndef USING_GLES2 + if (gl_extensions.ARB_framebuffer_object) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } else if (gl_extensions.EXT_framebuffer_object) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); -#endif } +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif + #ifdef IOS bindDefaultFBO(); #endif @@ -364,7 +368,7 @@ void fbo_destroy(FBO *fbo) { return; } - if (gl_extensions.FBO_ARB) { + if (gl_extensions.ARB_framebuffer_object) { 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); @@ -373,7 +377,7 @@ void fbo_destroy(FBO *fbo) { glDeleteRenderbuffers(1, &fbo->z_stencil_buffer); glDeleteRenderbuffers(1, &fbo->z_buffer); glDeleteRenderbuffers(1, &fbo->stencil_buffer); - } else { + } 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); diff --git a/gfx_es2/fbo.h b/gfx_es2/fbo.h index 9fd9426171..52c3daf5a6 100644 --- a/gfx_es2/fbo.h +++ b/gfx_es2/fbo.h @@ -29,6 +29,7 @@ FBO *fbo_create(int width, int height, int num_color_textures, bool z_stencil, F // 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); diff --git a/gfx_es2/gl_state.cpp b/gfx_es2/gl_state.cpp index 8923d50ac5..d91472c6a1 100644 --- a/gfx_es2/gl_state.cpp +++ b/gfx_es2/gl_state.cpp @@ -256,18 +256,13 @@ void CheckGLExtensions() { gl_extensions.OES_texture_npot = strstr(extString, "GL_ARB_texture_non_power_of_two") != 0 && !(((strncmp(renderer, "ATI RADEON X", 12) == 0) || (strncmp(renderer, "ATI MOBILITY RADEON X", 21) == 0))); - gl_extensions.NV_draw_texture = strstr(extString, "GL_NV_draw_texture") != 0; gl_extensions.ARB_blend_func_extended = strstr(extString, "GL_ARB_blend_func_extended") != 0; + gl_extensions.EXT_blend_func_extended = strstr(extString, "GL_EXT_blend_func_extended") != 0; gl_extensions.ARB_conservative_depth = strstr(extString, "GL_ARB_conservative_depth") != 0; gl_extensions.ARB_shader_image_load_store = (strstr(extString, "GL_ARB_shader_image_load_store") != 0) || (strstr(extString, "GL_EXT_shader_image_load_store") != 0); gl_extensions.EXT_bgra = strstr(extString, "GL_EXT_bgra") != 0; gl_extensions.EXT_gpu_shader4 = strstr(extString, "GL_EXT_gpu_shader4") != 0; gl_extensions.NV_framebuffer_blit = strstr(extString, "GL_NV_framebuffer_blit") != 0; - if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) { - // Force this extension to off on sub 3.0 OpenGL versions as it does not seem reliable - // Also on Intel, see https://github.com/hrydgard/ppsspp/issues/4867 - gl_extensions.ARB_blend_func_extended = false; - } if (gl_extensions.IsGLES) { gl_extensions.OES_texture_npot = strstr(extString, "OES_texture_npot") != 0; @@ -280,15 +275,8 @@ void CheckGLExtensions() { gl_extensions.EXT_shader_framebuffer_fetch = strstr(extString, "GL_EXT_shader_framebuffer_fetch") != 0; gl_extensions.NV_shader_framebuffer_fetch = strstr(extString, "GL_NV_shader_framebuffer_fetch") != 0; gl_extensions.ARM_shader_framebuffer_fetch = strstr(extString, "GL_ARM_shader_framebuffer_fetch") != 0; - gl_extensions.ANY_shader_framebuffer_fetch = gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch; gl_extensions.NV_copy_image = strstr(extString, "GL_NV_copy_image") != 0; - // Framebuffer fetch appears to be buggy at least on Tegra 3 devices. So we blacklist it. - // Tales of Destiny 2 has been reported to display green. - if (gl_extensions.ANY_shader_framebuffer_fetch && strstr(renderer, "NVIDIA Tegra 3") != 0) { - gl_extensions.ANY_shader_framebuffer_fetch = false; - } - #if defined(ANDROID) || defined(BLACKBERRY) // On Android, incredibly, this is not consistently non-zero! It does seem to have the same value though. // https://twitter.com/ID_AA_Carmack/status/387383037794603008 @@ -298,10 +286,6 @@ void CheckGLExtensions() { DLOG("Addresses returned for invalid extensions: %p %p", invalidAddress, invalidAddress2); #endif - if (gl_extensions.NV_draw_texture) { - glDrawTextureNV = (PFNGLDRAWTEXTURENVPROC)eglGetProcAddress("glDrawTextureNV"); - } - if (gl_extensions.NV_copy_image) { glCopyImageSubDataNV = (PFNGLCOPYIMAGESUBDATANVPROC)eglGetProcAddress("glCopyImageSubDataNV"); } @@ -362,6 +346,7 @@ void CheckGLExtensions() { } #endif + // This is probably a waste of time, implementations lie. if (gl_extensions.IsGLES || strstr(extString, "GL_ARB_ES2_compatibility")) { const GLint precisions[6] = { GL_LOW_FLOAT, GL_MEDIUM_FLOAT, GL_HIGH_FLOAT, @@ -377,21 +362,10 @@ void CheckGLExtensions() { } } - if (gl_extensions.IsGLES) { - gl_extensions.FBO_ARB = true; - gl_extensions.FBO_EXT = false; - } else { - gl_extensions.FBO_ARB = false; - gl_extensions.FBO_EXT = false; - gl_extensions.PBO_ARB = true; - gl_extensions.PBO_NV = true; - if (strlen(extString) != 0) { - gl_extensions.FBO_ARB = strstr(extString, "GL_ARB_framebuffer_object") != 0; - gl_extensions.FBO_EXT = strstr(extString, "GL_EXT_framebuffer_object") != 0; - gl_extensions.PBO_ARB = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; - gl_extensions.PBO_NV = strstr(extString, "GL_NV_pixel_buffer_object") != 0; - } - } + gl_extensions.ARB_framebuffer_object = strstr(extString, "GL_ARB_framebuffer_object") != 0; + gl_extensions.EXT_framebuffer_object = strstr(extString, "GL_EXT_framebuffer_object") != 0; + gl_extensions.ARB_pixel_buffer_object = strstr(extString, "GL_ARB_pixel_buffer_object") != 0; + gl_extensions.NV_pixel_buffer_object = strstr(extString, "GL_NV_pixel_buffer_object") != 0; ProcessGPUFeatures(); diff --git a/gfx_es2/gl_state.h b/gfx_es2/gl_state.h index fa38e6b822..a1fccfaa55 100644 --- a/gfx_es2/gl_state.h +++ b/gfx_es2/gl_state.h @@ -57,8 +57,25 @@ extern PFNGLISVERTEXARRAYOESPROC glIsVertexArrayOES; #define glDeleteVertexArrays glDeleteVertexArraysOES #define glIsVertexArray glIsVertexArrayOES +#if !defined(BLACKBERRY) +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER GL_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER +#endif +#ifndef GL_DEPTH_COMPONENT24 +#define GL_DEPTH_COMPONENT24 GL_DEPTH_COMPONENT24_OES +#endif +#endif + +#ifndef GL_RGBA8 +#define GL_RGBA8 GL_RGBA +#endif + #endif /* EGL_NV_system_time */ +#ifndef GL_DEPTH24_STENCIL8_OES +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif // OpenGL state cache. Should convert all code to use this instead of directly calling glEnable etc, // as GL state changes can be expensive on some hardware. diff --git a/gfx_es2/gpu_features.cpp b/gfx_es2/gpu_features.cpp index f230b7c96d..57ff968a38 100644 --- a/gfx_es2/gpu_features.cpp +++ b/gfx_es2/gpu_features.cpp @@ -34,5 +34,6 @@ void ProcessGPUFeatures() { WLOG("GL DRIVER BUG: PVR with bad precision"); gl_extensions.bugs |= BUG_PVR_SHADER_PRECISION_BAD; } + gl_extensions.bugs |= BUG_PVR_GENMIPMAP_HEIGHT_GREATER; } } diff --git a/gfx_es2/gpu_features.h b/gfx_es2/gpu_features.h index d4207970c8..5baa67ecd5 100644 --- a/gfx_es2/gpu_features.h +++ b/gfx_es2/gpu_features.h @@ -21,6 +21,7 @@ enum { BUG_FBO_UNUSABLE = 1, BUG_PVR_SHADER_PRECISION_BAD = 2, BUG_PVR_SHADER_PRECISION_TERRIBLE = 4, + BUG_PVR_GENMIPMAP_HEIGHT_GREATER = 8, }; // Extensions to look at using: @@ -45,9 +46,10 @@ struct GLExtensions { bool OES_vertex_array_object; // ARB - bool FBO_ARB; - bool PBO_ARB; + bool ARB_framebuffer_object; + bool ARB_pixel_buffer_object; bool ARB_blend_func_extended; // dual source blending + bool EXT_blend_func_extended; // dual source blending (GLES, new 2015) bool ARB_shader_image_load_store; bool ARB_conservative_depth; @@ -59,15 +61,14 @@ struct GLExtensions { bool EXT_shader_framebuffer_fetch; bool EXT_gpu_shader4; bool EXT_blend_minmax; - bool FBO_EXT; + bool EXT_framebuffer_object; bool PBO_EXT; // NV bool NV_shader_framebuffer_fetch; - bool NV_draw_texture; bool NV_copy_image; bool NV_framebuffer_blit; - bool PBO_NV; // GL_NV_pixel_buffer_object + bool NV_pixel_buffer_object; // GL_NV_pixel_buffer_object // ARM bool ARM_shader_framebuffer_fetch; @@ -76,9 +77,6 @@ struct GLExtensions { bool EGL_NV_system_time; bool EGL_NV_coverage_sample; - // Convenience (in case we need to know which, but can treat them mostly the same.) - bool ANY_shader_framebuffer_fetch; - // Bugs int bugs;