Added support for per primitive scissor.

This commit is contained in:
bkaradzic 2013-07-27 15:27:54 -07:00
parent a1e226cb5b
commit bac2073b76
7 changed files with 151 additions and 48 deletions

View file

@ -130,6 +130,7 @@ struct Imgui
, m_insideCurrentScroll(false)
, m_areaId(0)
, m_widgetId(0)
, m_scissor(UINT16_MAX)
, m_scrollTop(0)
, m_scrollBottom(0)
, m_scrollRight(0)
@ -403,7 +404,7 @@ struct Imgui
, 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;
}
@ -411,7 +412,7 @@ struct Imgui
void endScrollArea()
{
// Disable scissoring.
// setScissor(-1, -1, -1, -1);
m_scissor = UINT16_MAX;
// Draw scroll bar
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::setProgram(m_colorProgram);
bgfx::setScissor(m_scissor);
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::setProgram(m_textureProgram);
bgfx::setScissor(m_scissor);
bgfx::submit(m_view);
}
}
@ -1380,6 +1383,7 @@ struct Imgui
uint32_t m_areaId;
uint32_t m_widgetId;
uint16_t m_scissor;
float m_tempCoords[MAX_TEMP_COORDS * 2];
float m_tempNormals[MAX_TEMP_COORDS * 2];

View file

@ -853,9 +853,10 @@ namespace bgfx
/// 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
/// be rendered with identity model matrix.

View file

@ -651,6 +651,38 @@ namespace bgfx
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
{
uint32_t m_flags;
@ -860,7 +892,7 @@ namespace bgfx
m_instanceDataStride = 0;
m_numInstances = 1;
m_num = 1;
m_scissor = 0;
m_scissor = UINT16_MAX;
m_vertexBuffer.idx = invalidHandle;
m_vertexDecl.idx = invalidHandle;
m_indexBuffer.idx = invalidHandle;
@ -958,6 +990,7 @@ namespace bgfx
{
m_state.reset();
m_matrixCache.reset();
m_rectCache.reset();
m_key.reset();
m_num = 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)
{
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)
@ -1256,6 +1289,7 @@ namespace bgfx
uint16_t m_numDropped;
MatrixCache m_matrixCache;
RectCache m_rectCache;
uint32_t m_iboffset;
uint32_t m_vboffset;

View file

@ -127,6 +127,10 @@
# define BGFX_CONFIG_MAX_MATRIX_CACHE (16<<10)
#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
# define BGFX_CONFIG_MAX_VIEWS 32
#endif // BGFX_CONFIG_MAX_VIEWS

View file

@ -2314,7 +2314,7 @@ namespace bgfx
}
bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME);
bool scissor = false;
bool scissorEnabled = false;
s_renderCtx.setDebugWireframe(wireframe);
uint16_t programIdx = invalidHandle;
@ -2349,6 +2349,7 @@ namespace bgfx
if (key.m_view != view)
{
currentState.clear();
currentState.m_scissor = !state.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
@ -2383,21 +2384,8 @@ namespace bgfx
m_clearQuad.clear(rect, clear);
}
Rect& scissorRect = m_render->m_scissor[view];
scissor = !scissorRect.isZero();
if (scissor)
{
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);
}
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);
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])
@ -2408,6 +2396,40 @@ namespace bgfx
}
}
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;
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);
}
s_renderCtx.setRasterizerState(newFlags, wireframe, scissorEnabled);
}
if ( (BGFX_STATE_DEPTH_WRITE|BGFX_STATE_DEPTH_TEST_MASK) & changedFlags
|| 0 != changedStencil)
{
@ -2433,7 +2455,7 @@ namespace bgfx
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)

View file

@ -2287,6 +2287,7 @@ namespace bgfx
if (key.m_view != view)
{
currentState.clear();
currentState.m_scissor = !state.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
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;
rc.left = scissorRect.m_x;
rc.top = scissorRect.m_y;
@ -2366,13 +2394,6 @@ namespace bgfx
rc.bottom = scissorRect.m_y + scissorRect.m_height;
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)

View file

@ -2836,9 +2836,11 @@ namespace bgfx
if (key.m_view != view)
{
currentState.clear();
currentState.m_scissor = !state.m_scissor;
changedFlags = BGFX_STATE_MASK;
changedStencil = packStencil(BGFX_STENCIL_MASK, BGFX_STENCIL_MASK);
currentState.m_flags = newFlags;
currentState.m_stencil = newStencil;
GREMEDY_SETMARKER(s_viewName[key.m_view]);
@ -2862,18 +2864,6 @@ namespace bgfx
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(glEnable(GL_DEPTH_TEST) );
GL_CHECK(glDepthFunc(GL_LESS) );
@ -2881,6 +2871,33 @@ namespace bgfx
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 != newStencil)