Added view scissor support.

This commit is contained in:
bkaradzic 2013-07-14 14:32:09 -07:00
parent 59d6f3d8ee
commit f5edb6cdf4
6 changed files with 150 additions and 25 deletions

View file

@ -70,7 +70,7 @@
#define BGFX_STATE_SRGBWRITE UINT64_C(0x0010000000000000) #define BGFX_STATE_SRGBWRITE UINT64_C(0x0010000000000000)
#define BGFX_STATE_MSAA UINT64_C(0x0020000000000000) #define BGFX_STATE_MSAA UINT64_C(0x0020000000000000)
#define BGFX_STATE_RESERVED UINT64_C(0xff00000000000000) #define BGFX_STATE_RESERVED_MASK UINT64_C(0xff00000000000000)
#define BGFX_STATE_NONE UINT64_C(0x0000000000000000) #define BGFX_STATE_NONE UINT64_C(0x0000000000000000)
#define BGFX_STATE_MASK UINT64_C(0xffffffffffffffff) #define BGFX_STATE_MASK UINT64_C(0xffffffffffffffff)
@ -640,18 +640,20 @@ namespace bgfx
/// Allocate transient index buffer. /// Allocate transient index buffer.
/// ///
/// @param[out] _tib is valid for the duration of frame, and it can be /// @param[out] _tib TransientIndexBuffer structure is filled and is valid
/// reused for multiple draw calls. /// for the duration of frame, and it can be reused for multiple draw
/// @param _num number of indices to allocate. /// calls.
/// @param _num Number of indices to allocate.
/// ///
void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num); void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num);
/// Allocate transient vertex buffer. /// Allocate transient vertex buffer.
/// ///
/// @param[out] _tvb is valid for the duration of frame, and it can be /// @param[out] _tvb TransientVertexBuffer structure is filled and is valid
/// reused for multiple draw calls. /// for the duration of frame, and it can be reused for multiple draw
/// @param _num number of vertices to allocate. /// calls.
/// @param _decl vertex declaration. /// @param _num Number of vertices to allocate.
/// @param _decl Vertex declaration.
/// ///
void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl); void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl);
@ -674,8 +676,8 @@ namespace bgfx
/// Create program with vertex and fragment shaders. /// Create program with vertex and fragment shaders.
/// ///
/// @param _vsh vertex shader. /// @param _vsh Vertex shader.
/// @param _fsh fragment shader. /// @param _fsh Fragment shader.
/// @returns Program handle if vertex shader output and fragment shader /// @returns Program handle if vertex shader output and fragment shader
/// input are matching, otherwise returns invalid program handle. /// input are matching, otherwise returns invalid program handle.
/// ///
@ -759,6 +761,14 @@ namespace bgfx
/// Set view rectangle for multiple views. /// Set view rectangle for multiple views.
void setViewRectMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height); void setViewRectMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
/// Set view scissor. Draw primitive outside view will be clipped. When
/// _x, _y, _width and _height are set to 0, scissor will be disabled.
void setViewScissor(uint8_t _id, uint16_t _x = 0, uint16_t _y = 0, uint16_t _width = 0, uint16_t _height = 0);
/// Set view scissor for multiple views. When _x, _y, _width and _height
/// are set to 0, scissor will be disabled.
void setViewScissorMask(uint32_t _viewMask, uint16_t _x = 0, uint16_t _y = 0, uint16_t _width = 0, uint16_t _height = 0);
/// Set view clear flags. /// Set view clear flags.
/// ///
/// @param _id View id. /// @param _id View id.
@ -843,11 +853,20 @@ namespace bgfx
/// ///
void setStencil(uint32_t _fstencil, uint32_t _bstencil = BGFX_STENCIL_NONE); void setStencil(uint32_t _fstencil, uint32_t _bstencil = BGFX_STENCIL_NONE);
/// Set scissor for draw primitive.
uint16_t setScissor(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
/// Set scissor from cache for draw primitive.
///
/// @param _cache Index in scissor cache.
///
void setScissor(uint16_t _cache);
/// 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.
/// ///
/// @param _mtx pointer to first matrix in array. /// @param _mtx Pointer to first matrix in array.
/// @param _num number of matrices in array. /// @param _num Number of matrices in array.
/// @returns index into matrix cache in case the same model matrix has /// @returns index into matrix cache in case the same model matrix has
/// to be used for other draw primitive call. /// to be used for other draw primitive call.
/// ///
@ -855,8 +874,8 @@ namespace bgfx
/// Set model matrix from matrix cache for draw primitive. /// Set model matrix from matrix cache for draw primitive.
/// ///
/// @param _cache index in matrix cache. /// @param _cache Index in matrix cache.
/// @param _num number of matrices from cache. /// @param _num Number of matrices from cache.
/// ///
void setTransform(uint32_t _cache, uint16_t _num = 1); void setTransform(uint32_t _cache, uint16_t _num = 1);
@ -896,14 +915,14 @@ namespace bgfx
/// Submit primitive for rendering into single view. /// Submit primitive for rendering into single view.
/// ///
/// @param _id View id. /// @param _id View id.
/// @param _depth depth for sorting. /// @param _depth Depth for sorting.
/// ///
void submit(uint8_t _id, int32_t _depth = 0); void submit(uint8_t _id, int32_t _depth = 0);
/// Submit primitive for rendering into multiple views. /// Submit primitive for rendering into multiple views.
/// ///
/// @param _viewMask mask to which views to submit draw primitive calls. /// @param _viewMask Mask to which views to submit draw primitive calls.
/// @param _depth depth for sorting. /// @param _depth Depth for sorting.
/// ///
void submitMask(uint32_t _viewMask, int32_t _depth = 0); void submitMask(uint32_t _viewMask, int32_t _depth = 0);

View file

@ -733,6 +733,7 @@ namespace bgfx
memset(m_rt, 0xff, sizeof(m_rt) ); memset(m_rt, 0xff, sizeof(m_rt) );
memset(m_clear, 0, sizeof(m_clear) ); memset(m_clear, 0, sizeof(m_clear) );
memset(m_rect, 0, sizeof(m_rect) ); memset(m_rect, 0, sizeof(m_rect) );
memset(m_scissor, 0, sizeof(m_scissor) );
memset(m_seq, 0, sizeof(m_seq) ); memset(m_seq, 0, sizeof(m_seq) );
memset(m_seqMask, 0, sizeof(m_seqMask) ); memset(m_seqMask, 0, sizeof(m_seqMask) );
@ -1305,6 +1306,18 @@ namespace bgfx
s_ctx.setViewRectMask(_viewMask, _x, _y, _width, _height); s_ctx.setViewRectMask(_viewMask, _x, _y, _width, _height);
} }
void setViewScissor(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx.setViewScissor(_id, _x, _y, _width, _height);
}
void setViewScissorMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx.setViewScissorMask(_viewMask, _x, _y, _width, _height);
}
void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
{ {
BGFX_CHECK_MAIN_THREAD(); BGFX_CHECK_MAIN_THREAD();
@ -1371,6 +1384,18 @@ namespace bgfx
s_ctx.m_submit->setStencil(_fstencil, _bstencil); s_ctx.m_submit->setStencil(_fstencil, _bstencil);
} }
uint16_t setScissor(uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
{
BGFX_CHECK_MAIN_THREAD();
return s_ctx.m_submit->setScissor(_x, _y, _width, _height);
}
void setScissor(uint16_t _cache)
{
BGFX_CHECK_MAIN_THREAD();
s_ctx.m_submit->setScissor(_cache);
}
uint32_t setTransform(const void* _mtx, uint16_t _num) uint32_t setTransform(const void* _mtx, uint16_t _num)
{ {
BGFX_CHECK_MAIN_THREAD(); BGFX_CHECK_MAIN_THREAD();

View file

@ -172,6 +172,12 @@ namespace bgfx
struct Rect struct Rect
{ {
bool isZero() const
{
uint64_t ui64 = *( (uint64_t*)this);
return UINT64_C(0) == ui64;
}
uint16_t m_x; uint16_t m_x;
uint16_t m_y; uint16_t m_y;
uint16_t m_width; uint16_t m_width;
@ -850,6 +856,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_vertexBuffer.idx = invalidHandle; m_vertexBuffer.idx = invalidHandle;
m_vertexDecl.idx = invalidHandle; m_vertexDecl.idx = invalidHandle;
m_indexBuffer.idx = invalidHandle; m_indexBuffer.idx = invalidHandle;
@ -876,6 +883,7 @@ namespace bgfx
uint16_t m_instanceDataStride; uint16_t m_instanceDataStride;
uint16_t m_numInstances; uint16_t m_numInstances;
uint16_t m_num; uint16_t m_num;
uint16_t m_scissor;
VertexBufferHandle m_vertexBuffer; VertexBufferHandle m_vertexBuffer;
VertexDeclHandle m_vertexDecl; VertexDeclHandle m_vertexDecl;
@ -994,6 +1002,18 @@ namespace bgfx
m_state.m_stencil = packStencil(_fstencil, _bstencil); m_state.m_stencil = packStencil(_fstencil, _bstencil);
} }
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;
}
void setScissor(uint16_t _cache)
{
m_state.m_scissor = _cache;
}
uint32_t setTransform(const void* _mtx, uint16_t _num) uint32_t setTransform(const void* _mtx, uint16_t _num)
{ {
m_state.m_matrix = m_matrixCache.add(_mtx, _num); m_state.m_matrix = m_matrixCache.add(_mtx, _num);
@ -1208,6 +1228,7 @@ namespace bgfx
RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS];
Clear m_clear[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[BGFX_CONFIG_MAX_VIEWS];
Rect m_rect[BGFX_CONFIG_MAX_VIEWS]; Rect m_rect[BGFX_CONFIG_MAX_VIEWS];
Rect m_scissor[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS]; Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_proj[BGFX_CONFIG_MAX_VIEWS]; Matrix4 m_proj[BGFX_CONFIG_MAX_VIEWS];
uint8_t m_other[BGFX_CONFIG_MAX_VIEWS]; uint8_t m_other[BGFX_CONFIG_MAX_VIEWS];
@ -2209,6 +2230,26 @@ namespace bgfx
} }
} }
void setViewScissor(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
{
Rect& scissor = m_scissor[_id];
scissor.m_x = _x;
scissor.m_y = _y;
scissor.m_width = _width;
scissor.m_height = _height;
}
void setViewScissorMask(uint32_t _viewMask, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height)
{
for (uint32_t id = 0, viewMask = _viewMask, ntz = uint32_cnttz(_viewMask); 0 != viewMask; viewMask >>= 1, id += 1, ntz = uint32_cnttz(viewMask) )
{
viewMask >>= ntz;
id += ntz;
setViewScissor(id, _x, _y, _width, _height);
}
}
void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil) void setViewClear(uint8_t _id, uint8_t _flags, uint32_t _rgba, float _depth, uint8_t _stencil)
{ {
Clear& clear = m_clear[_id]; Clear& clear = m_clear[_id];
@ -2387,6 +2428,7 @@ namespace bgfx
memcpy(m_submit->m_rt, m_rt, sizeof(m_rt) ); memcpy(m_submit->m_rt, m_rt, sizeof(m_rt) );
memcpy(m_submit->m_clear, m_clear, sizeof(m_clear) ); memcpy(m_submit->m_clear, m_clear, sizeof(m_clear) );
memcpy(m_submit->m_rect, m_rect, sizeof(m_rect) ); memcpy(m_submit->m_rect, m_rect, sizeof(m_rect) );
memcpy(m_submit->m_scissor, m_scissor, sizeof(m_scissor) );
memcpy(m_submit->m_view, m_view, sizeof(m_view) ); memcpy(m_submit->m_view, m_view, sizeof(m_view) );
memcpy(m_submit->m_proj, m_proj, sizeof(m_proj) ); memcpy(m_submit->m_proj, m_proj, sizeof(m_proj) );
memcpy(m_submit->m_other, m_other, sizeof(m_other) ); memcpy(m_submit->m_other, m_other, sizeof(m_other) );
@ -3068,6 +3110,7 @@ namespace bgfx
RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS];
Clear m_clear[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[BGFX_CONFIG_MAX_VIEWS];
Rect m_rect[BGFX_CONFIG_MAX_VIEWS]; Rect m_rect[BGFX_CONFIG_MAX_VIEWS];
Rect m_scissor[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS]; Matrix4 m_view[BGFX_CONFIG_MAX_VIEWS];
Matrix4 m_proj[BGFX_CONFIG_MAX_VIEWS]; Matrix4 m_proj[BGFX_CONFIG_MAX_VIEWS];
uint8_t m_other[BGFX_CONFIG_MAX_VIEWS]; uint8_t m_other[BGFX_CONFIG_MAX_VIEWS];

View file

@ -902,10 +902,11 @@ namespace bgfx
} }
} }
void setRasterizerState(uint64_t _state, bool _wireframe = false) void setRasterizerState(uint64_t _state, bool _wireframe = false, bool _scissor = false)
{ {
_state &= BGFX_STATE_CULL_MASK|BGFX_STATE_MSAA; _state &= BGFX_STATE_CULL_MASK|BGFX_STATE_MSAA;
_state |= _wireframe ? BGFX_STATE_PT_LINES : BGFX_STATE_NONE; _state |= _wireframe ? BGFX_STATE_PT_LINES : BGFX_STATE_NONE;
_state |= _scissor ? BGFX_STATE_RESERVED_MASK : 0;
ID3D11RasterizerState* rs = m_rasterizerStateCache.find(_state); ID3D11RasterizerState* rs = m_rasterizerStateCache.find(_state);
if (NULL == rs) if (NULL == rs)
@ -920,7 +921,7 @@ namespace bgfx
desc.DepthBiasClamp = 0.0f; desc.DepthBiasClamp = 0.0f;
desc.SlopeScaledDepthBias = 0.0f; desc.SlopeScaledDepthBias = 0.0f;
desc.DepthClipEnable = false; desc.DepthClipEnable = false;
desc.ScissorEnable = false; desc.ScissorEnable = _scissor;
desc.MultisampleEnable = !!(_state&BGFX_STATE_MSAA); desc.MultisampleEnable = !!(_state&BGFX_STATE_MSAA);
desc.AntialiasedLineEnable = false; desc.AntialiasedLineEnable = false;
@ -1367,7 +1368,7 @@ namespace bgfx
s_renderCtx.setBlendState(state); s_renderCtx.setBlendState(state);
s_renderCtx.setDepthStencilState(state); s_renderCtx.setDepthStencilState(state);
s_renderCtx.setRasterizerState(state, false); s_renderCtx.setRasterizerState(state);
Program& program = s_renderCtx.m_program[m_program.idx]; Program& program = s_renderCtx.m_program[m_program.idx];
s_renderCtx.m_currentProgram = &program; s_renderCtx.m_currentProgram = &program;
@ -1446,7 +1447,7 @@ namespace bgfx
s_renderCtx.setBlendState(state); s_renderCtx.setBlendState(state);
s_renderCtx.setDepthStencilState(state, stencil); s_renderCtx.setDepthStencilState(state, stencil);
s_renderCtx.setRasterizerState(state, false); s_renderCtx.setRasterizerState(state);
Program& program = s_renderCtx.m_program[m_program.idx]; Program& program = s_renderCtx.m_program[m_program.idx];
s_renderCtx.m_currentProgram = &program; s_renderCtx.m_currentProgram = &program;
@ -2308,6 +2309,7 @@ namespace bgfx
} }
bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME); bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME);
bool scissor = false;
s_renderCtx.setDebugWireframe(wireframe); s_renderCtx.setDebugWireframe(wireframe);
uint16_t programIdx = invalidHandle; uint16_t programIdx = invalidHandle;
@ -2376,9 +2378,21 @@ namespace bgfx
m_clearQuad.clear(rect, clear); 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.setBlendState(BGFX_STATE_DEFAULT);
s_renderCtx.setDepthStencilState(BGFX_STATE_DEFAULT, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) ); s_renderCtx.setDepthStencilState(BGFX_STATE_DEFAULT, packStencil(BGFX_STENCIL_DEFAULT, BGFX_STENCIL_DEFAULT) );
s_renderCtx.setRasterizerState(BGFX_STATE_DEFAULT, wireframe); s_renderCtx.setRasterizerState(BGFX_STATE_DEFAULT, wireframe, scissor);
uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT); uint8_t primIndex = uint8_t( (newFlags&BGFX_STATE_PT_MASK)>>BGFX_STATE_PT_SHIFT);
if (primType != s_primType[primIndex]) if (primType != s_primType[primIndex])
@ -2415,7 +2429,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); s_renderCtx.setRasterizerState(newFlags, wireframe, scissor);
} }
if (BGFX_STATE_ALPHA_REF_MASK & changedFlags) if (BGFX_STATE_ALPHA_REF_MASK & changedFlags)

View file

@ -2257,7 +2257,6 @@ namespace bgfx
} }
Rect& rect = m_render->m_rect[view]; Rect& rect = m_render->m_rect[view];
D3DVIEWPORT9 vp; D3DVIEWPORT9 vp;
vp.X = rect.m_x; vp.X = rect.m_x;
vp.Y = rect.m_y; vp.Y = rect.m_y;
@ -2307,6 +2306,19 @@ namespace bgfx
} }
} }
Rect& scissorRect = m_render->m_scissor[view];
bool scissor = !scissorRect.isZero();
DX_CHECK(device->SetRenderState(D3DRS_SCISSORTESTENABLE, scissor) );
if (scissor)
{
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) );
}
DX_CHECK(device->SetRenderState(D3DRS_STENCILENABLE, FALSE) ); DX_CHECK(device->SetRenderState(D3DRS_STENCILENABLE, FALSE) );
DX_CHECK(device->SetRenderState(D3DRS_ZENABLE, TRUE) ); DX_CHECK(device->SetRenderState(D3DRS_ZENABLE, TRUE) );
DX_CHECK(device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS) ); DX_CHECK(device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS) );

View file

@ -2739,6 +2739,18 @@ 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) );