* @param[in] item The current RenderItem about to be rendered
* @param[in] context The context
*/
-inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context, int orientation )
+inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context )
{
// Get the number of child scissors in the stack (do not include layer or root box).
size_t childStackDepth = mScissorStack.size() - 1u;
// This is a clipping node. We generate the AABB for this node and intersect it with the previous intersection further up the tree.
// Get the AABB bounding box for the current render item.
- const ClippingBox scissorBox( item.CalculateViewportSpaceAABB( mViewportRectangle.width, mViewportRectangle.height ) );
+ const ClippingBox scissorBox( item.CalculateViewportSpaceAABB( item.mSize, mViewportRectangle.width, mViewportRectangle.height ) );
// Get the AABB for the parent item that we must intersect with.
const ClippingBox& parentBox( mScissorStack.back() );
if( scissorEnabled )
{
ClippingBox useScissorBox( mScissorStack.back() );
- GLint x = useScissorBox.x;
- GLint y = useScissorBox.y;
- if( orientation == 90 )
- {
- x = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
- y = useScissorBox.x;
- context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
- }
- else if( orientation == 180 )
- {
- x = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
- y = mViewportRectangle.height - (useScissorBox.y + useScissorBox.height);
- context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
- }
- else if( orientation == 270 )
- {
- x = useScissorBox.y;
- y = mViewportRectangle.width - (useScissorBox.x + useScissorBox.width);
- context.Scissor( x, y, useScissorBox.height, useScissorBox.width );
- }
- else
- {
- context.Scissor( x, y, useScissorBox.width, useScissorBox.height );
- }
+ context.Scissor( useScissorBox.x, useScissorBox.y, useScissorBox.width, useScissorBox.height );
}
}
}
bool& usedStencilBuffer,
uint32_t& lastClippingDepth,
uint32_t& lastClippingId,
- Integration::StencilBufferAvailable stencilBufferAvailable,
- int orientation )
+ Integration::StencilBufferAvailable stencilBufferAvailable )
{
RenderMode::Type renderMode = RenderMode::AUTO;
const Renderer *renderer = item.mRenderer;
// As both scissor and stencil clips can be nested, we may be simultaneously traversing up the scissor tree, requiring a scissor to be un-done. Whilst simultaneously adding a new stencil clip.
// We process both based on our current and old clipping depths for each mode.
// Both methods with return rapidly if there is nothing to be done for that type of clipping.
- SetupScissorClipping( item, context, orientation );
+ SetupScissorClipping( item, context );
if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE )
{
Integration::StencilBufferAvailable stencilBufferAvailable,
Vector<GLuint>& boundTextures,
const RenderInstruction& instruction,
- int orientation )
+ const Rect<int>& rootClippingRect
+ )
{
DALI_PRINT_RENDER_LIST( renderList );
mViewportRectangle = context.GetViewport();
mHasLayerScissor = false;
- if( orientation == 90 || orientation == 270 )
+ // Setup Scissor testing (for both viewport and per-node scissor)
+ mScissorStack.clear();
+
+ // Add root clipping rect (set manually for Render function ny partial update for example)
+ // on the bottom of the stack
+ if (!rootClippingRect.IsEmpty())
+ {
+ context.SetScissorTest( true );
+ context.Scissor( rootClippingRect.x, rootClippingRect.y, rootClippingRect.width, rootClippingRect.height );
+ mScissorStack.push_back( rootClippingRect );
+ }
+ // We are not performing a layer clip and no clipping rect set. Add the viewport as the root scissor rectangle.
+ else if (!renderList.IsClipping())
{
- int temp = mViewportRectangle.width;
- mViewportRectangle.width = mViewportRectangle.height;
- mViewportRectangle.height = temp;
+ context.SetScissorTest( false );
+ mScissorStack.push_back( mViewportRectangle );
}
- // Setup Scissor testing (for both viewport and per-node scissor)
- mScissorStack.clear();
if( renderList.IsClipping() )
{
context.SetScissorTest( true );
const ClippingBox& layerScissorBox = renderList.GetClippingBox();
- GLint x = layerScissorBox.x;
- GLint y = layerScissorBox.y;
-
- if( orientation == 90 )
- {
- x = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
- y = layerScissorBox.x;
- context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
- }
- else if( orientation == 180 )
- {
- x = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
- y = mViewportRectangle.height - (layerScissorBox.y + layerScissorBox.height);
- context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
- }
- else if( orientation == 270 )
- {
- x = layerScissorBox.y;
- y = mViewportRectangle.width - (layerScissorBox.x + layerScissorBox.width);
- context.Scissor( x, y, layerScissorBox.height, layerScissorBox.width );
- }
- else
- {
- context.Scissor( x, y, layerScissorBox.width, layerScissorBox.height );
- }
-
+ context.Scissor( layerScissorBox.x, layerScissorBox.y, layerScissorBox.width, layerScissorBox.height );
mScissorStack.push_back( layerScissorBox );
mHasLayerScissor = true;
}
- else
- {
- // We are not performing a layer clip. Add the viewport as the root scissor rectangle.
- context.SetScissorTest( false );
- mScissorStack.push_back( mViewportRectangle );
- }
// Loop through all RenderList in the RenderList, set up any prerequisites to render them, then perform the render.
for( uint32_t index = 0u; index < count; ++index )
{
const RenderItem& item = renderList.GetItem( index );
+
+ // Discard renderers outside the root clipping rect
+ bool skip = true;
+ if( !rootClippingRect.IsEmpty() )
+ {
+ auto rect = item.CalculateViewportSpaceAABB( item.mUpdateSize, mViewportRectangle.width, mViewportRectangle.height );
+
+ if(rect.Intersect( rootClippingRect ))
+ {
+ skip = false;
+ }
+ }
+ else
+ {
+ skip = false;
+ }
+
DALI_PRINT_RENDER_ITEM( item );
// Set up clipping based on both the Renderer and Actor APIs.
// The Renderer API will be used if specified. If AUTO, the Actors automatic clipping feature will be used.
- SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, orientation );
+ SetupClipping( item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable );
if( DALI_LIKELY( item.mRenderer ) )
{
// draw-mode state, such as Overlays.
// If the flags are set to "AUTO", the behavior then depends on the type of renderer. Overlay Renderers will always
// disable depth testing and writing. Color Renderers will enable them if the Layer does.
- if( depthBufferAvailable == Integration::DepthBufferAvailable::TRUE )
+ if (depthBufferAvailable == Integration::DepthBufferAvailable::TRUE)
{
- SetupDepthBuffer( item, context, autoDepthTestMode, firstDepthBufferUse );
+ SetupDepthBuffer(item, context, autoDepthTestMode, firstDepthBufferUse);
}
- // Render the item.
- item.mRenderer->Render( context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
- viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction ); // Added instruction for reflection effect
+ // Depending on whether the renderer has draw commands attached or not the rendering process will
+ // iterate through all the render queues. If there are no draw commands attached, only one
+ // iteration must be done and the default behaviour of the renderer will be executed.
+ // The queues allow to iterate over the same renderer multiple times changing the state of the renderer.
+ // It is similar to the multi-pass rendering.
+ if( !skip )
+ {
+ auto const MAX_QUEUE = item.mRenderer->GetDrawCommands().empty() ? 1 : DevelRenderer::RENDER_QUEUE_MAX;
+ for (auto queue = 0u; queue < MAX_QUEUE; ++queue)
+ {
+ // Render the item.
+ item.mRenderer->Render(context, bufferIndex, *item.mNode, item.mModelMatrix, item.mModelViewMatrix,
+ viewMatrix, projectionMatrix, item.mSize, !item.mIsOpaque, boundTextures, instruction, queue);
+ }
+ }
}
}
}
Integration::DepthBufferAvailable depthBufferAvailable,
Integration::StencilBufferAvailable stencilBufferAvailable,
Vector<GLuint>& boundTextures,
- int orientation )
+ const Rect<int>& rootClippingRect )
{
DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
stencilBufferAvailable,
boundTextures,
instruction, //added for reflection effect
- orientation );
+ rootClippingRect );
}
}
}