From 43e2080419cc7ba14dd0ff0a526299dd9a064547 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Tue, 29 Mar 2022 11:54:24 +0900 Subject: [PATCH] Hit-test can hit more than 32 depth clipping actor. When clipping mode is CLIP_TO_BOUNDING_BOX, the limitation of clipping depth doesn't exist. We can clipping near 2^15-depth. But current clipping algorithm only allow 31-depth of clipping. This patch make that we don't use depthmask in hit-test algorithm When clipping mode is enabled, and current actor hit test failed, just skip all children's hit test. Note : CLIP_CHILDREN is kind of rendering method, So when clipping mode is CLIP_CHILDREN, we can't detect how it "really" clipped. This is physically limitation, so just ignore it. Change-Id: I83524d6f96ccbb59d7b2802f1630c7e338b251a0 Signed-off-by: Eunki, Hong --- .../src/dali/utc-Dali-HitTestAlgorithm.cpp | 64 ++++++++++++++++++++++ .../event/events/hit-test-algorithm-impl.cpp | 61 ++++----------------- 2 files changed, 74 insertions(+), 51 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp b/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp index 2229015..cea3e03 100644 --- a/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp +++ b/automated-tests/src/dali/utc-Dali-HitTestAlgorithm.cpp @@ -324,6 +324,70 @@ int UtcDaliHitTestAlgorithmClippingActor(void) END_TEST; } +int UtcDaliHitTestAlgorithmClippingActorStress(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm with many many stencil"); + + Stage stage = Stage::GetCurrent(); + Actor rootLayer = stage.GetRootLayer(); + rootLayer.SetProperty(Actor::Property::NAME, "RootLayer"); + + // Create a layer + Layer layer = Layer::New(); + layer.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + layer.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + layer.SetProperty(Actor::Property::NAME, "layer"); + stage.Add(layer); + + // Create a clipping actor and add it to the layer. + Actor clippingActor = CreateRenderableActor(); + clippingActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + clippingActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + clippingActor.SetProperty(Actor::Property::SIZE, Vector2(220.0f, 220.0f)); + clippingActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); + clippingActor.SetProperty(Actor::Property::NAME, "clippingActor"); + layer.Add(clippingActor); + + // Create a renderable actor and add it to the clipping actor. + Actor latestActor = clippingActor; + const int depthMax = 100; + for(int i = 0; i < depthMax; i++) + { + char tmp[29]; + sprintf(tmp, "depth%03d", i); + + Actor childActor = CreateRenderableActor(); + childActor.SetProperty(Actor::Property::SIZE, Vector2(220.0f, 220.0f)); + childActor.SetProperty(Actor::Property::POSITION, Vector2(200.0f / depthMax, 200.0f / depthMax)); + childActor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT); + childActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::TOP_LEFT); + childActor.SetProperty(Actor::Property::CLIPPING_MODE, ClippingMode::CLIP_TO_BOUNDING_BOX); + childActor.SetProperty(Actor::Property::NAME, tmp); + + latestActor.Add(childActor); + latestActor = childActor; + } + // NOTE : latestActor's TOP_LEFT position become 200.f, 200.0f + + // Render and notify + application.SendNotification(); + application.Render(); + + // Hit within clippingActor and latestActor. + HitTestAlgorithm::Results results; + HitTest(stage, Vector2(201.0f, 201.0f), results, &DefaultIsActorTouchableFunction); + tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty(Actor::Property::NAME).c_str() : "NULL")); + DALI_TEST_CHECK(results.actor == latestActor); + + // Hit within childActor but outside of clippingActor, should hit the root-layer instead. + HitTest(stage, Vector2(221.0f, 221.0f), results, &DefaultIsActorTouchableFunction); + tet_printf("Hit: %s\n", (results.actor ? results.actor.GetProperty(Actor::Property::NAME).c_str() : "NULL")); + DALI_TEST_CHECK(results.actor == rootLayer); + + END_TEST; +} + int UtcDaliHitTestAlgorithmOverlay(void) { TestApplication application; diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp index 267c1ff..0ed24be 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.cpp +++ b/dali/internal/event/events/hit-test-algorithm-impl.cpp @@ -167,8 +167,6 @@ HitActor HitTestWithinLayer(Actor& actor, const bool& overlayed, bool& overlayHit, bool layerIs3d, - uint32_t clippingDepth, - uint32_t clippingBitPlaneMask, const RayTest& rayTest, const Integration::Point& point, const uint32_t eventTime) @@ -180,17 +178,11 @@ HitActor HitTestWithinLayer(Actor& actor, return hit; } - // For clipping, regardless of whether we have hit this actor or not, - // we increase the clipping depth if we have hit a clipping actor. + // For clipping, regardless of whether we have hit this actor or not. // This is used later to ensure all nested clipped children have hit // all clipping actors also for them to be counted as hit. - uint32_t newClippingDepth = clippingDepth; - bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED; - bool overlayedActor = overlayed || actor.IsOverlay(); - if(clippingActor) - { - ++newClippingDepth; - } + bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED; + bool overlayedActor = overlayed || actor.IsOverlay(); // If we are a clipping actor or hittable... if(clippingActor || hitCheck.IsActorHittable(&actor)) @@ -215,13 +207,6 @@ HitActor HitTestWithinLayer(Actor& actor, // Check if cameraDepthDistance is between clipping plane if(cameraDepthDistance >= nearClippingPlane && cameraDepthDistance <= farClippingPlane) { - // If the hit has happened on a clipping actor, then add this clipping depth to the mask of hit clipping depths. - // This mask shows all the actors that have been hit at different clipping depths. - if(clippingActor) - { - clippingBitPlaneMask |= 1u << clippingDepth; - } - if(overlayHit && !overlayedActor) { // If we have already hit an overlay and current actor is not an overlay ignore current actor. @@ -233,34 +218,8 @@ HitActor HitTestWithinLayer(Actor& actor, overlayHit = true; } - // At this point we have hit an actor. - // Now perform checks for clipping. - // Assume we have hit the actor first as if it is not clipped this would be the case. - bool haveHitActor = true; - - // Check if we are performing clipping. IE. if any actors so far have clipping enabled - not necessarily this one. - // We can do this by checking the clipping depth has a value 1 or above. - if(newClippingDepth >= 1u) - { - // Now for us to count this actor as hit, we must have also hit - // all CLIPPING actors up to this point in the hierarchy as well. - // This information is stored in the clippingBitPlaneMask we updated above. - // Here we calculate a comparison mask by setting all the bits up to the current depth value. - // EG. a depth of 4 (10000 binary) = a mask of 1111 binary. - // This allows us a fast way of comparing all bits are set up to this depth. - // Note: If the current Actor has clipping, that is included in the depth mask too. - uint32_t clippingDepthMask = (1u << newClippingDepth) - 1u; - - // The two masks must be equal to be a hit, as we are already assuming a hit - // (for non-clipping mode) then they must be not-equal to disqualify the hit. - if(clippingBitPlaneMask != clippingDepthMask) - { - haveHitActor = false; - } - } - // If the hit actor does not want to hit, the hit-test continues. - if(haveHitActor && hitCheck.ActorRequiresHitResultCheck(&actor, point, hitPointLocal, eventTime)) + if(hitCheck.ActorRequiresHitResultCheck(&actor, point, hitPointLocal, eventTime)) { hit.actor = &actor; hit.hitPosition = hitPointLocal; @@ -288,6 +247,12 @@ HitActor HitTestWithinLayer(Actor& actor, } } + // If current actor is clipping, and hit failed, We should not checkup child actors. Fast return + if(clippingActor && !(hit.actor)) + { + return hit; + } + // Find a child hit, until we run out of actors in the current layer. HitActor childHit; if(actor.GetChildCount() > 0) @@ -316,8 +281,6 @@ HitActor HitTestWithinLayer(Actor& actor, overlayedActor, overlayHit, layerIs3d, - newClippingDepth, - clippingBitPlaneMask, rayTest, point, eventTime)); @@ -505,8 +468,6 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives, overlayHit, overlayHit, layer->GetBehavior() == Dali::Layer::LAYER_3D, - 0u, - 0u, rayTest, results.point, results.eventTime); @@ -525,8 +486,6 @@ bool HitTestRenderTask(const RenderTaskList::ExclusivesContainer& exclusives, overlayHit, overlayHit, layer->GetBehavior() == Dali::Layer::LAYER_3D, - 0u, - 0u, rayTest, results.point, results.eventTime); -- 2.7.4