From 24def5f2404af8733d5a50beb1249639707c3d08 Mon Sep 17 00:00:00 2001 From: Heeyong Song Date: Wed, 30 Dec 2020 13:25:45 +0900 Subject: [PATCH] Fix scissor clipping issue - Should consider y-axis inversion for the scissor box Change-Id: I27d3e0842d0095198caf243d80ce2b2af6825750 --- automated-tests/src/dali/utc-Dali-RenderTask.cpp | 123 ++++++++++++++++++++- dali/internal/render/common/render-algorithms.cpp | 26 +++-- dali/internal/render/common/render-algorithms.h | 21 ++-- .../update/render-tasks/scene-graph-camera.h | 9 ++ 4 files changed, 157 insertions(+), 22 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp index d60bc54..e58f206 100644 --- a/automated-tests/src/dali/utc-Dali-RenderTask.cpp +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -184,16 +184,18 @@ RenderTask CreateRenderTask(TestApplication& application, Actor rootActor, // Reset default render task to point at this actor Actor secondRootActor, // Source actor unsigned int refreshRate, - bool glSync) + bool glSync, + uint32_t frameBufferWidth = 10, + uint32_t frameBufferHeight = 10) { // Change main render task to use a different root RenderTaskList taskList = application.GetScene().GetRenderTaskList(); taskList.GetTask(0u).SetSourceActor(rootActor); - FrameBuffer frameBuffer = FrameBuffer::New(10, 10); + FrameBuffer frameBuffer = FrameBuffer::New(frameBufferWidth, frameBufferHeight); if(glSync) { - NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10); + NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(frameBufferWidth, frameBufferHeight); Texture texture = Texture::New(*testNativeImagePtr); frameBuffer.AttachColorTexture(texture); } @@ -3357,3 +3359,118 @@ int UtcDaliRenderTaskGetScreenToFrameBufferMappingActorNegative(void) } END_TEST; } + +int UtcDaliRenderTaskClippingMode01(void) +{ + TestApplication application; + + tet_infoline("Testing clipping mode: CLIP_TO_BOUNDING_BOX.\n"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + TraceCallStack& scissorTrace = glAbstraction.GetScissorTrace(); + + enabledDisableTrace.Enable(true); + scissorTrace.Enable(true); + + // SETUP AN OFFSCREEN RENDER TASK + Actor rootActor = Actor::New(); + application.GetScene().Add(rootActor); + + CameraActor offscreenCameraActor = CameraActor::New(Size(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT)); + offscreenCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + offscreenCameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + application.GetScene().Add(offscreenCameraActor); + + Shader shader = CreateShader(); + Texture image = CreateTexture(); + TextureSet textureSet = CreateTextureSet(image); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, shader); + renderer.SetTextures(textureSet); + + Vector2 position(100.0f, 100.0f); + Vector2 size(200.0f, 200.0f); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetProperty(Actor::Property::POSITION, position); + secondRootActor.SetProperty(Actor::Property::SIZE, size); + secondRootActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + secondRootActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + secondRootActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); + application.GetScene().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(enabledDisableTrace.FindMethodAndParams("Enable", "3089")); // 3089 = 0xC11 (GL_SCISSOR_TEST) + + // Check the scissor was set, and the coordinates are correct. + Vector4 expectResults(position.x, TestApplication::DEFAULT_SURFACE_HEIGHT - size.height - position.y, size.width, size.height); // (100, 500, 200, 200) + std::stringstream compareParametersString; + compareParametersString << expectResults.x << ", " << expectResults.y << ", " << expectResults.z << ", " << expectResults.w; + DALI_TEST_CHECK(scissorTrace.FindMethodAndParams("Scissor", compareParametersString.str())); // Compare with the expected result + + END_TEST; +} + +int UtcDaliRenderTaskClippingMode02(void) +{ + TestApplication application; + + tet_infoline("Testing clipping mode with the inverted camera: CLIP_TO_BOUNDING_BOX.\n"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& enabledDisableTrace = glAbstraction.GetEnableDisableTrace(); + TraceCallStack& scissorTrace = glAbstraction.GetScissorTrace(); + + enabledDisableTrace.Enable(true); + scissorTrace.Enable(true); + + // SETUP AN OFFSCREEN RENDER TASK + Actor rootActor = Actor::New(); + application.GetScene().Add(rootActor); + + CameraActor offscreenCameraActor = CameraActor::New(Size(TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT)); + offscreenCameraActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + offscreenCameraActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::CENTER); + offscreenCameraActor.SetInvertYAxis(true); + application.GetScene().Add(offscreenCameraActor); + + Shader shader = CreateShader(); + Texture image = CreateTexture(); + TextureSet textureSet = CreateTextureSet(image); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, shader); + renderer.SetTextures(textureSet); + + Vector2 position(100.0f, 100.0f); + Vector2 size(200.0f, 200.0f); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetProperty(Actor::Property::POSITION, position); + secondRootActor.SetProperty(Actor::Property::SIZE, size); + secondRootActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + secondRootActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + secondRootActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); + application.GetScene().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true, TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(enabledDisableTrace.FindMethodAndParams("Enable", "3089")); // 3089 = 0xC11 (GL_SCISSOR_TEST) + + // Check the scissor was set, and the coordinates are correct. + Vector4 expectResults(position.x, position.y, size.width, size.height); // (100, 100, 200, 200) + std::stringstream compareParametersString; + compareParametersString << expectResults.x << ", " << expectResults.y << ", " << expectResults.z << ", " << expectResults.w; + DALI_TEST_CHECK(scissorTrace.FindMethodAndParams("Scissor", compareParametersString.str())); // Compare with the expected result + + END_TEST; +} diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp index 314a974..fc1c0c1 100755 --- a/dali/internal/render/common/render-algorithms.cpp +++ b/dali/internal/render/common/render-algorithms.cpp @@ -223,15 +223,15 @@ inline void SetupDepthBuffer( const RenderItem& item, Context& context, bool dep } // Unnamed namespace - /** * @brief This method is responsible for making decisions on when to apply and unapply scissor clipping, and what rectangular dimensions should be used. * A stack of scissor clips at each depth of clipping is maintained, so it can be applied and unapplied. * As the clips are hierarchical, this RenderItems AABB is clipped against the current "active" scissor bounds via an intersection operation. * @param[in] item The current RenderItem about to be rendered * @param[in] context The context + * @param[in] instruction The render-instruction to process. */ -inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Context& context ) +inline void RenderAlgorithms::SetupScissorClipping(const RenderItem& item, Context& context, const RenderInstruction& instruction) { // Get the number of child scissors in the stack (do not include layer or root box). size_t childStackDepth = mScissorStack.size() - 1u; @@ -292,17 +292,23 @@ inline void RenderAlgorithms::SetupScissorClipping( const RenderItem& item, Cont if( scissorEnabled ) { ClippingBox useScissorBox( mScissorStack.back() ); + + if(instruction.mFrameBuffer && instruction.GetCamera()->IsYAxisInverted()) + { + useScissorBox.y = (instruction.mFrameBuffer->GetHeight() - useScissorBox.height) - useScissorBox.y; + } context.Scissor( useScissorBox.x, useScissorBox.y, useScissorBox.width, useScissorBox.height ); } } } -inline void RenderAlgorithms::SetupClipping( const RenderItem& item, - Context& context, - bool& usedStencilBuffer, - uint32_t& lastClippingDepth, - uint32_t& lastClippingId, - Integration::StencilBufferAvailable stencilBufferAvailable ) +inline void RenderAlgorithms::SetupClipping(const RenderItem& item, + Context& context, + bool& usedStencilBuffer, + uint32_t& lastClippingDepth, + uint32_t& lastClippingId, + Integration::StencilBufferAvailable stencilBufferAvailable, + const RenderInstruction& instruction) { RenderMode::Type renderMode = RenderMode::AUTO; const Renderer *renderer = item.mRenderer; @@ -324,7 +330,7 @@ inline void RenderAlgorithms::SetupClipping( const RenderItem& item, // 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 ); + SetupScissorClipping(item, context, instruction); if( stencilBufferAvailable == Integration::StencilBufferAvailable::TRUE ) { @@ -462,7 +468,7 @@ inline void RenderAlgorithms::ProcessRenderList( const RenderList& renderList, // 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 ); + SetupClipping(item, context, usedStencilBuffer, lastClippingDepth, lastClippingId, stencilBufferAvailable, instruction); if( DALI_LIKELY( item.mRenderer ) ) { diff --git a/dali/internal/render/common/render-algorithms.h b/dali/internal/render/common/render-algorithms.h index 9d359b4..d0d90fe 100644 --- a/dali/internal/render/common/render-algorithms.h +++ b/dali/internal/render/common/render-algorithms.h @@ -86,10 +86,11 @@ class RenderAlgorithms * - If the node is a clipping node, apply the nodes clip intersected with the current/parent scissor clip. * - If we have gone up the scissor hierarchy, and need to un-apply a scissor clip. * - Disable scissor clipping completely if it is not needed - * @param[in] item The current RenderItem (about to be rendered) - * @param[in] context The current Context + * @param[in] item The current RenderItem (about to be rendered) + * @param[in] context The current Context + * @param[in] instruction The render-instruction to process. */ - inline void SetupScissorClipping( const Dali::Internal::SceneGraph::RenderItem& item, Context& context ); + inline void SetupScissorClipping(const Dali::Internal::SceneGraph::RenderItem& item, Context& context, const Dali::Internal::SceneGraph::RenderInstruction& instruction); /** * @brief Set up the clipping based on the specified clipping settings. @@ -99,13 +100,15 @@ class RenderAlgorithms * @param[in/out] lastClippingDepth The stencil depth of the last renderer drawn. Used by the clipping feature. * @param[in/out] lastClippingId The clipping ID of the last renderer drawn. Used by the clipping feature. * @param[in] stencilBufferAvailable Whether the stencil buffer is available + * @param[in] instruction The render-instruction to process. */ - inline void SetupClipping( const Dali::Internal::SceneGraph::RenderItem& item, - Context& context, - bool& usedStencilBuffer, - uint32_t& lastClippingDepth, - uint32_t& lastClippingId, - Integration::StencilBufferAvailable stencilBufferAvailable ); + inline void SetupClipping(const Dali::Internal::SceneGraph::RenderItem& item, + Context& context, + bool& usedStencilBuffer, + uint32_t& lastClippingDepth, + uint32_t& lastClippingId, + Integration::StencilBufferAvailable stencilBufferAvailable, + const Dali::Internal::SceneGraph::RenderInstruction& instruction); /** * @brief Process a render-list. diff --git a/dali/internal/update/render-tasks/scene-graph-camera.h b/dali/internal/update/render-tasks/scene-graph-camera.h index d752b5c..a5db970 100644 --- a/dali/internal/update/render-tasks/scene-graph-camera.h +++ b/dali/internal/update/render-tasks/scene-graph-camera.h @@ -116,6 +116,15 @@ public: void SetInvertYAxis( bool invertYAxis ); /** + * Returns whether the Y axis is inverted. + * @return True if the Y axis is inverted, false otherwise. + */ + bool IsYAxisInverted() const + { + return mInvertYAxis; + } + + /** * @copydoc Dali::Internal::CameraActor::SetProjectionMode */ void SetProjectionMode( Dali::Camera::ProjectionMode projectionMode ); -- 2.7.4