diff --git a/include/bgfx.h b/include/bgfx.h index 2d18b682..6ca2aeb6 100644 --- a/include/bgfx.h +++ b/include/bgfx.h @@ -70,7 +70,7 @@ #define BGFX_STATE_SRGBWRITE UINT64_C(0x0010000000000000) #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_MASK UINT64_C(0xffffffffffffffff) @@ -640,18 +640,20 @@ namespace bgfx /// Allocate transient index buffer. /// - /// @param[out] _tib is valid for the duration of frame, and it can be - /// reused for multiple draw calls. - /// @param _num number of indices to allocate. + /// @param[out] _tib TransientIndexBuffer structure is filled and is valid + /// for the duration of frame, and it can be reused for multiple draw + /// calls. + /// @param _num Number of indices to allocate. /// void allocTransientIndexBuffer(TransientIndexBuffer* _tib, uint32_t _num); /// Allocate transient vertex buffer. /// - /// @param[out] _tvb is valid for the duration of frame, and it can be - /// reused for multiple draw calls. - /// @param _num number of vertices to allocate. - /// @param _decl vertex declaration. + /// @param[out] _tvb TransientVertexBuffer structure is filled and is valid + /// for the duration of frame, and it can be reused for multiple draw + /// calls. + /// @param _num Number of vertices to allocate. + /// @param _decl Vertex declaration. /// void allocTransientVertexBuffer(TransientVertexBuffer* _tvb, uint32_t _num, const VertexDecl& _decl); @@ -674,8 +676,8 @@ namespace bgfx /// Create program with vertex and fragment shaders. /// - /// @param _vsh vertex shader. - /// @param _fsh fragment shader. + /// @param _vsh Vertex shader. + /// @param _fsh Fragment shader. /// @returns Program handle if vertex shader output and fragment shader /// input are matching, otherwise returns invalid program handle. /// @@ -756,9 +758,17 @@ namespace bgfx /// Set view rectangle. Draw primitive outside view will be clipped. void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height); - /// 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); + /// 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. /// /// @param _id View id. @@ -843,11 +853,20 @@ namespace bgfx /// 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 /// be rendered with identity model matrix. /// - /// @param _mtx pointer to first matrix in array. - /// @param _num number of matrices in array. + /// @param _mtx Pointer to first matrix in array. + /// @param _num Number of matrices in array. /// @returns index into matrix cache in case the same model matrix has /// to be used for other draw primitive call. /// @@ -855,8 +874,8 @@ namespace bgfx /// Set model matrix from matrix cache for draw primitive. /// - /// @param _cache index in matrix cache. - /// @param _num number of matrices from cache. + /// @param _cache Index in matrix cache. + /// @param _num Number of matrices from cache. /// void setTransform(uint32_t _cache, uint16_t _num = 1); @@ -896,14 +915,14 @@ namespace bgfx /// Submit primitive for rendering into single view. /// /// @param _id View id. - /// @param _depth depth for sorting. + /// @param _depth Depth for sorting. /// void submit(uint8_t _id, int32_t _depth = 0); /// Submit primitive for rendering into multiple views. /// - /// @param _viewMask mask to which views to submit draw primitive calls. - /// @param _depth depth for sorting. + /// @param _viewMask Mask to which views to submit draw primitive calls. + /// @param _depth Depth for sorting. /// void submitMask(uint32_t _viewMask, int32_t _depth = 0); diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 1e56edcc..6694161d 100755 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -733,6 +733,7 @@ namespace bgfx memset(m_rt, 0xff, sizeof(m_rt) ); memset(m_clear, 0, sizeof(m_clear) ); memset(m_rect, 0, sizeof(m_rect) ); + memset(m_scissor, 0, sizeof(m_scissor) ); memset(m_seq, 0, sizeof(m_seq) ); memset(m_seqMask, 0, sizeof(m_seqMask) ); @@ -1305,6 +1306,18 @@ namespace bgfx 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) { BGFX_CHECK_MAIN_THREAD(); @@ -1371,6 +1384,18 @@ namespace bgfx 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) { BGFX_CHECK_MAIN_THREAD(); diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 9ee58b11..00192c2e 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -172,6 +172,12 @@ namespace bgfx struct Rect { + bool isZero() const + { + uint64_t ui64 = *( (uint64_t*)this); + return UINT64_C(0) == ui64; + } + uint16_t m_x; uint16_t m_y; uint16_t m_width; @@ -850,6 +856,7 @@ namespace bgfx m_instanceDataStride = 0; m_numInstances = 1; m_num = 1; + m_scissor = 0; m_vertexBuffer.idx = invalidHandle; m_vertexDecl.idx = invalidHandle; m_indexBuffer.idx = invalidHandle; @@ -876,6 +883,7 @@ namespace bgfx uint16_t m_instanceDataStride; uint16_t m_numInstances; uint16_t m_num; + uint16_t m_scissor; VertexBufferHandle m_vertexBuffer; VertexDeclHandle m_vertexDecl; @@ -994,6 +1002,18 @@ namespace bgfx 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) { m_state.m_matrix = m_matrixCache.add(_mtx, _num); @@ -1208,6 +1228,7 @@ namespace bgfx RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[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_proj[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) { 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_clear, m_clear, sizeof(m_clear) ); 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_proj, m_proj, sizeof(m_proj) ); memcpy(m_submit->m_other, m_other, sizeof(m_other) ); @@ -3068,6 +3110,7 @@ namespace bgfx RenderTargetHandle m_rt[BGFX_CONFIG_MAX_VIEWS]; Clear m_clear[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_proj[BGFX_CONFIG_MAX_VIEWS]; uint8_t m_other[BGFX_CONFIG_MAX_VIEWS]; diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 08374de6..263b7cd8 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -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 |= _wireframe ? BGFX_STATE_PT_LINES : BGFX_STATE_NONE; + _state |= _scissor ? BGFX_STATE_RESERVED_MASK : 0; ID3D11RasterizerState* rs = m_rasterizerStateCache.find(_state); if (NULL == rs) @@ -920,7 +921,7 @@ namespace bgfx desc.DepthBiasClamp = 0.0f; desc.SlopeScaledDepthBias = 0.0f; desc.DepthClipEnable = false; - desc.ScissorEnable = false; + desc.ScissorEnable = _scissor; desc.MultisampleEnable = !!(_state&BGFX_STATE_MSAA); desc.AntialiasedLineEnable = false; @@ -1367,7 +1368,7 @@ namespace bgfx s_renderCtx.setBlendState(state); s_renderCtx.setDepthStencilState(state); - s_renderCtx.setRasterizerState(state, false); + s_renderCtx.setRasterizerState(state); Program& program = s_renderCtx.m_program[m_program.idx]; s_renderCtx.m_currentProgram = &program; @@ -1446,7 +1447,7 @@ namespace bgfx s_renderCtx.setBlendState(state); s_renderCtx.setDepthStencilState(state, stencil); - s_renderCtx.setRasterizerState(state, false); + s_renderCtx.setRasterizerState(state); Program& program = s_renderCtx.m_program[m_program.idx]; s_renderCtx.m_currentProgram = &program; @@ -2308,6 +2309,7 @@ namespace bgfx } bool wireframe = !!(m_render->m_debug&BGFX_DEBUG_WIREFRAME); + bool scissor = false; s_renderCtx.setDebugWireframe(wireframe); uint16_t programIdx = invalidHandle; @@ -2376,9 +2378,21 @@ 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); + 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]) @@ -2415,7 +2429,7 @@ namespace bgfx 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) diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index ac294bcd..54fd9815 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -2257,7 +2257,6 @@ namespace bgfx } Rect& rect = m_render->m_rect[view]; - D3DVIEWPORT9 vp; vp.X = rect.m_x; 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_ZENABLE, TRUE) ); DX_CHECK(device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESS) ); diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index a25c821d..d0694eed 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -2739,6 +2739,18 @@ 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) );