Browse Source

Added support for per primitive scissor.

bkaradzic 12 years ago
parent
commit
bac2073b76
7 changed files with 150 additions and 47 deletions
  1. 6 2
      examples/common/imgui/imgui.cpp
  2. 3 2
      include/bgfx.h
  3. 38 4
      src/bgfx_p.h
  4. 4 0
      src/config.h
  5. 38 16
      src/renderer_d3d11.cpp
  6. 32 11
      src/renderer_d3d9.cpp
  7. 29 12
      src/renderer_gl.cpp

+ 6 - 2
examples/common/imgui/imgui.cpp

@@ -130,6 +130,7 @@ struct Imgui
 		, m_insideCurrentScroll(false)
 		, m_insideCurrentScroll(false)
 		, m_areaId(0)
 		, m_areaId(0)
 		, m_widgetId(0)
 		, m_widgetId(0)
+		, m_scissor(UINT16_MAX)
 		, m_scrollTop(0)
 		, m_scrollTop(0)
 		, m_scrollBottom(0)
 		, m_scrollBottom(0)
 		, m_scrollRight(0)
 		, m_scrollRight(0)
@@ -403,7 +404,7 @@ struct Imgui
 			, imguiRGBA(255, 255, 255, 128)
 			, imguiRGBA(255, 255, 255, 128)
 			);
 			);
 
 
-//		setScissor(_x + SCROLL_AREA_PADDING, _y + SCROLL_AREA_PADDING, _width - SCROLL_AREA_PADDING * 4, _height - AREA_HEADER - SCROLL_AREA_PADDING);
+		m_scissor = bgfx::setScissor(_x + SCROLL_AREA_PADDING, _y + SCROLL_AREA_PADDING, _width - SCROLL_AREA_PADDING * 4, _height - AREA_HEADER - SCROLL_AREA_PADDING);
 
 
 		return m_insideScrollArea;
 		return m_insideScrollArea;
 	}
 	}
@@ -411,7 +412,7 @@ struct Imgui
 	void endScrollArea()
 	void endScrollArea()
 	{
 	{
 		// Disable scissoring.
 		// Disable scissoring.
-//		setScissor(-1, -1, -1, -1);
+		m_scissor = UINT16_MAX;
 
 
 		// Draw scroll bar
 		// Draw scroll bar
 		int32_t xx = m_scrollRight + SCROLL_AREA_PADDING / 2;
 		int32_t xx = m_scrollRight + SCROLL_AREA_PADDING / 2;
@@ -1066,6 +1067,7 @@ struct Imgui
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				);
 				);
 			bgfx::setProgram(m_colorProgram);
 			bgfx::setProgram(m_colorProgram);
+			bgfx::setScissor(m_scissor);
 			bgfx::submit(m_view);
 			bgfx::submit(m_view);
 		}
 		}
 	}
 	}
@@ -1354,6 +1356,7 @@ struct Imgui
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
 				);
 				);
 			bgfx::setProgram(m_textureProgram);
 			bgfx::setProgram(m_textureProgram);
+			bgfx::setScissor(m_scissor);
 			bgfx::submit(m_view);
 			bgfx::submit(m_view);
 		}
 		}
 	}
 	}
@@ -1380,6 +1383,7 @@ struct Imgui
 
 
 	uint32_t m_areaId;
 	uint32_t m_areaId;
 	uint32_t m_widgetId;
 	uint32_t m_widgetId;
+	uint16_t m_scissor;
 
 
 	float m_tempCoords[MAX_TEMP_COORDS * 2];
 	float m_tempCoords[MAX_TEMP_COORDS * 2];
 	float m_tempNormals[MAX_TEMP_COORDS * 2];
 	float m_tempNormals[MAX_TEMP_COORDS * 2];

+ 3 - 2
include/bgfx.h

@@ -853,9 +853,10 @@ namespace bgfx
 
 
 	/// Set scissor from cache for draw primitive.
 	/// Set scissor from cache for draw primitive.
 	///
 	///
-	/// @param _cache Index in scissor cache.
+	/// @param _cache Index in scissor cache. Passing UINT16_MAX unset primitive
+	///   scissor and primitive will use view scissor instead.
 	///
 	///
-	void setScissor(uint16_t _cache);
+	void setScissor(uint16_t _cache = UINT16_MAX);
 
 
 	/// Set model matrix for draw primitive. If it is not called model will
 	/// Set model matrix for draw primitive. If it is not called model will
 	/// be rendered with identity model matrix.
 	/// be rendered with identity model matrix.

+ 38 - 4
src/bgfx_p.h

@@ -651,6 +651,38 @@ namespace bgfx
 		uint32_t m_num;
 		uint32_t m_num;
 	};
 	};
 
 
+	struct RectCache
+	{
+		RectCache()
+			: m_num(0)
+		{
+		}
+
+		void reset()
+		{
+			m_num = 0;
+		}
+
+		uint32_t add(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
+		{
+			BX_CHECK(m_num+1 < BGFX_CONFIG_MAX_RECT_CACHE, "Rect cache overflow. %d (max: %d)", m_num, BGFX_CONFIG_MAX_RECT_CACHE);
+
+			uint32_t first = m_num;
+			Rect& rect = m_cache[m_num];
+
+			rect.m_x = _x;
+			rect.m_y = _y;
+			rect.m_width = _width;
+			rect.m_height = _height;
+
+			m_num++;
+			return first;
+		}
+
+		Rect m_cache[BGFX_CONFIG_MAX_RECT_CACHE];
+		uint32_t m_num;
+	};
+
 	struct Sampler
 	struct Sampler
 	{
 	{
 		uint32_t m_flags;
 		uint32_t m_flags;
@@ -860,7 +892,7 @@ namespace bgfx
 			m_instanceDataStride = 0;
 			m_instanceDataStride = 0;
 			m_numInstances = 1;
 			m_numInstances = 1;
 			m_num = 1;
 			m_num = 1;
-			m_scissor = 0;
+			m_scissor = UINT16_MAX;
 			m_vertexBuffer.idx = invalidHandle;
 			m_vertexBuffer.idx = invalidHandle;
 			m_vertexDecl.idx = invalidHandle;
 			m_vertexDecl.idx = invalidHandle;
 			m_indexBuffer.idx = invalidHandle;
 			m_indexBuffer.idx = invalidHandle;
@@ -958,6 +990,7 @@ namespace bgfx
 		{
 		{
 			m_state.reset();
 			m_state.reset();
 			m_matrixCache.reset();
 			m_matrixCache.reset();
+			m_rectCache.reset();
 			m_key.reset();
 			m_key.reset();
 			m_num = 0;
 			m_num = 0;
 			m_numRenderStates = 0;
 			m_numRenderStates = 0;
@@ -1008,9 +1041,9 @@ namespace bgfx
 
 
 		uint16_t setScissor(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
 		uint16_t setScissor(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
 		{
 		{
-			BX_UNUSED(_x, _y, _width, _height);
-			m_state.m_scissor = 0;
-			return 0;
+			uint16_t scissor = m_rectCache.add(_x, _y, _width, _height);
+			m_state.m_scissor = scissor;
+			return scissor;
 		}
 		}
 
 
 		void setScissor(uint16_t _cache)
 		void setScissor(uint16_t _cache)
@@ -1256,6 +1289,7 @@ namespace bgfx
 		uint16_t m_numDropped;
 		uint16_t m_numDropped;
 
 
 		MatrixCache m_matrixCache;
 		MatrixCache m_matrixCache;
+		RectCache m_rectCache;
 
 
 		uint32_t m_iboffset;
 		uint32_t m_iboffset;
 		uint32_t m_vboffset;
 		uint32_t m_vboffset;

+ 4 - 0
src/config.h

@@ -127,6 +127,10 @@
 #	define BGFX_CONFIG_MAX_MATRIX_CACHE (16<<10)
 #	define BGFX_CONFIG_MAX_MATRIX_CACHE (16<<10)
 #endif // BGFX_CONFIG_MAX_MATRIX_CACHE
 #endif // BGFX_CONFIG_MAX_MATRIX_CACHE
 
 
+#ifndef BGFX_CONFIG_MAX_RECT_CACHE
+#	define BGFX_CONFIG_MAX_RECT_CACHE 512
+#endif //  BGFX_CONFIG_MAX_RECT_CACHE
+
 #ifndef BGFX_CONFIG_MAX_VIEWS
 #ifndef BGFX_CONFIG_MAX_VIEWS
 #	define BGFX_CONFIG_MAX_VIEWS 32
 #	define BGFX_CONFIG_MAX_VIEWS 32
 #endif // BGFX_CONFIG_MAX_VIEWS
 #endif // BGFX_CONFIG_MAX_VIEWS

+ 38 - 16
src/renderer_d3d11.cpp

@@ -2314,7 +2314,7 @@ namespace bgfx
 		}
 		}
 
 
 		bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME);
 		bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME);
-		bool scissor = false;
+		bool scissorEnabled = false;
 		s_renderCtx.setDebugWireframe(wireframe);
 		s_renderCtx.setDebugWireframe(wireframe);
 
 
 		uint16_t programIdx = invalidHandle;
 		uint16_t programIdx = invalidHandle;
@@ -2349,6 +2349,7 @@ namespace bgfx
 				if (key.m_view != view)
 				if (key.m_view != view)
 				{
 				{
 					currentState.clear();
 					currentState.clear();
+					currentState.m_scissor = !state.m_scissor;
 					changedFlags = BGFX_STATE_MASK;
 					changedFlags = BGFX_STATE_MASK;
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					currentState.m_flags = newFlags;
 					currentState.m_flags = newFlags;
@@ -2383,10 +2384,41 @@ namespace bgfx
 						m_clearQuad.clear(rect, clear);
 						m_clearQuad.clear(rect, clear);
 					}
 					}
 
 
-					Rect& scissorRect = m_render->m_scissor[view];
-					scissor = !scissorRect.isZero();
-					if (scissor)
+					s_renderCtx.setBlendState(newFlags);
+					s_renderCtx.setDepthStencilState(newFlags, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) );
+
+					uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT);
+					if (primType != s_primType[primIndex])
 					{
 					{
+						primType = s_primType[primIndex];
+						primNumVerts = 3-primIndex;
+						deviceCtx->IASetPrimitiveTopology(primType);
+					}
+				}
+
+				uint16_t scissor = state.m_scissor;
+				if (currentState.m_scissor != scissor)
+				{
+					currentState.m_scissor = scissor;
+
+					if (UINT16_MAX == scissor)
+					{
+						const Rect& scissorRect = m_render->m_scissor[view];
+						scissorEnabled = !scissorRect.isZero();
+						if (scissorEnabled)
+						{
+							D3D11_RECT rc;
+							rc.left = scissorRect.m_x;
+							rc.top = scissorRect.m_y;
+							rc.right = scissorRect.m_x + scissorRect.m_width;
+							rc.bottom = scissorRect.m_y + scissorRect.m_height;
+							deviceCtx->RSSetScissorRects(1, &rc);
+						}
+					}
+					else
+					{
+						const Rect& scissorRect = m_render->m_rectCache.m_cache[scissor];
+						scissorEnabled = true;
 						D3D11_RECT rc;
 						D3D11_RECT rc;
 						rc.left = scissorRect.m_x;
 						rc.left = scissorRect.m_x;
 						rc.top = scissorRect.m_y;
 						rc.top = scissorRect.m_y;
@@ -2395,17 +2427,7 @@ namespace bgfx
 						deviceCtx->RSSetScissorRects(1, &rc);
 						deviceCtx->RSSetScissorRects(1, &rc);
 					}
 					}
 
 
-					s_renderCtx.setBlendState(BGFX_STATE_DEFAULT);
-					s_renderCtx.setDepthStencilState(BGFX_STATE_DEFAULT, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) );
-					s_renderCtx.setRasterizerState(BGFX_STATE_DEFAULT, wireframe, scissor);
-
-					uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT);
-					if (primType != s_primType[primIndex])
-					{
-						primType = s_primType[primIndex];
-						primNumVerts = 3-primIndex;
-						deviceCtx->IASetPrimitiveTopology(primType);
-					}
+					s_renderCtx.setRasterizerState(newFlags, wireframe, scissorEnabled);
 				}
 				}
 
 
 				if ( (BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
 				if ( (BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
@@ -2433,7 +2455,7 @@ namespace bgfx
 
 
 					if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_MSAA) & changedFlags)
 					if ( (BGFX_STATE_CULL_MASK|BGFX_STATE_MSAA) & changedFlags)
 					{
 					{
-						s_renderCtx.setRasterizerState(newFlags, wireframe, scissor);
+						s_renderCtx.setRasterizerState(newFlags, wireframe, scissorEnabled);
 					}
 					}
 
 
 					if (BGFX_STATE_ALPHA_REF_MASK & changedFlags)
 					if (BGFX_STATE_ALPHA_REF_MASK & changedFlags)

+ 32 - 11
src/renderer_d3d9.cpp

@@ -2287,6 +2287,7 @@ namespace bgfx
 				if (key.m_view != view)
 				if (key.m_view != view)
 				{
 				{
 					currentState.clear();
 					currentState.clear();
+					currentState.m_scissor = !state.m_scissor;
 					changedFlags = BGFX_STATE_MASK;
 					changedFlags = BGFX_STATE_MASK;
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					currentState.m_flags = newFlags;
 					currentState.m_flags = newFlags;
@@ -2354,11 +2355,38 @@ namespace bgfx
 						}
 						}
 					}
 					}
 
 
-					Rect& scissorRect = m_render->m_scissor[view];
-					bool scissor = !scissorRect.isZero();
-					DX_CHECK(device->SetRenderState(D3DRS_SCISSORTESTENABLE, scissor) );
-					if (scissor)
+					DX_CHECK(device->SetRenderState(D3DRS_STENCILENABLE, FALSE) );
+					DX_CHECK(device->SetRenderState(D3DRS_ZENABLE, TRUE) );
+					DX_CHECK(device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS) );
+					DX_CHECK(device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) );
+					DX_CHECK(device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE) );
+					DX_CHECK(device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER) );
+				}
+
+				uint16_t scissor = state.m_scissor;
+				if (currentState.m_scissor != scissor)
+				{
+					currentState.m_scissor = scissor;
+
+					if (UINT16_MAX == scissor)
+					{
+						const Rect& scissorRect = m_render->m_scissor[view];
+						bool scissorEnabled = !scissorRect.isZero();
+						DX_CHECK(device->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled) );
+						if (scissorEnabled)
+						{
+							RECT rc;
+							rc.left = scissorRect.m_x;
+							rc.top = scissorRect.m_y;
+							rc.right = scissorRect.m_x + scissorRect.m_width;
+							rc.bottom = scissorRect.m_y + scissorRect.m_height;
+							DX_CHECK(device->SetScissorRect(&rc) );
+						}
+					}
+					else
 					{
 					{
+						DX_CHECK(device->SetRenderState(D3DRS_SCISSORTESTENABLE, true) );
+						const Rect& scissorRect = m_render->m_rectCache.m_cache[scissor];
 						RECT rc;
 						RECT rc;
 						rc.left = scissorRect.m_x;
 						rc.left = scissorRect.m_x;
 						rc.top = scissorRect.m_y;
 						rc.top = scissorRect.m_y;
@@ -2366,13 +2394,6 @@ namespace bgfx
 						rc.bottom = scissorRect.m_y + scissorRect.m_height;
 						rc.bottom = scissorRect.m_y + scissorRect.m_height;
 						DX_CHECK(device->SetScissorRect(&rc) );
 						DX_CHECK(device->SetScissorRect(&rc) );
 					}
 					}
-
-					DX_CHECK(device->SetRenderState(D3DRS_STENCILENABLE, FALSE) );
-					DX_CHECK(device->SetRenderState(D3DRS_ZENABLE, TRUE) );
-					DX_CHECK(device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS) );
-					DX_CHECK(device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) );
-					DX_CHECK(device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE) );
-					DX_CHECK(device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER) );
 				}
 				}
 
 
 				if (0 != changedStencil)
 				if (0 != changedStencil)

+ 29 - 12
src/renderer_gl.cpp

@@ -2836,9 +2836,11 @@ namespace bgfx
 				if (key.m_view != view)
 				if (key.m_view != view)
 				{
 				{
 					currentState.clear();
 					currentState.clear();
+					currentState.m_scissor = !state.m_scissor;
 					changedFlags = BGFX_STATE_MASK;
 					changedFlags = BGFX_STATE_MASK;
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
 					currentState.m_flags = newFlags;
 					currentState.m_flags = newFlags;
+					currentState.m_stencil = newStencil;
 
 
 					GREMEDY_SETMARKER(s_viewName[key.m_view]);
 					GREMEDY_SETMARKER(s_viewName[key.m_view]);
 
 
@@ -2862,18 +2864,6 @@ namespace bgfx
 						m_clearQuad.clear(rect, clear, height);
 						m_clearQuad.clear(rect, clear, height);
 					}
 					}
 
 
-					Rect& scissorRect = m_render->m_scissor[view];
-					bool scissor = !scissorRect.isZero();
-					if (scissor)
-					{
-						GL_CHECK(glEnable(GL_SCISSOR_TEST) );
-						GL_CHECK(glScissor(scissorRect.m_x, height-scissorRect.m_height-scissorRect.m_y, scissorRect.m_width, scissorRect.m_height) );
-					}
-					else
-					{
-						GL_CHECK(glDisable(GL_SCISSOR_TEST) );
-					}
-
 					GL_CHECK(glDisable(GL_STENCIL_TEST) );
 					GL_CHECK(glDisable(GL_STENCIL_TEST) );
 					GL_CHECK(glEnable(GL_DEPTH_TEST) );
 					GL_CHECK(glEnable(GL_DEPTH_TEST) );
 					GL_CHECK(glDepthFunc(GL_LESS) );
 					GL_CHECK(glDepthFunc(GL_LESS) );
@@ -2881,6 +2871,33 @@ namespace bgfx
 					GL_CHECK(glDisable(GL_BLEND) );
 					GL_CHECK(glDisable(GL_BLEND) );
 				}
 				}
 
 
+				uint16_t scissor = state.m_scissor;
+				if (currentState.m_scissor != scissor)
+				{
+					currentState.m_scissor = scissor;
+
+					if (UINT16_MAX == scissor)
+					{
+						const Rect& scissorRect = m_render->m_scissor[view];
+						bool scissor = !scissorRect.isZero();
+						if (scissor)
+						{
+							GL_CHECK(glEnable(GL_SCISSOR_TEST) );
+							GL_CHECK(glScissor(scissorRect.m_x, height-scissorRect.m_height-scissorRect.m_y, scissorRect.m_width, scissorRect.m_height) );
+						}
+						else
+						{
+							GL_CHECK(glDisable(GL_SCISSOR_TEST) );
+						}
+					}
+					else
+					{
+						const Rect& scissorRect = m_render->m_rectCache.m_cache[scissor];
+						GL_CHECK(glEnable(GL_SCISSOR_TEST) );
+						GL_CHECK(glScissor(scissorRect.m_x, height-scissorRect.m_height-scissorRect.m_y, scissorRect.m_width, scissorRect.m_height) );
+					}
+				}
+
 				if (0 != changedStencil)
 				if (0 != changedStencil)
 				{
 				{
 					if (0 != newStencil)
 					if (0 != newStencil)