#include <test-native-image.h>
#include <iostream>
+#include "test-application.h"
#define BOOLSTR(x) ((x) ? "T" : "F")
END_TEST;
}
-int UtcDaliRenderTaskRenderUntil(void)
+int UtcDaliRenderTaskRenderUntil01(void)
{
TestApplication application;
- tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the actor.");
+ tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the renderable actor.");
- // Make a new render task and compose a tree.
+ // Get default rendertask
RenderTaskList taskList = application.GetScene().GetRenderTaskList();
RenderTask task = taskList.GetTask(0u);
END_TEST;
}
+int UtcDaliRenderTaskRenderUntil02(void)
+{
+ TestApplication application;
+ tet_infoline("Testing RenderTask::RenderUntil(actor) Check that rendering stops at the empty actor.");
+
+ // Get default rendertask
+ RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+ RenderTask task = taskList.GetTask(0u);
+
+ Integration::Scene stage = application.GetScene();
+
+ Actor secondChild;
+ for(int i = 0; i < 5; i++)
+ {
+ Actor parent = CreateRenderableActor();
+ parent.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+ parent.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ Actor child = Actor::New(); // Has no renderer
+ child.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ stage.Add(parent);
+ parent.Add(child);
+
+ if (i == 1)
+ {
+ secondChild = child;
+ }
+ }
+ task.RenderUntil(secondChild);
+
+ // Update & Render with the actor on-stage
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& drawTrace = gl.GetDrawTrace();
+ drawTrace.Enable(true);
+
+ // Update & Render
+ application.SendNotification();
+ application.Render();
+
+ // Check that rendering was cut.
+ DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliRenderTaskRenderUntil03(void)
+{
+ TestApplication application;
+ tet_infoline("Testing RenderTask::RenderUntil(actor) Check that other preceding layers are rendered.");
+
+ // Get default rendertask
+ RenderTaskList taskList = application.GetScene().GetRenderTaskList();
+ RenderTask task = taskList.GetTask(0u);
+
+ Integration::Scene stage = application.GetScene();
+
+ // Compose a tree
+ Actor a0 = CreateRenderableActor();
+ a0.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+ a0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ Layer l0 = Layer::New();
+ l0.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+ l0.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+ l0.LowerToBottom(); // drawn later
+
+ Actor a1 = CreateRenderableActor();
+ a1.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ Actor target = CreateRenderableActor();
+ target.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ Layer l2 = Layer::New(); // same depth index to root, added(drawn) later
+ l2.SetProperty(Actor::Property::SIZE, Vector2(10.0f, 10.0f));
+ l2.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
+
+ Actor a2 = CreateRenderableActor();
+ a2.SetProperty(Actor::Property::SIZE, Vector2(1.0f, 1.0f));
+
+ stage.Add(a0);
+ a0.Add(l0);
+ l0.Add(CreateRenderableActor());
+
+ stage.Add(a1);
+ a1.Add(target);
+
+ stage.Add(a2);
+ a2.Add(l2);
+ l2.Add(CreateRenderableActor());
+
+ // draw only a0 and a1 (2 items)
+ // l0 and children is cut(low depth index)
+ // a2 and children are cut(added after target)
+ task.RenderUntil(target);
+
+ // Update & Render with the actor on-stage
+ TestGlAbstraction& gl = application.GetGlAbstraction();
+ TraceCallStack& drawTrace = gl.GetDrawTrace();
+ drawTrace.Enable(true);
+
+ // Update & Render
+ application.SendNotification();
+ application.Render();
+
+ // Check that rendering was cut
+ DALI_TEST_EQUALS(drawTrace.CountMethod("DrawElements"), 2, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliRenderTaskSetExclusive(void)
{
TestApplication application;
return mRenderTaskId;
}
-void RenderTask::RenderUntil(Actor* actor)
+void RenderTask::RenderUntil(Actor* stopperActor)
{
Actor* target = mSourceActor.GetActor();
- DALI_ASSERT_ALWAYS((target && actor)
+ DALI_ASSERT_ALWAYS((target && stopperActor)
&& "RenderTask::RenderUntil() has empty actors.");
- DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < actor->GetHierarchyDepth())
+ DALI_ASSERT_ALWAYS((target->GetHierarchyDepth() < stopperActor->GetHierarchyDepth())
&& "RenderTask::RenderUntil() has reversed hierarchy.");
- Actor* parent = actor;
+ Actor* parent = stopperActor;
while(parent != target && !(parent->IsLayer()))
{
parent = parent->GetParent();
if(parent == target && GetRenderTaskSceneObject())
{
- mStopperActor.SetActor(actor);
- SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &actor->GetNode());
+ mStopperActor.SetActor(stopperActor);
+ SetStopperNodeMessage(GetEventThreadServices(), *GetRenderTaskSceneObject(), &stopperActor->GetNode());
}
}
*/
Actor* GetSourceActor() const;
+ /**
+ * @copydoc Dali::RenderTask::GetStopperActor()
+ */
Actor* GetStopperActor() const;
/**
*/
uint32_t GetRenderTaskId() const;
- void RenderUntil(Actor* actor);
+ /**
+ * @copydoc Dali::RenderTask::RenderUntil
+ */
+ void RenderUntil(Actor* stopperActor);
public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks
/**
// EXTERNAL INCLUDES
#include <cstdint>
+#include <dali/internal/update/nodes/node.h>
// INTERNAL INCLUDES
#include <dali/devel-api/common/owner-container.h>
}
}
+ /**
+ * Trim the list by stopperNode
+ * @param stopperNode The node to stop rendering. Rendering will not include the node.
+ * @return Whether trimming actually occured.
+ */
+ bool RenderUntil(Node* stopperNode)
+ {
+ RenderItemContainer::Iterator iter = mItems.Begin();
+ for(uint32_t index = 0u; iter != mItems.End(); ++iter, ++index)
+ {
+ RenderItem* item = iter->Get();
+ if(item->mNode == stopperNode)
+ {
+ mNextFree = index;
+ ReleaseUnusedItems();
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* @return the source layer these renderitems originate from
*/
* @param viewportSet Whether the viewport is set or not
* @param viewport The viewport
* @param cullingEnabled Whether frustum culling is enabled or not
+ * @param stopperNode Marker node that stops rendering(must be rendered)
*/
inline void AddRendererToRenderList(BufferIndex updateBufferIndex,
uint32_t renderPass,
bool isLayer3d,
bool viewportSet,
const Viewport& viewport,
- bool cullingEnabled)
+ bool cullingEnabled,
+ Node* stopperNode)
{
bool inside(true);
Node* node = renderable.mNode;
bool hasRenderCallback = (rendererExist && renderable.mRenderer->GetRenderCallback());
auto requiredInsideCheck = [&]() {
- if(cullingEnabled &&
+ if(node != stopperNode &&
+ cullingEnabled &&
!hasRenderCallback &&
node->GetClippingMode() == ClippingMode::DISABLED &&
rendererExist)
const Renderer::OpacityType opacityType = rendererExist ? (isVisualRendererUnder3D ? Renderer::TRANSLUCENT : renderable.mRenderer->GetOpacityType(updateBufferIndex, renderPass, *node)) : Renderer::OPAQUE;
// We can skip render when node is not clipping and transparent
- skipRender = (opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
+ // We must not skip when node is a stopper
+ skipRender = (opacityType == Renderer::TRANSPARENT &&
+ node->GetClippingMode() == ClippingMode::DISABLED &&
+ node != stopperNode);
isOpaque = (opacityType == Renderer::OPAQUE);
}
* @param viewportSet Whether the viewport is set or not
* @param viewport The viewport
* @param cullingEnabled Whether frustum culling is enabled or not
+ * @param stopperNode Marker node that stops rendering(must be rendered)
*/
inline void AddRenderersToRenderList(BufferIndex updateBufferIndex,
uint32_t renderPass,
bool isLayer3d,
bool viewportSet,
const Viewport& viewport,
- bool cullingEnabled)
+ bool cullingEnabled,
+ Node* stopperNode)
{
DALI_LOG_INFO(gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
isLayer3d,
viewportSet,
viewport,
- cullingEnabled);
+ cullingEnabled,
+ stopperNode);
}
}
Viewport viewport;
bool viewportSet = renderTask.QueryViewport(updateBufferIndex, viewport);
+ Node* stopperNode = renderTask.GetStopperNode();
+
const SortedLayersIter endIter = sortedLayers.end();
for(SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter)
{
isLayer3D,
viewportSet,
viewport,
- cull);
+ cull,
+ stopperNode);
// We only use the clipping version of the sort comparitor if any clipping nodes exist within the RenderList.
SortRenderItems(updateBufferIndex, *renderList, layer, hasClippingNodes, isOrthographicCamera);
}
isRenderListAdded = true;
+
+ if(stopperNode && renderList->RenderUntil(stopperNode))
+ {
+ break;
+ }
}
if(!layer.overlayRenderables.Empty())
isLayer3D,
viewportSet,
viewport,
- cull);
+ cull,
+ stopperNode);
// Clipping hierarchy is irrelevant when sorting overlay items, so we specify using the non-clipping version of the sort comparitor.
SortRenderItems(updateBufferIndex, *renderList, layer, false, isOrthographicCamera);
}
isRenderListAdded = true;
+
+ if(stopperNode && renderList->RenderUntil(stopperNode))
+ {
+ break;
+ }
}
}
* @param[in] clippingDepth The current scissor clipping depth
* @param[out] clippingUsed Gets set to true if any clipping nodes have been found
* @param[out] keepRendering Gets set to true if rendering should be kept.
- * @param[out] renderStopped Gets set to true if rendering should be stopped.
*/
void AddRenderablesForTask(BufferIndex updateBufferIndex,
Node& node,
uint32_t clippingDepth,
uint32_t scissorDepth,
bool& clippingUsed,
- bool& keepRendering,
- bool& renderStopped)
+ bool& keepRendering)
{
- if(renderStopped)
- {
- return;
- }
-
// Short-circuit for invisible nodes
if(!node.IsVisible(updateBufferIndex))
{
keepRendering = keepRendering || (rendererKey->GetRenderingBehavior() == DevelRenderer::Rendering::CONTINUOUSLY);
}
+ if(DALI_UNLIKELY(node == renderTask.GetStopperNode() && count == 0u))
+ {
+ // Forcibly add renderables if stopper node don't have renderer.
+ target.PushBack(Renderable(&node, RendererKey{}));
+ }
+
// Recurse children.
NodeContainer& children = node.GetChildren();
const NodeIter endIter = children.End();
- for(NodeIter iter = children.Begin(); !renderStopped && iter != endIter; ++iter)
+ for(NodeIter iter = children.Begin(); iter != endIter; ++iter)
{
Node& child = **iter;
- if(child == renderTask.GetStopperNode())
- {
- renderStopped = true;
- break;
- }
- AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering, renderStopped);
+ AddRenderablesForTask(updateBufferIndex, child, parentVisibilityChanged, *layer, renderTask, inheritedDrawMode, currentClippingId, clippingDepth, scissorDepth, clippingUsed, keepRendering);
}
}
sortedLayer->ClearRenderables();
}
- bool stopRendering = false;
-
AddRenderablesForTask(updateBufferIndex,
*sourceNode,
false,
0u,
0u,
hasClippingNodes,
- keepRendering,
- stopRendering);
+ keepRendering);
renderInstructionProcessor.Prepare(updateBufferIndex,
sortedLayers,
mRenderMessageDispatcher(nullptr),
mRenderSyncTracker(nullptr),
mSourceNode(nullptr),
+ mStopperNode(nullptr),
mCameraNode(nullptr),
mViewportGuideNode(nullptr),
mFrameBuffer(nullptr),
*/
Node* GetSourceNode() const;
+ /**
+ * Set the node to stop rendering.
+ * @param[in] node This node will mark where to stop rendering.
+ */
void SetStopperNode(Node* node);
+
+ /**
+ * Retrieve the stopper node.
+ * @return A marker node to stop rendering.
+ */
Node* GetStopperNode() const;
/**
return GetImplementation(*this).GetRenderTaskId();
}
-void RenderTask::RenderUntil(Actor actor)
+void RenderTask::RenderUntil(Actor stopperActor)
{
- DALI_ASSERT_ALWAYS(actor && "RenderUntil() actor does not exist.");
- Internal::Actor* actorImpl(&GetImplementation(actor));
+ DALI_ASSERT_ALWAYS(stopperActor && "RenderUntil() stopperActor does not exist.");
+ Internal::Actor* actorImpl(&GetImplementation(stopperActor));
return GetImplementation(*this).RenderUntil(actorImpl);
}
*/
Actor GetSourceActor() const;
+ /**
+ * @brief Retrives stopper actor.
+ * @SINCE_2_3.23
+ * @return The actor that marks where to stop rendering.
+ */
Actor GetStopperActor() const;
/**
*/
uint32_t GetRenderTaskId() const;
- void RenderUntil(Actor actor);
+ /**
+ * @brief Stop rendering from given actor. The actor is not included.
+ * @SINCE_2_3.23
+ * @param[in] stopperActor A marker to stop rendering.
+ */
+ void RenderUntil(Actor stopperActor);
public: // Signals
/**