diff --git a/src/glimports.h b/src/glimports.h index 1bde45fff..cac44e6f4 100644 --- a/src/glimports.h +++ b/src/glimports.h @@ -73,6 +73,7 @@ typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum targ typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void); typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); @@ -266,6 +267,7 @@ GL_IMPORT______(false, PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedT GL_IMPORT______(true , PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D); GL_IMPORT______(true , PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D); GL_IMPORT______(true , PFNGLCOPYIMAGESUBDATAPROC, glCopyImageSubData); +GL_IMPORT______(true , PFNGLCOPYTEXSUBIMAGE2DPROC, glCopyTexSubImage2D); GL_IMPORT______(false, PFNGLCREATEPROGRAMPROC, glCreateProgram); GL_IMPORT______(false, PFNGLCREATESHADERPROC, glCreateShader); GL_IMPORT______(false, PFNGLCULLFACEPROC, glCullFace); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index cbae2ee2f..38ef57d18 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2747,13 +2747,14 @@ namespace bgfx { namespace gl || s_extension[Extension:: NV_copy_image].m_supported || s_extension[Extension::OES_copy_image].m_supported) { - m_blitSupported = NULL != glCopyImageSubData; - g_caps.supported |= m_blitSupported - ? BGFX_CAPS_TEXTURE_BLIT - : 0 - ; + m_blitSupported = NULL != glCopyImageSubData; } + g_caps.supported |= m_blitSupported || BX_ENABLED(BGFX_GL_CONFIG_BLIT_EMULATION) + ? BGFX_CAPS_TEXTURE_BLIT + : 0 + ; + g_caps.supported |= m_readBackSupported ? BGFX_CAPS_TEXTURE_READ_BACK : 0 @@ -6991,6 +6992,60 @@ namespace bgfx { namespace gl , height , bx::uint32_imax(depth, 1) ) ); + } + } + else if (BX_ENABLED(BGFX_GL_CONFIG_BLIT_EMULATION) ) + { + while (_bs.hasItem(_view) ) + { + const BlitItem& bi = _bs.advance(); + + const TextureGL& src = m_textures[bi.m_src.idx]; + const TextureGL& dst = m_textures[bi.m_dst.idx]; + + uint32_t srcWidth = bx::uint32_min(src.m_width, bi.m_srcX + bi.m_width) - bi.m_srcX; + uint32_t srcHeight = bx::uint32_min(src.m_height, bi.m_srcY + bi.m_height) - bi.m_srcY; + uint32_t dstWidth = bx::uint32_min(dst.m_width, bi.m_dstX + bi.m_width) - bi.m_dstX; + uint32_t dstHeight = bx::uint32_min(dst.m_height, bi.m_dstY + bi.m_height) - bi.m_dstY; + uint32_t dstDepth = bx::uint32_min(dst.m_depth, bi.m_dstZ + bi.m_depth) - bi.m_dstZ; + uint32_t width = bx::uint32_min(srcWidth, dstWidth); + uint32_t height = bx::uint32_min(srcHeight, dstHeight); + + BX_ASSERT((bi.m_srcZ == 0) && (bi.m_dstZ == 0) && (bi.m_depth == 0) + , "Blitting 3D regions is not supported" + ); + + GLuint fbo; + GL_CHECK(glGenFramebuffers(1, &fbo) ); + + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, fbo) ); + + GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER + , GL_COLOR_ATTACHMENT0 + , GL_TEXTURE_2D + , src.m_id + , bi.m_srcMip + ) ); + + BX_ASSERT(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER) + , "glCheckFramebufferStatus failed 0x%08x" + , glCheckFramebufferStatus(GL_FRAMEBUFFER) + ); + + GL_CHECK(glActiveTexture(GL_TEXTURE0) ); + GL_CHECK(glBindTexture(GL_TEXTURE_2D, dst.m_id) ); + + GL_CHECK(glCopyTexSubImage2D(GL_TEXTURE_2D + , bi.m_dstMip + , bi.m_dstX + , bi.m_dstY + , bi.m_srcX + , bi.m_srcY + , width + , height) ); + + GL_CHECK(glDeleteFramebuffers(1, &fbo) ); + GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); } } } diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 124d76e90..a2480fd37 100644 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -36,6 +36,10 @@ // on the following platforms. #define BGFX_GL_CONFIG_UNIFORM_CACHE BX_PLATFORM_EMSCRIPTEN +#ifndef BGFX_GL_CONFIG_BLIT_EMULATION +# define BGFX_GL_CONFIG_BLIT_EMULATION 0 +#endif // BGFX_GL_CONFIG_BLIT_EMULATION + #define BGFX_GL_PROFILER_BEGIN(_view, _abgr) \ BX_MACRO_BLOCK_BEGIN \ GL_CHECK(glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, s_viewName[view]) ); \