From bf60b513aaa00af8a2548d4a6ef95f22a63f30f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= <branimirkaradzic@gmail.com>
Date: Fri, 16 Oct 2015 17:42:40 -0700
Subject: [PATCH] Added blit caps.

---
 include/bgfx/bgfxdefines.h |  1 +
 src/bgfx.cpp               |  1 +
 src/renderer_d3d11.cpp     |  5 ++-
 src/renderer_d3d12.cpp     |  1 +
 src/renderer_d3d9.cpp      | 23 ++++++------
 src/renderer_gl.cpp        | 77 +++++++++++++++++++++++---------------
 6 files changed, 65 insertions(+), 43 deletions(-)

diff --git a/include/bgfx/bgfxdefines.h b/include/bgfx/bgfxdefines.h
index 05f4bad0..8d4b30ae 100644
--- a/include/bgfx/bgfxdefines.h
+++ b/include/bgfx/bgfxdefines.h
@@ -367,6 +367,7 @@
 #define BGFX_CAPS_INDEX32                UINT64_C(0x0000000000002000) //!< 32-bit indices are supported.
 #define BGFX_CAPS_DRAW_INDIRECT          UINT64_C(0x0000000000004000) //!< Draw indirect is supported.
 #define BGFX_CAPS_HIDPI                  UINT64_C(0x0000000000008000) //!< HiDPI rendering is supported.
+#define BGFX_CAPS_BLIT                   UINT64_C(0x0000000000010000) //!< Blit is supported.
 
 ///
 #define BGFX_CAPS_FORMAT_TEXTURE_NONE             UINT8_C(0x00) //!< Texture format is not supported.
diff --git a/src/bgfx.cpp b/src/bgfx.cpp
index 3196d617..2b9caeb7 100644
--- a/src/bgfx.cpp
+++ b/src/bgfx.cpp
@@ -977,6 +977,7 @@ namespace bgfx
 		CAPS_FLAGS(BGFX_CAPS_INDEX32),
 		CAPS_FLAGS(BGFX_CAPS_DRAW_INDIRECT),
 		CAPS_FLAGS(BGFX_CAPS_HIDPI),
+		CAPS_FLAGS(BGFX_CAPS_BLIT),
 #undef CAPS_FLAGS
 	};
 
diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp
index e6239ed9..ad0d2098 100644
--- a/src/renderer_d3d11.cpp
+++ b/src/renderer_d3d11.cpp
@@ -1156,6 +1156,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 					| BGFX_CAPS_SWAP_CHAIN
 					| (m_ovr.isInitialized() ? BGFX_CAPS_HMD : 0)
 					| BGFX_CAPS_DRAW_INDIRECT
+					| BGFX_CAPS_BLIT
 					);
 
 				if (m_featureLevel <= D3D_FEATURE_LEVEL_9_2)
@@ -4593,7 +4594,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 						prim = s_primInfo[BX_COUNTOF(s_primName)]; // Force primitive type update after clear quad.
 					}
 
-					for (; blitItem < numBlitItems && blitKey.m_view == view; blitItem++)
+					for (; blitItem < numBlitItems && blitKey.m_view <= view; blitItem++)
 					{
 						const BlitItem& blit = _render->m_blitItem[blitItem];
 						blitKey.decode(_render->m_blitKeys[blitItem+1]);
@@ -4616,7 +4617,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
 						box.top    = blit.m_srcY;
 						box.front  = blit.m_srcZ;
 						box.right  = blit.m_srcX + width;
-						box.bottom = blit.m_srcY + height;
+						box.bottom = blit.m_srcY + height;;
 						box.back   = blit.m_srcZ + bx::uint32_max(1, depth);
 
 						deviceCtx->CopySubresourceRegion(dst.m_ptr
diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp
index 902eb8b4..e3cbff67 100644
--- a/src/renderer_d3d12.cpp
+++ b/src/renderer_d3d12.cpp
@@ -884,6 +884,7 @@ namespace bgfx { namespace d3d12
 									| BGFX_CAPS_COMPUTE
 									| (m_options.ROVsSupported ? BGFX_CAPS_FRAGMENT_ORDERING : 0)
 //									| BGFX_CAPS_SWAP_CHAIN
+//									| BGFX_CAPS_BLIT
 									);
 				g_caps.maxTextureSize   = 16384;
 				g_caps.maxFBAttachments = uint8_t(bx::uint32_min(16, BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS) );
diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp
index 6062e0c4..f0adb9c4 100644
--- a/src/renderer_d3d9.cpp
+++ b/src/renderer_d3d9.cpp
@@ -528,14 +528,15 @@ namespace bgfx { namespace d3d9
 			BX_TRACE("Max vertex index: %d", m_caps.MaxVertexIndex);
 
 			g_caps.supported |= ( 0
-								| BGFX_CAPS_TEXTURE_3D
-								| BGFX_CAPS_TEXTURE_COMPARE_LEQUAL
-								| BGFX_CAPS_VERTEX_ATTRIB_HALF
-								| BGFX_CAPS_VERTEX_ATTRIB_UINT10
-								| BGFX_CAPS_FRAGMENT_DEPTH
-								| BGFX_CAPS_SWAP_CHAIN
-								| ( (UINT16_MAX < m_caps.MaxVertexIndex) ? BGFX_CAPS_INDEX32 : 0)
-								);
+				| BGFX_CAPS_TEXTURE_3D
+				| BGFX_CAPS_TEXTURE_COMPARE_LEQUAL
+				| BGFX_CAPS_VERTEX_ATTRIB_HALF
+				| BGFX_CAPS_VERTEX_ATTRIB_UINT10
+				| BGFX_CAPS_FRAGMENT_DEPTH
+				| BGFX_CAPS_SWAP_CHAIN
+				| ( (UINT16_MAX < m_caps.MaxVertexIndex) ? BGFX_CAPS_INDEX32 : 0)
+				| BGFX_CAPS_BLIT
+				);
 			g_caps.maxTextureSize = uint16_t(bx::uint32_min(m_caps.MaxTextureWidth, m_caps.MaxTextureHeight) );
 //			g_caps.maxVertexIndex = m_caps.MaxVertexIndex;
 
@@ -3300,7 +3301,7 @@ namespace bgfx { namespace d3d9
 					DX_CHECK(device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE) );
 					DX_CHECK(device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER) );
 
-					for (; blitItem < numBlitItems && blitKey.m_view == view; blitItem++)
+					for (; blitItem < numBlitItems && blitKey.m_view <= view; blitItem++)
 					{
 						const BlitItem& blit = _render->m_blitItem[blitItem];
 						blitKey.decode(_render->m_blitKeys[blitItem+1]);
@@ -3315,8 +3316,8 @@ namespace bgfx { namespace d3d9
 						uint32_t width     = bx::uint32_min(srcWidth,  dstWidth);
 						uint32_t height    = bx::uint32_min(srcHeight, dstHeight);
 
-						RECT srcRect = { blit.m_srcX, blit.m_srcY, blit.m_srcX + width, blit.m_srcY + height };
-						RECT dstRect = { blit.m_dstX, blit.m_dstY, blit.m_dstX + width, blit.m_dstY + height };
+						RECT srcRect = { LONG(blit.m_srcX), LONG(blit.m_srcY), LONG(blit.m_srcX + width), LONG(blit.m_srcY + height) };
+						RECT dstRect = { LONG(blit.m_dstX), LONG(blit.m_dstY), LONG(blit.m_dstX + width), LONG(blit.m_dstY + height) };
 
 						IDirect3DSurface9* srcSurface;
 						DX_CHECK(src.m_texture2d->GetSurfaceLevel(blit.m_srcMip, &srcSurface) );
diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp
index 842d61fd..75c0fc12 100644
--- a/src/renderer_gl.cpp
+++ b/src/renderer_gl.cpp
@@ -1203,6 +1203,7 @@ namespace bgfx { namespace gl
 			, m_maxAnisotropyDefault(0.0f)
 			, m_maxMsaa(0)
 			, m_vao(0)
+			, m_blitSupported(false)
 			, m_vaoSupport(false)
 			, m_samplerObjectSupport(false)
 			, m_shadowSamplersSupport(false)
@@ -1705,6 +1706,18 @@ namespace bgfx { namespace gl
 				: 0
 				;
 
+			if (s_extension[Extension::ARB_copy_image].m_supported
+			||  s_extension[Extension::EXT_copy_image].m_supported
+			||  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_BLIT
+					: 0
+					;
+			}
+
 			g_caps.maxTextureSize = uint16_t(glGet(GL_MAX_TEXTURE_SIZE) );
 
 			if (BX_ENABLED(BGFX_CONFIG_RENDERER_OPENGL)
@@ -3092,6 +3105,7 @@ namespace bgfx { namespace gl
 		float m_maxAnisotropyDefault;
 		int32_t m_maxMsaa;
 		GLuint m_vao;
+		bool m_blitSupported;
 		bool m_vaoSupport;
 		bool m_samplerObjectSupport;
 		bool m_shadowSamplersSupport;
@@ -5272,40 +5286,43 @@ namespace bgfx { namespace gl
 					GL_CHECK(glEnable(GL_CULL_FACE) );
 					GL_CHECK(glDisable(GL_BLEND) );
 
-					for (; blitItem < numBlitItems && blitKey.m_view == view; blitItem++)
+					if (m_blitSupported)
 					{
-						const BlitItem& bi = _render->m_blitItem[blitItem];
-						blitKey.decode(_render->m_blitKeys[blitItem+1]);
+						for (; blitItem < numBlitItems && blitKey.m_view <= view; blitItem++)
+						{
+							const BlitItem& bi = _render->m_blitItem[blitItem];
+							blitKey.decode(_render->m_blitKeys[blitItem + 1]);
 
-						const TextureGL& src = m_textures[bi.m_src.idx];
-						const TextureGL& dst = m_textures[bi.m_dst.idx];
+							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 srcDepth  = bx::uint32_min(src.m_depth,  bi.m_srcZ + bi.m_depth)  - bi.m_srcZ;
-						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);
-						uint32_t depth     = bx::uint32_min(srcDepth,  dstDepth);
+							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 srcDepth  = bx::uint32_min(src.m_depth,  bi.m_srcZ + bi.m_depth)  - bi.m_srcZ;
+							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);
+							uint32_t depth     = bx::uint32_min(srcDepth,  dstDepth);
 
-						GL_CHECK(glCopyImageSubData(src.m_id
-							, src.m_target
-							, bi.m_srcMip
-							, bi.m_srcX
-							, bi.m_srcY
-							, bi.m_srcZ
-							, dst.m_id
-							, dst.m_target
-							, bi.m_dstMip
-							, bi.m_dstX
-							, bi.m_dstY
-							, bi.m_dstZ
-							, width
-							, height
-							, bx::uint32_max(depth, 1)
-							) );
+							GL_CHECK(glCopyImageSubData(src.m_id
+								, src.m_target
+								, bi.m_srcMip
+								, bi.m_srcX
+								, bi.m_srcY
+								, bi.m_srcZ
+								, dst.m_id
+								, dst.m_target
+								, bi.m_dstMip
+								, bi.m_dstX
+								, bi.m_dstY
+								, bi.m_dstZ
+								, width
+								, height
+								, bx::uint32_max(depth, 1)
+								) );
+						}
 					}
 				}