Added text renderer culling 66/25066/4
authorDavid Steele <david.steele@partner.samsung.com>
Wed, 23 Jul 2014 13:17:28 +0000 (14:17 +0100)
committerDavid Steele <david.steele@partner.samsung.com>
Wed, 30 Jul 2014 13:59:23 +0000 (14:59 +0100)
Text renderers can use the same culling algorithm as images;
have moved the 2D OBB culling algorithm to a new file; changed
the interface slightly (to pass a potentially uncentered bounding box)

Change-Id: Ic4379fdc6e7a25f39377bab2c1169697bef0e641
Signed-off-by: David Steele <david.steele@partner.samsung.com>
18 files changed:
automated-tests/src/dali-internal/CMakeLists.txt
automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp
automated-tests/src/dali-internal/utc-Dali-Internal-Text-Culling.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp
dali/internal/common/text-vertex-buffer.h
dali/internal/event/text/generator/text-vertex-generator.cpp
dali/internal/file.list
dali/internal/render/common/culling-algorithms.cpp [new file with mode: 0644]
dali/internal/render/common/culling-algorithms.h [new file with mode: 0644]
dali/internal/render/common/render-debug.cpp
dali/internal/render/renderers/scene-graph-image-renderer.cpp
dali/internal/render/renderers/scene-graph-image-renderer.h
dali/internal/render/renderers/scene-graph-renderer-debug.cpp [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer-debug.h [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer.cpp
dali/internal/render/renderers/scene-graph-renderer.h
dali/internal/render/renderers/scene-graph-text-renderer.cpp
dali/internal/render/renderers/scene-graph-text-renderer.h

index 9728100..08fbd2c 100644 (file)
@@ -14,6 +14,7 @@ SET(TC_SOURCES
         utc-Dali-Internal-Text.cpp
         utc-Dali-Internal-ResourceClient.cpp
         utc-Dali-Internal-Image-Culling.cpp
+        utc-Dali-Internal-Text-Culling.cpp
 )
 
 LIST(APPEND TC_SOURCES
index 57c5a47..29af606 100644 (file)
@@ -150,7 +150,7 @@ void TestImageInside( TestApplication& application, int width, int height )
 }
 
 
-void RepositionActor(TestApplication& application, Actor actor, float x, float y, bool inside)
+bool RepositionActor(TestApplication& application, Actor actor, float x, float y, bool inside)
 {
   TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
 
@@ -158,20 +158,12 @@ void RepositionActor(TestApplication& application, Actor actor, float x, float y
   actor.SetPosition( x, y, 0.0f);
   application.SendNotification();
   application.Render(16);
-  if( inside )
-  {
-    bool found = drawTrace.FindMethod( "DrawArrays" );
-    if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y );
-    DALI_TEST_CHECK( found );
-  }
-  else
-  {
-    bool found = drawTrace.FindMethod( "DrawArrays" );
-    if( found ) tet_printf( "Drawn when not needed: Position:(%3.0f, %3.0f)\n", x, y );
-    DALI_TEST_CHECK( ! found );
-  }
+
+  bool found = drawTrace.FindMethod( "DrawArrays" );
+  return (inside && found) || (!inside && !found);
 }
 
+
 void RepositionActorWithAngle(TestApplication& application, Actor actor, float x, float y, float angle, bool inside)
 {
   TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
@@ -289,6 +281,8 @@ void OBBTestImageAtBoundary( TestApplication& application, int width, int height
   tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) \n",
              stageSize.x, stageSize.y, imageSize.x, imageSize.y);
 
+  int successCount = 0;
+  int totalCount = 0;
   for( int i=0; i<100; i++ )
   {
     float x1 = -stageSize.x/2.0f - imageSize.x*i/200.0f;
@@ -311,12 +305,16 @@ void OBBTestImageAtBoundary( TestApplication& application, int width, int height
       float x = ((stageSize.x+imageSize.x/2.0f)/21.0f) * j;
       float y = ((stageSize.y+imageSize.y/2.0f)/21.0f) * j;
 
-      RepositionActor( application, imageActor, x1, y, true );
-      RepositionActor( application, imageActor, x2, y, true );
-      RepositionActor( application, imageActor, x, y1, true );
-      RepositionActor( application, imageActor, x, y2, true );
+      if(RepositionActor( application, imageActor, x1, y, true )) successCount++;
+      if(RepositionActor( application, imageActor, x2, y, true )) successCount++;
+      if(RepositionActor( application, imageActor, x, y1, true )) successCount++;
+      if(RepositionActor( application, imageActor, x, y2, true )) successCount++;
+
+      totalCount += 4;
     }
   }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
 }
 
 
@@ -384,6 +382,9 @@ void OBBTestImageOutsideBoundary( TestApplication& application, int width, int h
   tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f)\n",
              stageSize.x, stageSize.y, imageSize.x, imageSize.y);
 
+  int successCount=0;
+  int totalCount=0;
+
   for( int i=0; i<=100; i++ )
   {
     float x1 = -stageSize.x/2.0f - imageSize.x * (1.5f + i/100.0f);
@@ -396,12 +397,15 @@ void OBBTestImageOutsideBoundary( TestApplication& application, int width, int h
       float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area
       float y = (stageSize.y/17.0f) * j;
 
-      RepositionActor( application, imageActor, x1, y, false );
-      RepositionActor( application, imageActor, x2, y, false );
-      RepositionActor( application, imageActor, x, y1, false );
-      RepositionActor( application, imageActor, x, y2, false );
+      if(RepositionActor( application, imageActor, x1, y, false )) successCount++;
+      if(RepositionActor( application, imageActor, x2, y, false )) successCount++;
+      if(RepositionActor( application, imageActor, x, y1, false )) successCount++;
+      if(RepositionActor( application, imageActor, x, y2, false )) successCount++;
+      totalCount+=4;
     }
   }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
 }
 
 void TestPlaneOfImages(TestApplication& application, float z)
@@ -791,8 +795,6 @@ int UtcDaliImageCulling_Plane04(void)
   END_TEST;
 }
 
-
-
 int UtcDaliImageCulling_Disable(void)
 {
   tet_infoline("Test that culling can be disabled");
@@ -814,17 +816,16 @@ int UtcDaliImageCulling_Disable(void)
   DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
 
   imageSize.z = 0.0f;
-  float radius = imageSize.Length() * 0.5f; // Radius of bounding box
 
   tet_infoline("Setting cull mode to false\n");
   Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(false);
 
-  float x1 = -stageSize.x/2.0f - imageSize.x;
-  float x2 =  stageSize.x/2.0f + imageSize.x;
-  float y1 = -stageSize.y/2.0f - imageSize.y;
-  float y2 =  stageSize.y/2.0f + imageSize.y;
+  float x1 = -stageSize.x - imageSize.x;
+  float x2 =  stageSize.x + imageSize.x;
+  float y1 = -stageSize.y - imageSize.y;
+  float y2 =  stageSize.y + imageSize.y;
 
-  // Positioning actors well outside stage, with no culling, they should still be drawn.
+  // Positioning actors outside stage, with no culling, they should still be drawn.
   RepositionActorOutside( application, imageActor, x1, y1, true );
   RepositionActorOutside( application, imageActor, x2, y1, true );
   RepositionActorOutside( application, imageActor, x1, y2, true );
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Text-Culling.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Text-Culling.cpp
new file mode 100644 (file)
index 0000000..6fb1bf6
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_internal_text_culling_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_text_culling_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+namespace
+{
+#define NUM_ROWS 9
+#define NUM_COLS 9
+#define NUM_ROWS_PER_PANE 3
+#define NUM_COLS_PER_PANE 3
+
+
+TextActor CreateOnStageActor(TestApplication& application, Text text, int width, int height, bool testDraw)
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  TextActor textActor = TextActor::New(text);
+  textActor.SetParentOrigin(ParentOrigin::CENTER);
+  textActor.SetSize(width, height);
+  Stage::GetCurrent().Add(textActor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  Integration::ResourceRequest* request = platform.GetRequest();
+  DALI_TEST_CHECK( request != NULL );
+  DALI_TEST_CHECK( request->GetType() != NULL );
+  DALI_TEST_CHECK( request->GetType()->id == Integration::ResourceText );
+
+  Integration::TextResourceType* textRequest = static_cast<Integration::TextResourceType*>(request->GetType());
+
+  std::string font("Font");
+  Integration::GlyphSet* set = platform.GetGlyphData(*textRequest, font, true);
+  platform.SetResourceLoaded( request->GetId(), Integration::ResourceText, Integration::ResourcePointer(set) );
+
+  application.SendNotification();
+  application.Render(16);
+
+  platform.ClearReadyResources();
+
+  if(testDraw)
+  {
+    DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+  }
+  return textActor;
+}
+
+
+void TestTextInside( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  std::string text("Text");
+
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+  textActor.SetPosition(0.0f, 0.0f, 0.0f);
+
+  Vector3 textSize = textActor.GetCurrentSize();
+  DALI_TEST_EQUALS( textSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  drawTrace.Reset();
+  textActor.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  textActor.SetParentOrigin(ParentOrigin::TOP_RIGHT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  textActor.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  textActor.SetParentOrigin(ParentOrigin::BOTTOM_LEFT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+}
+
+
+bool RepositionActor(TestApplication& application, Actor actor, float x, float y, bool inside)
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  application.SendNotification();
+  application.Render(16);
+
+  bool found = drawTrace.FindMethod( "DrawElements" );
+  bool result = (inside && found) || (!inside && !found);
+  return result;
+}
+
+
+void RepositionActorWithAngle(TestApplication& application, Actor actor, float x, float y, float angle, bool inside)
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  actor.SetRotation( Degree(angle), Vector3::ZAXIS );
+  application.SendNotification();
+  application.Render(16);
+  if( inside )
+  {
+    bool found = drawTrace.FindMethod( "DrawElements" );
+    if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( found );
+  }
+  else
+  {
+    bool found = drawTrace.FindMethod( "DrawElements" );
+    if( found ) tet_printf( "Drawn when not needed: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( ! found );
+  }
+}
+
+void RepositionActorOutside(TestApplication& application, Actor actor, float x, float y, bool drawn )
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  application.SendNotification();
+  application.Render(16);
+  if( drawn )
+  {
+    bool found = drawTrace.FindMethod( "DrawElements" );
+    if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( found );
+  }
+  else
+  {
+    bool found = drawTrace.FindMethod( "DrawElements" );
+    if( found ) tet_printf( "Drawn unnecessarily: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( ! found );
+  }
+}
+
+void OBBTestTextAtBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  std::string text("Text");
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+
+  Vector3 textSize = textActor.GetCurrentSize();
+  DALI_TEST_EQUALS( textSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  textSize.z = 0.0f;
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) text size:(%3.0f, %3.0f) \n",
+             stageSize.x, stageSize.y, textSize.x, textSize.y);
+
+  int successCount = 0;
+  int totalCount = 0;
+  for( int i=0; i<100; i++ )
+  {
+    float x1 = -stageSize.x/2.0f - textSize.x*i/200.0f;
+    float x2 =  stageSize.x/2.0f + textSize.x*i/200.0f;
+    float y1 = -stageSize.y/2.0f - textSize.y*i/200.0f;
+    float y2 =  stageSize.y/2.0f + textSize.y*i/200.0f;
+
+    //tet_printf("Testing i=%d\n",i);
+
+    // Test paths marked with dots
+    //  + . . . . . .
+    //  .\_     ^
+    //  .  \_   | within radius
+    //  .    \  v
+    //  .     +-----
+    //  .     | Stage
+
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = ((stageSize.x+textSize.x/2.0f)/21.0f) * j;
+      float y = ((stageSize.y+textSize.y/2.0f)/21.0f) * j;
+
+      if(RepositionActor( application, textActor, x1, y, true )) successCount++;
+      if(RepositionActor( application, textActor, x2, y, true )) successCount++;
+      if(RepositionActor( application, textActor, x, y1, true )) successCount++;
+      if(RepositionActor( application, textActor, x, y2, true )) successCount++;
+
+      totalCount += 4;
+    }
+  }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
+}
+
+
+void OBBTestTextOutsideBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  std::string text("Text");
+
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+  Vector3 textSize = textActor.GetCurrentSize();
+  DALI_TEST_EQUALS( textSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  textSize.z = 0.0f;
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) text size:(%3.0f, %3.0f)\n",
+             stageSize.x, stageSize.y, textSize.x, textSize.y);
+
+  int successCount=0;
+  int totalCount=0;
+
+  for( int i=0; i<=100; i++ )
+  {
+    float x1 = -stageSize.x/2.0f - textSize.x * (1.5f + i/100.0f);
+    float x2 =  stageSize.x/2.0f + textSize.x * (1.5f + i/100.0f);
+    float y1 = -stageSize.y/2.0f - textSize.y * (1.5f + i/100.0f);
+    float y2 =  stageSize.y/2.0f + textSize.y * (1.5f + i/100.0f);
+
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area
+      float y = (stageSize.y/17.0f) * j;
+
+      if(RepositionActor( application, textActor, x1, y, false )) successCount++;
+      if(RepositionActor( application, textActor, x2, y, false )) successCount++;
+      if(RepositionActor( application, textActor, x, y1, false )) successCount++;
+      if(RepositionActor( application, textActor, x, y2, false )) successCount++;
+      totalCount+=4;
+    }
+  }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
+}
+
+
+} // namespace
+
+int UtcDaliTextCulling_Inside01(void)
+{
+  tet_infoline( "Testing that 80x80 text positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestTextInside(application, 80, 80);
+
+  END_TEST;
+}
+
+int UtcDaliTextCulling_Inside02(void)
+{
+  tet_infoline( "Testing that 120x40 text positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestTextInside(application, 120, 40);
+
+  END_TEST;
+}
+
+int UtcDaliTextCulling_Inside03(void)
+{
+  tet_infoline( "Testing that 40x120 text positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestTextInside(application, 40, 120);
+
+  END_TEST;
+}
+
+int UtcDaliTextCulling_Inside04(void)
+{
+  tet_infoline( "Testing that 500x2 text positioned inside the stage is drawn\n");
+  TestApplication application;
+  TestTextInside(application, 500, 2);
+  END_TEST;
+}
+
+int UtcDaliTextCulling_Inside05(void)
+{
+  tet_infoline( "Testing that 2x500 text positioned inside the stage is drawn\n");
+  TestApplication application;
+  TestTextInside(application, 2, 500);
+  END_TEST;
+}
+
+
+int UtcDaliTextCulling_WithinBoundary01(void)
+{
+  tet_infoline("Test that 80x80 text positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestTextAtBoundary( application, 80, 80);
+  END_TEST;
+}
+int UtcDaliTextCulling_WithinBoundary02(void)
+{
+  tet_infoline("Test that 120x40 text positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestTextAtBoundary( application, 120, 40 );
+  END_TEST;
+}
+int UtcDaliTextCulling_WithinBoundary03(void)
+{
+  tet_infoline("Test that 40x120 text positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestTextAtBoundary( application, 40, 120);
+  END_TEST;
+}
+
+int UtcDaliTextCulling_WithinBoundary04(void)
+{
+  tet_infoline("Test that 500x2 texts positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestTextAtBoundary( application, 500, 2 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_WithinBoundary05(void)
+{
+  tet_infoline("Test that 2x500 texts positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestTextAtBoundary( application, 2, 500 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideBoundary01(void)
+{
+  tet_infoline("Test that 80x80 text positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestTextOutsideBoundary( application, 80, 80 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideBoundary02(void)
+{
+  tet_infoline("Test that 120x40 text positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestTextOutsideBoundary( application, 120, 40 );
+  END_TEST;
+}
+int UtcDaliTextCulling_OutsideBoundary03(void)
+{
+  tet_infoline("Test that 40x120 text positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestTextOutsideBoundary( application, 40, 120 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideBoundary04(void)
+{
+  tet_infoline("Test that 500x2 text positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestTextOutsideBoundary( application, 500, 2 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideBoundary05(void)
+{
+  tet_infoline("Test that 2x500 text positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestTextOutsideBoundary( application, 2, 500 );
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideIntersect01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n"
+               "outside the stage but intersecting it are still drawn");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*0.2f;
+  std::string text("Text");
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+
+  RepositionActor( application, textActor, stageSize.x*1.2f, 0.0f, true);
+  RepositionActor( application, textActor, stageSize.x*1.2f, -stageSize.y*0.55f, true);
+  RepositionActor( application, textActor, stageSize.x*1.2f, stageSize.y*0.55f, true);
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideIntersect02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n"
+               "outside the stage that cross planes are not drawn");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*0.2f;
+  std::string text("Text");
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+
+  RepositionActor( application, textActor,  stageSize.x*10.0f,  stageSize.y*0.5f, false);
+  RepositionActor( application, textActor, -stageSize.x*10.0f,  stageSize.y*0.5f, false);
+  RepositionActor( application, textActor,  stageSize.x*10.0f, -stageSize.y*0.5f, false);
+  RepositionActor( application, textActor, -stageSize.x*10.0f, -stageSize.y*0.5f, false);
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideIntersect03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that text actor larger than the stage, positioned outside the stage \n"
+               "with bounding boxes also outside the stage but intersecting it is still drawn\n");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // Try an actor bigger than the stage, with center outside stage
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*5.0f;
+  std::string text("Text");
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+
+  RepositionActor( application, textActor, stageSize.x*1.2f, 0.0f, true);
+  RepositionActor( application, textActor, stageSize.x*1.2f, -stageSize.y*1.1f, true);
+  RepositionActor( application, textActor, stageSize.x*1.2f, stageSize.y*1.1f, true);
+
+  END_TEST;
+}
+
+int UtcDaliTextCulling_OutsideIntersect04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that text actors positioned outside the stage, with bounding boxes\n"
+               "also outside the stage but intersecting it, and angled at 45 degrees to\n"
+               "the corners are still drawn\n");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // Test text at 45 degrees outside corners of stage
+  float width = 400.0f;
+  float height = 200.0f;
+  std::string text("Text");
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+
+  RepositionActorWithAngle( application, textActor, -stageSize.x*0.55f, -stageSize.y*0.55, 135.0f, true);
+  RepositionActorWithAngle( application, textActor, -stageSize.x*0.55f,  stageSize.y*0.55, 225.0f, true);
+  RepositionActorWithAngle( application, textActor,  stageSize.x*0.55f, -stageSize.y*0.55,  45.0f, true);
+  RepositionActorWithAngle( application, textActor,  stageSize.x*0.55f,  stageSize.y*0.55, 315.0f, true);
+
+  END_TEST;
+}
+
+
+int UtcDaliTextCulling_Disable(void)
+{
+  tet_infoline("Test that culling can be disabled");
+
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TestPlatformAbstraction& platformAbstraction = application.GetPlatform();
+  TraceCallStack& platformTrace = platformAbstraction.GetTrace();
+
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  float width=80;
+  float height=80;
+  std::string text("Text");
+
+
+  TextActor textActor = CreateOnStageActor(application, text, width, height, true);
+  Vector3 textSize = textActor.GetCurrentSize();
+  DALI_TEST_EQUALS( textSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  textSize.z = 0.0f;
+
+  tet_infoline("Setting cull mode to false\n");
+  Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(false);
+
+  float x1 = -stageSize.x - textSize.x;
+  float x2 =  stageSize.x + textSize.x;
+  float y1 = -stageSize.y - textSize.y;
+  float y2 =  stageSize.y + textSize.y;
+
+  // Positioning actors outside stage, with no culling, they should still be drawn.
+  RepositionActorOutside( application, textActor, x1, y1, true );
+  RepositionActorOutside( application, textActor, x2, y1, true );
+  RepositionActorOutside( application, textActor, x1, y2, true );
+  RepositionActorOutside( application, textActor, x2, y2, true );
+
+  tet_infoline("Setting cull mode to true\n");
+  Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(true);
+
+  RepositionActorOutside( application, textActor, x1, y1, false );
+  RepositionActorOutside( application, textActor, x2, y1, false );
+  RepositionActorOutside( application, textActor, x1, y2, false );
+  RepositionActorOutside( application, textActor, x2, y2, false );
+
+  END_TEST;
+}
index 6b6a8f8..4f749ce 100644 (file)
@@ -86,7 +86,19 @@ void TestPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer
  */
 void TestPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request)
 {
-  mTrace.PushCall("LoadResource", "");
+  std::ostringstream out;
+  out << "Type:";
+  if( request.GetType()->id == Integration::ResourceText )
+  {
+    out << "Text";
+  }
+  else
+  {
+    out << request.GetType()->id;
+  }
+  out << ", Path: " << request.GetPath() << std::endl ;
+
+  mTrace.PushCall("LoadResource", out.str());
   if(mRequest != NULL)
   {
     delete mRequest;
index 4c234b2..1459ace 100644 (file)
@@ -21,6 +21,7 @@
 // INTERNAL INCLUDES
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/rect.h>
 #include <dali/internal/common/text-vertex-2d.h>
 
 namespace Dali
@@ -38,7 +39,8 @@ struct TextVertexBuffer
 {
   std::vector<TextVertex2D> mVertices;    ///< List of vertices (coordinates and texture coordinates)
   unsigned int mTextureId;                ///< Texture id
-  Vector2 mVertexMax;                     ///< Maximum extent of 2d vertex array
+  Vector2 mVertexMax;                     ///< Calculated unskewed geometry size
+  Vector2 mGeometryExtent;                ///< Actual extents of geometry
 };
 
 } // namespace Internal
index 6ce9e0d..05f2872 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/public-api/common/constants.h>
 #include <dali/internal/event/text/glyph-status/glyph-status.h>
 #include <dali/internal/event/text/special-characters.h>
+#include <dali/integration-api/debug.h>
 
 // EXTERNAL INCLUDES
 #include <cmath>  // for std::sin
@@ -35,6 +36,10 @@ namespace Internal
 namespace // unnamed namespace
 {
 
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gTextVertsLogFilter = Debug::Filter::New( Debug::Concise, false, "LOG_TEXT_VERTEX_FILTER" );
+#endif
+
 typedef std::vector<TextVertex2D> VertexBuffer;
 
 void RepositionData( TextVertexBuffer& buffer )
@@ -91,6 +96,9 @@ void RepositionData( TextVertexBuffer& buffer )
     vertex.mX -= offset.x;
     vertex.mY -= offset.y;
   }
+
+  buffer.mGeometryExtent.width = maxX - minX;
+  buffer.mGeometryExtent.height = maxY - minY;
 }
 
 void AddVertex( VertexBuffer& vertexBuffer,
@@ -407,6 +415,11 @@ TextVertexBuffer* TextVertexGenerator::Generate( const TextArray& text,
   DebugVertexBuffer( vertexBuffer );
 #endif
 
+  DALI_LOG_INFO(gTextVertsLogFilter, Debug::General, "TextVertexBuffer for %c%c%c...: Calculated Extents:(%5.2f, %5.2f)\n  Geometry Extents:(%5.2f, %5.2f )\n",
+                text.size()>0?(char)text[0]:' ', text.size()>1?(char)text[1]:' ', text.size()>2?(char)text[2]:' ',
+                textVertexBuffer->mVertexMax.x,textVertexBuffer->mVertexMax.y,
+                textVertexBuffer->mGeometryExtent.width,textVertexBuffer->mGeometryExtent.height);
+
   return textVertexBuffer;
 }
 
index e0f0775..a02838c 100644 (file)
@@ -120,6 +120,7 @@ internal_src_files = \
   $(internal_src_dir)/event/text/resource/debug/glyph-resource-debug.cpp \
   $(internal_src_dir)/event/text/generator/text-vertex-generator.cpp \
   \
+  $(internal_src_dir)/render/common/culling-algorithms.cpp \
   $(internal_src_dir)/render/common/performance-monitor.cpp \
   $(internal_src_dir)/render/common/render-algorithms.cpp \
   $(internal_src_dir)/render/common/render-debug.cpp \
@@ -144,6 +145,7 @@ internal_src_files = \
   $(internal_src_dir)/render/renderers/scene-graph-image-renderer.cpp \
   $(internal_src_dir)/render/renderers/scene-graph-mesh-renderer.cpp \
   $(internal_src_dir)/render/renderers/scene-graph-renderer.cpp \
+  $(internal_src_dir)/render/renderers/scene-graph-renderer-debug.cpp \
   $(internal_src_dir)/render/renderers/scene-graph-text-renderer.cpp \
   $(internal_src_dir)/render/shaders/custom-uniform.cpp \
   $(internal_src_dir)/render/shaders/program.cpp \
diff --git a/dali/internal/render/common/culling-algorithms.cpp b/dali/internal/render/common/culling-algorithms.cpp
new file mode 100644 (file)
index 0000000..d60f7ef
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "culling-algorithms.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+bool Is2dBoxOutsideClipSpace(const Matrix& modelMatrix,
+                             const Matrix& modelViewProjectionMatrix,
+                             const Rect<float>& boundingBox )
+{
+  // First, calculate if the center is inside clip space:
+
+  // Downside is mvp matrix calc per renderer per frame
+  // and up to 4 matrix * vector calls.
+  const Matrix& mvp = modelViewProjectionMatrix;
+  const Vector4 translation = mvp.GetTranslation();
+
+  // Upside is point test is very simple:
+  if( -translation.w <= translation.x  &&  translation.x <= translation.w &&
+      -translation.w <= translation.y  &&  translation.y <= translation.w &&
+      -translation.w <= translation.z  &&  translation.z <= translation.w)
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  // Transform oriented bounding box to clip space:
+  Vector4 topLeft(    boundingBox.x, boundingBox.y, 0.0f, 1.0f);
+  Vector4 topRight(   boundingBox.x + boundingBox.width, boundingBox.y, 0.0f, 1.0f);
+  Vector4 bottomLeft( boundingBox.x, boundingBox.y + boundingBox.height, 0.0f, 1.0f);
+  Vector4 bottomRight(boundingBox.x + boundingBox.width, boundingBox.y + boundingBox.height, 0.0f, 1.0f);
+
+  Vector4 topLeftClip = mvp * topLeft;
+  if( -topLeftClip.w <= topLeftClip.x && topLeftClip.x <= topLeftClip.w &&
+      -topLeftClip.w <= topLeftClip.y && topLeftClip.y <= topLeftClip.w &&
+      -topLeftClip.w <= topLeftClip.z && topLeftClip.z <= topLeftClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 bottomRightClip = mvp * bottomRight;
+  if( -bottomRightClip.w <= bottomRightClip.x && bottomRightClip.x <= bottomRightClip.w &&
+      -bottomRightClip.w <= bottomRightClip.y && bottomRightClip.y <= bottomRightClip.w &&
+      -bottomRightClip.w <= bottomRightClip.z && bottomRightClip.z <= bottomRightClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 topRightClip = mvp * topRight;
+  if( -topRightClip.w <= topRightClip.x && topRightClip.x <= topRightClip.w &&
+      -topRightClip.w <= topRightClip.y && topRightClip.y <= topRightClip.w &&
+      -topRightClip.w <= topRightClip.z && topRightClip.z <= topRightClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 bottomLeftClip = mvp * bottomLeft;
+  if( -bottomLeftClip.w <= bottomLeftClip.x && bottomLeftClip.x <= bottomLeftClip.w &&
+      -bottomLeftClip.w <= bottomLeftClip.y && bottomLeftClip.y <= bottomLeftClip.w &&
+      -bottomLeftClip.w <= bottomLeftClip.z && bottomLeftClip.z <= bottomLeftClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  // Check to see if all four points are outside each plane
+
+  unsigned int insideLeftPlaneCount=0;
+  unsigned int insideRightPlaneCount=0;
+  unsigned int insideTopPlaneCount=0;
+  unsigned int insideBottomPlaneCount=0;
+
+  if(-topLeftClip.w <= topLeftClip.x) { insideLeftPlaneCount++; }
+  if(-topRightClip.w <= topRightClip.x){ insideLeftPlaneCount++; }
+  if(-bottomRightClip.w <= bottomRightClip.x) {insideLeftPlaneCount++;}
+  if(-bottomLeftClip.w <= bottomLeftClip.x) {insideLeftPlaneCount++;}
+
+  if( insideLeftPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(topLeftClip.x <= topLeftClip.w) { insideRightPlaneCount++;}
+  if(topRightClip.x <= topRightClip.w) { insideRightPlaneCount++; }
+  if(bottomRightClip.x <= bottomRightClip.w) { insideRightPlaneCount++; }
+  if(bottomLeftClip.x <= bottomLeftClip.w ) { insideRightPlaneCount++; }
+
+  if( insideRightPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(-topLeftClip.w <= topLeftClip.y ) {insideTopPlaneCount++; }
+  if(-topRightClip.w <= topRightClip.y) {insideTopPlaneCount++; }
+  if(-bottomRightClip.w <= bottomRightClip.y) {insideTopPlaneCount++;}
+  if(-bottomLeftClip.w <= bottomLeftClip.y) { insideTopPlaneCount++;}
+
+  if( insideTopPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(topLeftClip.y <= topLeftClip.w) { insideBottomPlaneCount++; }
+  if(topRightClip.y <= topRightClip.w) { insideBottomPlaneCount++; }
+  if(bottomRightClip.y <= bottomRightClip.w) { insideBottomPlaneCount++; }
+  if(bottomLeftClip.y <= bottomLeftClip.w) { insideBottomPlaneCount++; }
+
+  if( insideBottomPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  // Test if any planes are bisected, if they are, then there is likely to
+  // be an intersection into clip space.
+
+  if( insideLeftPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideRightPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideTopPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideBottomPlaneCount < 4 )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/common/culling-algorithms.h b/dali/internal/render/common/culling-algorithms.h
new file mode 100644 (file)
index 0000000..b2e451e
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
+#define _DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * Determine if the given bounding box is outside clip space (given by the
+ * model view projection matrix).
+ * @param[in] modelMatrix The world matrix of the bounding box.
+ * @param[in] modelViewProjectionMatrix The clip space matrix
+ * @param[in] boundingBox The bounding box of the geometry in object space
+ * @return true if the bounding box is outside clip space
+ */
+bool Is2dBoxOutsideClipSpace(const Matrix& modelMatrix,
+                             const Matrix& modelViewProjectionMatrix,
+                             const Rect<float>& boundingBox );
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif //_DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
index d5995d4..6a512bd 100644 (file)
@@ -137,7 +137,7 @@ void PrintRendererCount( unsigned int frameCount, unsigned int rendererCount )
 {
   if( frameCount % 120 == 30 ) // Print every 2 seconds reg
   {
-    Debug::LogMessage( Debug::DebugInfo, "ImageRenderer Total # renderers: %u\n", rendererCount );
+    Debug::LogMessage( Debug::DebugInfo, "Renderer Total # renderers: %u\n", rendererCount );
   }
 }
 
@@ -145,7 +145,7 @@ void PrintCullCount( unsigned int frameCount, unsigned int culledCount )
 {
   if( frameCount % 120 == 30 ) // Print every 2 seconds reg
   {
-    Debug::LogMessage( Debug::DebugInfo, "ImageRenderer # Culled renderers: %u\n", culledCount );
+    Debug::LogMessage( Debug::DebugInfo, "Renderer # Culled renderers: %u\n", culledCount );
   }
 }
 
index 370aa92..c44b29b 100644 (file)
 // EXTERNAL INCLUDES
 #include <dali/public-api/common/dali-common.h>
 #include <dali/internal/common/internal-constants.h>
+#include <dali/internal/render/common/culling-algorithms.h>
 #include <dali/internal/render/common/performance-monitor.h>
 #include <dali/internal/render/common/vertex.h>
 #include <dali/internal/render/gl-resources/gpu-buffer.h>
 #include <dali/internal/render/gl-resources/texture.h>
 #include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-debug.h>
 #include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/shaders/shader.h>
 #include <dali/internal/update/controllers/scene-controller.h>
@@ -228,7 +230,12 @@ void ImageRenderer::ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType&
 bool ImageRenderer::IsOutsideClipSpace( const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
 {
   mContext->IncrementRendererCount();
-  if(IsOutsideClipSpaceImpl( modelMatrix, modelViewProjectionMatrix ) )
+
+  Rect<float> boundingBox( mGeometrySize.x * -0.5f, mGeometrySize.y * -0.5f, mGeometrySize.x, mGeometrySize.y );
+
+  DEBUG_BOUNDING_BOX( *mContext, boundingBox, modelViewProjectionMatrix );
+
+  if(Is2dBoxOutsideClipSpace( modelMatrix, modelViewProjectionMatrix, boundingBox ) )
   {
     mContext->IncrementCulledCount();
     return true;
@@ -817,138 +824,6 @@ ImageRenderer::ImageRenderer( RenderDataProvider& dataprovider )
 {
 }
 
-// Frustum culling using clip space and oriented bounding box checks
-bool ImageRenderer::IsOutsideClipSpaceImpl(const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix)
-{
-  // First, calculate if the center is inside clip space:
-
-  // Downside is mvp matrix calc per renderer per frame
-  // and up to 4 matrix * vector calls.
-  const Matrix& mvp = modelViewProjectionMatrix;
-  const Vector4 translation = mvp.GetTranslation();
-
-  // Upside is point test is very simple:
-  if( -translation.w <= translation.x  &&  translation.x <= translation.w &&
-      -translation.w <= translation.y  &&  translation.y <= translation.w &&
-      -translation.w <= translation.z  &&  translation.z <= translation.w)
-  {
-    // Definitely inside clip space - don't do any more processing
-    return false;
-  }
-
-  // Transform oriented bounding box to clip space:
-  Vector4 topLeft(    mGeometrySize.x * -0.5f, mGeometrySize.y * -0.5f, 0.0f, 1.0f);
-  Vector4 topRight(   mGeometrySize.x *  0.5f, mGeometrySize.y * -0.5f, 0.0f, 1.0f);
-  Vector4 bottomLeft( mGeometrySize.x * -0.5f, mGeometrySize.y *  0.5f, 0.0f, 1.0f);
-  Vector4 bottomRight(mGeometrySize.x *  0.5f, mGeometrySize.y *  0.5f, 0.0f, 1.0f);
-
-  Vector4 topLeftClip = mvp * topLeft;
-  if( -topLeftClip.w <= topLeftClip.x && topLeftClip.x <= topLeftClip.w &&
-      -topLeftClip.w <= topLeftClip.y && topLeftClip.y <= topLeftClip.w &&
-      -topLeftClip.w <= topLeftClip.z && topLeftClip.z <= topLeftClip.w )
-  {
-    // Definitely inside clip space - don't do any more processing
-    return false;
-  }
-
-  Vector4 bottomRightClip = mvp * bottomRight;
-  if( -bottomRightClip.w <= bottomRightClip.x && bottomRightClip.x <= bottomRightClip.w &&
-      -bottomRightClip.w <= bottomRightClip.y && bottomRightClip.y <= bottomRightClip.w &&
-      -bottomRightClip.w <= bottomRightClip.z && bottomRightClip.z <= bottomRightClip.w )
-  {
-    // Definitely inside clip space - don't do any more processing
-    return false;
-  }
-
-  Vector4 topRightClip = mvp * topRight;
-  if( -topRightClip.w <= topRightClip.x && topRightClip.x <= topRightClip.w &&
-      -topRightClip.w <= topRightClip.y && topRightClip.y <= topRightClip.w &&
-      -topRightClip.w <= topRightClip.z && topRightClip.z <= topRightClip.w )
-  {
-    // Definitely inside clip space - don't do any more processing
-    return false;
-  }
-
-  Vector4 bottomLeftClip = mvp * bottomLeft;
-  if( -bottomLeftClip.w <= bottomLeftClip.x && bottomLeftClip.x <= bottomLeftClip.w &&
-      -bottomLeftClip.w <= bottomLeftClip.y && bottomLeftClip.y <= bottomLeftClip.w &&
-      -bottomLeftClip.w <= bottomLeftClip.z && bottomLeftClip.z <= bottomLeftClip.w )
-  {
-    // Definitely inside clip space - don't do any more processing
-    return false;
-  }
-
-  // Check to see if all four points are outside each plane (AABB would cut this processing
-  // in half)
-
-  unsigned int insideLeftPlaneCount=0;
-  unsigned int insideRightPlaneCount=0;
-  unsigned int insideTopPlaneCount=0;
-  unsigned int insideBottomPlaneCount=0;
-
-  if(-topLeftClip.w <= topLeftClip.x) { insideLeftPlaneCount++; }
-  if(-topRightClip.w <= topRightClip.x){ insideLeftPlaneCount++; }
-  if(-bottomRightClip.w <= bottomRightClip.x) {insideLeftPlaneCount++;}
-  if(-bottomLeftClip.w <= bottomLeftClip.x) {insideLeftPlaneCount++;}
-
-  if( insideLeftPlaneCount == 0 )
-  {
-    return true;
-  }
-
-  if(topLeftClip.x <= topLeftClip.w) { insideRightPlaneCount++;}
-  if(topRightClip.x <= topRightClip.w) { insideRightPlaneCount++; }
-  if(bottomRightClip.x <= bottomRightClip.w) { insideRightPlaneCount++; }
-  if(bottomLeftClip.x <= bottomLeftClip.w ) { insideRightPlaneCount++; }
-
-  if( insideRightPlaneCount == 0 )
-  {
-    return true;
-  }
-
-  if(-topLeftClip.w <= topLeftClip.y ) {insideTopPlaneCount++; }
-  if(-topRightClip.w <= topRightClip.y) {insideTopPlaneCount++; }
-  if(-bottomRightClip.w <= bottomRightClip.y) {insideTopPlaneCount++;}
-  if(-bottomLeftClip.w <= bottomLeftClip.y) { insideTopPlaneCount++;}
-
-  if( insideTopPlaneCount == 0 )
-  {
-    return true;
-  }
-
-  if(topLeftClip.y <= topLeftClip.w) { insideBottomPlaneCount++; }
-  if(topRightClip.y <= topRightClip.w) { insideBottomPlaneCount++; }
-  if(bottomRightClip.y <= bottomRightClip.w) { insideBottomPlaneCount++; }
-  if(bottomLeftClip.y <= bottomLeftClip.w) { insideBottomPlaneCount++; }
-
-  if( insideBottomPlaneCount == 0 )
-  {
-    return true;
-  }
-
-  // Test if any planes are bisected, if they are, then there is likely to
-  // be an intersection into clip space.
-
-  if( insideLeftPlaneCount < 4 )
-  {
-    return false;
-  }
-  if( insideRightPlaneCount < 4 )
-  {
-    return false;
-  }
-  if( insideTopPlaneCount < 4 )
-  {
-    return false;
-  }
-  if( insideBottomPlaneCount < 4 )
-  {
-    return false;
-  }
-
-  return true;
-}
-
 } // namespace SceneGraph
 
 } // namespace Internal
index 764bc4f..0017573 100644 (file)
@@ -204,13 +204,6 @@ private:
   // Undefined
   ImageRenderer& operator=(const ImageRenderer& rhs);
 
-  /**
-   * @param modelMatrix
-   * @param modelViewProjectionMatrix
-   * @return true if the renderer is outside clip space and doesn't need rendering
-   */
-  bool IsOutsideClipSpaceImpl(const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix);
-
 private:
 
   Texture*    mTexture;
diff --git a/dali/internal/render/renderers/scene-graph-renderer-debug.cpp b/dali/internal/render/renderers/scene-graph-renderer-debug.cpp
new file mode 100644 (file)
index 0000000..f60e546
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scene-graph-renderer-debug.h"
+#include <dali/integration-api/shader-data.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/renderers/render-data-provider.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+namespace
+{
+#if defined ( DEBUG_ENABLED )
+
+// Create shader for debug drawing
+const std::string DEBUG_DRAW_VERTEX_SHADER(
+  "attribute mediump vec3 aPosition;\n"
+  "uniform mediump mat4 uMvpMatrix;\n"
+  "void main()\n"
+  "{\n"
+  "  gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
+  "}\n" );
+
+const std::string DEBUG_DRAW_FRAGMENT_SHADER(
+  "uniform lowp vec4 uColor;\n"
+  "void main()\n"
+  "{\n"
+  "  gl_FragColor = uColor;\n"
+  "}\n" );
+
+static Program* gDebugProgram(NULL); ///< a simple debug shader
+
+#endif
+} // anonymous namespace
+
+void DebugBoundingBox(Context& context, Rect<float> boundingBox, const Matrix& mvp)
+{
+#if defined ( DEBUG_ENABLED )
+  if( gDebugProgram == NULL )
+  {
+    Integration::ShaderDataPtr shaderData( new Integration::ShaderData( DEBUG_DRAW_VERTEX_SHADER, DEBUG_DRAW_FRAGMENT_SHADER ) );
+    const Integration::ResourceId dummyId(99999999);
+    gDebugProgram = Program::New( dummyId, shaderData.Get(), context, true );
+  }
+
+  context.SetBlend( false );
+  context.CullFace( CullNone );
+
+  const unsigned int numPoints=8;
+  GLfloat vertices[numPoints*3] = {
+    boundingBox.x,                      boundingBox.y, 0.0f,
+    boundingBox.x,                      boundingBox.y + boundingBox.height, 0.0f,
+
+    boundingBox.x,                      boundingBox.y + boundingBox.height, 0.0f,
+    boundingBox.x + boundingBox.width,  boundingBox.y + boundingBox.height, 0.0f,
+
+    boundingBox.x + boundingBox.width,  boundingBox.y + boundingBox.height, 0.0f,
+    boundingBox.x + boundingBox.width,  boundingBox.y, 0.0f,
+
+    boundingBox.x + boundingBox.width,  boundingBox.y, 0.0f,
+    boundingBox.x,                      boundingBox.y, 0.0f,
+  };
+
+  gDebugProgram->Use();
+
+  GpuBuffer vertexBuffer(context,GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW);
+  vertexBuffer.UpdateDataBuffer(numPoints * 3 * sizeof(float), &vertices[0]);
+  vertexBuffer.Bind();
+
+  GLint positionLoc    = gDebugProgram->GetAttribLocation(Program::ATTRIB_POSITION);
+  context.VertexAttribPointer( positionLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0 );
+  context.EnableVertexAttributeArray( positionLoc );
+
+  GLint mvpLoc = gDebugProgram->GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
+  if( mvpLoc != Program::UNIFORM_UNKNOWN )
+  {
+    gDebugProgram->SetUniformMatrix4fv( mvpLoc, 1, mvp.AsFloat() );
+  }
+  GLint colorLoc = gDebugProgram->GetUniformLocation(Program::UNIFORM_COLOR);
+  if( colorLoc != Program::UNIFORM_UNKNOWN )
+  {
+    gDebugProgram->SetUniform4f( colorLoc, 0.0f, 1.0f, 1.0f, 1.0f );
+  }
+
+  context.DrawArrays(GL_LINES, 0, numPoints);
+
+  context.DisableVertexAttributeArray( positionLoc );
+#endif
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/renderers/scene-graph-renderer-debug.h b/dali/internal/render/renderers/scene-graph-renderer-debug.h
new file mode 100644 (file)
index 0000000..9f91c14
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
+#define __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/rect.h>
+
+// Uncomment to debug bounding boxes of objects
+//#define DEBUG_DISPLAY_BOUNDING_BOX 1
+
+namespace Dali
+{
+namespace Internal
+{
+class Context;
+
+namespace SceneGraph
+{
+class RenderDataProvider;
+
+void DebugBoundingBox(Context& context, Rect<float> boundingBox, const Matrix& mvp);
+
+#if defined(DEBUG_ENABLED) && defined(DEBUG_DISPLAY_BOUNDING_BOX)
+#define DEBUG_BOUNDING_BOX( context, boundingBox, mvp )                     \
+  DebugBoundingBox( context, boundingBox, mvp )
+#else
+#define DEBUG_BOUNDING_BOX( context, boundingBox, mvp )
+#endif
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+
+#endif // __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
index 55fdbdd..352d578 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/internal/render/gl-resources/context.h>
 #include <dali/internal/render/shaders/shader.h>
 #include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-debug.h>
 #include <dali/internal/render/renderers/render-data-provider.h>
 #include <dali/public-api/actors/blending.h>
 #include <dali/internal/common/image-sampler.h>
@@ -35,6 +36,8 @@ namespace Internal
 
 namespace
 {
+
+
 static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it locally to reduce storage overhead
 static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it locally to reduce storage overhead
 
@@ -99,6 +102,7 @@ inline void SetMatrices( Program& program,
     program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
   }
 }
+
 }
 
 namespace SceneGraph
@@ -183,6 +187,7 @@ void Renderer::Render( BufferIndex bufferIndex,
       return;
     }
   }
+
   // Take the program into use so we can send uniforms to it
   program.Use();
 
@@ -240,6 +245,7 @@ void Renderer::Render( BufferIndex bufferIndex,
 Renderer::Renderer( RenderDataProvider& dataprovider )
 : mDataProvider( dataprovider ),
   mContext( NULL ),
+
   mTextureCache( NULL ),
   mShader( NULL ),
   mSamplerBitfield( ImageSampler::DefaultOptions() ),
index dfb26bb..c44e0d3 100644 (file)
@@ -157,7 +157,7 @@ private:
   virtual void ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType& outType, ShaderSubTypes& outSubType ) = 0;
 
   /**
-   * Checks if renderer's is culled.
+   * Checks if renderer is culled.
    * @param[in] modelMatrix The model matrix.
    * @param[in] modelViewProjectionMatrix The MVP matrix.
    * @return \e true if it is. Otherwise \e false.
@@ -186,7 +186,6 @@ private:
   BlendingOptions mBlendingOptions;
   bool mUseBlend:1;                 ///< True if blending should be enabled, 1 bit is enough
   CullFaceMode mCullFaceMode:3;     ///< cullface enum, 3 bits is enough
-
 };
 
 } // namespace SceneGraph
index 81d7c0f..1c2a857 100644 (file)
 #include <dali/internal/common/text-vertex-2d.h>
 #include <dali/internal/event/text/font-impl.h>
 #include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/common/culling-algorithms.h>
 #include <dali/internal/render/common/performance-monitor.h>
-#include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-debug.h>
+#include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/shaders/shader.h>
 #include <dali/internal/render/gl-resources/texture-cache.h>
-#include <dali/internal/update/controllers/scene-controller.h>
 #include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/update/controllers/scene-controller.h>
 
 using namespace std;
 
@@ -180,9 +182,7 @@ void TextRenderer::SetVertexData( TextVertexBuffer* vertexData )
     // Get inverted text size, as this is faster for the shader to operate on,
     // and shader won't throw any errors performing a multiplication rather than a divide by zero
     // on a bad size value.
-    mInvTextSize = vertexData->mVertexMax;
-    mInvTextSize.x = mInvTextSize.x > Math::MACHINE_EPSILON_1 ? 1.0f / mInvTextSize.x : 1.0f;
-    mInvTextSize.y = mInvTextSize.y > Math::MACHINE_EPSILON_1 ? 1.0f / mInvTextSize.y : 1.0f;
+    mGeometryExtent = vertexData->mGeometryExtent;
   }
   else
   {
@@ -334,7 +334,17 @@ void TextRenderer::ResolveGeometryTypes( BufferIndex bufferIndex, GeometryType&
 
 bool TextRenderer::IsOutsideClipSpace( const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
 {
-  return false; // @todo add implementation
+  mContext->IncrementRendererCount();
+
+  Rect<float> boundingBox(mGeometryExtent.width*-0.5f, mGeometryExtent.height*-0.5f, mGeometryExtent.width, mGeometryExtent.height);
+  DEBUG_BOUNDING_BOX( *mContext, boundingBox, modelViewProjectionMatrix );
+
+  if(Is2dBoxOutsideClipSpace( modelMatrix, modelViewProjectionMatrix, boundingBox ) )
+  {
+    mContext->IncrementCulledCount();
+    return true;
+  }
+  return false;
 }
 
 void TextRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
@@ -452,7 +462,12 @@ void TextRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Ma
       {
         const Vector4& color = mTextParameters->GetGradientColor();
         program.SetUniform4f( gradientColorLoc, color.r, color.g, color.b, color.a );
-        program.SetUniform2f( textSizeLoc, mInvTextSize.width, mInvTextSize.height );
+
+        Vector2 invTextSize( mGeometryExtent );
+        invTextSize.x = invTextSize.x > Math::MACHINE_EPSILON_1 ? 1.0f / invTextSize.x : 1.0f;
+        invTextSize.y = invTextSize.y > Math::MACHINE_EPSILON_1 ? 1.0f / invTextSize.y : 1.0f;
+
+        program.SetUniform2f( textSizeLoc, invTextSize.width, invTextSize.height );
       }
     }
 
@@ -496,6 +511,7 @@ void TextRenderer::DoRender( BufferIndex bufferIndex, Program& program, const Ma
 
   mContext->DisableVertexAttributeArray( positionLoc );
   mContext->DisableVertexAttributeArray( texCoordLoc );
+
 }
 
 TextRenderer::TextRenderer( RenderDataProvider& dataprovider )
@@ -505,7 +521,7 @@ TextRenderer::TextRenderer( RenderDataProvider& dataprovider )
   mVertexBuffer(),
   mIndexBuffer(),
   mTextParameters(),
-  mInvTextSize(),
+  mGeometryExtent(),
   mTextureId( 0 ),
   mSmoothing( Dali::TextStyle::DEFAULT_SMOOTH_EDGE_DISTANCE_FIELD ),
   mPixelSize(0.0f)
index 7310e9a..fdb18ad 100644 (file)
@@ -185,12 +185,12 @@ private:
   OwnerPointer< GpuBuffer > mIndexBuffer;         ///< GPU Buffer containing Index information
   OwnerPointer< TextParameters > mTextParameters; ///< Optional text parameters
 
-  Vector2    mInvTextSize;                        ///< 1.0 / (2D size of Vertices in vertex buffer (max extent - min extent))
+  Vector2    mGeometryExtent; // actual geometry extent
+
   ResourceId mTextureId;
 
   float   mSmoothing;
   float   mPixelSize;
-
 };
 
 } // namespace SceneGraph