Merge "Merge branch 'devel/master' into devel/graphics" into devel/master
authorDavid Steele <david.steele@samsung.com>
Wed, 26 May 2021 12:27:06 +0000 (12:27 +0000)
committerGerrit Code Review <gerrit@review>
Wed, 26 May 2021 12:27:06 +0000 (12:27 +0000)
106 files changed:
automated-tests/src/dali-adaptor-internal/CMakeLists.txt
automated-tests/src/dali-adaptor-internal/utc-Dali-FontClient.cpp
automated-tests/src/dali-adaptor/CMakeLists.txt
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-actor-utils.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-actor-utils.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-application.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-abstraction.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-application.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-buffer.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-controller.h
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.h [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-pass.h [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-target.h [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp [moved from automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp with 66% similarity]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.h [moved from automated-tests/src/dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.h with 64% similarity]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.h [new file with mode: 0644]
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.h
automated-tests/src/dali-adaptor/utc-Dali-Application.cpp
automated-tests/src/dali-adaptor/utc-Dali-Window.cpp
automated-tests/src/dali-graphics/CMakeLists.txt
automated-tests/src/dali-graphics/utc-Dali-GraphicsProgram.cpp [new file with mode: 0644]
automated-tests/src/dali-graphics/utc-Dali-GraphicsSampler.cpp
automated-tests/src/dali-platform-abstraction/CMakeLists.txt
dali/devel-api/adaptor-framework/accessibility-impl.cpp
dali/devel-api/adaptor-framework/atspi-accessibility.h
dali/devel-api/adaptor-framework/web-engine-context.h [changed mode: 0755->0644]
dali/devel-api/adaptor-framework/web-engine-cookie-manager.h [changed mode: 0755->0644]
dali/devel-api/text-abstraction/font-client.cpp
dali/devel-api/text-abstraction/font-client.h
dali/devel-api/text-abstraction/text-abstraction.h [changed mode: 0755->0644]
dali/integration-api/adaptor-framework/render-surface-interface.h
dali/integration-api/adaptor-framework/scene-holder-impl.cpp
dali/integration-api/adaptor-framework/scene-holder-impl.h
dali/internal/accessibility/bridge/bridge-accessible.cpp
dali/internal/accessibility/bridge/bridge-base.cpp
dali/internal/accessibility/bridge/bridge-base.h
dali/internal/accessibility/bridge/bridge-impl.cpp
dali/internal/accessibility/bridge/dummy-atspi.cpp
dali/internal/accessibility/bridge/dummy-atspi.h
dali/internal/adaptor/common/application-impl.cpp
dali/internal/adaptor/common/combined-update-render-controller.cpp
dali/internal/graphics/common/graphics-interface.h
dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp [new file with mode: 0644]
dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h [new file with mode: 0644]
dali/internal/graphics/gles-impl/egl-graphics-controller.cpp
dali/internal/graphics/gles-impl/egl-graphics-controller.h
dali/internal/graphics/gles-impl/egl-sync-object.cpp [new file with mode: 0644]
dali/internal/graphics/gles-impl/egl-sync-object.h [new file with mode: 0644]
dali/internal/graphics/gles-impl/file.list
dali/internal/graphics/gles-impl/gles-context.cpp
dali/internal/graphics/gles-impl/gles-context.h
dali/internal/graphics/gles-impl/gles-graphics-command-buffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.cpp
dali/internal/graphics/gles-impl/gles-graphics-framebuffer.h
dali/internal/graphics/gles-impl/gles-graphics-pipeline-cache.cpp
dali/internal/graphics/gles-impl/gles-graphics-pipeline.cpp
dali/internal/graphics/gles-impl/gles-graphics-reflection.cpp
dali/internal/graphics/gles-impl/gles-graphics-reflection.h
dali/internal/graphics/gles-impl/gles-graphics-render-pass.cpp
dali/internal/graphics/gles-impl/gles-graphics-render-pass.h
dali/internal/graphics/gles-impl/gles-graphics-render-target.cpp
dali/internal/graphics/gles-impl/gles-graphics-render-target.h
dali/internal/graphics/gles-impl/gles-graphics-texture.cpp
dali/internal/graphics/gles-impl/gles-graphics-texture.h
dali/internal/graphics/gles-impl/gles-graphics-types.h
dali/internal/graphics/gles-impl/gles-sync-object.cpp [new file with mode: 0644]
dali/internal/graphics/gles-impl/gles-sync-object.h [new file with mode: 0644]
dali/internal/graphics/gles-impl/gles2-graphics-memory.cpp
dali/internal/graphics/gles-impl/gles3-graphics-memory.cpp
dali/internal/graphics/gles/egl-graphics.cpp
dali/internal/graphics/gles/egl-graphics.h
dali/internal/graphics/gles/egl-sync-implementation.cpp
dali/internal/graphics/gles/egl-sync-implementation.h
dali/internal/imaging/common/image-loader.cpp
dali/internal/imaging/common/pixel-manipulation.cpp
dali/internal/imaging/tizen/native-image-source-impl-tizen.cpp
dali/internal/imaging/tizen/native-image-source-queue-impl-tizen.cpp
dali/internal/system/windows/callback-manager-win.cpp
dali/internal/text/text-abstraction/font-client-impl.cpp
dali/internal/text/text-abstraction/font-client-impl.h
dali/internal/text/text-abstraction/font-client-plugin-impl.cpp
dali/internal/text/text-abstraction/font-client-plugin-impl.h
dali/internal/vector-animation/common/vector-animation-renderer-plugin-proxy.h
dali/internal/window-system/common/gl-window-render-thread.h
dali/internal/window-system/common/window-base.cpp
dali/internal/window-system/common/window-base.h
dali/internal/window-system/common/window-render-surface.cpp
dali/internal/window-system/common/window-render-surface.h
dali/internal/window-system/tizen-wayland/ecore-wl2/window-base-ecore-wl2.cpp
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.cpp
dali/internal/window-system/tizen-wayland/native-render-surface-ecore-wl.h
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.cpp
dali/internal/window-system/ubuntu-x11/pixmap-render-surface-ecore-x.h
dali/public-api/adaptor-framework/application.cpp

index 08169fd..3fe5502 100644 (file)
@@ -28,10 +28,12 @@ LIST(APPEND TC_SOURCES
     ../dali-adaptor/dali-test-suite-utils/test-harness.cpp
     ../dali-adaptor/dali-test-suite-utils/test-application.cpp
     ../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
-    ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-reflection.cpp
index ebf8994..bd868f9 100644 (file)
@@ -19,8 +19,8 @@
 
 #include <dali-test-suite-utils.h>
 #include <dali/dali.h>
-#include <dali/internal/text/text-abstraction/font-client-helper.h>
 #include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/internal/text/text-abstraction/font-client-helper.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -90,8 +90,8 @@ int UtcDaliFontClient(void)
 
 int UtcDaliFontClientAtlasLimitation(void)
 {
-  TestApplication application;
-  bool             result = 0;
+  TestApplication             application;
+  bool                        result     = 0;
   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
 
   tet_infoline("UtcDaliFontClientAtlasLimitation Default");
@@ -107,21 +107,20 @@ int UtcDaliFontClientAtlasLimitation(void)
   fontClient.EnableAtlasLimitation(false);
   result = fontClient.IsAtlasLimitationEnabled();
   DALI_TEST_EQUALS(false, result, TEST_LOCATION);
- END_TEST;
- }
 END_TEST;
+}
 
-const std::string DEFAULT_FONT_DIR( "/resources/fonts" );
-const uint32_t    MAX_WIDTH_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
+const std::string DEFAULT_FONT_DIR("/resources/fonts");
+const uint32_t    MAX_WIDTH_FIT_IN_ATLAS  = TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
 const uint32_t    MAX_HEIGHT_FIT_IN_ATLAS = TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT - TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
 
 int UtcDaliFontClientAtlasLimitationEnabled(void)
 {
-
   TestApplication application;
 
-  char* pathNamePtr = get_current_dir_name();
-  const std::string pathName( pathNamePtr );
-  free( pathNamePtr );
+  char*             pathNamePtr = get_current_dir_name();
+  const std::string pathName(pathNamePtr);
+  free(pathNamePtr);
 
   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
   fontClient.EnableAtlasLimitation(true);
@@ -130,109 +129,106 @@ int UtcDaliFontClientAtlasLimitationEnabled(void)
   // Note the block size depends on font-family.
   // This is to create FontDescription and pass it to GetFontId with point-size (various cases).
   TextAbstraction::FontDescription fontDescription;
-  fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+  fontDescription.path   = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
   fontDescription.family = "DejaVuSans";
-  fontDescription.width = TextAbstraction::FontWidth::NONE;
+  fontDescription.width  = TextAbstraction::FontWidth::NONE;
   fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
-  fontDescription.slant = TextAbstraction::FontSlant::NONE;
-
+  fontDescription.slant  = TextAbstraction::FontSlant::NONE;
 
   // Block's width or height are less than 512
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=200");
-  uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+  uint32_t                                     pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId                      fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
   glyphBufferData200.width  = 0;
   glyphBufferData200.height = 0;
   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
 
-  DALI_TEST_GREATER( MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION );
-  DALI_TEST_GREATER( MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION );
+  DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData200.width, TEST_LOCATION);
+  DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData200.height, TEST_LOCATION);
 
   // Block's width or height are  greater than 512 and less than 1024
   uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=1000");
-  TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+  TextAbstraction::FontId                      fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
   glyphBufferData1000.width  = 0;
   glyphBufferData1000.height = 0;
   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
 
-  DALI_TEST_GREATER(  MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION );
-  DALI_TEST_GREATER(  MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION );
+  DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData1000.width, TEST_LOCATION);
+  DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData1000.height, TEST_LOCATION);
 
   // Block's width or height are greater than 1024 and less than 2048
   uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
   tet_infoline("UtcDaliFontClientAtlasLimitationEnabled PointSize=2000");
-  TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+  TextAbstraction::FontId                      fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
   glyphBufferData2000.width  = 0;
   glyphBufferData2000.height = 0;
   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
 
-  DALI_TEST_GREATER(  MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION );
-  DALI_TEST_GREATER(  MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION );
+  DALI_TEST_GREATER(MAX_WIDTH_FIT_IN_ATLAS, glyphBufferData2000.width, TEST_LOCATION);
+  DALI_TEST_GREATER(MAX_HEIGHT_FIT_IN_ATLAS, glyphBufferData2000.height, TEST_LOCATION);
 
- END_TEST;
 END_TEST;
 }
 
-
 int UtcDaliFontClientAtlasLimitationDisabled(void)
 {
-
   TestApplication application;
 
-  char* pathNamePtr = get_current_dir_name();
-  const std::string pathName( pathNamePtr );
-  free( pathNamePtr );
+  char*             pathNamePtr = get_current_dir_name();
+  const std::string pathName(pathNamePtr);
+  free(pathNamePtr);
 
   TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
   fontClient.EnableAtlasLimitation(false);
 
   TextAbstraction::FontDescription fontDescription;
-  fontDescription.path = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
+  fontDescription.path   = pathName + DEFAULT_FONT_DIR + "/dejavu/DejaVuSans.ttf";
   fontDescription.family = "DejaVuSans";
-  fontDescription.width = TextAbstraction::FontWidth::NONE;
+  fontDescription.width  = TextAbstraction::FontWidth::NONE;
   fontDescription.weight = TextAbstraction::FontWeight::NORMAL;
-  fontDescription.slant = TextAbstraction::FontSlant::NONE;
+  fontDescription.slant  = TextAbstraction::FontSlant::NONE;
 
   // Block's width or height are less than 512
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=200");
-  uint32_t pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId fontId200 = fontClient.GetFontId(fontDescription, pointSize200);
+  uint32_t                                     pointSize200 = 200 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId                      fontId200    = fontClient.GetFontId(fontDescription, pointSize200);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData200;
   glyphBufferData200.width  = 0;
   glyphBufferData200.height = 0;
   fontClient.CreateBitmap(fontId200, 68, false, false, glyphBufferData200, 0);
 
-  DALI_TEST_GREATER(512u, glyphBufferData200.width,  TEST_LOCATION ); //93u
-  DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION ); //115u
+  DALI_TEST_GREATER(512u, glyphBufferData200.width, TEST_LOCATION);  //93u
+  DALI_TEST_GREATER(512u, glyphBufferData200.height, TEST_LOCATION); //115u
 
   // Block's width or height are  greater than 512 and less than 1024
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=1000");
-  uint32_t pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId fontId1000 = fontClient.GetFontId(fontDescription, pointSize1000);
+  uint32_t                                     pointSize1000 = 1000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId                      fontId1000    = fontClient.GetFontId(fontDescription, pointSize1000);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData1000;
   glyphBufferData1000.width  = 0;
   glyphBufferData1000.height = 0;
   fontClient.CreateBitmap(fontId1000, 68, false, false, glyphBufferData1000, 0);
 
-  DALI_TEST_GREATER( 512u, glyphBufferData1000.width, TEST_LOCATION ); //462u
-  DALI_TEST_GREATER( glyphBufferData1000.height, 512u, TEST_LOCATION ); //574u
+  DALI_TEST_GREATER(512u, glyphBufferData1000.width, TEST_LOCATION);  //462u
+  DALI_TEST_GREATER(glyphBufferData1000.height, 512u, TEST_LOCATION); //574u
 
   // Block's width or height are greater than 1024 and less than 2048
   tet_infoline("UtcDaliFontClientAtlasLimitationDisabled PointSize=2000");
-  uint32_t pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  TextAbstraction::FontId fontId2000 = fontClient.GetFontId(fontDescription, pointSize2000);
+  uint32_t                                     pointSize2000 = 2000 * TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  TextAbstraction::FontId                      fontId2000    = fontClient.GetFontId(fontDescription, pointSize2000);
   TextAbstraction::FontClient::GlyphBufferData glyphBufferData2000;
   glyphBufferData2000.width  = 0;
   glyphBufferData2000.height = 0;
   fontClient.CreateBitmap(fontId2000, 68, false, false, glyphBufferData2000, 0);
 
-  DALI_TEST_GREATER( 1024u, glyphBufferData2000.width, TEST_LOCATION ); //924u
-  DALI_TEST_GREATER( glyphBufferData2000.height, 1024u, TEST_LOCATION ); //1148u
+  DALI_TEST_GREATER(1024u, glyphBufferData2000.width, TEST_LOCATION);  //924u
+  DALI_TEST_GREATER(glyphBufferData2000.height, 1024u, TEST_LOCATION); //1148u
 
- END_TEST;
 END_TEST;
 }
 
 int UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas(void)
@@ -240,90 +236,89 @@ int UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas(void)
   TestApplication application;
   tet_infoline(" UtcDaliFontClientCurrentMaximumBlockSizeFitInAtlas ");
 
-  bool isChanged ;
+  bool                        isChanged;
   TextAbstraction::FontClient fontClient;
   fontClient = TextAbstraction::FontClient::Get();
 
-  Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
-  Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
+  Size defaultTextAtlasSize              = fontClient.GetDefaultTextAtlasSize();
+  Size maximumTextAtlasSize              = fontClient.GetMaximumTextAtlasSize();
   Size currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
 
   tet_infoline("CurrentMaximumBlockSizeFitInAtlas start with default ");
-  DALI_TEST_EQUALS( currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION );
+  DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, TEST_LOCATION);
 
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(currentMaximumBlockSizeFitInAtlas);
-  DALI_TEST_CHECK (isChanged);
+  DALI_TEST_CHECK(isChanged);
 
-  Size decreaseOnlyWidth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
+  Size decreaseOnlyWidth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with width < current ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyWidth);
-  DALI_TEST_CHECK (isChanged);
+  DALI_TEST_CHECK(isChanged);
 
-  Size decreaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
+  Size decreaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height - 1u);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with height < current ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseOnlyHeigth);
-  DALI_TEST_CHECK (isChanged);
+  DALI_TEST_CHECK(isChanged);
 
-  Size decreaseBoth (currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
+  Size decreaseBoth(currentMaximumBlockSizeFitInAtlas.width - 1u, currentMaximumBlockSizeFitInAtlas.height - 1u);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with size < current ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(decreaseBoth);
-  DALI_TEST_CHECK (isChanged);
+  DALI_TEST_CHECK(isChanged);
 
-  Size increaseOnlyWidth (maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
+  Size increaseOnlyWidth(maximumTextAtlasSize.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with width > max ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyWidth);
-  DALI_TEST_CHECK (!isChanged);
+  DALI_TEST_CHECK(!isChanged);
 
-  Size increaseOnlyHeigth (currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
+  Size increaseOnlyHeigth(currentMaximumBlockSizeFitInAtlas.width, maximumTextAtlasSize.height + 1u);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with height > max ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseOnlyHeigth);
-  DALI_TEST_CHECK (!isChanged);
+  DALI_TEST_CHECK(!isChanged);
 
-  Size increaseBoth (maximumTextAtlasSize.width  + 1u, maximumTextAtlasSize.height + 1u);
+  Size increaseBoth(maximumTextAtlasSize.width + 1u, maximumTextAtlasSize.height + 1u);
   tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size > max ");
   isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseBoth);
-  DALI_TEST_CHECK (!isChanged);
+  DALI_TEST_CHECK(!isChanged);
 
   currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
   if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
   {
     tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is changed with current < size < max ");
     Size increaseWidth = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height);
-    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
-    DALI_TEST_CHECK (isChanged);
+    isChanged          = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseWidth);
+    DALI_TEST_CHECK(isChanged);
     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
 
     Size increaseHeigth = Size(currentMaximumBlockSizeFitInAtlas.width, currentMaximumBlockSizeFitInAtlas.height + 1u);
-    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
-    DALI_TEST_CHECK (isChanged);
+    isChanged           = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(increaseHeigth);
+    DALI_TEST_CHECK(isChanged);
     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
 
     Size sizeLessThanMax = Size(currentMaximumBlockSizeFitInAtlas.width + 1u, currentMaximumBlockSizeFitInAtlas.height + 1u);
-    isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
+    isChanged            = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(sizeLessThanMax);
 
     if(currentMaximumBlockSizeFitInAtlas.width < maximumTextAtlasSize.width && currentMaximumBlockSizeFitInAtlas.height < maximumTextAtlasSize.height)
     {
-      DALI_TEST_CHECK (isChanged);
+      DALI_TEST_CHECK(isChanged);
     }
     else
     {
-      DALI_TEST_CHECK (!isChanged);
+      DALI_TEST_CHECK(!isChanged);
     }
 
     currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
 
-    DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION );
-    DALI_TEST_EQUALS (currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION );
+    DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, defaultTextAtlasSize, 0.0f, TEST_LOCATION);
+    DALI_TEST_EQUALS(currentMaximumBlockSizeFitInAtlas, sizeLessThanMax, TEST_LOCATION);
 
     tet_infoline("SetCurrentMaximumBlockSizeFitInAtlas is not changed with size == max ");
     isChanged = fontClient.SetCurrentMaximumBlockSizeFitInAtlas(maximumTextAtlasSize);
-    DALI_TEST_CHECK (!isChanged);
+    DALI_TEST_CHECK(!isChanged);
   }
 
   currentMaximumBlockSizeFitInAtlas = fontClient.GetCurrentMaximumBlockSizeFitInAtlas();
-  DALI_TEST_NOT_EQUALS (currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize,  0.0f, TEST_LOCATION );
-
+  DALI_TEST_NOT_EQUALS(currentMaximumBlockSizeFitInAtlas, maximumTextAtlasSize, 0.0f, TEST_LOCATION);
 
   END_TEST;
 }
@@ -338,18 +333,16 @@ int UtcDaliFontClientTextAtlasConstants(void)
 
   Size defaultTextAtlasSize = fontClient.GetDefaultTextAtlasSize();
   Size defaultTextAtlasWidthHeight(TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_HEIGHT);
-  DALI_TEST_EQUALS (defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION );
-  DALI_TEST_EQUALS (defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION );
-
+  DALI_TEST_EQUALS(defaultTextAtlasSize, TextAbstraction::FontClient::DEFAULT_TEXT_ATLAS_SIZE, TEST_LOCATION);
+  DALI_TEST_EQUALS(defaultTextAtlasSize, defaultTextAtlasWidthHeight, TEST_LOCATION);
 
   Size maximumTextAtlasSize = fontClient.GetMaximumTextAtlasSize();
   Size maxTextAtlasWidthHeight(TextAbstraction::FontClient::MAX_TEXT_ATLAS_WIDTH, TextAbstraction::FontClient::MAX_TEXT_ATLAS_HEIGHT);
-  DALI_TEST_EQUALS (maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION );
-  DALI_TEST_EQUALS (maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION );
-
+  DALI_TEST_EQUALS(maximumTextAtlasSize, TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE, TEST_LOCATION);
+  DALI_TEST_EQUALS(maximumTextAtlasSize, maxTextAtlasWidthHeight, TEST_LOCATION);
 
   uint32_t numberOfPointsPerOneUnitOfPointSize = fontClient.GetNumberOfPointsPerOneUnitOfPointSize();
-  DALI_TEST_EQUALS (numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION );
+  DALI_TEST_EQUALS(numberOfPointsPerOneUnitOfPointSize, TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE, TEST_LOCATION);
 
   END_TEST;
 }
\ No newline at end of file
index df77d7f..4b3f4b4 100644 (file)
@@ -27,10 +27,12 @@ LIST(APPEND TC_SOURCES
     dali-test-suite-utils/test-application.cpp
     dali-test-suite-utils/test-gesture-generator.cpp
     dali-test-suite-utils/test-gl-abstraction.cpp
-    dali-test-suite-utils/test-gl-sync-abstraction.cpp
+    dali-test-suite-utils/test-graphics-sync-impl.cpp
+    dali-test-suite-utils/test-graphics-sync-object.cpp
     dali-test-suite-utils/test-graphics-buffer.cpp
     dali-test-suite-utils/test-graphics-command-buffer.cpp
     dali-test-suite-utils/test-graphics-controller.cpp
+    dali-test-suite-utils/test-graphics-framebuffer.cpp
     dali-test-suite-utils/test-graphics-pipeline.cpp
     dali-test-suite-utils/test-graphics-reflection.cpp
     dali-test-suite-utils/test-graphics-texture.cpp
index 2db4dbc..bf62bb8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -91,4 +91,44 @@ Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, co
   return actor;
 }
 
+Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader)
+{
+  // Create the geometry
+  Geometry geometry = CreateQuadGeometry();
+
+  // Create Shader
+  Shader shader = Shader::New(vertexShader, fragmentShader);
+
+  // Create renderer from geometry and material
+  Renderer renderer = Renderer::New(geometry, shader);
+
+  // Create actor and set renderer
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+
+  // If we a texture, then create a texture-set and add to renderer
+  if(textures)
+  {
+    renderer.SetTextures(textures);
+
+    auto texture = textures.GetTexture(0);
+
+    // Set actor to the size of the texture if set
+    actor.SetProperty(Actor::Property::SIZE, Vector2(texture.GetWidth(), texture.GetHeight()));
+  }
+
+  return actor;
+}
+
+Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height)
+{
+  Texture texture = Texture::New(type, format, width, height);
+
+  int       bufferSize = width * height * 2;
+  uint8_t*  buffer     = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+  PixelData pixelData  = PixelData::New(buffer, bufferSize, width, height, format, PixelData::FREE);
+  texture.Upload(pixelData, 0u, 0u, 0u, 0u, width, height);
+  return texture;
+}
+
 } // namespace Dali
index be085bf..0dbe07e 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_TEST_ACTOR_UTILS_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -19,6 +19,8 @@
  */
 
 // EXTERNAL INCLUDES
+#include <dali/public-api/rendering/texture-set.h>
+#include <dali/public-api/rendering/texture.h>
 #include <string>
 
 namespace Dali
@@ -49,6 +51,17 @@ Actor CreateRenderableActor(Texture texture);
  */
 Actor CreateRenderableActor(Texture texture, const std::string& vertexShader, const std::string& fragmentShader);
 
+/**
+ * @brief Creates a renderable-actor with a texture and custom shaders.
+ * @param[in] textures TextureSet to set.
+ * @param[in] vertexShader The vertex-shader.
+ * @param[in] fragmentShader The fragment-shader.
+ * @return An actor with a renderer.
+ */
+Actor CreateRenderableActor2(TextureSet textures, const std::string& vertexShader, const std::string& fragmentShader);
+
+Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height);
+
 } // namespace Dali
 
 #endif // DALI_TEST_ACTOR_UTILS_H
index a2a1848..5e69c95 100644 (file)
@@ -76,6 +76,12 @@ void TestApplication::CreateScene()
 {
   mScene = Dali::Integration::Scene::New(Size(static_cast<float>(mSurfaceWidth), static_cast<float>(mSurfaceHeight)));
   mScene.SetDpi(Vector2(static_cast<float>(mDpi.x), static_cast<float>(mDpi.y)));
+
+  // Create render target for the scene
+  Graphics::RenderTargetCreateInfo rtInfo{};
+  rtInfo.SetExtent({mSurfaceWidth, mSurfaceHeight});
+  mRenderTarget = mGraphicsController.CreateRenderTarget(rtInfo, nullptr);
+  mScene.SetSurfaceRenderTarget(mRenderTarget.get());
 }
 
 void TestApplication::InitializeCore()
@@ -149,14 +155,14 @@ TestGlAbstraction& TestApplication::GetGlAbstraction()
   return static_cast<TestGlAbstraction&>(mGraphicsController.GetGlAbstraction());
 }
 
-TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction()
+TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction()
 {
-  return static_cast<TestGlSyncAbstraction&>(mGraphicsController.GetGlSyncAbstraction());
+  return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
 }
 
-TestGlContextHelperAbstraction& TestApplication::GetGlContextHelperAbstraction()
+TestGraphicsSyncImplementation& TestApplication::GetGraphicsSyncImpl()
 {
-  return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
+  return static_cast<TestGraphicsSyncImplementation&>(mGraphicsController.GetGraphicsSyncImpl());
 }
 
 void TestApplication::ProcessEvent(const Integration::Event& event)
index e7d8c76..4f32cd8 100644 (file)
@@ -65,8 +65,8 @@ public:
   TestGraphicsController&  GetGraphicsController();
 
   TestGlAbstraction&              GetGlAbstraction();
-  TestGlSyncAbstraction&          GetGlSyncAbstraction();
   TestGlContextHelperAbstraction& GetGlContextHelperAbstraction();
+  TestGraphicsSyncImplementation& GetGraphicsSyncImpl();
 
   void        ProcessEvent(const Integration::Event& event);
   void        SendNotification();
@@ -108,6 +108,8 @@ protected:
   uint32_t mSurfaceHeight;
   uint32_t mFrame;
 
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget;
+
   struct
   {
     uint32_t x;
index f2086d6..b85cf4d 100644 (file)
 #include "test-gl-abstraction.h"
 #include "test-trace-call-stack.h"
 
+static const bool TRACE{
+  false};
+
 namespace Dali
 {
 TestGlAbstraction::TestGlAbstraction()
-: mBufferTrace(true, std::string("gl")),
-  mCullFaceTrace(true, "gl"),
-  mEnableDisableTrace(true, "gl"),
-  mShaderTrace(true, "gl"),
-  mTextureTrace(true, std::string("gl")),
-  mTexParameterTrace(true, "gl"),
-  mDrawTrace(true, "gl"),
-  mDepthFunctionTrace(true, "gl"),
-  mStencilFunctionTrace(true, "gl"),
-  mScissorTrace(true, "gl"),
-  mSetUniformTrace(true, "Uniform "),
-  mViewportTrace(true, "gl")
+: mBufferTrace(TRACE, std::string("gl")),
+  mCullFaceTrace(TRACE, "gl"),
+  mEnableDisableTrace(TRACE, "gl"),
+  mShaderTrace(TRACE, "gl"),
+  mTextureTrace(TRACE, std::string("gl")),
+  mTexParameterTrace(TRACE, "gl"),
+  mDrawTrace(TRACE, "gl"),
+  mDepthFunctionTrace(TRACE, "gl"),
+  mStencilFunctionTrace(TRACE, "gl"),
+  mScissorTrace(TRACE, "gl"),
+  mSetUniformTrace(TRACE, "Uniform "),
+  mViewportTrace(TRACE, "gl")
 {
   Initialize();
 }
@@ -46,7 +49,6 @@ void TestGlAbstraction::Initialize()
   mCurrentProgram                  = 0;
   mCompileStatus                   = GL_TRUE;
   mLinkStatus                      = GL_TRUE;
-  mNumberOfActiveUniforms          = 0;
   mGetErrorResult                  = 0;
   mGetStringResult                 = NULL;
   mIsBufferResult                  = 0;
@@ -112,6 +114,31 @@ void TestGlAbstraction::Initialize()
   {
     mVertexAttribArrayState[i] = false;
   }
+
+  mActiveUniforms = std::vector<ActiveUniform>{
+    {"uRendererColor", GL_FLOAT, 1},
+    {"uCustom", GL_FLOAT_VEC3, 1},
+    {"uCustom3", GL_FLOAT_VEC3, 1},
+    {"uFadeColor", GL_FLOAT_VEC4, 1},
+    {"uUniform1", GL_FLOAT_VEC4, 1},
+    {"uUniform2", GL_FLOAT_VEC4, 1},
+    {"uUniform3", GL_FLOAT_VEC4, 1},
+    {"uFadeProgress", GL_FLOAT, 1},
+    {"uANormalMatrix", GL_FLOAT_MAT3, 1},
+    {"sEffect", GL_SAMPLER_2D, 1},
+    {"sTexture", GL_SAMPLER_2D, 1},
+    {"sTextureRect", GL_SAMPLER_2D, 1},
+    {"sGloss", GL_SAMPLER_2D, 1},
+    {"uColor", GL_FLOAT_VEC4, 1},
+    {"uModelMatrix", GL_FLOAT_MAT4, 1},
+    {"uModelView", GL_FLOAT_MAT4, 1},
+    {"uMvpMatrix", GL_FLOAT_MAT4, 1},
+    {"uNormalMatrix", GL_FLOAT_MAT4, 1},
+    {"uProjection", GL_FLOAT_MAT4, 1},
+    {"uSize", GL_FLOAT_VEC3, 1},
+    {"uViewMatrix", GL_FLOAT_MAT4, 1},
+    {"uLightCameraProjectionMatrix", GL_FLOAT_MAT4, 1},
+    {"uLightCameraViewMatrix", GL_FLOAT_MAT4, 1}};
 }
 
 void TestGlAbstraction::PreRender()
index 9357803..aec9f5d 100644 (file)
@@ -49,6 +49,13 @@ struct UniformData
   }
 };
 
+struct ActiveUniform
+{
+  std::string name;
+  GLenum      type;
+  GLint       size;
+};
+
 class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction
 {
 public:
@@ -621,6 +628,11 @@ public:
     {
       mFramebufferStencilAttached = true;
     }
+    else if(attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+    {
+      mFramebufferStencilAttached = true;
+      mFramebufferDepthAttached   = true;
+    }
   }
 
   inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override
@@ -749,27 +761,18 @@ public:
   {
   }
 
+  inline void SetActiveUniforms(const std::vector<ActiveUniform>& uniforms)
+  {
+    mActiveUniforms = uniforms;
+  }
+
   inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override
   {
-    switch(index)
+    if(index < mActiveUniforms.size())
     {
-      case 0:
-        *length = snprintf(name, bufsize, "sTexture");
-        *type   = GL_SAMPLER_2D;
-        *size   = 1;
-        break;
-      case 1:
-        *length = snprintf(name, bufsize, "sEffect");
-        *type   = GL_SAMPLER_2D;
-        *size   = 1;
-        break;
-      case 2:
-        *length = snprintf(name, bufsize, "sGloss");
-        *type   = GL_SAMPLER_2D;
-        *size   = 1;
-        break;
-      default:
-        break;
+      *length = snprintf(name, bufsize, "%s", mActiveUniforms[index].name.c_str());
+      *type   = mActiveUniforms[index].type;
+      *size   = mActiveUniforms[index].size;
     }
   }
 
@@ -837,7 +840,7 @@ public:
         *params = mProgramBinaryLength;
         break;
       case GL_ACTIVE_UNIFORMS:
-        *params = mNumberOfActiveUniforms;
+        *params = mActiveUniforms.size();
         break;
       case GL_ACTIVE_UNIFORM_MAX_LENGTH:
         *params = 100;
@@ -981,31 +984,10 @@ public:
     namedParams["program"] << program;
     mShaderTrace.PushCall("LinkProgram", out.str(), namedParams);
 
-    mNumberOfActiveUniforms = 3;
-
-    GetUniformLocation(program, "uRendererColor");
-    GetUniformLocation(program, "uCustom");
-    GetUniformLocation(program, "uCustom3");
-    GetUniformLocation(program, "uFadeColor");
-    GetUniformLocation(program, "uUniform1");
-    GetUniformLocation(program, "uUniform2");
-    GetUniformLocation(program, "uUniform3");
-    GetUniformLocation(program, "uFadeProgress");
-    GetUniformLocation(program, "uANormalMatrix");
-    GetUniformLocation(program, "sEffect");
-    GetUniformLocation(program, "sTexture");
-    GetUniformLocation(program, "sTextureRect");
-    GetUniformLocation(program, "sGloss");
-    GetUniformLocation(program, "uColor");
-    GetUniformLocation(program, "uModelMatrix");
-    GetUniformLocation(program, "uModelView");
-    GetUniformLocation(program, "uMvpMatrix");
-    GetUniformLocation(program, "uNormalMatrix");
-    GetUniformLocation(program, "uProjection");
-    GetUniformLocation(program, "uSize");
-    GetUniformLocation(program, "uViewMatrix");
-    GetUniformLocation(program, "uLightCameraProjectionMatrix");
-    GetUniformLocation(program, "uLightCameraViewMatrix");
+    for(const auto& uniform : mActiveUniforms)
+    {
+      GetUniformLocation(program, uniform.name.c_str());
+    }
 
     for(const auto& uniform : mCustomUniformData)
     {
@@ -2465,14 +2447,13 @@ public: // TEST FUNCTIONS
     mBufferSubDataCalls.clear();
   }
 
-private:
+public:
   GLuint                                mCurrentProgram;
   GLuint                                mCompileStatus;
   BufferDataCalls                       mBufferDataCalls;
   BufferSubDataCalls                    mBufferSubDataCalls;
   GLvoid*                               mMappedBuffer{nullptr};
   GLuint                                mLinkStatus;
-  GLint                                 mNumberOfActiveUniforms;
   GLenum                                mGetErrorResult;
   GLubyte*                              mGetStringResult;
   GLboolean                             mIsBufferResult;
@@ -2547,8 +2528,8 @@ private:
   typedef std::map<std::string, GLint>   UniformIDMap;
   typedef std::map<GLuint, UniformIDMap> ProgramUniformMap;
   ProgramUniformMap                      mUniforms;
-
-  std::vector<UniformData> mCustomUniformData{};
+  std::vector<ActiveUniform>             mActiveUniforms;
+  std::vector<UniformData>               mCustomUniformData{};
 
   template<typename T>
   struct ProgramUniformValue : public std::map<GLuint, std::map<GLint, T> >
index 6a2efc0..cb025d0 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include "test-graphics-application.h"
+#include <test-graphics-sync-impl.h>
 
 namespace Dali
 {
@@ -59,8 +60,9 @@ void TestGraphicsApplication::CreateCore()
   // We always need the first update!
   mStatus.keepUpdating = Integration::KeepUpdating::STAGE_KEEP_RENDERING;
 
+  mGraphics.Initialize();
   mGraphicsController.InitializeGLES(mGlAbstraction);
-  mGraphicsController.Initialize(mGlSyncAbstraction, mGlContextHelperAbstraction);
+  mGraphicsController.Initialize(mGraphicsSyncImplementation, mGlContextHelperAbstraction, mGraphics);
 
   mCore = Dali::Integration::Core::New(mRenderController,
                                        mPlatformAbstraction,
@@ -79,6 +81,13 @@ void TestGraphicsApplication::CreateScene()
 {
   mScene = Dali::Integration::Scene::New(Size(static_cast<float>(mSurfaceWidth), static_cast<float>(mSurfaceHeight)));
   mScene.SetDpi(Vector2(static_cast<float>(mDpi.x), static_cast<float>(mDpi.y)));
+
+  Graphics::RenderTargetCreateInfo createInfo{};
+  createInfo.SetSurface({nullptr})
+    .SetExtent({mSurfaceWidth, mSurfaceHeight})
+    .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
+  mRenderTarget = mGraphicsController.CreateRenderTarget(createInfo, nullptr);
+  mScene.SetSurfaceRenderTarget(mRenderTarget.get());
 }
 
 void TestGraphicsApplication::InitializeCore()
@@ -152,11 +161,6 @@ TestGlAbstraction& TestGraphicsApplication::GetGlAbstraction()
   return static_cast<TestGlAbstraction&>(mGraphicsController.GetGlAbstraction());
 }
 
-TestGlSyncAbstraction& TestGraphicsApplication::GetGlSyncAbstraction()
-{
-  return static_cast<TestGlSyncAbstraction&>(mGraphicsController.GetGlSyncAbstraction());
-}
-
 TestGlContextHelperAbstraction& TestGraphicsApplication::GetGlContextHelperAbstraction()
 {
   return static_cast<TestGlContextHelperAbstraction&>(mGraphicsController.GetGlContextHelperAbstraction());
@@ -269,7 +273,7 @@ void TestGraphicsApplication::ResetContext()
 {
   mCore->ContextDestroyed();
   mGraphicsController.InitializeGLES(mGlAbstraction);
-  mGraphicsController.Initialize(mGlSyncAbstraction, mGlContextHelperAbstraction);
+  mGraphicsController.Initialize(mGraphicsSyncImplementation, mGlContextHelperAbstraction, mGraphics);
   mCore->ContextCreated();
 }
 
index e71ea41..b51bbda 100644 (file)
 #include <dali/integration-api/scene.h>
 #include <dali/integration-api/trace.h>
 
+#include <dali/internal/graphics/common/graphics-interface.h>
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
 #include <dali/public-api/common/dali-common.h>
 
 #include <test-gl-abstraction.h>
 #include <test-gl-context-helper-abstraction.h>
-#include <test-gl-sync-abstraction.h>
+#include <test-graphics-sync-impl.h>
 #include <test-platform-abstraction.h>
 #include <test-render-controller.h>
 
 namespace Dali
 {
+namespace Internal::Adaptor
+{
+class ConfigurationManager;
+}
+
+class TestGraphicsImpl : public Internal::Adaptor::GraphicsInterface
+{
+public:
+  TestGraphicsImpl()
+  : GraphicsInterface()
+  {
+  }
+  virtual ~TestGraphicsImpl() = default;
+
+  Dali::Graphics::Controller& GetController() override
+  {
+    Dali::Graphics::Controller* controller{nullptr};
+    return *controller;
+  }
+
+  /**
+   * Initialize the graphics subsystem, configured from environment
+   */
+  void Initialize() override
+  {
+    mCallstack.PushCall("Initialize()", "");
+  }
+
+  /**
+   * Initialize the graphics subsystem, providing explicit parameters.
+   *
+   * @param[in] depth True if depth buffer is required
+   * @param[in] stencil True if stencil buffer is required
+   * @param[in] partialRendering True if partial rendering is required
+   * @param[in] msaa level of anti-aliasing required (-1 = off)
+   */
+  void Initialize(bool depth, bool stencil, bool partialRendering, int msaa) override
+  {
+    TraceCallStack::NamedParams namedParams;
+    namedParams["depth"] << depth;
+    namedParams["stencil"] << stencil;
+    namedParams["partialRendering"] << partialRendering;
+    namedParams["msaa"] << msaa;
+    mCallstack.PushCall("Initialize()", "");
+  }
+
+  /**
+   * Configure the graphics surface
+   *
+   * @param[in] surface The surface to configure, or NULL if not present
+   */
+  void ConfigureSurface(Dali::RenderSurfaceInterface* surface) override
+  {
+  }
+
+  /**
+   * Activate the resource context
+   */
+  void ActivateResourceContext() override
+  {
+    mCallstack.PushCall("ActivateResourceContext()", "");
+  }
+
+  /**
+   * Activate the resource context
+   *
+   * @param[in] surface The surface whose context to be switched to.
+   */
+  void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) override
+  {
+    TraceCallStack::NamedParams namedParams;
+    namedParams["surface"] << std::hex << surface;
+    mCallstack.PushCall("ActivateResourceContext()", namedParams.str(), namedParams);
+  }
+
+  /**
+   * Inform graphics interface that this is the first frame after a resume.
+   */
+  void SetFirstFrameAfterResume() override
+  {
+  }
+
+  /**
+   * Shut down the graphics implementation
+   */
+  void Shutdown() override
+  {
+    mCallstack.PushCall("Shutdown()", "");
+  }
+
+  /**
+   * Destroy the Graphics implementation
+   */
+  void Destroy() override
+  {
+    mCallstack.PushCall("Destroy()", "");
+  }
+
+  /**
+   * @return true if advanced blending options are supported
+   */
+  bool IsAdvancedBlendEquationSupported() override
+  {
+    return true;
+  }
+
+  /**
+   * @return true if graphics subsystem is initialized
+   */
+  bool IsInitialized() override
+  {
+    return true;
+  }
+
+  /**
+   * @return true if a separate resource context is supported
+   */
+  bool IsResourceContextSupported() override
+  {
+    return true;
+  }
+
+  /**
+   * @return the maximum texture size
+   */
+  uint32_t GetMaxTextureSize() override
+  {
+    return 32768u;
+  }
+
+  /**
+   * @return the version number of the shader language
+   */
+  uint32_t GetShaderLanguageVersion() override
+  {
+    return 320;
+  }
+
+  /**
+   * Store cached configurations
+   */
+  void CacheConfigurations(Internal::Adaptor::ConfigurationManager& configurationManager) override
+  {
+  }
+
+public:
+  TraceCallStack mCallstack{true, "GraphicsImpl"};
+};
+
 class DALI_CORE_API TestGraphicsApplication : public ConnectionTracker
 {
 public:
@@ -69,7 +219,6 @@ public:
   Graphics::Controller&    GetGraphicsController();
 
   TestGlAbstraction&              GetGlAbstraction();
-  TestGlSyncAbstraction&          GetGlSyncAbstraction();
   TestGlContextHelperAbstraction& GetGlContextHelperAbstraction();
 
   void        ProcessEvent(const Integration::Event& event);
@@ -98,12 +247,14 @@ private:
   void DoUpdate(uint32_t intervalMilliseconds, const char* location = NULL);
 
 protected:
-  TestPlatformAbstraction         mPlatformAbstraction;
-  TestRenderController            mRenderController;
-  Graphics::EglGraphicsController mGraphicsController; // Use real controller in Adaptor
-  TestGlAbstraction               mGlAbstraction;
-  TestGlSyncAbstraction           mGlSyncAbstraction;
-  TestGlContextHelperAbstraction  mGlContextHelperAbstraction;
+  TestPlatformAbstraction                     mPlatformAbstraction;
+  TestRenderController                        mRenderController;
+  Graphics::EglGraphicsController             mGraphicsController; // Use real controller in Adaptor
+  TestGlAbstraction                           mGlAbstraction;
+  TestGlContextHelperAbstraction              mGlContextHelperAbstraction;
+  TestGraphicsSyncImplementation              mGraphicsSyncImplementation;
+  TestGraphicsImpl                            mGraphics;
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
 
   Integration::UpdateStatus mStatus;
   Integration::RenderStatus mRenderStatus;
index d8a1b1a..21eecf4 100644 (file)
@@ -80,14 +80,15 @@ GLenum TestGraphicsBuffer::GetTarget()
   return target;
 }
 
-void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program) const
+void TestGraphicsBuffer::BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const
 {
   auto* reflection = static_cast<const TestGraphicsReflection*>(&program->GetReflection());
 
   Graphics::UniformBlockInfo uboInfo{};
   reflection->GetUniformBlock(0, uboInfo);
 
-  auto* data = memory.data();
+  auto  offset = uboBinding.offset;
+  auto* data   = memory.data() + offset;
 
   for(const auto& member : uboInfo.members)
   {
index 87c9f87..1dc2715 100644 (file)
@@ -26,6 +26,7 @@
 namespace Dali
 {
 class TestGraphicsProgram;
+class UniformBufferBindingDescriptor;
 class TestGraphicsBuffer : public Graphics::Buffer
 {
 public:
@@ -40,7 +41,7 @@ public:
     return true;
   }
 
-  void BindAsUniformBuffer(const TestGraphicsProgram* program) const;
+  void BindAsUniformBuffer(const TestGraphicsProgram* program, const Dali::UniformBufferBindingDescriptor& uboBinding) const;
 
   TraceCallStack&            mCallStack;
   TestGlAbstraction&         mGl;
index ed63416..9f86b99 100644 (file)
 
 namespace Dali
 {
+std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op)
+{
+  switch(op)
+  {
+    case Graphics::StencilOp::KEEP:
+      os << "KEEP";
+      return os;
+    case Graphics::StencilOp::ZERO:
+      os << "ZERO";
+      return os;
+    case Graphics::StencilOp::REPLACE:
+      os << "REPLACE";
+      return os;
+    case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+      os << "INCREMENT_AND_CLAMP";
+      return os;
+    case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+      os << "DECREMENT_AND_CLAMP";
+      return os;
+    case Graphics::StencilOp::INVERT:
+      os << "INVERT";
+      return os;
+    case Graphics::StencilOp::INCREMENT_AND_WRAP:
+      os << "INCREMENT_AND_WRAP";
+      return os;
+    case Graphics::StencilOp::DECREMENT_AND_WRAP:
+      os << "DECREMENT_AND_WRAP";
+      return os;
+  }
+  return os;
+};
+
+std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op)
+{
+  switch(op)
+  {
+    case Graphics::CompareOp::NEVER:
+      os << "NEVER";
+      return os;
+    case Graphics::CompareOp::LESS:
+      os << "LESS";
+      return os;
+    case Graphics::CompareOp::EQUAL:
+      os << "EQUAL";
+      return os;
+    case Graphics::CompareOp::LESS_OR_EQUAL:
+      os << "LESS_OR_EQUAL";
+      return os;
+    case Graphics::CompareOp::GREATER:
+      os << "GREATER";
+      return os;
+    case Graphics::CompareOp::NOT_EQUAL:
+      os << "NOT_EQUAL";
+      return os;
+    case Graphics::CompareOp::GREATER_OR_EQUAL:
+      os << "GREATER_OR_EQUAL";
+      return os;
+    case Graphics::CompareOp::ALWAYS:
+      os << "ALWAYS";
+      return os;
+  }
+  return os;
+};
+
 TestGraphicsCommandBuffer::TestGraphicsCommandBuffer(TraceCallStack& callstack, TestGlAbstraction& glAbstraction)
 : mCallStack(callstack),
   mGlAbstraction(glAbstraction)
@@ -60,9 +124,9 @@ void TestGraphicsCommandBuffer::GetStateForDrawCall(int drawCallIndex)
   }
 }
 
-std::vector<Command*> TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask)
+std::vector<const Command*> TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMask mask) const
 {
-  std::vector<Command*> mCommandStack{};
+  std::vector<const Command*> mCommandStack{};
   for(auto& cmd : mCommands)
   {
     if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type)))
@@ -73,4 +137,27 @@ std::vector<Command*> TestGraphicsCommandBuffer::GetCommandsByType(CommandTypeMa
   return mCommandStack;
 }
 
+std::vector<const Command*> TestGraphicsCommandBuffer::GetChildCommandsByType(CommandTypeMask mask) const
+{
+  std::vector<const Command*> mCommandStack{};
+  for(auto& cmd : mCommands)
+  {
+    if(uint32_t(cmd.type) == (mask & uint32_t(cmd.type)))
+    {
+      mCommandStack.emplace_back(&cmd);
+    }
+    if(cmd.type == CommandType::EXECUTE_COMMAND_BUFFERS)
+    {
+      for(auto secondaryCB : cmd.data.executeCommandBuffers.buffers)
+      {
+        for(auto command : secondaryCB->GetChildCommandsByType(mask))
+        {
+          mCommandStack.push_back(command);
+        }
+      }
+    }
+  }
+  return mCommandStack;
+}
+
 } // namespace Dali
index c10c3f1..3df3219 100644 (file)
@@ -32,27 +32,45 @@ namespace Dali
 {
 class TestGraphicsTexture;
 class TestGraphicsBuffer;
+class TestGraphicsCommandBuffer;
 class TestGraphicsSampler;
 class TestGraphicsPipeline;
 
 enum class CommandType
 {
-  FLUSH                 = 1 << 0,
-  BIND_TEXTURES         = 1 << 1,
-  BIND_SAMPLERS         = 1 << 2,
-  BIND_VERTEX_BUFFERS   = 1 << 3,
-  BIND_INDEX_BUFFER     = 1 << 4,
-  BIND_UNIFORM_BUFFER   = 1 << 5,
-  BIND_PIPELINE         = 1 << 6,
-  DRAW                  = 1 << 7,
-  DRAW_INDEXED          = 1 << 8,
-  DRAW_INDEXED_INDIRECT = 1 << 9,
-  SET_SCISSOR           = 1 << 10,
-  SET_SCISSOR_TEST      = 1 << 11,
-  SET_VIEWPORT          = 1 << 12,
-  SET_VIEWPORT_TEST     = 1 << 13
+  FLUSH                   = 1 << 0,
+  BIND_TEXTURES           = 1 << 1,
+  BIND_SAMPLERS           = 1 << 2,
+  BIND_VERTEX_BUFFERS     = 1 << 3,
+  BIND_INDEX_BUFFER       = 1 << 4,
+  BIND_UNIFORM_BUFFER     = 1 << 5,
+  BIND_PIPELINE           = 1 << 6,
+  DRAW                    = 1 << 7,
+  DRAW_INDEXED            = 1 << 8,
+  DRAW_INDEXED_INDIRECT   = 1 << 9,
+  SET_SCISSOR             = 1 << 10,
+  SET_SCISSOR_TEST        = 1 << 11,
+  SET_VIEWPORT            = 1 << 12,
+  SET_VIEWPORT_TEST       = 1 << 13,
+  BEGIN_RENDER_PASS       = 1 << 14,
+  END_RENDER_PASS         = 1 << 15,
+  EXECUTE_COMMAND_BUFFERS = 1 << 16,
+  SET_COLOR_MASK          = 1 << 17,
+  CLEAR_STENCIL_BUFFER    = 1 << 18,
+  CLEAR_DEPTH_BUFFER      = 1 << 19,
+  SET_STENCIL_TEST_ENABLE = 1 << 20,
+  SET_STENCIL_WRITE_MASK  = 1 << 21,
+  SET_STENCIL_OP          = 1 << 22,
+  SET_STENCIL_FUNC        = 1 << 23,
+  SET_DEPTH_COMPARE_OP    = 1 << 24,
+  SET_DEPTH_TEST_ENABLE   = 1 << 25,
+  SET_DEPTH_WRITE_ENABLE  = 1 << 26,
 };
 
+std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op);
+
+std::ostream& operator<<(std::ostream& os, Graphics::CompareOp op);
+
 using CommandTypeMask = uint32_t;
 template<typename T>
 inline CommandTypeMask operator|(T flags, CommandType bit)
@@ -160,8 +178,37 @@ struct Command
   {
   }
 
+  Command(CommandType type)
+  : type(type)
+  {
+    // do non-trivial initialization
+    switch(type)
+    {
+      case CommandType::BEGIN_RENDER_PASS:
+      {
+        new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor();
+        break;
+      }
+      default:
+      {
+      }
+    }
+  }
+
   ~Command()
   {
+    switch(type)
+    {
+      case CommandType::BEGIN_RENDER_PASS:
+      {
+        data.beginRenderPass.~BeginRenderPassDescriptor();
+        break;
+      }
+      default:
+      {
+        break;
+      }
+    }
   }
 
   /**
@@ -172,6 +219,22 @@ struct Command
   {
     switch(rhs.type)
     {
+      case CommandType::BEGIN_RENDER_PASS:
+      {
+        new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(rhs.data.beginRenderPass);
+        break;
+      }
+      case CommandType::END_RENDER_PASS:
+      {
+        data.endRenderPass = rhs.data.endRenderPass;
+        break;
+      }
+      case CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        data.executeCommandBuffers = rhs.data.executeCommandBuffers;
+        break;
+      }
+
       case CommandType::BIND_VERTEX_BUFFERS:
       {
         data.bindVertexBuffers = rhs.data.bindVertexBuffers;
@@ -245,6 +308,59 @@ struct Command
         data.viewportTest.enable = rhs.data.viewportTest.enable;
         break;
       }
+      case CommandType::SET_COLOR_MASK:
+      {
+        data.colorMask.enabled = rhs.data.colorMask.enabled;
+        break;
+      }
+      case CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        break;
+      }
+      case CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        break;
+      }
+      case CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        data.stencilTest.enabled = rhs.data.stencilTest.enabled;
+        break;
+      }
+      case CommandType::SET_STENCIL_FUNC:
+      {
+        data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
+        data.stencilFunc.compareOp   = rhs.data.stencilFunc.compareOp;
+        data.stencilFunc.reference   = rhs.data.stencilFunc.reference;
+        break;
+      }
+      case CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
+        break;
+      }
+      case CommandType::SET_STENCIL_OP:
+      {
+        data.stencilOp.failOp      = rhs.data.stencilOp.failOp;
+        data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
+        data.stencilOp.passOp      = rhs.data.stencilOp.passOp;
+        break;
+      }
+
+      case CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        data.depth.compareOp = rhs.data.depth.compareOp;
+        break;
+      }
+      case CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        data.depth.testEnabled = rhs.data.depth.testEnabled;
+        break;
+      }
+      case CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        data.depth.writeEnabled = rhs.data.depth.writeEnabled;
+        break;
+      }
     }
     type = rhs.type;
   }
@@ -257,6 +373,21 @@ struct Command
   {
     switch(rhs.type)
     {
+      case CommandType::BEGIN_RENDER_PASS:
+      {
+        new(&data.beginRenderPass) CommandData::BeginRenderPassDescriptor(std::move(rhs.data.beginRenderPass));
+        break;
+      }
+      case CommandType::END_RENDER_PASS:
+      {
+        data.endRenderPass = std::move(rhs.data.endRenderPass);
+        break;
+      }
+      case CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        data.executeCommandBuffers = std::move(rhs.data.executeCommandBuffers);
+        break;
+      }
       case CommandType::BIND_VERTEX_BUFFERS:
       {
         data.bindVertexBuffers = std::move(rhs.data.bindVertexBuffers);
@@ -330,6 +461,59 @@ struct Command
         data.viewportTest.enable = rhs.data.viewportTest.enable;
         break;
       }
+
+      case CommandType::SET_COLOR_MASK:
+      {
+        data.colorMask.enabled = rhs.data.colorMask.enabled;
+        break;
+      }
+      case CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        break;
+      }
+      case CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        break;
+      }
+      case CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        data.stencilTest.enabled = rhs.data.stencilTest.enabled;
+        break;
+      }
+      case CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        data.stencilWriteMask.mask = rhs.data.stencilWriteMask.mask;
+        break;
+      }
+      case CommandType::SET_STENCIL_OP:
+      {
+        data.stencilOp.failOp      = rhs.data.stencilOp.failOp;
+        data.stencilOp.depthFailOp = rhs.data.stencilOp.depthFailOp;
+        data.stencilOp.passOp      = rhs.data.stencilOp.passOp;
+        break;
+      }
+      case CommandType::SET_STENCIL_FUNC:
+      {
+        data.stencilFunc.compareMask = rhs.data.stencilFunc.compareMask;
+        data.stencilFunc.compareOp   = rhs.data.stencilFunc.compareOp;
+        data.stencilFunc.reference   = rhs.data.stencilFunc.reference;
+        break;
+      }
+      case CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        data.depth.compareOp = rhs.data.depth.compareOp;
+        break;
+      }
+      case CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        data.depth.testEnabled = rhs.data.depth.testEnabled;
+        break;
+      }
+      case CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        data.depth.writeEnabled = rhs.data.depth.writeEnabled;
+        break;
+      }
     }
     type = rhs.type;
   }
@@ -398,6 +582,60 @@ struct Command
     {
       bool enable;
     } viewportTest;
+
+    struct BeginRenderPassDescriptor
+    {
+      Graphics::RenderPass*             renderPass;
+      Graphics::RenderTarget*           renderTarget;
+      Graphics::Rect2D                  renderArea;
+      std::vector<Graphics::ClearValue> clearValues;
+    } beginRenderPass;
+
+    struct
+    {
+      Graphics::SyncObject* syncObject;
+    } endRenderPass;
+
+    struct
+    {
+      std::vector<const TestGraphicsCommandBuffer*> buffers;
+    } executeCommandBuffers;
+
+    struct
+    {
+      Graphics::CompareOp compareOp;
+      bool                testEnabled;
+      bool                writeEnabled;
+    } depth;
+
+    struct
+    {
+      Graphics::StencilOp failOp;
+      Graphics::StencilOp passOp;
+      Graphics::StencilOp depthFailOp;
+    } stencilOp;
+
+    struct
+    {
+      uint32_t mask;
+    } stencilWriteMask;
+
+    struct
+    {
+      uint32_t            compareMask;
+      Graphics::CompareOp compareOp;
+      uint32_t            reference;
+    } stencilFunc;
+
+    struct
+    {
+      bool enabled;
+    } stencilTest;
+
+    struct
+    {
+      bool enabled;
+    } colorMask;
   } data;
 };
 
@@ -509,12 +747,23 @@ public:
   }
 
   void BeginRenderPass(
-    Graphics::RenderPass&             renderPass,
-    Graphics::RenderTarget&           renderTarget,
-    Graphics::Extent2D                renderArea,
+    Graphics::RenderPass*             renderPass,
+    Graphics::RenderTarget*           renderTarget,
+    Graphics::Rect2D                  renderArea,
     std::vector<Graphics::ClearValue> clearValues) override
   {
-    mCallStack.PushCall("BeginRenderPass", "");
+    mCommands.emplace_back(CommandType::BEGIN_RENDER_PASS);
+    auto& cmd                             = mCommands.back();
+    cmd.data.beginRenderPass.renderPass   = renderPass;
+    cmd.data.beginRenderPass.renderTarget = renderTarget;
+    cmd.data.beginRenderPass.renderArea   = renderArea;
+    cmd.data.beginRenderPass.clearValues  = clearValues;
+
+    TraceCallStack::NamedParams namedParams;
+    namedParams["renderPass"] << std::hex << renderPass;
+    namedParams["renderTarget"] << std::hex << renderTarget;
+    namedParams["renderArea"] << renderArea.width << ", " << renderArea.height;
+    mCallStack.PushCall("BeginRenderPass", namedParams.str(), namedParams);
   }
 
   /**
@@ -526,9 +775,29 @@ public:
    * dependencies (for example, to know when target texture is ready
    * before passing it to another render pass).
    */
-  void EndRenderPass() override
+  void EndRenderPass(Graphics::SyncObject* syncObject) override
   {
-    mCallStack.PushCall("EndRenderPass", "");
+    mCommands.emplace_back(CommandType::END_RENDER_PASS);
+    auto& cmd = mCommands.back();
+
+    cmd.data.endRenderPass.syncObject = syncObject;
+
+    TraceCallStack::NamedParams namedParams;
+    namedParams["syncObject"] << std::hex << syncObject;
+    mCallStack.PushCall("EndRenderPass", namedParams.str(), namedParams);
+  }
+
+  void ExecuteCommandBuffers(std::vector<const CommandBuffer*>&& commandBuffers) override
+  {
+    mCommands.emplace_back();
+    auto& cmd = mCommands.back();
+    cmd.type  = CommandType::EXECUTE_COMMAND_BUFFERS;
+    cmd.data.executeCommandBuffers.buffers.reserve(commandBuffers.size());
+    for(auto&& item : commandBuffers)
+    {
+      cmd.data.executeCommandBuffers.buffers.emplace_back(static_cast<const TestGraphicsCommandBuffer*>(item));
+    }
+    mCallStack.PushCall("ExecuteCommandBuffers", "");
   }
 
   void Draw(
@@ -642,6 +911,112 @@ public:
     mCommands.back().data.viewportTest.enable = value;
   }
 
+  void SetColorMask(bool enabled) override
+  {
+    TraceCallStack::NamedParams params;
+    params["enabled"] << (enabled ? "T" : "F");
+    mCallStack.PushCall("SetColorMask", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                   = CommandType::SET_COLOR_MASK;
+    mCommands.back().data.colorMask.enabled = enabled;
+  }
+
+  void ClearStencilBuffer() override
+  {
+    mCallStack.PushCall("SetStencilMask", "");
+    mCommands.emplace_back();
+    mCommands.back().type = CommandType::CLEAR_STENCIL_BUFFER;
+  }
+
+  void SetStencilTestEnable(bool stencilEnable) override
+  {
+    TraceCallStack::NamedParams params;
+    params["enabled"] << (stencilEnable ? "T" : "F");
+    mCallStack.PushCall("SetStencilTestEnable", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                     = CommandType::SET_STENCIL_TEST_ENABLE;
+    mCommands.back().data.stencilTest.enabled = stencilEnable;
+  }
+
+  void SetStencilWriteMask(uint32_t writeMask) override
+  {
+    TraceCallStack::NamedParams params;
+    params["writeMask"] << std::hex << writeMask;
+    mCallStack.PushCall("SetStencilWriteMask", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                       = CommandType::SET_STENCIL_WRITE_MASK;
+    mCommands.back().data.stencilWriteMask.mask = writeMask;
+  }
+
+  void SetStencilOp(Graphics::StencilOp failOp,
+                    Graphics::StencilOp passOp,
+                    Graphics::StencilOp depthFailOp) override
+  {
+    TraceCallStack::NamedParams params;
+    params["failOp"] << failOp;
+    params["passOp"] << passOp;
+    params["depthFailOp"] << depthFailOp;
+    mCallStack.PushCall("SetStencilOp", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                       = CommandType::SET_STENCIL_OP;
+    mCommands.back().data.stencilOp.failOp      = failOp;
+    mCommands.back().data.stencilOp.passOp      = passOp;
+    mCommands.back().data.stencilOp.depthFailOp = depthFailOp;
+  }
+
+  void SetStencilFunc(Graphics::CompareOp compareOp,
+                      uint32_t            reference,
+                      uint32_t            compareMask) override
+  {
+    TraceCallStack::NamedParams params;
+    params["compareOp"] << compareOp;
+    params["compareMask"] << std::hex << compareMask;
+    params["reference"] << std::hex << reference;
+    mCallStack.PushCall("SetStencilFunc", params.str(), params);
+
+    mCommands.emplace_back();
+    mCommands.back().type = CommandType::SET_STENCIL_FUNC;
+
+    mCommands.back().data.stencilFunc.compareOp   = compareOp;
+    mCommands.back().data.stencilFunc.compareMask = compareMask;
+    mCommands.back().data.stencilFunc.reference   = reference;
+  }
+
+  void SetDepthCompareOp(Graphics::CompareOp compareOp) override
+  {
+    TraceCallStack::NamedParams params;
+    params["compareOp"] << compareOp;
+    mCallStack.PushCall("SetDepthCompareOp", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                 = CommandType::SET_DEPTH_COMPARE_OP;
+    mCommands.back().data.depth.compareOp = compareOp;
+  }
+
+  void SetDepthTestEnable(bool depthTestEnable) override
+  {
+    TraceCallStack::NamedParams params;
+    params["enabled"] << (depthTestEnable ? "T" : "F");
+    mCallStack.PushCall("SetDepthTestEnable", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                   = CommandType::SET_DEPTH_TEST_ENABLE;
+    mCommands.back().data.depth.testEnabled = depthTestEnable;
+  }
+  void SetDepthWriteEnable(bool depthWriteEnable) override
+  {
+    TraceCallStack::NamedParams params;
+    params["enabled"] << (depthWriteEnable ? "T" : "F");
+    mCallStack.PushCall("SetDepthWriteEnable", params.str(), params);
+    mCommands.emplace_back();
+    mCommands.back().type                    = CommandType::SET_DEPTH_WRITE_ENABLE;
+    mCommands.back().data.depth.writeEnabled = depthWriteEnable;
+  }
+  void ClearDepthBuffer() override
+  {
+    mCallStack.PushCall("ClearDepthBuffer", "");
+    mCommands.emplace_back();
+    mCommands.back().type = CommandType::CLEAR_DEPTH_BUFFER;
+  }
+
   [[nodiscard]] const std::vector<Command>& GetCommands() const
   {
     return mCommands;
@@ -662,7 +1037,9 @@ public:
   /**
    * Retrieves commands of specified type
    */
-  std::vector<Command*> GetCommandsByType(CommandTypeMask mask);
+  std::vector<const Command*> GetCommandsByType(CommandTypeMask mask) const;
+
+  std::vector<const Command*> GetChildCommandsByType(CommandTypeMask mask) const;
 
 private:
   TraceCallStack&    mCallStack;
index 51f0721..cbdd5dd 100644 (file)
 
 #include "test-graphics-buffer.h"
 #include "test-graphics-command-buffer.h"
+#include "test-graphics-framebuffer.h"
 #include "test-graphics-reflection.h"
+#include "test-graphics-render-pass.h"
+#include "test-graphics-render-target.h"
 #include "test-graphics-sampler.h"
 #include "test-graphics-shader.h"
+#include "test-graphics-sync-object.h"
 #include "test-graphics-texture.h"
 
 #include <dali/integration-api/gl-defines.h>
 
 namespace Dali
 {
-template<typename T>
-T* Uncast(const Graphics::CommandBuffer* object)
-{
-  return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Texture* object)
-{
-  return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Sampler* object)
-{
-  return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Buffer* object)
-{
-  return const_cast<T*>(static_cast<const T*>(object));
-}
-
-template<typename T>
-T* Uncast(const Graphics::Shader* object)
-{
-  return const_cast<T*>(static_cast<const T*>(object));
-}
-
 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
 {
   return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
@@ -173,70 +147,34 @@ std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& cre
   return o;
 }
 
-class TestGraphicsMemory : public Graphics::Memory
+std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
 {
-public:
-  TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
-  : mCallStack(callStack),
-    mBuffer(buffer),
-    mMappedOffset(mappedOffset),
-    mMappedSize(mappedSize),
-    mLockedOffset(0u),
-    mLockedSize(0u)
-  {
-  }
-
-  void* LockRegion(uint32_t offset, uint32_t size) override
-  {
-    std::ostringstream o;
-    o << offset << ", " << size;
-    mCallStack.PushCall("Memory::LockRegion", o.str());
-
-    if(offset > mMappedOffset + mMappedSize ||
-       size + offset > mMappedOffset + mMappedSize)
-    {
-      fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
-      mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
-    }
-    mLockedOffset = offset;
-    mLockedSize   = size;
-    return &mBuffer.memory[mMappedOffset + offset];
-  }
+  o << "attachmentId:" << colorAttachment.attachmentId
+    << " layerId:" << colorAttachment.layerId
+    << " levelId:" << colorAttachment.levelId
+    << " texture:" << colorAttachment.texture;
+  return o;
+}
 
-  void Unlock(bool flush) override
-  {
-    mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
-    if(flush)
-    {
-      Flush();
-    }
-  }
+std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
+{
+  o << "depthTexture:" << depthStencilAttachment.depthTexture
+    << "depthLevel:" << depthStencilAttachment.depthLevel
+    << "stencilTexture:" << depthStencilAttachment.stencilTexture
+    << "stencilLevel:" << depthStencilAttachment.stencilLevel;
+  return o;
+}
 
-  void Flush() override
+std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
+{
+  o << "colorAttachments:";
+  for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
   {
-    mCallStack.PushCall("Memory::Flush", "");
-    mBuffer.Bind();
-    mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
-    mBuffer.Unbind();
+    o << "[" << i << "]=" << createInfo.colorAttachments[i] << "  ";
   }
-
-  TraceCallStack&     mCallStack;
-  TestGraphicsBuffer& mBuffer;
-  uint32_t            mMappedOffset;
-  uint32_t            mMappedSize;
-  uint32_t            mLockedOffset;
-  uint32_t            mLockedSize;
-};
-
-TestGraphicsController::TestGraphicsController()
-: mCallStack(true, "TestGraphicsController."),
-  mCommandBufferCallStack(true, "TestCommandBuffer.")
-{
-  mCallStack.Enable(true);
-  mCommandBufferCallStack.Enable(true);
-  auto& trace = mGl.GetTextureTrace();
-  trace.Enable(true);
-  trace.EnableLogging(true);
+  o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
+  o << "size: " << createInfo.size;
+  return o;
 }
 
 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
@@ -447,6 +385,143 @@ GLenum GetBlendOp(Graphics::BlendOp blendOp)
   return op;
 }
 
+struct GLCompareOp
+{
+  constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
+  {
+    switch(compareOp)
+    {
+      case Graphics::CompareOp::NEVER:
+        op = GL_NEVER;
+        break;
+      case Graphics::CompareOp::LESS:
+        op = GL_LESS;
+        break;
+      case Graphics::CompareOp::EQUAL:
+        op = GL_EQUAL;
+        break;
+      case Graphics::CompareOp::LESS_OR_EQUAL:
+        op = GL_LEQUAL;
+        break;
+      case Graphics::CompareOp::GREATER:
+        op = GL_GREATER;
+        break;
+      case Graphics::CompareOp::NOT_EQUAL:
+        op = GL_NOTEQUAL;
+        break;
+      case Graphics::CompareOp::GREATER_OR_EQUAL:
+        op = GL_GEQUAL;
+        break;
+      case Graphics::CompareOp::ALWAYS:
+        op = GL_ALWAYS;
+        break;
+    }
+  }
+  GLenum op{GL_LESS};
+};
+
+struct GLStencilOp
+{
+  constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
+  {
+    switch(stencilOp)
+    {
+      case Graphics::StencilOp::KEEP:
+        op = GL_KEEP;
+        break;
+      case Graphics::StencilOp::ZERO:
+        op = GL_ZERO;
+        break;
+      case Graphics::StencilOp::REPLACE:
+        op = GL_REPLACE;
+        break;
+      case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+        op = GL_INCR;
+        break;
+      case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+        op = GL_DECR;
+        break;
+      case Graphics::StencilOp::INVERT:
+        op = GL_INVERT;
+        break;
+      case Graphics::StencilOp::INCREMENT_AND_WRAP:
+        op = GL_INCR_WRAP;
+        break;
+      case Graphics::StencilOp::DECREMENT_AND_WRAP:
+        op = GL_DECR_WRAP;
+        break;
+    }
+  }
+  GLenum op{GL_KEEP};
+};
+
+class TestGraphicsMemory : public Graphics::Memory
+{
+public:
+  TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
+  : mCallStack(callStack),
+    mBuffer(buffer),
+    mMappedOffset(mappedOffset),
+    mMappedSize(mappedSize),
+    mLockedOffset(0u),
+    mLockedSize(0u)
+  {
+  }
+
+  void* LockRegion(uint32_t offset, uint32_t size) override
+  {
+    std::ostringstream o;
+    o << offset << ", " << size;
+    mCallStack.PushCall("Memory::LockRegion", o.str());
+
+    if(offset > mMappedOffset + mMappedSize ||
+       size + offset > mMappedOffset + mMappedSize)
+    {
+      fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
+      mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
+    }
+    mLockedOffset = offset;
+    mLockedSize   = size;
+    return &mBuffer.memory[mMappedOffset + offset];
+  }
+
+  void Unlock(bool flush) override
+  {
+    mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
+    if(flush)
+    {
+      Flush();
+    }
+  }
+
+  void Flush() override
+  {
+    mCallStack.PushCall("Memory::Flush", "");
+    mBuffer.Bind();
+    mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
+    mBuffer.Unbind();
+  }
+
+  TraceCallStack&     mCallStack;
+  TestGraphicsBuffer& mBuffer;
+  uint32_t            mMappedOffset;
+  uint32_t            mMappedSize;
+  uint32_t            mLockedOffset;
+  uint32_t            mLockedSize;
+};
+
+TestGraphicsController::TestGraphicsController()
+: mCallStack(true, "TestGraphicsController."),
+  mCommandBufferCallStack(true, "TestCommandBuffer."),
+  mFrameBufferCallStack(true, "TestFrameBuffer.")
+{
+  mCallStack.Enable(true);
+  mCommandBufferCallStack.Enable(true);
+  auto& trace = mGl.GetTextureTrace();
+  trace.Enable(true);
+  trace.EnableLogging(true);
+}
+
 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
 {
   TraceCallStack::NamedParams namedParams;
@@ -460,193 +535,407 @@ void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& su
   for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
   {
     auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
+    ProcessCommandBuffer(*commandBuffer);
+  }
+}
+
+void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
+{
+  bool                     scissorEnabled = false;
+  TestGraphicsFramebuffer* currentFramebuffer{nullptr};
+  TestGraphicsPipeline*    currentPipeline{nullptr};
 
-    auto value = commandBuffer->GetCommandsByType(0 | CommandType::BIND_TEXTURES);
-    if(!value.empty())
+  for(auto& cmd : commandBuffer.GetCommands())
+  {
+    // process command
+    switch(cmd.type)
     {
-      // must be fixed
-      for(auto& binding : value[0]->data.bindTextures.textureBindings)
+      case CommandType::FLUSH:
+      {
+        // Nothing to do here
+        break;
+      }
+      case CommandType::BIND_TEXTURES:
       {
-        if(binding.texture)
+        for(auto& binding : cmd.data.bindTextures.textureBindings)
         {
-          auto texture = Uncast<TestGraphicsTexture>(binding.texture);
-
-          texture->Bind(binding.binding);
-
-          if(binding.sampler)
+          if(binding.texture)
           {
-            auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
-            if(sampler)
+            auto texture = Uncast<TestGraphicsTexture>(binding.texture);
+            texture->Bind(binding.binding);
+
+            if(binding.sampler)
             {
-              sampler->Apply(texture->GetTarget());
+              auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
+              if(sampler)
+              {
+                sampler->Apply(texture->GetTarget());
+              }
             }
-          }
 
-          texture->Prepare(); // Ensure native texture is ready
+            texture->Prepare(); // Ensure native texture is ready
+          }
         }
+        break;
       }
-    }
-
-    // IndexBuffer binding,
-    auto bindIndexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_INDEX_BUFFER);
-    if(!bindIndexBufferCmds.empty())
-    {
-      auto& indexBufferBinding = bindIndexBufferCmds[0]->data.bindIndexBuffer;
-      if(indexBufferBinding.buffer)
+      case CommandType::BIND_VERTEX_BUFFERS:
       {
-        auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
-        buffer->Bind();
+        for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
+        {
+          auto graphicsBuffer = binding.buffer;
+          auto vertexBuffer   = Uncast<TestGraphicsBuffer>(graphicsBuffer);
+          vertexBuffer->Bind();
+        }
+        break;
       }
-    }
-
-    // VertexBuffer binding,
-    auto bindVertexBufferCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_VERTEX_BUFFERS);
-    if(!bindVertexBufferCmds.empty())
-    {
-      for(auto& binding : bindVertexBufferCmds[0]->data.bindVertexBuffers.vertexBufferBindings)
+      case CommandType::BIND_INDEX_BUFFER:
       {
-        auto graphicsBuffer = binding.buffer;
-        auto vertexBuffer   = Uncast<TestGraphicsBuffer>(graphicsBuffer);
-        vertexBuffer->Bind();
+        auto& indexBufferBinding = cmd.data.bindIndexBuffer;
+        if(indexBufferBinding.buffer)
+        {
+          auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
+          buffer->Bind();
+        }
+        break;
       }
-    }
-
-    bool scissorEnabled = false;
+      case CommandType::BIND_UNIFORM_BUFFER:
+      {
+        auto& bindings = cmd.data.bindUniformBuffers;
+        auto  buffer   = bindings.standaloneUniformsBufferBinding;
 
-    auto scissorTestList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR_TEST);
-    if(!scissorTestList.empty())
-    {
-      if(scissorTestList[0]->data.scissorTest.enable)
+        // based on reflection, issue gl calls
+        buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding);
+        break;
+      }
+      case CommandType::BIND_SAMPLERS:
       {
-        mGl.Enable(GL_SCISSOR_TEST);
-        scissorEnabled = true;
+        break;
       }
-      else
+      case CommandType::BIND_PIPELINE:
       {
-        mGl.Disable(GL_SCISSOR_TEST);
+        currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
+        BindPipeline(currentPipeline);
+        break;
+      }
+      case CommandType::DRAW:
+      {
+        mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
+                       0,
+                       cmd.data.draw.draw.vertexCount);
+        break;
+      }
+      case CommandType::DRAW_INDEXED:
+      {
+        mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+                         static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+                         GL_UNSIGNED_SHORT,
+                         reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+        break;
+      }
+      case CommandType::DRAW_INDEXED_INDIRECT:
+      {
+        mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
+                         static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
+                         GL_UNSIGNED_SHORT,
+                         reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
+        break;
+      }
+      case CommandType::SET_SCISSOR:
+      {
+        if(scissorEnabled)
+        {
+          auto& rect = cmd.data.scissor.region;
+          mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
+        }
+        break;
+      }
+      case CommandType::SET_SCISSOR_TEST:
+      {
+        if(cmd.data.scissorTest.enable)
+        {
+          mGl.Enable(GL_SCISSOR_TEST);
+          scissorEnabled = true;
+        }
+        else
+        {
+          mGl.Disable(GL_SCISSOR_TEST);
+          scissorEnabled = false;
+        }
+        break;
+      }
+      case CommandType::SET_VIEWPORT_TEST:
+      {
+        break;
+      }
+      case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+      {
+        auto& rect = cmd.data.viewport.region;
+        mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
+        break;
       }
-    }
-
-    auto scissorList = commandBuffer->GetCommandsByType(0 | CommandType::SET_SCISSOR);
-    if(!scissorList.empty() && scissorEnabled)
-    {
-      auto& rect = scissorList[0]->data.scissor.region;
-      mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
-    }
 
-    auto viewportList = commandBuffer->GetCommandsByType(0 | CommandType::SET_VIEWPORT);
-    if(!viewportList.empty())
-    {
-      mGl.Viewport(viewportList[0]->data.viewport.region.x, viewportList[0]->data.viewport.region.y, viewportList[0]->data.viewport.region.width, viewportList[0]->data.viewport.region.height);
-    }
+      case CommandType::SET_COLOR_MASK:
+      {
+        // Set all channels to the same mask
+        const bool mask = cmd.data.colorMask.enabled;
+        mGl.ColorMask(mask, mask, mask, mask);
+        break;
+      }
+      case CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        mGl.Clear(GL_STENCIL_BUFFER_BIT);
+        break;
+      }
+      case CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        mGl.Clear(GL_DEPTH_BUFFER_BIT);
+        break;
+      }
 
-    // ignore viewport enable
+      case CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        if(cmd.data.stencilTest.enabled)
+        {
+          mGl.Enable(GL_STENCIL_TEST);
+        }
+        else
+        {
+          mGl.Disable(GL_STENCIL_TEST);
+        }
+        break;
+      }
 
-    // Pipeline attribute setup
-    auto bindPipelineCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_PIPELINE);
-    if(!bindPipelineCmds.empty())
-    {
-      auto  pipeline = bindPipelineCmds[0]->data.bindPipeline.pipeline;
-      auto& vi       = pipeline->vertexInputState;
-      for(auto& attribute : vi.attributes)
+      case CommandType::SET_STENCIL_FUNC:
       {
-        mGl.EnableVertexAttribArray(attribute.location);
-        uint32_t attributeOffset = attribute.offset;
-        GLsizei  stride          = vi.bufferBindings[attribute.binding].stride;
-
-        mGl.VertexAttribPointer(attribute.location,
-                                GetNumComponents(attribute.format),
-                                GetGlType(attribute.format),
-                                GL_FALSE, // Not normalized
-                                stride,
-                                reinterpret_cast<void*>(attributeOffset));
+        mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
+                        cmd.data.stencilFunc.reference,
+                        cmd.data.stencilFunc.compareMask);
+        break;
       }
 
-      // Cull face setup
-      auto& rasterizationState = pipeline->rasterizationState;
-      if(rasterizationState.cullMode == Graphics::CullMode::NONE)
+      case CommandType::SET_STENCIL_WRITE_MASK:
       {
-        mGl.Disable(GL_CULL_FACE);
+        mGl.StencilMask(cmd.data.stencilWriteMask.mask);
+        break;
       }
-      else
+      case CommandType::SET_STENCIL_OP:
       {
-        mGl.Enable(GL_CULL_FACE);
-        mGl.CullFace(GetCullFace(rasterizationState.cullMode));
+        mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
+                      GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
+                      GLStencilOp(cmd.data.stencilOp.passOp).op);
+        break;
       }
 
-      mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
-      // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default),
-      // so it isn't present in the API (and won't have any tests!)
-
-      // Blending setup
-      auto& colorBlendState = pipeline->colorBlendState;
-      if(colorBlendState.blendEnable)
+      case CommandType::SET_DEPTH_COMPARE_OP:
       {
-        mGl.Enable(GL_BLEND);
-
-        mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
-                              GetBlendFactor(colorBlendState.dstColorBlendFactor),
-                              GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
-                              GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
-        if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
+        mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
+        break;
+      }
+      case CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        if(cmd.data.depth.testEnabled)
         {
-          mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
+          mGl.Enable(GL_DEPTH_TEST);
         }
         else
         {
-          mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
+          mGl.Disable(GL_DEPTH_TEST);
         }
-        mGl.BlendColor(colorBlendState.blendConstants[0],
-                       colorBlendState.blendConstants[1],
-                       colorBlendState.blendConstants[2],
-                       colorBlendState.blendConstants[3]);
+        break;
       }
-      else
+      case CommandType::SET_DEPTH_WRITE_ENABLE:
       {
-        mGl.Disable(GL_BLEND);
+        mGl.DepthMask(cmd.data.depth.writeEnabled);
+        break;
       }
 
-      // draw call
-      auto topology = pipeline->inputAssemblyState.topology;
-
-      // UniformBuffer binding (once we know pipeline)
-      auto bindUniformBuffersCmds = commandBuffer->GetCommandsByType(0 | CommandType::BIND_UNIFORM_BUFFER);
-      if(!bindUniformBuffersCmds.empty())
+      case CommandType::EXECUTE_COMMAND_BUFFERS:
       {
-        auto buffer = bindUniformBuffersCmds[0]->data.bindUniformBuffers.standaloneUniformsBufferBinding;
-
-        // based on reflection, issue gl calls
-        buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(pipeline->programState.program));
+        // Process secondary command buffers
+        for(auto& buf : cmd.data.executeCommandBuffers.buffers)
+        {
+          ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
+        }
+        break;
       }
-
-      auto drawCmds = commandBuffer->GetCommandsByType(0 |
-                                                       CommandType::DRAW |
-                                                       CommandType::DRAW_INDEXED_INDIRECT |
-                                                       CommandType::DRAW_INDEXED);
-
-      if(!drawCmds.empty())
+      case CommandType::BEGIN_RENDER_PASS:
       {
-        if(drawCmds[0]->data.draw.type == DrawCallDescriptor::Type::DRAW_INDEXED)
+        auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
+
+        if(renderTarget)
         {
-          mGl.DrawElements(GetTopology(topology),
-                           static_cast<GLsizei>(drawCmds[0]->data.draw.drawIndexed.indexCount),
-                           GL_UNSIGNED_SHORT,
-                           reinterpret_cast<void*>(drawCmds[0]->data.draw.drawIndexed.firstIndex));
+          auto fb = renderTarget->mCreateInfo.framebuffer;
+          if(fb)
+          {
+            if(currentFramebuffer != fb)
+            {
+              currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
+              currentFramebuffer->Bind();
+            }
+          }
+          else
+          {
+            mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+          }
         }
         else
         {
-          mGl.DrawArrays(GetTopology(topology), 0, drawCmds[0]->data.draw.draw.vertexCount);
+          mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
         }
+
+        auto& clearValues = cmd.data.beginRenderPass.clearValues;
+        if(clearValues.size() > 0)
+        {
+          const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
+          if(renderPass)
+          {
+            const auto& color0 = renderPass->attachments[0];
+            GLuint      mask   = 0;
+            if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
+            {
+              mask |= GL_COLOR_BUFFER_BIT;
+
+              // Set clear color (todo: cache it!)
+              // Something goes wrong here if Alpha mask is GL_TRUE
+              mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+              mGl.ClearColor(clearValues[0].color.r,
+                             clearValues[0].color.g,
+                             clearValues[0].color.b,
+                             clearValues[0].color.a);
+            }
+
+            // check for depth stencil
+            if(renderPass->attachments.size() > 1)
+            {
+              const auto& depthStencil = renderPass->attachments.back();
+              if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
+              {
+                mGl.DepthMask(true);
+                uint32_t depthClearColor = 0u;
+                if(clearValues.size() == renderPass->attachments.size())
+                {
+                  depthClearColor = clearValues.back().depthStencil.depth;
+                }
+                mGl.ClearDepthf(depthClearColor);
+                mask |= GL_DEPTH_BUFFER_BIT;
+              }
+              if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
+              {
+                uint32_t stencilClearColor = 0u;
+                if(clearValues.size() == renderPass->attachments.size())
+                {
+                  stencilClearColor = clearValues.back().depthStencil.stencil;
+                }
+                mGl.ClearStencil(stencilClearColor);
+                mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
+                mask |= GL_STENCIL_BUFFER_BIT;
+              }
+            }
+
+            if(mask != 0)
+            {
+              // Test scissor area and RT size
+              const auto& area = cmd.data.beginRenderPass.renderArea;
+              if(area.x == 0 &&
+                 area.y == 0 &&
+                 area.width == renderTarget->mCreateInfo.extent.width &&
+                 area.height == renderTarget->mCreateInfo.extent.height)
+              {
+                mGl.Disable(GL_SCISSOR_TEST);
+                mGl.Clear(mask);
+              }
+              else
+              {
+                mGl.Enable(GL_SCISSOR_TEST);
+                mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
+                mGl.Clear(mask);
+                mGl.Disable(GL_SCISSOR_TEST);
+              }
+            }
+          }
+          else
+          {
+            DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
+          }
+        }
+        break;
       }
-      // attribute clear
-      for(auto& attribute : vi.attributes)
+      case CommandType::END_RENDER_PASS:
       {
-        mGl.DisableVertexAttribArray(attribute.location);
+        if(cmd.data.endRenderPass.syncObject != nullptr)
+        {
+          auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
+          syncObject->InitializeResource(); // create the sync object.
+        }
+        break;
       }
     }
   }
 }
 
+void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
+{
+  auto& vi = pipeline->vertexInputState;
+  for(auto& attribute : vi.attributes)
+  {
+    mGl.EnableVertexAttribArray(attribute.location);
+    uint32_t attributeOffset = attribute.offset;
+    GLsizei  stride          = vi.bufferBindings[attribute.binding].stride;
+
+    mGl.VertexAttribPointer(attribute.location,
+                            GetNumComponents(attribute.format),
+                            GetGlType(attribute.format),
+                            GL_FALSE, // Not normalized
+                            stride,
+                            reinterpret_cast<void*>(attributeOffset));
+  }
+
+  // Cull face setup
+  auto& rasterizationState = pipeline->rasterizationState;
+  if(rasterizationState.cullMode == Graphics::CullMode::NONE)
+  {
+    mGl.Disable(GL_CULL_FACE);
+  }
+  else
+  {
+    mGl.Enable(GL_CULL_FACE);
+    mGl.CullFace(GetCullFace(rasterizationState.cullMode));
+  }
+
+  mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
+
+  // Blending setup
+  auto& colorBlendState = pipeline->colorBlendState;
+  if(colorBlendState.blendEnable)
+  {
+    mGl.Enable(GL_BLEND);
+
+    mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
+                          GetBlendFactor(colorBlendState.dstColorBlendFactor),
+                          GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
+                          GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
+    if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
+    {
+      mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
+    }
+    else
+    {
+      mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
+    }
+    mGl.BlendColor(colorBlendState.blendConstants[0],
+                   colorBlendState.blendConstants[1],
+                   colorBlendState.blendConstants[2],
+                   colorBlendState.blendConstants[3]);
+  }
+  else
+  {
+    mGl.Disable(GL_BLEND);
+  }
+
+  auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
+  mGl.UseProgram(program->mImpl->mId);
+}
+
 /**
  * @brief Presents render target
  * @param renderTarget render target to present
@@ -713,6 +1002,15 @@ void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureU
   }
 }
 
+void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
+{
+  mCallStack.PushCall("GenerateTextureMipmaps", "");
+
+  auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
+  mGl.BindTexture(gfxTexture->GetTarget(), 0);
+  mGl.GenerateMipmap(gfxTexture->GetTarget());
+}
+
 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
 {
   TraceCallStack::NamedParams namedParams;
@@ -770,7 +1068,7 @@ Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateComma
 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
 {
   mCallStack.PushCall("CreateRenderPass", "");
-  return nullptr;
+  return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
 }
 
 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
@@ -782,10 +1080,15 @@ Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(con
   return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
 }
 
-Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
+Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
+  const Graphics::FramebufferCreateInfo&       createInfo,
+  Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
 {
-  mCallStack.PushCall("CreateFramebuffer", "");
-  return nullptr;
+  TraceCallStack::NamedParams namedParams;
+  namedParams["framebufferCreateInfo"] << createInfo;
+  mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
+
+  return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
 }
 
 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
@@ -849,7 +1152,15 @@ Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(con
 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
 {
   mCallStack.PushCall("CreateRenderTarget", "");
-  return nullptr;
+  return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
+}
+
+Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
+  const Graphics::SyncObjectCreateInfo&       syncObjectCreateInfo,
+  Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
+{
+  mCallStack.PushCall("CreateSyncObject", "");
+  return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
 }
 
 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
index 803678e..cabc414 100644 (file)
 #include <dali/graphics-api/graphics-controller.h>
 #include "test-gl-abstraction.h"
 #include "test-gl-context-helper-abstraction.h"
-#include "test-gl-sync-abstraction.h"
+#include "test-graphics-command-buffer.h"
 #include "test-graphics-program.h"
 #include "test-graphics-reflection.h"
+#include "test-graphics-sync-impl.h"
 
 namespace Dali
 {
@@ -36,6 +37,60 @@ std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode);
 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode);
 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo);
 
+template<typename T>
+T* Uncast(const Graphics::CommandBuffer* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Texture* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Sampler* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Buffer* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Shader* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Framebuffer* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::Pipeline* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::RenderTarget* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
+template<typename T>
+T* Uncast(const Graphics::SyncObject* object)
+{
+  return const_cast<T*>(static_cast<const T*>(object));
+}
+
 class TestGraphicsController : public Dali::Graphics::Controller
 {
 public:
@@ -53,14 +108,14 @@ public:
     return mGl;
   }
 
-  Integration::GlSyncAbstraction& GetGlSyncAbstraction() override
+  Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override
   {
-    return mGlSyncAbstraction;
+    return mGlContextHelperAbstraction;
   }
 
-  Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override
+  TestGraphicsSyncImplementation& GetGraphicsSyncImpl()
   {
-    return mGlContextHelperAbstraction;
+    return mGraphicsSyncImpl;
   }
 
   void SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo) override;
@@ -113,6 +168,12 @@ public:
                       const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList) override;
 
   /**
+   * Auto generates mipmaps for the texture
+   * @param[in] texture The texture
+   */
+  void GenerateTextureMipmaps(const Graphics::Texture& texture) override;
+
+  /**
    * TBD: do we need those functions in the new implementation?
    */
   bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override;
@@ -219,11 +280,20 @@ public:
   Graphics::UniquePtr<Graphics::RenderTarget> CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget) override;
 
   /**
+   * @brief Creates new sync object
+   * Could add timeout etc to createinfo... but nah.
+   *
+   * @return pointer to the SyncObject
+   */
+  Graphics::UniquePtr<Graphics::SyncObject> CreateSyncObject(const Graphics::SyncObjectCreateInfo&       syncObjectCreateInfo,
+                                                             Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject) override;
+
+  /**
    * @brief Maps memory associated with Buffer object
    *
    * @param[in] mapInfo Filled details of mapped resource
    *
-   * @return Returns pointer to Memory object or Graphicsnullptr on error
+   * @return Returns pointer to Memory object or nullptr on error
    */
   Graphics::UniquePtr<Graphics::Memory> MapBufferRange(const Graphics::MapBufferInfo& mapInfo) override;
 
@@ -331,13 +401,18 @@ public: // Test Functions
    */
   bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override;
 
+  void ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer);
+
+  void BindPipeline(TestGraphicsPipeline* pipeline);
+
 public:
   mutable TraceCallStack                    mCallStack;
   mutable TraceCallStack                    mCommandBufferCallStack;
+  mutable TraceCallStack                    mFrameBufferCallStack;
   mutable std::vector<Graphics::SubmitInfo> mSubmitStack;
 
   TestGlAbstraction              mGl;
-  TestGlSyncAbstraction          mGlSyncAbstraction;
+  TestGraphicsSyncImplementation mGraphicsSyncImpl;
   TestGlContextHelperAbstraction mGlContextHelperAbstraction;
 
   bool isDiscardQueueEmptyResult{true};
@@ -352,6 +427,10 @@ public:
   };
   std::vector<ProgramCache> mProgramCache;
 
+  struct PipelineCache
+  {
+  };
+
   std::vector<UniformData> mCustomUniforms;
 };
 
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
new file mode 100644 (file)
index 0000000..74f1e29
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2021 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 "test-graphics-framebuffer.h"
+#include <dali/integration-api/gl-defines.h>
+#include "test-graphics-controller.h"
+#include "test-graphics-texture.h"
+
+namespace
+{
+const GLenum COLOR_ATTACHMENTS[] =
+  {
+    GL_COLOR_ATTACHMENT0,
+    GL_COLOR_ATTACHMENT1,
+    GL_COLOR_ATTACHMENT2,
+    GL_COLOR_ATTACHMENT3,
+    GL_COLOR_ATTACHMENT4,
+    GL_COLOR_ATTACHMENT5,
+    GL_COLOR_ATTACHMENT6,
+    GL_COLOR_ATTACHMENT7,
+};
+
+struct DEPTH_STENCIL_ATTACHMENT_TYPE
+{
+  constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
+  {
+    switch(textureFormat)
+    {
+      case Graphics::Format::D16_UNORM:
+      case Graphics::Format::D32_SFLOAT:
+      case Graphics::Format::X8_D24_UNORM_PACK32:
+      {
+        attachment = GL_DEPTH_ATTACHMENT;
+        break;
+      }
+
+      case Graphics::Format::S8_UINT:
+      {
+        attachment = GL_STENCIL_ATTACHMENT;
+        break;
+      }
+
+      case Graphics::Format::D16_UNORM_S8_UINT:
+      case Graphics::Format::D24_UNORM_S8_UINT:
+      case Graphics::Format::D32_SFLOAT_S8_UINT:
+      {
+        attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+        break;
+      }
+      default:
+      {
+        attachment = GL_NONE;
+        break;
+      }
+    }
+  }
+  GLenum attachment{GL_NONE};
+};
+
+} // namespace
+//namespace
+
+namespace Dali
+{
+TestGraphicsFramebuffer::TestGraphicsFramebuffer(
+  TraceCallStack&                        callStack,
+  TestGlAbstraction&                     glAbstraction,
+  const Graphics::FramebufferCreateInfo& createInfo)
+: mGl(glAbstraction),
+  mCallStack(callStack)
+{
+  mCreateInfo.colorAttachments       = std::move(createInfo.colorAttachments);
+  mCreateInfo.depthStencilAttachment = createInfo.depthStencilAttachment;
+  mCreateInfo.size                   = createInfo.size;
+}
+
+TestGraphicsFramebuffer::~TestGraphicsFramebuffer()
+{
+  if(mId)
+  {
+    mGl.DeleteFramebuffers(1, &mId);
+  }
+}
+
+void TestGraphicsFramebuffer::Initialize()
+{
+  mCallStack.PushCall("Initialize", "");
+
+  mGl.GenFramebuffers(1, &mId);
+  mGl.BindFramebuffer(GL_FRAMEBUFFER, mId);
+
+  for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
+  {
+    AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
+  }
+  mGl.DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+
+  if(mCreateInfo.depthStencilAttachment.depthTexture)
+  {
+    // Create a depth or depth/stencil render target.
+    auto depthTexture = Uncast<TestGraphicsTexture>(mCreateInfo.depthStencilAttachment.depthTexture);
+    auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetFormat()).attachment;
+
+    mGl.GenRenderbuffers(1, &mDepthBuffer);
+    mGl.BindRenderbuffer(GL_RENDERBUFFER, mDepthBuffer);
+    mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
+    mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBuffer);
+
+    AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
+  }
+
+  if(mCreateInfo.depthStencilAttachment.stencilTexture)
+  {
+    auto stencilTexture = Uncast<TestGraphicsTexture>(mCreateInfo.depthStencilAttachment.stencilTexture);
+    auto attachmentId   = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetFormat()).attachment;
+
+    // Create a stencil render target.
+    mGl.GenRenderbuffers(1, &mStencilBuffer);
+    mGl.BindRenderbuffer(GL_RENDERBUFFER, mStencilBuffer);
+    mGl.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
+    mGl.FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBuffer);
+
+    AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
+  }
+  mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void TestGraphicsFramebuffer::AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+  auto graphicsTexture = Uncast<TestGraphicsTexture>(texture);
+  if(graphicsTexture->GetType() == Graphics::TextureType::TEXTURE_2D)
+  {
+    mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetTarget(), graphicsTexture->mId, levelId);
+  }
+  else
+  {
+    mGl.FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->mId, levelId);
+  }
+}
+
+void TestGraphicsFramebuffer::Bind()
+{
+  mCallStack.PushCall("Bind", "");
+
+  if(!mId)
+  {
+    Initialize();
+  }
+  mGl.BindFramebuffer(GL_FRAMEBUFFER, mId);
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.h
new file mode 100644 (file)
index 0000000..664c28b
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef TEST_GRAPHICS_FRAMEBUFFER_H
+#define TEST_GRAPHICS_FRAMEBUFFER_H
+
+/*
+ * Copyright (c) 2021 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/graphics-api/graphics-framebuffer-create-info.h>
+#include <dali/graphics-api/graphics-framebuffer.h>
+#include <dali/graphics-api/graphics-types.h>
+#include "test-gl-abstraction.h"
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+class TestGraphicsFramebuffer : public Graphics::Framebuffer
+{
+public:
+  TestGraphicsFramebuffer(TraceCallStack& callStack, TestGlAbstraction& glAbstraction, const Graphics::FramebufferCreateInfo& createInfo);
+  ~TestGraphicsFramebuffer();
+
+  void Initialize();
+  void AttachTexture(Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
+  void Bind();
+
+  TestGlAbstraction&              mGl;
+  Graphics::FramebufferCreateInfo mCreateInfo;
+  TraceCallStack&                 mCallStack;
+
+  GLuint mId{0};
+  GLuint mDepthBuffer;
+  GLuint mStencilBuffer;
+};
+
+} // namespace Dali
+
+#endif //TEST_GRAPHICS_FRAMEBUFFER_H
index d303d56..9e80f8f 100644 (file)
@@ -21,7 +21,7 @@ namespace Dali
 TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics::PipelineCreateInfo& createInfo)
 : mGl(gl)
 {
-  // Need to deep copy, otherwise pointed at memory will go out of scope. Probably should do something about this.
+  // Need to deep copy, otherwise pointed at memory will go out of scope. @todo Probably should do something about this.
 
   if(createInfo.colorBlendState)
     colorBlendState = *createInfo.colorBlendState;
@@ -32,9 +32,6 @@ TestGraphicsPipeline::TestGraphicsPipeline(TestGlAbstraction& gl, const Graphics
   if(createInfo.viewportState)
     viewportState = *createInfo.viewportState;
 
-  if(createInfo.framebufferState)
-    framebufferState = *createInfo.framebufferState;
-
   if(createInfo.depthStencilState)
     depthStencilState = *createInfo.depthStencilState;
 
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-pass.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-pass.h
new file mode 100644 (file)
index 0000000..b52dd2d
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef DALI_TEST_GRAPHICS_RENDER_PASS_H
+#define DALI_TEST_GRAPHICS_RENDER_PASS_H
+
+/*
+ * Copyright (c) 2021 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/graphics-api/graphics-render-pass-create-info.h>
+#include <dali/graphics-api/graphics-render-pass.h>
+
+namespace Dali
+{
+class TestGraphicsRenderPass : public Graphics::RenderPass
+{
+public:
+  TestGraphicsRenderPass(TestGlAbstraction& gl, Graphics::RenderPassCreateInfo createInfo)
+  : mGl(gl)
+  {
+    attachments = *createInfo.attachments; // Deep copy the vector's contents... @todo FIXME!
+  }
+  ~TestGraphicsRenderPass() = default;
+
+  TestGlAbstraction&                           mGl;
+  std::vector<Graphics::AttachmentDescription> attachments;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_RENDER_PASS_H
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-target.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-render-target.h
new file mode 100644 (file)
index 0000000..1ad7a5a
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef DALI_TEST_GRAPHICS_RENDER_TARGET_H
+#define DALI_TEST_GRAPHICS_RENDER_TARGET_H
+
+/*
+ * Copyright (c) 2021 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/graphics-api/graphics-render-target-create-info.h>
+#include <dali/graphics-api/graphics-render-target.h>
+
+namespace Dali
+{
+class TestGraphicsRenderTarget : public Graphics::RenderTarget
+{
+public:
+  TestGraphicsRenderTarget(TestGlAbstraction& gl, Graphics::RenderTargetCreateInfo createInfo)
+  : mGl(gl)
+  {
+    mCreateInfo.surface      = createInfo.surface;
+    mCreateInfo.framebuffer  = createInfo.framebuffer;
+    mCreateInfo.extent       = createInfo.extent;
+    mCreateInfo.preTransform = createInfo.preTransform;
+  }
+  ~TestGraphicsRenderTarget() = default;
+
+  TestGlAbstraction&               mGl;
+  Graphics::RenderTargetCreateInfo mCreateInfo;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_RENDER_TARGET_H
  *
  */
 
-#include "test-gl-sync-abstraction.h"
+#include "test-graphics-sync-impl.h"
 
 namespace Dali
 {
-TestSyncObject::TestSyncObject(TraceCallStack& trace)
+TestSyncObject::TestSyncObject(Dali::TraceCallStack& trace)
+
 : synced(false),
   mTrace(trace)
 {
+  mTrace.PushCall("TestSyncObject cons", ""); // Trace the method
 }
 
 TestSyncObject::~TestSyncObject()
 {
+  mTrace.PushCall("TestSyncObject dstr", ""); // Trace the method
 }
 
 bool TestSyncObject::IsSynced()
@@ -35,7 +38,7 @@ bool TestSyncObject::IsSynced()
   return synced;
 }
 
-TestGlSyncAbstraction::TestGlSyncAbstraction()
+TestGraphicsSyncImplementation::TestGraphicsSyncImplementation()
 {
   Initialize();
 }
@@ -43,7 +46,7 @@ TestGlSyncAbstraction::TestGlSyncAbstraction()
 /**
  * Destructor
  */
-TestGlSyncAbstraction::~TestGlSyncAbstraction()
+TestGraphicsSyncImplementation::~TestGraphicsSyncImplementation()
 {
   for(SyncIter iter = mSyncObjects.begin(), end = mSyncObjects.end(); iter != end; ++iter)
   {
@@ -52,18 +55,14 @@ TestGlSyncAbstraction::~TestGlSyncAbstraction()
 }
 
 /**
- * Initialize the sync objects - clear down the map
+ * Initialize the sync objects
  */
-void TestGlSyncAbstraction::Initialize()
+void TestGraphicsSyncImplementation::Initialize()
 {
   mSyncObjects.clear();
 }
 
-/**
- * Create a sync object
- * @return the sync object
- */
-Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::CreateSyncObject()
 {
   mTrace.PushCall("CreateSyncObject", ""); // Trace the method
 
@@ -76,7 +75,7 @@ Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObj
  * Destroy a sync object
  * @param[in] syncObject The object to destroy
  */
-void TestGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void TestGraphicsSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
 {
   std::stringstream out;
   out << syncObject;
@@ -93,7 +92,7 @@ void TestGlSyncAbstraction::DestroySyncObject(Integration::GlSyncAbstraction::Sy
   }
 }
 
-Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* TestGraphicsSyncImplementation::GetLastSyncObject()
 {
   if(!mSyncObjects.empty())
   {
@@ -107,7 +106,7 @@ Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncOb
  * @param[in]
  * @param[in] sync The sync value to set
  */
-void TestGlSyncAbstraction::SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync)
+void TestGraphicsSyncImplementation::SetObjectSynced(Integration::GraphicsSyncAbstraction::SyncObject* syncObject, bool sync)
 {
   TestSyncObject* testSyncObject = static_cast<TestSyncObject*>(syncObject);
   testSyncObject->synced         = sync;
@@ -116,7 +115,7 @@ void TestGlSyncAbstraction::SetObjectSynced(Integration::GlSyncAbstraction::Sync
 /**
  * Turn trace on
  */
-void TestGlSyncAbstraction::EnableTrace(bool enable)
+void TestGraphicsSyncImplementation::EnableTrace(bool enable)
 {
   mTrace.Enable(enable);
 }
@@ -124,7 +123,7 @@ void TestGlSyncAbstraction::EnableTrace(bool enable)
 /**
  * Reset the trace callstack
  */
-void TestGlSyncAbstraction::ResetTrace()
+void TestGraphicsSyncImplementation::ResetTrace()
 {
   mTrace.Reset();
 }
@@ -132,12 +131,12 @@ void TestGlSyncAbstraction::ResetTrace()
 /**
  * Get the trace object (allows test case to find methods on it)
  */
-TraceCallStack& TestGlSyncAbstraction::GetTrace()
+TraceCallStack& TestGraphicsSyncImplementation::GetTrace()
 {
   return mTrace;
 }
 
-int32_t TestGlSyncAbstraction::GetNumberOfSyncObjects()
+int32_t TestGraphicsSyncImplementation::GetNumberOfSyncObjects()
 {
   return static_cast<int32_t>(mSyncObjects.size());
 }
@@ -1,5 +1,5 @@
-#ifndef TEST_GL_SYNC_ABSTRACTION_H
-#define TEST_GL_SYNC_ABSTRACTION_H
+#ifndef TEST_SYNC_IMPLEMENTATION_H
+#define TEST_SYNC_IMPLEMENTATION_H
 
 /*
  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
 #include <string>
 
 // INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
 #include <dali/integration-api/core.h>
-#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
 
 #include "test-trace-call-stack.h"
 
 namespace Dali
 {
-class DALI_CORE_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject
+class TestGraphicsSyncImplementation;
+
+class TestSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject
 {
 public:
   TestSyncObject(TraceCallStack& trace);
@@ -42,47 +46,45 @@ public:
 };
 
 /**
- * Class to emulate the GL sync functions with tracing
+ * Class to emulate the gpu sync functions with tracing
  */
-class DALI_CORE_API TestGlSyncAbstraction : public Integration::GlSyncAbstraction
+class TestGraphicsSyncImplementation : public Integration::GraphicsSyncAbstraction
 {
 public:
   /**
    * Constructor
    */
-  TestGlSyncAbstraction();
+  TestGraphicsSyncImplementation();
 
   /**
    * Destructor
    */
-  ~TestGlSyncAbstraction() override;
+  virtual ~TestGraphicsSyncImplementation();
 
   /**
-   * Initialize the sync objects - clear down the map
+   * Initialize the sync objects
    */
   void Initialize();
 
   /**
-   * Create a sync object
-   * @return the sync object
+   * Create a sync object that can be polled
    */
-  Integration::GlSyncAbstraction::SyncObject* CreateSyncObject() override;
+  GraphicsSyncAbstraction::SyncObject* CreateSyncObject() override;
 
   /**
    * Destroy a sync object
-   * @param[in] syncObject The object to destroy
    */
-  void DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject) override;
+  void DestroySyncObject(GraphicsSyncAbstraction::SyncObject* syncObject) override;
 
 public: // TEST FUNCTIONS
-  Integration::GlSyncAbstraction::SyncObject* GetLastSyncObject();
+  GraphicsSyncAbstraction::SyncObject* GetLastSyncObject();
 
   /**
    * Test method to trigger the object sync behaviour.
    * @param[in]
    * @param[in] sync The sync value to set
    */
-  void SetObjectSynced(Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync);
+  void SetObjectSynced(GraphicsSyncAbstraction::SyncObject* syncObject, bool sync);
 
   /**
    * Turn trace on
@@ -106,10 +108,10 @@ public: // TEST FUNCTIONS
    */
   int32_t GetNumberOfSyncObjects();
 
-private:
-  TestGlSyncAbstraction(const TestGlSyncAbstraction&);            ///< Undefined
-  TestGlSyncAbstraction& operator=(const TestGlSyncAbstraction&); ///< Undefined
+  TestGraphicsSyncImplementation(const TestGraphicsSyncImplementation&) = delete;
+  TestGraphicsSyncImplementation& operator=(const TestGraphicsSyncImplementation&) = delete;
 
+private:
   typedef std::vector<TestSyncObject*> SyncContainer;
   typedef SyncContainer::iterator      SyncIter;
   SyncContainer                        mSyncObjects;       ///< The sync objects
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
new file mode 100644 (file)
index 0000000..cf9b3c9
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 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 "test-graphics-sync-object.h"
+
+namespace Dali
+{
+TestGraphicsSyncObject::TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo)
+: mSyncImplementation(syncImpl),
+  mSyncObject(nullptr),
+  mCreateInfo(createInfo)
+{
+}
+
+TestGraphicsSyncObject::~TestGraphicsSyncObject()
+{
+  mSyncImplementation.DestroySyncObject(mSyncObject);
+}
+
+void TestGraphicsSyncObject::InitializeResource()
+{
+  mSyncObject = static_cast<TestSyncObject*>(mSyncImplementation.CreateSyncObject());
+}
+
+bool TestGraphicsSyncObject::IsSynced()
+{
+  bool synced = false;
+  if(mSyncObject)
+  {
+    synced = mSyncObject->IsSynced();
+  }
+  return synced;
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.h b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.h
new file mode 100644 (file)
index 0000000..c33de6c
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef DALI_TEST_GRAPHICS_SYNC_OBJECT_H_
+#define DALI_TEST_GRAPHICS_SYNC_OBJECT_H_
+
+/*
+ * Copyright (c) 2021 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/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+#include <test-graphics-sync-impl.h>
+
+namespace Dali
+{
+class TestGraphicsSyncObject : public Graphics::SyncObject
+{
+public:
+  TestGraphicsSyncObject(TestGraphicsSyncImplementation& syncImpl, const Graphics::SyncObjectCreateInfo& createInfo);
+  ~TestGraphicsSyncObject() override;
+  void InitializeResource();
+  bool IsSynced() override;
+
+public:
+  TestGraphicsSyncImplementation& mSyncImplementation;
+  TestSyncObject*                 mSyncObject;
+  Graphics::SyncObjectCreateInfo  mCreateInfo;
+};
+
+} // namespace Dali
+
+#endif //DALI_TEST_GRAPHICS_SYNC_OBJECT_H
index adeeeca..9e1ad3e 100644 (file)
@@ -183,6 +183,7 @@ bool IsCompressedFormat(Graphics::Format pixelFormat)
     case Graphics::Format::R64G64B64A64_SINT:
     case Graphics::Format::R64G64B64A64_SFLOAT:
     case Graphics::Format::B10G11R11_UFLOAT_PACK32:
+    case Graphics::Format::R11G11B10_UFLOAT_PACK32:
     case Graphics::Format::E5B9G9R9_UFLOAT_PACK32:
     case Graphics::Format::D16_UNORM:
     case Graphics::Format::X8_D24_UNORM_PACK32:
@@ -618,6 +619,12 @@ void PixelFormatToGl(Graphics::Format pixelFormat, GLenum& glFormat, GLint& glIn
       glFormat = 0;
       break;
     }
+    case Graphics::Format::R11G11B10_UFLOAT_PACK32:
+    {
+      glFormat      = GL_RGB;
+      pixelDataType = GL_FLOAT;
+      break;
+    }
 
     case Graphics::Format::R4G4_UNORM_PACK8:
     case Graphics::Format::A1R5G5B5_UNORM_PACK16:
@@ -768,6 +775,7 @@ void PixelFormatToGl(Graphics::Format pixelFormat, GLenum& glFormat, GLint& glIn
   {
     case Graphics::Format::R16G16B16A16_SFLOAT:
     case Graphics::Format::R32G32B32A32_SFLOAT:
+    case Graphics::Format::R11G11B10_UFLOAT_PACK32:
     {
       glInternalFormat = GL_R11F_G11F_B10F;
       break;
index 3eb54d3..58f7738 100644 (file)
@@ -49,6 +49,22 @@ public:
   GLuint GetTarget();
 
   /**
+   * Get the texture type
+   */
+  Graphics::TextureType GetType()
+  {
+    return mCreateInfo.textureType;
+  }
+
+  /**
+   * Get the texture format
+   */
+  Graphics::Format GetFormat()
+  {
+    return mCreateInfo.format;
+  }
+
+  /**
    * Bind this texture, ensure Native image is initialized if necessary.
    */
   void Bind(uint32_t textureUnit);
index e7f8678..232c4f7 100644 (file)
  *
  */
 
-#include <stdlib.h>
 #include <dali-test-suite-utils.h>
 #include <dali/dali.h>
 #include <dali/devel-api/adaptor-framework/application-devel.h>
+#include <stdlib.h>
 
 using namespace Dali;
 
@@ -594,7 +594,7 @@ int UtcDaliApplicationAddIdleWithReturnValueN(void)
 
 int UtcDaliApplicationGetDataPathP(void)
 {
-  setenv( "DALI_APPLICATION_DATA_DIR", "MyDataPath", 1);
+  setenv("DALI_APPLICATION_DATA_DIR", "MyDataPath", 1);
   std::string dataPath = DevelApplication::GetDataPath();
   DALI_TEST_EQUALS(dataPath, "MyDataPath", TEST_LOCATION);
   END_TEST;
index db19976..96d3810 100644 (file)
@@ -474,7 +474,7 @@ int UtcDaliWindowAddAuxiliaryHintNegative(void)
   {
     std::string arg1;
     std::string arg2;
-    instance.AddAuxiliaryHint(arg1,arg2);
+    instance.AddAuxiliaryHint(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -584,8 +584,8 @@ int UtcDaliWindowSetAuxiliaryHintValueNegative(void)
   try
   {
     unsigned int arg1(0u);
-    std::string arg2;
-    instance.SetAuxiliaryHintValue(arg1,arg2);
+    std::string  arg2;
+    instance.SetAuxiliaryHintValue(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -804,7 +804,7 @@ int UtcDaliWindowSetClassNegative(void)
   {
     std::string arg1;
     std::string arg2;
-    instance.SetClass(arg1,arg2);
+    instance.SetClass(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -1122,9 +1122,9 @@ int UtcDaliWindowSetPositionSizeNegative(void)
 {
   try
   {
-    Dali::Window arg1;
+    Dali::Window    arg1;
     Dali::Rect<int> arg2;
-    DevelWindow::SetPositionSize(arg1,arg2);
+    DevelWindow::SetPositionSize(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -1198,10 +1198,10 @@ int UtcDaliWindowAddFrameRenderedCallbackNegative(void)
 {
   try
   {
-    Dali::Window arg1;
+    Dali::Window                        arg1;
     std::unique_ptr<Dali::CallbackBase> arg2;
-    int arg3(0);
-    DevelWindow::AddFrameRenderedCallback(arg1,std::move(arg2),arg3);
+    int                                 arg3(0);
+    DevelWindow::AddFrameRenderedCallback(arg1, std::move(arg2), arg3);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -1215,9 +1215,9 @@ int UtcDaliWindowSetAvailableOrientationsNegative(void)
 {
   try
   {
-    Dali::Window arg1;
+    Dali::Window                          arg1;
     Dali::Vector<Dali::WindowOrientation> arg2;
-    DevelWindow::SetAvailableOrientations(arg1,arg2);
+    DevelWindow::SetAvailableOrientations(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -1231,10 +1231,10 @@ int UtcDaliWindowAddFramePresentedCallbackNegative(void)
 {
   try
   {
-    Dali::Window arg1;
+    Dali::Window                        arg1;
     std::unique_ptr<Dali::CallbackBase> arg2;
-    int arg3(0);
-    DevelWindow::AddFramePresentedCallback(arg1,std::move(arg2),arg3);
+    int                                 arg3(0);
+    DevelWindow::AddFramePresentedCallback(arg1, std::move(arg2), arg3);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
@@ -1325,7 +1325,7 @@ int UtcDaliWindowSetParentNegative(void)
   {
     Dali::Window arg1;
     Dali::Window arg2;
-    DevelWindow::SetParent(arg1,arg2);
+    DevelWindow::SetParent(arg1, arg2);
     DALI_TEST_CHECK(false); // Should not get here
   }
   catch(...)
index 5ac7e09..639ee31 100644 (file)
@@ -7,6 +7,7 @@ SET(CAPI_LIB "dali-graphics")
 SET(TC_SOURCES
     utc-Dali-GraphicsSampler.cpp
     utc-Dali-GraphicsGeometry.cpp
+    utc-Dali-GraphicsProgram.cpp
     utc-Dali-GraphicsNativeImage.cpp
 )
 
@@ -17,10 +18,12 @@ LIST(APPEND TC_SOURCES
   ../dali-adaptor/dali-test-suite-utils/test-actor-utils.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-application.cpp
   ../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
-  ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+  ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+  ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+  ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
   ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
diff --git a/automated-tests/src/dali-graphics/utc-Dali-GraphicsProgram.cpp b/automated-tests/src/dali-graphics/utc-Dali-GraphicsProgram.cpp
new file mode 100644 (file)
index 0000000..9677500
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2021 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-test-suite-utils.h>
+#include <dali/dali.h>
+
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <test-actor-utils.h>
+#include <test-graphics-application.h>
+#include <test-graphics-sampler.h>
+
+using namespace Dali;
+
+void utc_dali_program_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+void utc_dali_program_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+const std::string VERT_SHADER_SOURCE = "myVertShaderSource";
+const std::string FRAG_SHADER_SOURCE =
+  "\n"
+  "uniform sampler2D sAlbedo;\n"
+  "uniform sampler2D sMetalRoughness;\n"
+  "uniform sampler2D sNormals;\n"
+  "uniform sampler2D sAmbientOcclusion;\n"
+  "uniform mediump vec3 lightDirection;\n"
+  "in mediump vec2 vTexCoord;\n"
+  "main()\n"
+  "{\n"
+  "  gl_fragColor = texture2d(sAlbedo, vTexCoord) + lightDirection*texture2d(sNormals, vTexCoord);\n"
+  "}\n";
+} //anonymous namespace
+
+int UtcDaliGraphicsProgram(void)
+{
+  TestGraphicsApplication app;
+  tet_infoline("UtcDaliProgram - check that right sampler uniforms are bound for textures");
+
+  Texture normals        = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+  Texture metalroughness = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+  Texture ao             = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+  Texture albedo         = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
+
+  TextureSet textureSet = TextureSet::New();
+  textureSet.SetTexture(0, albedo);
+  textureSet.SetTexture(1, metalroughness);
+  textureSet.SetTexture(2, normals);
+  textureSet.SetTexture(3, ao);
+
+  Actor actor = CreateRenderableActor2(textureSet, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
+  app.GetScene().Add(actor);
+
+  auto& gl             = app.GetGlAbstraction();
+  auto& glUniformTrace = gl.GetSetUniformTrace();
+  glUniformTrace.Enable(true);
+  glUniformTrace.EnableLogging(true);
+
+  std::vector<ActiveUniform> activeUniforms{
+    {"sAlbedo", GL_SAMPLER_2D, 1},
+    {"sAmbientOcclusion", GL_SAMPLER_2D, 1},
+    {"sNormals", GL_SAMPLER_2D, 1},
+    {"sMetalRoughness", GL_SAMPLER_2D, 1}};
+  gl.SetActiveUniforms(activeUniforms);
+
+  app.SendNotification();
+  app.Render(16); // The above actor will get rendered and drawn once.
+
+  // Check what uniform values were set:
+  int value;
+  DALI_TEST_CHECK(gl.GetUniformValue("sAlbedo", value)); // First in frag shader
+  DALI_TEST_EQUALS(value, 0, TEST_LOCATION);
+  DALI_TEST_CHECK(gl.GetUniformValue("sAmbientOcclusion", value)); // 4th
+  DALI_TEST_EQUALS(value, 3, TEST_LOCATION);
+  DALI_TEST_CHECK(gl.GetUniformValue("sNormals", value)); // 3rd
+  DALI_TEST_EQUALS(value, 2, TEST_LOCATION);
+  DALI_TEST_CHECK(gl.GetUniformValue("sMetalRoughness", value)); // 2nd
+  DALI_TEST_EQUALS(value, 1, TEST_LOCATION);
+
+  END_TEST;
+}
index 217fbd6..e452bbe 100644 (file)
@@ -33,21 +33,6 @@ void utc_dali_sampler_cleanup(void)
   test_return_value = TET_PASS;
 }
 
-namespace
-{
-Texture CreateTexture(TextureType::Type type, Pixel::Format format, int width, int height)
-{
-  Texture texture = Texture::New(type, format, width, height);
-
-  int       bufferSize = width * height * 2;
-  uint8_t*  buffer     = reinterpret_cast<uint8_t*>(malloc(bufferSize));
-  PixelData pixelData  = PixelData::New(buffer, bufferSize, width, height, format, PixelData::FREE);
-  texture.Upload(pixelData, 0u, 0u, 0u, 0u, width, height);
-  return texture;
-}
-
-} // namespace
-
 int UtcDaliGraphicsSamplerDefault(void)
 {
   TestGraphicsApplication app;
@@ -132,9 +117,7 @@ int UtcDaliGraphicsSamplerAllSet(void)
   DALI_TEST_CHECK(params != nullptr);
   auto iter = params->find("param");
 
-  //@todo Change back when mip-map generation is implemented
-  //DALI_TEST_CHECK(*iter == GL_LINEAR_MIPMAP_NEAREST);
-  DALI_TEST_CHECK(*iter == GL_LINEAR);
+  DALI_TEST_CHECK(*iter == GL_LINEAR_MIPMAP_NEAREST);
 
   TraceCallStack::NamedParams magFilter;
   magFilter["pname"] << std::hex << GL_TEXTURE_MAG_FILTER;
@@ -167,9 +150,7 @@ int UtcDaliGraphicsSamplerAllSet(void)
   params = glParamTrace.FindLastMatch("TexParameteri", minFilter);
   DALI_TEST_CHECK(params != nullptr);
   iter = params->find("param");
-  //@todo Change back when mip-map generation is implemented
-  //DALI_TEST_CHECK(*iter == GL_NEAREST_MIPMAP_LINEAR);
-  DALI_TEST_CHECK(*iter == GL_NEAREST);
+  DALI_TEST_CHECK(*iter == GL_NEAREST_MIPMAP_LINEAR);
 
   END_TEST;
 }
index 531ce4c..a7bb879 100644 (file)
@@ -16,10 +16,12 @@ LIST(APPEND TC_SOURCES
     ../dali-adaptor/dali-test-suite-utils/test-harness.cpp
     ../dali-adaptor/dali-test-suite-utils/test-application.cpp
     ../dali-adaptor/dali-test-suite-utils/test-gl-abstraction.cpp
-    ../dali-adaptor/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-impl.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-sync-object.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-buffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-command-buffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-controller.cpp
+    ../dali-adaptor/dali-test-suite-utils/test-graphics-framebuffer.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-sampler.cpp
     ../dali-adaptor/dali-test-suite-utils/test-graphics-pipeline.cpp
index 826ba37..dfbaa4d 100644 (file)
@@ -596,7 +596,7 @@ class NonControlAccessible : public virtual Accessible, public virtual Collectio
 {
 protected:
   Dali::WeakHandle<Dali::Actor> self;
-  bool        root = false;
+  bool                          root = false;
 
   Dali::Actor Self()
   {
@@ -618,12 +618,12 @@ public:
 
   Dali::Rect<> GetExtents(Dali::Accessibility::CoordType ctype) override
   {
-    Dali::Actor actor = Self();
-    Vector2 screenPosition          = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
-    Vector3 size                    = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
-    bool    positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
-    Vector3 anchorPointOffSet       = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
-    Vector2 position                = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
+    Dali::Actor actor                   = Self();
+    Vector2     screenPosition          = actor.GetProperty(Actor::Property::SCREEN_POSITION).Get<Vector2>();
+    Vector3     size                    = actor.GetCurrentProperty<Vector3>(Actor::Property::SIZE) * actor.GetCurrentProperty<Vector3>(Actor::Property::WORLD_SCALE);
+    bool        positionUsesAnchorPoint = actor.GetProperty(Actor::Property::POSITION_USES_ANCHOR_POINT).Get<bool>();
+    Vector3     anchorPointOffSet       = size * (positionUsesAnchorPoint ? actor.GetCurrentProperty<Vector3>(Actor::Property::ANCHOR_POINT) : AnchorPoint::TOP_LEFT);
+    Vector2     position                = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
 
     return {position.x, position.y, size.x, size.y};
   }
index ea95524..7e52419 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DALI_DEVEL_ATSPI_ACCESSIBILITY_H
 #define DALI_DEVEL_ATSPI_ACCESSIBILITY_H
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
old mode 100755 (executable)
new mode 100644 (file)
index a85d2f8..bb82dce
@@ -83,9 +83,9 @@ public:
   enum class ApplicationType
   {
     WEB_BROWSER = 0,
-    HBB_TV = 1,
+    HBB_TV      = 1,
     WEB_RUNTIME = 2,
-    OTHER = 3
+    OTHER       = 3
   };
 
   /**
old mode 100755 (executable)
new mode 100644 (file)
index 1df5a41..481c120
@@ -19,8 +19,8 @@
  */
 
 // EXTERNAL INCLUDES
-#include <string>
 #include <functional>
+#include <string>
 
 namespace Dali
 {
index 7531f55..b19fa22 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -29,9 +29,9 @@ const PointSize26Dot6 FontClient::DEFAULT_POINT_SIZE   = 768u;
 const float           FontClient::DEFAULT_ITALIC_ANGLE = 12.f * Dali::Math::PI_OVER_180; // FreeType documentation states the software italic is done by doing a horizontal shear of 12 degrees (file ftsynth.h).
 
 //Default atlas block
-const bool     FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED  = true;
-const uint32_t FontClient::DEFAULT_TEXT_ATLAS_WIDTH          = 512u;
-const uint32_t FontClient::DEFAULT_TEXT_ATLAS_HEIGHT         = 512u;
+const bool     FontClient::DEFAULT_ATLAS_LIMITATION_ENABLED = true;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_WIDTH         = 512u;
+const uint32_t FontClient::DEFAULT_TEXT_ATLAS_HEIGHT        = 512u;
 const Size     FontClient::DEFAULT_TEXT_ATLAS_SIZE(DEFAULT_TEXT_ATLAS_WIDTH, DEFAULT_TEXT_ATLAS_HEIGHT);
 
 //Maximum atlas block
@@ -44,9 +44,9 @@ const Size     FontClient::MAX_TEXT_ATLAS_SIZE(MAX_TEXT_ATLAS_WIDTH, MAX_TEXT_AT
 const uint16_t FontClient::PADDING_TEXT_ATLAS_BLOCK = 5u; // 2 * DOUBLE_PIXEL_PADDING + 1u
 
 //Maximum block size to fit into atlas block
-const Size  FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT_ATLAS_BLOCK, MAX_TEXT_ATLAS_HEIGHT - PADDING_TEXT_ATLAS_BLOCK );
+const Size FontClient::MAX_SIZE_FIT_IN_ATLAS(MAX_TEXT_ATLAS_WIDTH - PADDING_TEXT_ATLAS_BLOCK, MAX_TEXT_ATLAS_HEIGHT - PADDING_TEXT_ATLAS_BLOCK);
 
-const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u;//Found this value from toolkit
+const uint32_t FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE = 64u; //Found this value from toolkit
 
 FontClient::GlyphBufferData::GlyphBufferData()
 : buffer{nullptr},
@@ -262,22 +262,22 @@ void FontClient::EnableAtlasLimitation(bool enabled)
 
 bool FontClient::IsAtlasLimitationEnabled() const
 {
-  return GetImplementation(*this).IsAtlasLimitationEnabled( );
+  return GetImplementation(*this).IsAtlasLimitationEnabled();
 }
 
 Size FontClient::GetMaximumTextAtlasSize() const
 {
-  return GetImplementation(*this).GetMaximumTextAtlasSize( );
+  return GetImplementation(*this).GetMaximumTextAtlasSize();
 }
 
 Size FontClient::GetDefaultTextAtlasSize() const
 {
-  return GetImplementation(*this).GetDefaultTextAtlasSize( );
+  return GetImplementation(*this).GetDefaultTextAtlasSize();
 }
 
 Size FontClient::GetCurrentMaximumBlockSizeFitInAtlas() const
 {
-  return GetImplementation(*this).GetCurrentMaximumBlockSizeFitInAtlas( );
+  return GetImplementation(*this).GetCurrentMaximumBlockSizeFitInAtlas();
 }
 
 bool FontClient::SetCurrentMaximumBlockSizeFitInAtlas(const Size& currentMaximumBlockSizeFitInAtlas)
index e77b53f..ce00dd4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_PLATFORM_TEXT_ABSTRACTION_FONT_CLIENT_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -64,21 +64,19 @@ public:
   static const PointSize26Dot6 DEFAULT_POINT_SIZE;   ///< The default point size.
   static const float           DEFAULT_ITALIC_ANGLE; ///< The default software italic angle in radians.
 
-  static const bool            DEFAULT_ATLAS_LIMITATION_ENABLED;  ///< The default behavior of whether atlas limitation is enabled in dali.
-  static const uint32_t        DEFAULT_TEXT_ATLAS_WIDTH;          ///< The default width of text-atlas-block.
-  static const uint32_t        DEFAULT_TEXT_ATLAS_HEIGHT;         ///< The default height of text-atlas-block.
-  static const Size            DEFAULT_TEXT_ATLAS_SIZE;           ///< The default size(width, height) of text-atlas-block.
+  static const bool     DEFAULT_ATLAS_LIMITATION_ENABLED; ///< The default behavior of whether atlas limitation is enabled in dali.
+  static const uint32_t DEFAULT_TEXT_ATLAS_WIDTH;         ///< The default width of text-atlas-block.
+  static const uint32_t DEFAULT_TEXT_ATLAS_HEIGHT;        ///< The default height of text-atlas-block.
+  static const Size     DEFAULT_TEXT_ATLAS_SIZE;          ///< The default size(width, height) of text-atlas-block.
 
-  static const uint32_t        MAX_TEXT_ATLAS_WIDTH;             ///< The maximum width of text-atlas-block.
-  static const uint32_t        MAX_TEXT_ATLAS_HEIGHT;            ///< The maximum height of text-atlas-block.
-  static const Size            MAX_TEXT_ATLAS_SIZE;              ///< The maximum height of text-atlas-block.
-
-  static const uint16_t        PADDING_TEXT_ATLAS_BLOCK ;        ///< Padding per edge. How much the block size (width, height) less than the text-atlas-block size (width, height).
-  static const Size            MAX_SIZE_FIT_IN_ATLAS;            ///< The maximum block's size fit into text-atlas-block.
-
-  static const uint32_t        NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
+  static const uint32_t MAX_TEXT_ATLAS_WIDTH;  ///< The maximum width of text-atlas-block.
+  static const uint32_t MAX_TEXT_ATLAS_HEIGHT; ///< The maximum height of text-atlas-block.
+  static const Size     MAX_TEXT_ATLAS_SIZE;   ///< The maximum height of text-atlas-block.
 
+  static const uint16_t PADDING_TEXT_ATLAS_BLOCK; ///< Padding per edge. How much the block size (width, height) less than the text-atlas-block size (width, height).
+  static const Size     MAX_SIZE_FIT_IN_ATLAS;    ///< The maximum block's size fit into text-atlas-block.
 
+  static const uint32_t NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE; ///< Factor multiply point-size in toolkit.
 
   /**
    * @brief Struct used to retrieve the glyph's bitmap.
@@ -500,7 +498,7 @@ public:
    */
   bool IsAtlasLimitationEnabled() const;
 
-   /**
+  /**
    * @brief retrieve the maximum allowed width and height for text-atlas-block.
    *
    * @note Used default configuration.
@@ -508,7 +506,7 @@ public:
    */
   Size GetMaximumTextAtlasSize() const;
 
-   /**
+  /**
    * @brief retrieve the default width and height for text-atlas-block.
    *
    * @note Used default configuration.
@@ -524,7 +522,7 @@ public:
    */
   Size GetCurrentMaximumBlockSizeFitInAtlas() const;
 
-   /**
+  /**
    * @brief set the achieved size (width and height) for text-atlas-block.
    * If @p currentMaximumBlockSizeFitInAtlas larger than the current maximum text atlas then store, otherwise ignore.
    *
old mode 100755 (executable)
new mode 100644 (file)
index 9361f17..83dde1f
@@ -2,7 +2,7 @@
 #define DALI_TEXT_ABSTRACTION_H
 
 /*
- * Copyright (c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -23,9 +23,9 @@
 #include <dali/devel-api/text-abstraction/font-client.h>
 #include <dali/devel-api/text-abstraction/font-metrics.h>
 #include <dali/devel-api/text-abstraction/glyph-info.h>
+#include <dali/devel-api/text-abstraction/hyphenation.h>
 #include <dali/devel-api/text-abstraction/script.h>
 #include <dali/devel-api/text-abstraction/segmentation.h>
 #include <dali/devel-api/text-abstraction/shaping.h>
-#include <dali/devel-api/text-abstraction/hyphenation.h>
 
 #endif // DALI_TEXT_ABSTRACTION_H
index 45250b1..a3303a4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_RENDER_SURFACE_INTERFACE_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -81,6 +81,7 @@ public:
     mDisplayConnection(nullptr),
     mScene(),
     mFullSwapNextFrame(true),
+    mIsResizing(false),
     mDepthBufferRequired(Integration::DepthBufferAvailable::FALSE),
     mStencilBufferRequired(Integration::StencilBufferAvailable::FALSE)
   {
@@ -146,7 +147,7 @@ public:
   virtual void StartRender() = 0;
 
   /**
-   * @brief Invoked by render thread before Core::Render
+   * @brief Invoked by render thread before Core::RenderScene
    * If the operation fails, then Core::Render should not be called until there is
    * a surface to render onto.
    * @param[in] resizingSurface True if the surface is being resized
@@ -156,12 +157,9 @@ public:
   virtual bool PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect) = 0;
 
   /**
-   * @brief Invoked by render thread after Core::Render
-   * @param[in] renderToFbo True if render to FBO.
-   * @param[in] replacingSurface True if the surface is being replaced.
-   * @param[in] resizingSurface True if the surface is being resized.
+   * @brief Invoked by render thread after Core::RenderScene
    */
-  virtual void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) = 0;
+  virtual void PostRender() = 0;
 
   /**
    * @brief Invoked by render thread when the thread should be stop
@@ -235,6 +233,14 @@ public:
     mFullSwapNextFrame = true;
   }
 
+  /**
+   * @brief Sets whether this surface is being resized.
+   */
+  void SetIsResizing(bool isResizing)
+  {
+    mIsResizing = isResizing;
+  }
+
 private:
   /**
    * @brief Undefined copy constructor. RenderSurface cannot be copied
@@ -252,6 +258,7 @@ protected:
   Dali::DisplayConnection*                          mDisplayConnection;
   WeakHandle<Dali::Integration::Scene>              mScene;
   bool                                              mFullSwapNextFrame; ///< Whether the full surface swap is required
+  bool                                              mIsResizing;        ///< Whether the surface is being resized
 
 private:
   Integration::DepthBufferAvailable   mDepthBufferRequired;   ///< Whether the depth buffer is required
index ec4be19..fe93f69 100644 (file)
@@ -160,6 +160,9 @@ void SceneHolder::SetSurface(Dali::RenderSurfaceInterface* surface)
   mSurface->SetAdaptor(*mAdaptor);
   mSurface->SetScene(mScene);
 
+  // Recreate the render target
+  CreateRenderTarget();
+
   OnSurfaceSet(surface);
 }
 
@@ -169,6 +172,9 @@ void SceneHolder::SurfaceResized()
   mScene.SurfaceResized(static_cast<float>(surfacePositionSize.width), static_cast<float>(surfacePositionSize.height));
 
   mSurface->SetFullSwapNextFrame();
+
+  // Recreate the render target
+  CreateRenderTarget();
 }
 
 Dali::RenderSurfaceInterface* SceneHolder::GetSurface() const
@@ -219,9 +225,24 @@ void SceneHolder::SetAdaptor(Dali::Adaptor& adaptor)
   mSurface->SetAdaptor(*mAdaptor);
   mSurface->SetScene(mScene);
 
+  // Create the render target
+  CreateRenderTarget();
+
   OnAdaptorSet(adaptor);
 }
 
+void SceneHolder::CreateRenderTarget()
+{
+  Graphics::RenderTargetCreateInfo rtInfo{};
+  rtInfo
+    .SetSurface(mSurface.get())
+    .SetExtent({static_cast<uint32_t>(mSurface->GetPositionSize().width), static_cast<uint32_t>(mSurface->GetPositionSize().height)})
+    .SetPreTransform(0 | Graphics::RenderTargetTransformFlagBits::TRANSFORM_IDENTITY_BIT);
+  mRenderTarget = mAdaptor->GetGraphicsInterface().GetController().CreateRenderTarget(rtInfo, std::move(mRenderTarget));
+
+  mScene.SetSurfaceRenderTarget(mRenderTarget.get());
+}
+
 void SceneHolder::Pause()
 {
   Reset();
index 7eb7e56..ce33fb4 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTEGRATION_INTERNAL_SCENEHOLDER_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -19,6 +19,7 @@
  */
 
 // EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-controller.h>
 #include <dali/integration-api/events/key-event-integ.h>
 #include <dali/integration-api/events/point.h>
 #include <dali/integration-api/events/touch-event-combiner.h>
@@ -216,6 +217,11 @@ public:
   void AddFramePresentedCallback(std::unique_ptr<CallbackBase> callback, int32_t frameId);
 
   /**
+   * @brief Creates the render target for the surface when the surface is created/resized/replaced.
+   */
+  void CreateRenderTarget();
+
+  /**
    * @copydoc Dali::Integration::SceneHolder::Get()
    */
   static Dali::Integration::SceneHolder Get(Dali::Actor actor);
@@ -326,6 +332,9 @@ private:
   class SceneHolderLifeCycleObserver;
   std::unique_ptr<SceneHolderLifeCycleObserver> mLifeCycleObserver; ///< The adaptor life cycle observer
 
+private:
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};
+
 protected:
   uint32_t                 mId;    ///< A unique ID to identify the SceneHolder starting from 0
   Dali::Integration::Scene mScene; ///< The Scene
index 4f5ebb2..eed9437 100644 (file)
@@ -343,7 +343,7 @@ BridgeAccessible::ReadingMaterialType BridgeAccessible::GetReadingMaterial()
 
 void BridgeAccessible::SuppressScreenReader(bool suppress)
 {
-   suppressScreenReader = suppress;
+  suppressScreenReader = suppress;
 }
 
 DBus::ValueOrError<bool> BridgeAccessible::DoGesture(Dali::Accessibility::Gesture type, int32_t xBeg, int32_t yBeg, int32_t xEnd, int32_t yEnd, Dali::Accessibility::GestureState state, uint32_t eventTime)
index dcca27b..3c1ca0b 100644 (file)
@@ -91,7 +91,7 @@ bool BridgeBase::tickFilteredEvents()
 void BridgeBase::RegisteredEventsUpdate()
 {
   using ReturnType = std::vector<std::tuple<std::string, std::string>>;
-  registry.method<DBus::ValueOrError<ReturnType>()>( "GetRegisteredEvents" ).asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
+  registry.method<DBus::ValueOrError<ReturnType>()>("GetRegisteredEvents").asyncCall([this](DBus::ValueOrError<ReturnType> msg) {
     if(!msg)
     {
       LOG() << "Get registered events failed";
@@ -103,7 +103,7 @@ void BridgeBase::RegisteredEventsUpdate()
     ReturnType values = std::get<ReturnType>(msg.getValues());
     for(long unsigned int i = 0; i < values.size(); i++)
     {
-      if (!std::get<1>(values[i]).compare("Object:BoundsChanged"))
+      if(!std::get<1>(values[i]).compare("Object:BoundsChanged"))
       {
         allowObjectBoundsChangedEvent = true;
       }
@@ -295,7 +295,7 @@ int BridgeBase::IdGet()
   return this->id;
 }
 
-auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType> >
+auto BridgeBase::GetItems() -> DBus::ValueOrError<std::vector<CacheElementType>>
 {
   auto root = &application;
 
index 7361181..ea6c746 100644 (file)
@@ -143,17 +143,18 @@ public:
     DBus::DBusInterfaceDescription& desc, const std::string& funcName, DBus::ValueOrError<RET...> (SELF::*funcPtr)(ARGS...))
   {
     if(auto self = dynamic_cast<SELF*>(this))
-      desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(funcName,
-                                                          [=](ARGS... args) -> DBus::ValueOrError<RET...> {
-                                                            try
-                                                            {
-                                                              return (self->*funcPtr)(std::move(args)...);
-                                                            }
-                                                            catch(std::domain_error& e)
-                                                            {
-                                                              return DBus::Error{e.what()};
-                                                            }
-                                                          });
+      desc.addMethod<DBus::ValueOrError<RET...>(ARGS...)>(
+        funcName,
+        [=](ARGS... args) -> DBus::ValueOrError<RET...> {
+          try
+          {
+            return (self->*funcPtr)(std::move(args)...);
+          }
+          catch(std::domain_error& e)
+          {
+            return DBus::Error{e.what()};
+          }
+        });
   }
 
   template<typename T, typename SELF>
index 216b89b..85e6dc3 100644 (file)
 // CLASS HEADER
 
 // EXTERNAL INCLUDES
-#include <dali/public-api/actors/layer.h>
 #include <dali/devel-api/common/stage.h>
 #include <dali/integration-api/debug.h>
+#include <dali/public-api/actors/layer.h>
 #include <iostream>
 #include <unordered_map>
 
 // INTERNAL INCLUDES
+#include <dali/devel-api/adaptor-framework/environment-variable.h>
+#include <dali/devel-api/adaptor-framework/window-devel.h>
 #include <dali/internal/accessibility/bridge/bridge-accessible.h>
 #include <dali/internal/accessibility/bridge/bridge-action.h>
 #include <dali/internal/accessibility/bridge/bridge-collection.h>
@@ -36,8 +38,6 @@
 #include <dali/internal/accessibility/bridge/dummy-atspi.h>
 #include <dali/internal/adaptor/common/adaptor-impl.h>
 #include <dali/internal/system/common/environment-variables.h>
-#include <dali/devel-api/adaptor-framework/environment-variable.h>
-#include <dali/devel-api/adaptor-framework/window-devel.h>
 
 using namespace Dali::Accessibility;
 
@@ -348,15 +348,15 @@ static Bridge* CreateBridge()
   try
   {
     /* check environment variable first */
-    const char *envAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI);
-    if (envAtspiDisabled && std::atoi(envAtspiDisabled) != 0)
+    const charenvAtspiDisabled = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_DISABLE_ATSPI);
+    if(envAtspiDisabled && std::atoi(envAtspiDisabled) != 0)
     {
       return Dali::Accessibility::DummyBridge::GetInstance();
     }
 
     return new BridgeImpl;
   }
-  catch (const std::exception&)
+  catch(const std::exception&)
   {
     DALI_LOG_ERROR("Failed to initialize AT-SPI bridge");
     return Dali::Accessibility::DummyBridge::GetInstance();
@@ -367,17 +367,17 @@ Bridge* Bridge::GetCurrentBridge()
 {
   static Bridge* bridge;
 
-  if (bridge)
+  if(bridge)
   {
     return bridge;
   }
-  else if (autoInitState == AutoInitState::ENABLED)
+  else if(autoInitState == AutoInitState::ENABLED)
   {
     bridge = CreateBridge();
 
     /* check environment variable for suppressing screen-reader */
-    const char *envSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
-    if (envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
+    const charenvSuppressScreenReader = Dali::EnvironmentVariable::GetEnvironmentVariable(DALI_ENV_SUPPRESS_SCREEN_READER);
+    if(envSuppressScreenReader && std::atoi(envSuppressScreenReader) != 0)
     {
       bridge->SuppressScreenReader(true);
     }
@@ -390,7 +390,7 @@ Bridge* Bridge::GetCurrentBridge()
 
 void Bridge::DisableAutoInit()
 {
-  if (bridgeInitialized)
+  if(bridgeInitialized)
   {
     DALI_LOG_ERROR("Bridge::DisableAutoInit() called after bridge auto-initialization");
   }
@@ -402,13 +402,13 @@ void Bridge::EnableAutoInit()
 {
   autoInitState = AutoInitState::ENABLED;
 
-  if (bridgeInitialized)
+  if(bridgeInitialized)
   {
     return;
   }
 
-  auto rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
-  auto window = Dali::DevelWindow::Get(rootLayer);
+  auto rootLayer       = Dali::Stage::GetCurrent().GetRootLayer();
+  auto window          = Dali::DevelWindow::Get(rootLayer);
   auto applicationName = Dali::Internal::Adaptor::Adaptor::GetApplicationPackageName();
 
   auto* bridge = Bridge::GetCurrentBridge();
index e760c65..bf93553 100644 (file)
 
 namespace Dali::Accessibility
 {
-
 struct DummyBridge : Dali::Accessibility::Bridge
 {
-  static DummyBridge *GetInstance()
+  static DummyBridgeGetInstance()
   {
     static DummyBridge instance;
 
index d15756d..7d2c25c 100644 (file)
@@ -164,7 +164,7 @@ void Application::ChangePreInitializedWindowSize()
   else if(screenWidth != mWindowPositionSize.width || screenHeight != mWindowPositionSize.height)
   {
     //Some apps can receive screen size differently after launching by specifying size in manifest.
-    mWindowPositionSize.width = screenWidth;
+    mWindowPositionSize.width  = screenWidth;
     mWindowPositionSize.height = screenHeight;
     mMainWindow.SetSize(Dali::Window::WindowSize(mWindowPositionSize.width, mWindowPositionSize.height));
   }
index 2f970cb..a8a1401 100644 (file)
@@ -574,8 +574,7 @@ void CombinedUpdateRenderController::UpdateRenderThread()
       // Then create a new pixmap/window and new surface
       // If the new surface has a different display connection, then the context will be lost
       mAdaptorInterfaces.GetDisplayConnectionInterface().Initialize();
-      newSurface->InitializeGraphics();
-      newSurface->MakeContextCurrent();
+      graphics.ActivateSurfaceContext(newSurface);
       // TODO: ReplaceGraphicsSurface doesn't work, InitializeGraphics()
       // already creates new surface window, the surface and the context.
       // We probably don't need ReplaceGraphicsSurface at all.
@@ -689,6 +688,7 @@ void CombinedUpdateRenderController::UpdateRenderThread()
 
           // Get Surface Resized flag
           sceneSurfaceResized = scene.IsSurfaceRectChanged();
+          windowSurface->SetIsResizing(sceneSurfaceResized);
 
           windowSurface->InitializeGraphics();
 
@@ -706,18 +706,10 @@ void CombinedUpdateRenderController::UpdateRenderThread()
           // Switch to the context of the surface, merge damaged areas for previous frames
           windowSurface->PreRender(sceneSurfaceResized, mDamagedRects, clippingRect); // Switch GL context
 
-          if(clippingRect.IsEmpty())
-          {
-            mDamagedRects.clear();
-          }
-
           // Render the surface
           mCore.RenderScene(windowRenderStatus, scene, false, clippingRect);
 
-          if(windowRenderStatus.NeedsPostRender())
-          {
-            windowSurface->PostRender(false, false, sceneSurfaceResized, mDamagedRects); // Swap Buffer with damage
-          }
+          // Buffer swapping now happens when the surface render target is presented.
 
           // If surface is resized, the surface resized count is decreased.
           if(DALI_UNLIKELY(sceneSurfaceResized))
@@ -728,6 +720,11 @@ void CombinedUpdateRenderController::UpdateRenderThread()
       }
     }
 
+    if(!mUploadWithoutRendering)
+    {
+      graphics.ActivateResourceContext();
+    }
+
     mCore.PostRender(mUploadWithoutRendering);
 
     //////////////////////////////
index e61a2ac..b26738c 100644 (file)
@@ -86,6 +86,13 @@ public:
   virtual void ActivateResourceContext() = 0;
 
   /**
+   * Activate the surface context
+   *
+   * @param[in] surface The surface whose context to be switched to.
+   */
+  virtual void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) = 0;
+
+  /**
    * Inform graphics interface that this is the first frame after a resume.
    */
   virtual void SetFirstFrameAfterResume() = 0;
diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp b/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.cpp
new file mode 100644 (file)
index 0000000..ff11704
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2021 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/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
+#include <cstdio>
+#include <queue>
+
+namespace Dali::Graphics
+{
+std::string DumpCompareOp(Graphics::CompareOp compareOp)
+{
+  switch(compareOp)
+  {
+    case Graphics::CompareOp::NEVER:
+      return "Graphics::CompareOp::NEVER";
+      break;
+    case Graphics::CompareOp::LESS:
+      return "Graphics::CompareOp::LESS";
+      break;
+    case Graphics::CompareOp::EQUAL:
+      return "Graphics::CompareOp::EQUAL";
+      break;
+    case Graphics::CompareOp::LESS_OR_EQUAL:
+      return "Graphics::CompareOp::LESS_OR_EQUAL";
+      break;
+    case Graphics::CompareOp::GREATER:
+      return "Graphics::CompareOp::GREATER";
+      break;
+    case Graphics::CompareOp::NOT_EQUAL:
+      return "Graphics::CompareOp::NOT_EQUAL";
+      break;
+    case Graphics::CompareOp::GREATER_OR_EQUAL:
+      return "Graphics::CompareOp::GREATER_OR_EQUAL";
+      break;
+    case Graphics::CompareOp::ALWAYS:
+      return "Graphics::CompareOp::ALWAYS";
+      break;
+  }
+  return "UNKNOWN";
+}
+
+std::string DumpStencilOp(Graphics::StencilOp stencilOp)
+{
+  switch(stencilOp)
+  {
+    case Graphics::StencilOp::KEEP:
+      return "Graphics::StencilOp::KEEP";
+      break;
+    case Graphics::StencilOp::ZERO:
+      return "Graphics::StencilOp::ZERO";
+      break;
+    case Graphics::StencilOp::REPLACE:
+      return "Graphics::StencilOp::REPLACE";
+      break;
+    case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+      return "Graphics::StencilOp::INCREMENT_AND_CLAMP";
+      break;
+    case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+      return "Graphics::StencilOp::DECREMENT_AND_CLAMP";
+      break;
+    case Graphics::StencilOp::INVERT:
+      return "Graphics::StencilOp::INVERT";
+      break;
+    case Graphics::StencilOp::INCREMENT_AND_WRAP:
+      return "Graphics::StencilOp::INCREMENT_AND_WRAP";
+      break;
+    case Graphics::StencilOp::DECREMENT_AND_WRAP:
+      return "Graphics::StencilOp::DECREMENT_AND_WRAP";
+      break;
+  }
+  return "UNKNOWN";
+}
+
+void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
+{
+  bool first{true};
+  for(auto& cmd : commandBuffer->GetCommands())
+  {
+    if(!first)
+    {
+      fprintf(output, ",");
+    }
+    first = false;
+    // process command
+    switch(cmd.type)
+    {
+      case GLES::CommandType::FLUSH:
+      {
+        fprintf(output, "{\"Cmd\":\"FLUSH\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_TEXTURES:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_TEXTURES\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_VERTEX_BUFFERS:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_VERTEX_BUFFERS\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_UNIFORM_BUFFER:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_UNIFORM_BUFFERS\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_INDEX_BUFFER:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_INDEX_BUFFERS\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_SAMPLERS:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_SAMPLERS\"}\n");
+        break;
+      }
+      case GLES::CommandType::BIND_PIPELINE:
+      {
+        fprintf(output, "{\"Cmd\":\"BIND_PIPELINE\"}\n");
+        break;
+      }
+      case GLES::CommandType::DRAW:
+      {
+        fprintf(output, "{\"Cmd\":\"DRAW\"}\n");
+        break;
+      }
+      case GLES::CommandType::DRAW_INDEXED:
+      {
+        fprintf(output, "{\"Cmd\":\"DRAW_INDEXED\"}\n");
+        break;
+      }
+      case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+      {
+        fprintf(output, "{\"Cmd\":\"DRAW_INDEXED_INDIRECT\"}\n");
+        break;
+      }
+      case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+      {
+        fprintf(output, "{\"Cmd\":\"SET_SCISSOR\",\n\"region\":[%d,%d,%d,%d]\n}\n", cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
+        break;
+      }
+      case GLES::CommandType::SET_SCISSOR_TEST:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_SCISSOR_TEST\",\n\"enable\":%s\n}\n", (cmd.scissorTest.enable ? "\"true\"" : "\"false\""));
+        break;
+      }
+      case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+      {
+        fprintf(output, "{\"Cmd\":\"SET_VIEWPORT\",\n\"region\":[%f,%f,%f,%f]\n}\n", cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
+        break;
+      }
+      case GLES::CommandType::SET_COLOR_MASK:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_COLOR_MASK\",\n\"enable\":%s\n}\n", (cmd.colorMask.enabled ? "\"true\"" : "\"false\""));
+        break;
+      }
+      case GLES::CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        fprintf(output, "{\"Cmd\":\"CLEAR_STENCIL_BUFFER\"}\n");
+        break;
+      }
+      case GLES::CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        fprintf(output, "{\"Cmd\":\"CLEAR_DEPTH_BUFFER\"}\n");
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_STENCIL_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.stencilTest.enabled ? "\"true\"" : "\"false\""));
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_FUNC:
+      {
+        fprintf(output,
+                "{\"Cmd\":\"STENCIL_FUNC\",\n"
+                "\"compareOp\":\"%s\",\n"
+                "\"reference\":\"0x%x\",\n"
+                "\"compareMask\":\"0x%x\"\n}",
+                DumpCompareOp(cmd.stencilFunc.compareOp).c_str(),
+                cmd.stencilFunc.reference,
+                cmd.stencilFunc.compareMask);
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_STENCIL_WRITE_MASK\",\n\"mask\":%d\n}\n", cmd.stencilWriteMask.mask);
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_OP:
+      {
+        fprintf(output,
+                "{\"Cmd\":\"SET_STENCIL_OP\",\n"
+                "\"failOp\":\"%s\",\n"
+                "\"depthFailOp\":\"%s\",\n"
+                "\"passOp\":\"%s\"\n}",
+
+                DumpStencilOp(cmd.stencilOp.failOp).c_str(),
+                DumpStencilOp(cmd.stencilOp.depthFailOp).c_str(),
+                DumpStencilOp(cmd.stencilOp.passOp).c_str());
+        break;
+      }
+
+      case GLES::CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        fprintf(output,
+                "{\"Cmd\":\"SET_DEPTH_COMPARE_OP\",\n"
+                "\"compareOp\":\"%s\"\n}\n",
+                DumpCompareOp(cmd.depth.compareOp).c_str());
+        break;
+      }
+      case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_DEPTH_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.testEnabled ? "\"true\"" : "\"false\""));
+        break;
+      }
+      case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        fprintf(output, "{\"Cmd\":\"SET_DEPTH_WRITE_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.writeEnabled ? "\"true\"" : "\"false\""));
+        break;
+      }
+
+      case GLES::CommandType::BEGIN_RENDERPASS:
+      {
+        fprintf(output,
+                "{\"Cmd\":\"BEGIN_RENDER_PASS\",\n"
+                "\"renderTarget\":\"%p\",\n"
+                "\"renderPass\":\"%p\",\n"
+                "\"renderArea\":[%d,%d,%d,%d],\n",
+                cmd.beginRenderPass.renderTarget,
+                cmd.beginRenderPass.renderPass,
+                cmd.beginRenderPass.renderArea.x,
+                cmd.beginRenderPass.renderArea.y,
+                cmd.beginRenderPass.renderArea.width,
+                cmd.beginRenderPass.renderArea.height);
+        fprintf(output, "\"clearValues\":[");
+        bool firstV = true;
+        for(auto& value : cmd.beginRenderPass.clearValues)
+        {
+          if(!firstV)
+          {
+            fprintf(output, ",");
+          }
+          firstV = false;
+          fprintf(output, "[%f,%f,%f,%f]", value.color.r, value.color.g, value.color.b, value.color.a);
+        }
+        fprintf(output, "]\n}");
+        break;
+      }
+      case GLES::CommandType::END_RENDERPASS:
+      {
+        fprintf(output, "{\"Cmd\":\"END_RENDER_PASS\"}\n");
+        break;
+      }
+      case GLES::CommandType::PRESENT_RENDER_TARGET:
+      {
+        fprintf(output, "{\"Cmd\":\"PRESENT_RENDER_TARGET\"}\n");
+        break;
+      }
+      case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":[");
+        bool firstBuf{true};
+        for(auto& buf : cmd.executeCommandBuffers.buffers)
+        {
+          if(!firstBuf)
+          {
+            fprintf(output, ", ");
+          }
+          firstBuf = false;
+          DumpCommandBuffer(output, static_cast<const GLES::CommandBuffer*>(buf));
+        }
+        fprintf(output, "]\n}");
+        break;
+      }
+    }
+  }
+}
+
+GraphicsFrameDump::GraphicsFrameDump()
+: outputStream(nullptr, nullptr)
+{
+  char* outfile = getenv("GRAPHICS_CMDBUF_OUTFILE");
+  if(outfile)
+  {
+    outputStream = UniqueFilePtr(std::fopen(outfile, "w"), std::fclose);
+    output       = outputStream.get();
+  }
+  if(!output)
+    output = stderr;
+}
+
+void GraphicsFrameDump::Start()
+{
+  if(IsDumpFrame())
+  {
+    if(!firstFrame)
+    {
+      fprintf(output, ", \n");
+    }
+    firstFrame   = false;
+    firstBuffer  = true;
+    dumpingFrame = true;
+    fprintf(output, "{\"Queue #%d\":[\n", frameCount);
+  }
+}
+
+void GraphicsFrameDump::DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf)
+{
+  if(dumpingFrame)
+  {
+    if(!firstBuffer)
+    {
+      fprintf(output, ", \n");
+    }
+    firstBuffer = false;
+    fprintf(output, "[\n");
+    Graphics::DumpCommandBuffer(output, cmdBuf);
+    fprintf(output, "]\n");
+  }
+}
+
+void GraphicsFrameDump::End()
+{
+  if(dumpingFrame)
+  {
+    fprintf(output, "]}\n");
+  }
+  firstBuffer  = true;
+  dumpingFrame = false;
+}
+
+bool GraphicsFrameDump::IsDumpFrame()
+{
+  bool dump = false;
+
+  frameCount++;
+
+  dump = (frameCount < NTH_FRAME);
+
+  // Or, could also use an enviroment variable as a trigger
+  // e.g. if getenv(X) is set, then start dumping again, and clear X.
+
+  return dump;
+}
+
+} // namespace Dali::Graphics
diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h b/dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h
new file mode 100644 (file)
index 0000000..c6333f4
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
+#define DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
+
+/*
+ * Copyright (c) 2021 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/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
+
+namespace Dali::Graphics
+{
+/**
+ * Struct to manage dumping N command buffers. In this file, "frame" really 
+ * means each call to EglGraphicsController::Flush(), and doesn't necessarily
+ * correspond to a complete render frame. 
+ */
+struct GraphicsFrameDump
+{
+  using UniqueFilePtr = std::unique_ptr<std::FILE, int (*)(std::FILE*)>;
+  UniqueFilePtr outputStream;
+  FILE*         output{nullptr};
+  bool          dumpingFrame{false};
+  bool          firstBuffer{true};
+  bool          firstFrame{true};
+  int           frameCount{0};
+
+  const int NTH_FRAME{10}; // dump first N "frames"
+
+  // Constructor
+  GraphicsFrameDump();
+
+  void Start();
+  void End();
+  void DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf);
+  bool IsDumpFrame();
+};
+
+#if defined(DEBUG_ENABLED) && defined(ENABLE_COMMAND_BUFFER_FRAME_DUMP)
+#define DUMP_FRAME_INIT() std::unique_ptr<Dali::Graphics::GraphicsFrameDump> gGraphicsFrameDump(new Dali::Graphics::GraphicsFrameDump)
+#define DUMP_FRAME_START()       \
+  if(gGraphicsFrameDump)         \
+  {                              \
+    gGraphicsFrameDump->Start(); \
+  }
+#define DUMP_FRAME_COMMAND_BUFFER(cmdBuffer)          \
+  if(gGraphicsFrameDump)                              \
+  {                                                   \
+    gGraphicsFrameDump->DumpCommandBuffer(cmdBuffer); \
+  }
+#define DUMP_FRAME_END()       \
+  if(gGraphicsFrameDump)       \
+  {                            \
+    gGraphicsFrameDump->End(); \
+  }
+#else
+#define DUMP_FRAME_INIT()
+#define DUMP_FRAME_START()
+#define DUMP_FRAME_COMMAND_BUFFER(cmdBuffer)
+#define DUMP_FRAME_END()
+#endif
+
+} // namespace Dali::Graphics
+
+#endif //DALI_GRAPHICS_EGL_GRAPHICS_CONTROLLER_DEBUG_H
index 4ec725d..772d4ef 100644 (file)
 #include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
 
 // INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-program.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-render-pass.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-render-target.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
 #include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
 #include <dali/internal/graphics/gles-impl/gles3-graphics-memory.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
 #include <dali/public-api/common/dali-common.h>
-#include "gles-graphics-program.h"
+
+// Uncomment the following define to turn on frame dumping
+//#define ENABLE_COMMAND_BUFFER_FRAME_DUMP 1
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
+DUMP_FRAME_INIT();
 
 namespace Dali::Graphics
 {
@@ -98,16 +110,21 @@ EglGraphicsController::~EglGraphicsController() = default;
 void EglGraphicsController::InitializeGLES(Integration::GlAbstraction& glAbstraction)
 {
   DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #1\n");
-  mGlAbstraction = &glAbstraction;
-  mContext       = std::make_unique<GLES::Context>(*this);
+  mGlAbstraction  = &glAbstraction;
+  mContext        = std::make_unique<GLES::Context>(*this);
+  mCurrentContext = mContext.get();
 }
 
-void EglGraphicsController::Initialize(Integration::GlSyncAbstraction&          glSyncAbstraction,
-                                       Integration::GlContextHelperAbstraction& glContextHelperAbstraction)
+void EglGraphicsController::Initialize(Integration::GraphicsSyncAbstraction&    syncImplementation,
+                                       Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
+                                       Internal::Adaptor::GraphicsInterface&    graphicsInterface)
 {
   DALI_LOG_RELEASE_INFO("Initializing New Graphics Controller #2\n");
-  mGlSyncAbstraction          = &glSyncAbstraction;
+  auto* syncImplPtr = static_cast<Internal::Adaptor::EglSyncImplementation*>(&syncImplementation);
+
+  mEglSyncImplementation      = syncImplPtr;
   mGlContextHelperAbstraction = &glContextHelperAbstraction;
+  mGraphics                   = &graphicsInterface;
 }
 
 void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
@@ -125,16 +142,35 @@ void EglGraphicsController::SubmitCommandBuffers(const SubmitInfo& submitInfo)
   }
 }
 
-Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
+void EglGraphicsController::PresentRenderTarget(RenderTarget* renderTarget)
 {
-  DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
-  return *mGlAbstraction;
+  // Use command buffer to execute presentation (we should pool it)
+  CommandBufferCreateInfo info;
+  info.SetLevel(CommandBufferLevel::PRIMARY);
+  info.fixedCapacity        = 1; // only one command
+  auto presentCommandBuffer = new GLES::CommandBuffer(info, *this);
+  presentCommandBuffer->PresentRenderTarget(static_cast<GLES::RenderTarget*>(renderTarget));
+  SubmitInfo submitInfo;
+  submitInfo.cmdBuffer = {presentCommandBuffer};
+  submitInfo.flags     = 0 | SubmitFlagBits::FLUSH;
+  SubmitCommandBuffers(submitInfo);
+}
+
+void EglGraphicsController::ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget)
+{
+  auto* rt = static_cast<GLES::RenderTarget*>(renderTarget);
+  if(rt->GetCreateInfo().surface)
+  {
+    auto* surfaceInterface = reinterpret_cast<Dali::RenderSurfaceInterface*>(rt->GetCreateInfo().surface);
+    surfaceInterface->MakeContextCurrent();
+    surfaceInterface->PostRender();
+  }
 }
 
-Integration::GlSyncAbstraction& EglGraphicsController::GetGlSyncAbstraction()
+Integration::GlAbstraction& EglGraphicsController::GetGlAbstraction()
 {
-  DALI_ASSERT_DEBUG(mGlSyncAbstraction && "Graphics controller not initialized");
-  return *mGlSyncAbstraction;
+  DALI_ASSERT_DEBUG(mGlAbstraction && "Graphics controller not initialized");
+  return *mGlAbstraction;
 }
 
 Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelperAbstraction()
@@ -143,26 +179,44 @@ Integration::GlContextHelperAbstraction& EglGraphicsController::GetGlContextHelp
   return *mGlContextHelperAbstraction;
 }
 
-Graphics::UniquePtr<CommandBuffer>
-EglGraphicsController::CreateCommandBuffer(const CommandBufferCreateInfo&       commandBufferCreateInfo,
-                                           Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
+Internal::Adaptor::EglSyncImplementation& EglGraphicsController::GetEglSyncImplementation()
+{
+  DALI_ASSERT_DEBUG(mEglSyncImplementation && "Sync implementation not initialized");
+  return *mEglSyncImplementation;
+}
+
+Graphics::UniquePtr<CommandBuffer> EglGraphicsController::CreateCommandBuffer(
+  const CommandBufferCreateInfo&       commandBufferCreateInfo,
+  Graphics::UniquePtr<CommandBuffer>&& oldCommandBuffer)
 {
   return NewObject<GLES::CommandBuffer>(commandBufferCreateInfo, *this, std::move(oldCommandBuffer));
 }
 
+Graphics::UniquePtr<RenderPass> EglGraphicsController::CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass)
+{
+  return NewObject<GLES::RenderPass>(renderPassCreateInfo, *this, std::move(oldRenderPass));
+}
+
 Graphics::UniquePtr<Texture>
 EglGraphicsController::CreateTexture(const TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Texture>&& oldTexture)
 {
   return NewObject<GLES::Texture>(textureCreateInfo, *this, std::move(oldTexture));
 }
 
-Graphics::UniquePtr<Buffer>
-EglGraphicsController::CreateBuffer(const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
+Graphics::UniquePtr<Buffer> EglGraphicsController::CreateBuffer(
+  const BufferCreateInfo& bufferCreateInfo, Graphics::UniquePtr<Buffer>&& oldBuffer)
 {
   return NewObject<GLES::Buffer>(bufferCreateInfo, *this, std::move(oldBuffer));
 }
 
-Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
+Graphics::UniquePtr<Framebuffer> EglGraphicsController::CreateFramebuffer(
+  const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer)
+{
+  return NewObject<GLES::Framebuffer>(framebufferCreateInfo, *this, std::move(oldFramebuffer));
+}
+
+Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(
+  const PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
 {
   // Create pipeline cache if needed
   if(!mPipelineCache)
@@ -173,7 +227,8 @@ Graphics::UniquePtr<Pipeline> EglGraphicsController::CreatePipeline(const Pipeli
   return mPipelineCache->GetPipeline(pipelineCreateInfo, std::move(oldPipeline));
 }
 
-Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
+Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
+  const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
 {
   // Create program cache if needed
   if(!mPipelineCache)
@@ -194,11 +249,62 @@ Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerC
   return NewObject<GLES::Sampler>(samplerCreateInfo, *this, std::move(oldSampler));
 }
 
+Graphics::UniquePtr<RenderTarget> EglGraphicsController::CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget)
+{
+  return NewObject<GLES::RenderTarget>(renderTargetCreateInfo, *this, std::move(oldRenderTarget));
+}
+
+Graphics::UniquePtr<SyncObject> EglGraphicsController::CreateSyncObject(const SyncObjectCreateInfo& syncObjectCreateInfo,
+                                                                        UniquePtr<SyncObject>&&     oldSyncObject)
+{
+  if(GetGLESVersion() < GLES::GLESVersion::GLES_30)
+  {
+    return NewObject<EGL::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+  }
+  else
+  {
+    return NewObject<GLES::SyncObject>(syncObjectCreateInfo, *this, std::move(oldSyncObject));
+  }
+}
+
 const Graphics::Reflection& EglGraphicsController::GetProgramReflection(const Graphics::Program& program)
 {
   return static_cast<const Graphics::GLES::Program*>(&program)->GetReflection();
 }
 
+void EglGraphicsController::CreateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+  std::unique_ptr<GLES::Context> context = std::make_unique<GLES::Context>(*this);
+  mSurfaceContexts.push_back(std::move(std::make_pair(surface, std::move(context))));
+}
+
+void EglGraphicsController::DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+  mSurfaceContexts.erase(std::remove_if(
+                           mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) { return surface == iter.first; }),
+                         mSurfaceContexts.end());
+}
+
+void EglGraphicsController::ActivateResourceContext()
+{
+  mCurrentContext = mContext.get();
+}
+
+void EglGraphicsController::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+  if(surface && mGraphics->IsResourceContextSupported())
+  {
+    auto iter = std::find_if(mSurfaceContexts.begin(), mSurfaceContexts.end(), [surface](SurfaceContextPair& iter) {
+      return (iter.first == surface);
+    });
+
+    if(iter != mSurfaceContexts.end())
+    {
+      mCurrentContext = iter->second.get();
+    }
+  }
+}
+
 void EglGraphicsController::AddTexture(GLES::Texture& texture)
 {
   // Assuming we are on the correct context
@@ -211,6 +317,12 @@ void EglGraphicsController::AddBuffer(GLES::Buffer& buffer)
   mCreateBufferQueue.push(&buffer);
 }
 
+void EglGraphicsController::AddFramebuffer(GLES::Framebuffer& framebuffer)
+{
+  // Assuming we are on the correct context
+  mCreateFramebufferQueue.push(&framebuffer);
+}
+
 void EglGraphicsController::ProcessDiscardQueues()
 {
   // Process textures
@@ -219,6 +331,9 @@ void EglGraphicsController::ProcessDiscardQueues()
   // Process buffers
   ProcessDiscardQueue<GLES::Buffer>(mDiscardBufferQueue);
 
+  // Process Framebuffers
+  ProcessDiscardQueue<GLES::Framebuffer>(mDiscardFramebufferQueue);
+
   // Process pipelines
   ProcessDiscardQueue<GLES::Pipeline>(mDiscardPipelineQueue);
 
@@ -242,101 +357,226 @@ void EglGraphicsController::ProcessCreateQueues()
 
   // Process buffers
   ProcessCreateQueue(mCreateBufferQueue);
+
+  // Process framebuffers
+  ProcessCreateQueue(mCreateFramebufferQueue);
 }
 
-void EglGraphicsController::ProcessCommandQueues()
+void EglGraphicsController::ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer)
 {
-  // TODO: command queue per context, sync between queues should be
-  // done externally
-
-  while(!mCommandQueue.empty())
+  for(auto& cmd : commandBuffer.GetCommands())
   {
-    auto cmdBuf = mCommandQueue.front();
-    mCommandQueue.pop();
-
-    for(auto& cmd : cmdBuf->GetCommands())
+    // process command
+    switch(cmd.type)
     {
-      // process command
-      switch(cmd.type)
+      case GLES::CommandType::FLUSH:
       {
-        case GLES::CommandType::FLUSH:
-        {
-          // Nothing to do here
-          break;
-        }
-        case GLES::CommandType::BIND_TEXTURES:
-        {
-          mContext->BindTextures(cmd.bindTextures.textureBindings);
-          break;
-        }
-        case GLES::CommandType::BIND_VERTEX_BUFFERS:
-        {
-          auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
-          mContext->BindVertexBuffers(bindings);
-          break;
-        }
-        case GLES::CommandType::BIND_UNIFORM_BUFFER:
-        {
-          auto& bindings = cmd.bindUniformBuffers;
-          mContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
-          break;
-        }
-        case GLES::CommandType::BIND_INDEX_BUFFER:
-        {
-          mContext->BindIndexBuffer(cmd.bindIndexBuffer);
-          break;
-        }
-        case GLES::CommandType::BIND_SAMPLERS:
-        {
-          break;
-        }
-        case GLES::CommandType::BIND_PIPELINE:
-        {
-          mContext->BindPipeline(cmd.bindPipeline.pipeline);
-          break;
-        }
-        case GLES::CommandType::DRAW:
+        // Nothing to do here
+        break;
+      }
+      case GLES::CommandType::BIND_TEXTURES:
+      {
+        mCurrentContext->BindTextures(cmd.bindTextures.textureBindings);
+        break;
+      }
+      case GLES::CommandType::BIND_VERTEX_BUFFERS:
+      {
+        auto& bindings = cmd.bindVertexBuffers.vertexBufferBindings;
+        mCurrentContext->BindVertexBuffers(bindings);
+        break;
+      }
+      case GLES::CommandType::BIND_UNIFORM_BUFFER:
+      {
+        auto& bindings = cmd.bindUniformBuffers;
+        mCurrentContext->BindUniformBuffers(bindings.uniformBufferBindings, bindings.standaloneUniformsBufferBinding);
+        break;
+      }
+      case GLES::CommandType::BIND_INDEX_BUFFER:
+      {
+        mCurrentContext->BindIndexBuffer(cmd.bindIndexBuffer);
+        break;
+      }
+      case GLES::CommandType::BIND_SAMPLERS:
+      {
+        break;
+      }
+      case GLES::CommandType::BIND_PIPELINE:
+      {
+        auto pipeline = static_cast<const GLES::Pipeline*>(cmd.bindPipeline.pipeline);
+        mCurrentContext->BindPipeline(pipeline);
+        break;
+      }
+      case GLES::CommandType::DRAW:
+      {
+        mCurrentContext->Flush(false, cmd.draw);
+        break;
+      }
+      case GLES::CommandType::DRAW_INDEXED:
+      {
+        mCurrentContext->Flush(false, cmd.draw);
+        break;
+      }
+      case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+      {
+        mCurrentContext->Flush(false, cmd.draw);
+        break;
+      }
+      case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+      {
+        mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
+        break;
+      }
+      case GLES::CommandType::SET_SCISSOR_TEST:
+      {
+        if(cmd.scissorTest.enable)
         {
-          mContext->Flush(false, cmd.draw);
-          break;
+          mGlAbstraction->Enable(GL_SCISSOR_TEST);
         }
-        case GLES::CommandType::DRAW_INDEXED:
+        else
         {
-          mContext->Flush(false, cmd.draw);
-          break;
+          mGlAbstraction->Disable(GL_SCISSOR_TEST);
         }
-        case GLES::CommandType::DRAW_INDEXED_INDIRECT:
+        break;
+      }
+      case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+      {
+        mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
+        break;
+      }
+
+      case GLES::CommandType::SET_COLOR_MASK:
+      {
+        mCurrentContext->ColorMask(cmd.colorMask.enabled);
+        break;
+      }
+      case GLES::CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        mCurrentContext->ClearStencilBuffer();
+        break;
+      }
+      case GLES::CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        mCurrentContext->ClearDepthBuffer();
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        mCurrentContext->SetStencilTestEnable(cmd.stencilTest.enabled);
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_FUNC:
+      {
+        mCurrentContext->StencilFunc(cmd.stencilFunc.compareOp,
+                                     cmd.stencilFunc.reference,
+                                     cmd.stencilFunc.compareMask);
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        mCurrentContext->StencilMask(cmd.stencilWriteMask.mask);
+        break;
+      }
+
+      case GLES::CommandType::SET_STENCIL_OP:
+      {
+        mCurrentContext->StencilOp(cmd.stencilOp.failOp,
+                                   cmd.stencilOp.depthFailOp,
+                                   cmd.stencilOp.passOp);
+        break;
+      }
+
+      case GLES::CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        mCurrentContext->SetDepthCompareOp(cmd.depth.compareOp);
+        break;
+      }
+      case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        mCurrentContext->SetDepthTestEnable(cmd.depth.testEnabled);
+        break;
+      }
+      case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        mCurrentContext->SetDepthWriteEnable(cmd.depth.writeEnabled);
+        break;
+      }
+
+      case GLES::CommandType::BEGIN_RENDERPASS:
+      {
+        auto&       renderTarget = *cmd.beginRenderPass.renderTarget;
+        const auto& targetInfo   = renderTarget.GetCreateInfo();
+
+        if(targetInfo.surface)
         {
-          mContext->Flush(false, cmd.draw);
-          break;
+          // switch to surface context
+          mGraphics->ActivateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(targetInfo.surface));
         }
-        case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
+        else if(targetInfo.framebuffer)
         {
-          mGlAbstraction->Scissor(cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
-          break;
+          // switch to resource context
+          mGraphics->ActivateResourceContext();
         }
-        case GLES::CommandType::SET_SCISSOR_TEST:
+
+        mCurrentContext->BeginRenderPass(cmd.beginRenderPass);
+        break;
+      }
+      case GLES::CommandType::END_RENDERPASS:
+      {
+        mCurrentContext->EndRenderPass();
+
+        auto syncObject = const_cast<GLES::SyncObject*>(static_cast<const GLES::SyncObject*>(cmd.endRenderPass.syncObject));
+        if(syncObject)
         {
-          if(cmd.scissorTest.enable)
-          {
-            mGlAbstraction->Enable(GL_SCISSOR_TEST);
-          }
-          else
-          {
-            mGlAbstraction->Disable(GL_SCISSOR_TEST);
-          }
-          break;
+          syncObject->InitializeResource();
         }
-        case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
+        break;
+      }
+      case GLES::CommandType::PRESENT_RENDER_TARGET:
+      {
+        ResolvePresentRenderTarget(cmd.presentRenderTarget.targetToPresent);
+
+        // push this command buffer to the discard queue
+        mDiscardCommandBufferQueue.push(const_cast<GLES::CommandBuffer*>(&commandBuffer));
+        break;
+      }
+      case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        // Process secondary command buffers
+        // todo: check validity of the secondaries
+        //       there are operations which are illigal to be done
+        //       within secondaries.
+        for(auto& buf : cmd.executeCommandBuffers.buffers)
         {
-          mGlAbstraction->Viewport(cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
-          break;
+          ProcessCommandBuffer(*static_cast<const GLES::CommandBuffer*>(buf));
         }
+        break;
       }
     }
   }
 }
 
+void EglGraphicsController::ProcessCommandQueues()
+{
+  // TODO: command queue per context, sync between queues should be
+  // done externally
+  currentFramebuffer = nullptr;
+
+  DUMP_FRAME_START();
+
+  while(!mCommandQueue.empty())
+  {
+    auto cmdBuf = mCommandQueue.front();
+    mCommandQueue.pop();
+    DUMP_FRAME_COMMAND_BUFFER(cmdBuf);
+    ProcessCommandBuffer(*cmdBuf);
+  }
+
+  DUMP_FRAME_END();
+}
+
 void EglGraphicsController::ProcessTextureUpdateQueue()
 {
   while(!mTextureUpdateRequests.empty())
@@ -348,23 +588,100 @@ void EglGraphicsController::ProcessTextureUpdateQueue()
 
     if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY)
     {
-      // GPU memory must be already allocated (glTexImage2D())
-      auto*       texture    = static_cast<GLES::Texture*>(info.dstTexture);
-      const auto& createInfo = texture->GetCreateInfo();
+      // GPU memory must be already allocated.
+
+      // Check if it needs conversion
+      auto*       texture            = static_cast<GLES::Texture*>(info.dstTexture);
+      const auto& createInfo         = texture->GetCreateInfo();
+      auto        srcFormat          = GLES::GLTextureFormatType(info.srcFormat).format;
+      auto        srcType            = GLES::GLTextureFormatType(info.srcFormat).type;
+      auto        destInternalFormat = GLES::GLTextureFormatType(createInfo.format).internalFormat;
+      auto        destFormat         = GLES::GLTextureFormatType(createInfo.format).format;
+
+      // From render-texture.cpp
+      const bool isSubImage(info.dstOffset2D.x != 0 || info.dstOffset2D.y != 0 ||
+                            info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) ||
+                            info.srcExtent2D.height != (createInfo.size.height / (1 << info.level)));
+
+      auto*                sourceBuffer = reinterpret_cast<uint8_t*>(source.memorySource.memory);
+      std::vector<uint8_t> tempBuffer;
+      if(mGlAbstraction->TextureRequiresConverting(srcFormat, destFormat, isSubImage))
+      {
+        // Convert RGB to RGBA if necessary.
+        texture->TryConvertPixelData(source.memorySource.memory, info.srcFormat, createInfo.format, info.srcSize, info.srcExtent2D.width, info.srcExtent2D.height, tempBuffer);
+        sourceBuffer = &tempBuffer[0];
+        srcFormat    = destFormat;
+        srcType      = GLES::GLTextureFormatType(createInfo.format).type;
+      }
 
-      mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      // Calculate the maximum mipmap level for the texture
+      texture->SetMaxMipMapLevel(std::max(texture->GetMaxMipMapLevel(), info.level));
 
-      mGlAbstraction->BindTexture(GL_TEXTURE_2D, texture->GetGLTexture());
-      mGlAbstraction->TexSubImage2D(GL_TEXTURE_2D,
-                                    info.level,
-                                    info.dstOffset2D.x,
-                                    info.dstOffset2D.y,
-                                    info.srcExtent2D.width,
-                                    info.srcExtent2D.height,
-                                    GLES::GLTextureFormatType(createInfo.format).format,
-                                    GLES::GLTextureFormatType(createInfo.format).type,
-                                    source.memorySource.memory);
+      GLenum bindTarget{GL_TEXTURE_2D};
+      GLenum target{GL_TEXTURE_2D};
 
+      if(createInfo.textureType == Graphics::TextureType::TEXTURE_CUBEMAP)
+      {
+        bindTarget = GL_TEXTURE_CUBE_MAP;
+        target     = GL_TEXTURE_CUBE_MAP_POSITIVE_X + info.layer;
+      }
+
+      mGlAbstraction->PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+      mGlAbstraction->BindTexture(bindTarget, texture->GetGLTexture());
+
+      if(!isSubImage)
+      {
+        if(!texture->IsCompressed())
+        {
+          mGlAbstraction->TexImage2D(target,
+                                     info.level,
+                                     destInternalFormat,
+                                     info.srcExtent2D.width,
+                                     info.srcExtent2D.height,
+                                     0,
+                                     srcFormat,
+                                     srcType,
+                                     sourceBuffer);
+        }
+        else
+        {
+          mGlAbstraction->CompressedTexImage2D(target,
+                                               info.level,
+                                               destInternalFormat,
+                                               info.srcExtent2D.width,
+                                               info.srcExtent2D.height,
+                                               0,
+                                               info.srcSize,
+                                               sourceBuffer);
+        }
+      }
+      else
+      {
+        if(!texture->IsCompressed())
+        {
+          mGlAbstraction->TexSubImage2D(target,
+                                        info.level,
+                                        info.dstOffset2D.x,
+                                        info.dstOffset2D.y,
+                                        info.srcExtent2D.width,
+                                        info.srcExtent2D.height,
+                                        srcFormat,
+                                        srcType,
+                                        sourceBuffer);
+        }
+        else
+        {
+          mGlAbstraction->CompressedTexSubImage2D(target,
+                                                  info.level,
+                                                  info.dstOffset2D.x,
+                                                  info.dstOffset2D.y,
+                                                  info.srcExtent2D.width,
+                                                  info.srcExtent2D.height,
+                                                  srcFormat,
+                                                  info.srcSize,
+                                                  sourceBuffer);
+        }
+      }
       // free staging memory
       free(source.memorySource.memory);
     }
@@ -421,15 +738,35 @@ void EglGraphicsController::UpdateTextures(const std::vector<TextureUpdateInfo>&
   }
 
   // If upload buffer exceeds maximum size, flush.
-  if( mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB*1024 )
+  if(mTextureUploadTotalCPUMemoryUsed > TEXTURE_UPLOAD_MAX_BUFER_SIZE_MB * 1024)
   {
     Flush();
     mTextureUploadTotalCPUMemoryUsed = 0;
   }
 }
 
+void EglGraphicsController::ProcessTextureMipmapGenerationQueue()
+{
+  while(!mTextureMipmapGenerationRequests.empty())
+  {
+    auto* texture = mTextureMipmapGenerationRequests.front();
+
+    mGlAbstraction->BindTexture(texture->GetGlTarget(), texture->GetGLTexture());
+    mGlAbstraction->GenerateMipmap(texture->GetGlTarget());
+
+    mTextureMipmapGenerationRequests.pop();
+  }
+}
+
+void EglGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
+{
+  mTextureMipmapGenerationRequests.push(static_cast<const GLES::Texture*>(&texture));
+}
+
 Graphics::UniquePtr<Memory> EglGraphicsController::MapBufferRange(const MapBufferInfo& mapInfo)
 {
+  mGraphics->ActivateResourceContext();
+
   // Mapping buffer requires the object to be created NOW
   // Workaround - flush now, otherwise there will be given a staging buffer
   // in case when the buffer is not there yet
index 6886380..c1f7c8c 100644 (file)
 #include <queue>
 
 // INTERNAL INCLUDES
-#include "gles-context.h"
-#include "gles-graphics-buffer.h"
-#include "gles-graphics-command-buffer.h"
-#include "gles-graphics-pipeline-cache.h"
-#include "gles-graphics-pipeline.h"
-#include "gles-graphics-reflection.h"
-#include "gles-graphics-sampler.h"
-#include "gles-graphics-shader.h"
-#include "gles-graphics-texture.h"
-#include "gles-graphics-types.h"
-#include "gles2-graphics-memory.h"
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/common/graphics-interface.h>
+#include <dali/internal/graphics/gles-impl/gles-context.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-buffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-command-buffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-framebuffer.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline-cache.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-pipeline.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-reflection.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-sampler.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-shader.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-types.h>
+#include <dali/internal/graphics/gles-impl/gles2-graphics-memory.h>
 
 namespace Dali
 {
 namespace Integration
 {
 class GlAbstraction;
-class GlSyncAbstraction;
 class GlContextHelperAbstraction;
 } // namespace Integration
 
@@ -79,12 +81,13 @@ public:
    *
    * Note, this is now executed in the render thread, after core initialization
    */
-  void Initialize(Integration::GlSyncAbstraction&          glSyncAbstraction,
-                  Integration::GlContextHelperAbstraction& glContextHelperAbstraction);
+  void Initialize(Integration::GraphicsSyncAbstraction&    syncImplementation,
+                  Integration::GlContextHelperAbstraction& glContextHelperAbstraction,
+                  Internal::Adaptor::GraphicsInterface&    graphicsInterface);
 
-  Integration::GlAbstraction&              GetGlAbstraction() override;
-  Integration::GlSyncAbstraction&          GetGlSyncAbstraction() override;
-  Integration::GlContextHelperAbstraction& GetGlContextHelperAbstraction() override;
+  Integration::GlAbstraction&               GetGlAbstraction() override;
+  Integration::GlContextHelperAbstraction&  GetGlContextHelperAbstraction() override;
+  Internal::Adaptor::EglSyncImplementation& GetEglSyncImplementation();
 
   /**
    * @copydoc Dali::Graphics::SubmitCommandBuffers()
@@ -94,9 +97,7 @@ public:
   /**
    * @copydoc Dali::Graphics::PresentRenderTarget()
    */
-  void PresentRenderTarget(RenderTarget* renderTarget) override
-  {
-  }
+  void PresentRenderTarget(RenderTarget* renderTarget) override;
 
   /**
    * @copydoc Dali::Graphics::WaitIdle()
@@ -143,6 +144,11 @@ public:
                       const std::vector<TextureUpdateSourceInfo>& sourceList) override;
 
   /**
+   * @copydoc Dali::Graphics::GenerateTextureMipmaps()
+   */
+  void GenerateTextureMipmaps(const Texture& texture) override;
+
+  /**
    * @copydoc Dali::Graphics::EnableDepthStencilBuffer()
    */
   bool EnableDepthStencilBuffer(bool enableDepth, bool enableStencil) override
@@ -193,10 +199,7 @@ public:
   /**
    * @copydoc Dali::Graphics::CreateRenderPass()
    */
-  Graphics::UniquePtr<RenderPass> CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass) override
-  {
-    return nullptr;
-  }
+  Graphics::UniquePtr<RenderPass> CreateRenderPass(const RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<RenderPass>&& oldRenderPass) override;
 
   /**
    * @copydoc Dali::Graphics::CreateTexture()
@@ -206,10 +209,7 @@ public:
   /**
    * @copydoc Dali::Graphics::CreateFramebuffer()
    */
-  Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override
-  {
-    return nullptr;
-  }
+  Graphics::UniquePtr<Framebuffer> CreateFramebuffer(const FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Framebuffer>&& oldFramebuffer) override;
 
   /**
    * @copydoc Dali::Graphics::CreatePipeline()
@@ -234,10 +234,13 @@ public:
   /**
    * @copydoc Dali::Graphics::CreateRenderTarget()
    */
-  Graphics::UniquePtr<RenderTarget> CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget) override
-  {
-    return nullptr;
-  }
+  Graphics::UniquePtr<RenderTarget> CreateRenderTarget(const RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<RenderTarget>&& oldRenderTarget) override;
+
+  /**
+   * @copydoc Dali::Graphics::CreateSyncObject()
+   */
+  Graphics::UniquePtr<SyncObject> CreateSyncObject(const SyncObjectCreateInfo&       syncObjectCreateInfo,
+                                                   Graphics::UniquePtr<SyncObject>&& oldSyncObject) override;
 
   /**
    * @copydoc Dali::Graphics::MapBufferRange()
@@ -307,6 +310,11 @@ public:
     return mGlAbstraction;
   }
 
+  [[nodiscard]] Internal::Adaptor::GraphicsInterface* GetGraphicsInterface() const
+  {
+    return mGraphics;
+  }
+
   // Internal
   void AddTexture(GLES::Texture& texture);
 
@@ -317,6 +325,12 @@ public:
   void AddBuffer(GLES::Buffer& buffer);
 
   /**
+   * @brief Adds framebuffer to the creation queue
+   * @param buffer
+   */
+  void AddFramebuffer(GLES::Framebuffer& framebuffer);
+
+  /**
    * @brief Pushes Bufer to the discard queue
    *
    * Function is called from the UniquePtr custom deleter.
@@ -333,7 +347,7 @@ public:
    *
    * Function is called from the UniquePtr custom deleter.
    *
-   * @param[in] texture Pointer to the texture
+   * @param[in] buffer Pointer to the buffer object
    */
   void DiscardResource(GLES::Buffer* buffer)
   {
@@ -341,6 +355,18 @@ public:
   }
 
   /**
+   * @brief Pushes framebuffer to the discard queue
+   *
+   * Function is called from the UniquePtr custom deleter.
+   *
+   * @param[in] framebuffer Pointer to the framebuffer object
+   */
+  void DiscardResource(GLES::Framebuffer* framebuffer)
+  {
+    mDiscardFramebufferQueue.push(framebuffer);
+  }
+
+  /**
    * @brief Pushes Program to the discard queue
    *
    * Function is called from the UniquePtr custom deleter.
@@ -408,12 +434,17 @@ public:
    */
   void Flush()
   {
+    mGraphics->ActivateResourceContext();
+
     // Process creations
     ProcessCreateQueues();
 
     // Process updates
     ProcessTextureUpdateQueue();
 
+    // Process texture mipmap generation requests
+    ProcessTextureMipmapGenerationQueue();
+
     // Process main command queue
     ProcessCommandQueues();
 
@@ -461,7 +492,7 @@ public:
   {
     while(!queue.empty())
     {
-      auto* object = queue.front();
+      auto* object = const_cast<U*>(queue.front());
 
       // Destroy
       object->DestroyResource();
@@ -500,6 +531,11 @@ public:
   void ProcessTextureUpdateQueue();
 
   /**
+   * @brief Executes all pending texture mipmap generation
+   */
+  void ProcessTextureMipmapGenerationQueue();
+
+  /**
    * @brief Returns program custom parameter
    *
    * This function can be used as a backdoor in order to retrieve
@@ -526,9 +562,17 @@ public:
    */
   GLES::GLESVersion GetGLESVersion() const
   {
-    // TODO: return proper version but for now we can
-    // test fallbacks
-    return GLES::GLESVersion::GLES_20;
+    return mGLESVersion;
+  }
+
+  /**
+   * @brief Sets runtime supported GLES version
+   *
+   * @param[in] glesVersion The runtime supported GLES version
+   */
+  void SetGLESVersion(GLES::GLESVersion glesVersion)
+  {
+    mGLESVersion = glesVersion;
   }
 
   bool IsShuttingDown() const
@@ -536,35 +580,79 @@ public:
     return mIsShuttingDown;
   }
 
+  void ProcessCommandBuffer(const GLES::CommandBuffer& commandBuffer);
+
+  // Resolves presentation
+  void ResolvePresentRenderTarget(GLES::RenderTarget* renderTarget);
+
+  /**
+   * Creates a GLES context for the given render surface
+   *
+   * @param[in] surface The surface whose GLES context to be created.
+   */
+  void CreateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+  /**
+   * Deletes a GLES context
+   *
+   * @param[in] surface The surface whose GLES context to be deleted.
+   */
+  void DeleteSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
+  /**
+   * Activate the resource context (shared surfaceless context)
+   */
+  void ActivateResourceContext();
+
+  /**
+   * Activate the surface context
+   *
+   * @param[in] surface The surface whose context to be switched to.
+   */
+  void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface);
+
 private:
   Integration::GlAbstraction*              mGlAbstraction{nullptr};
-  Integration::GlSyncAbstraction*          mGlSyncAbstraction{nullptr};
   Integration::GlContextHelperAbstraction* mGlContextHelperAbstraction{nullptr};
 
+  Internal::Adaptor::EglSyncImplementation* mEglSyncImplementation;
+  Internal::Adaptor::GraphicsInterface*     mGraphics{nullptr}; // Pointer to owning structure via interface.
+
   std::queue<GLES::Texture*> mCreateTextureQueue;  ///< Create queue for texture resource
   std::queue<GLES::Texture*> mDiscardTextureQueue; ///< Discard queue for texture resource
 
   std::queue<GLES::Buffer*> mCreateBufferQueue;  ///< Create queue for buffer resource
   std::queue<GLES::Buffer*> mDiscardBufferQueue; ///< Discard queue for buffer resource
 
-  std::queue<GLES::Program*>       mDiscardProgramQueue;       ///< Discard queue for program resource
-  std::queue<GLES::Pipeline*>      mDiscardPipelineQueue;      ///< Discard queue of pipelines
-  std::queue<GLES::Shader*>        mDiscardShaderQueue;        ///< Discard queue of shaders
-  std::queue<GLES::Sampler*>       mDiscardSamplerQueue;       ///< Discard queue of samplers
-  std::queue<GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
+  std::queue<GLES::Program*>             mDiscardProgramQueue;       ///< Discard queue for program resource
+  std::queue<GLES::Pipeline*>            mDiscardPipelineQueue;      ///< Discard queue of pipelines
+  std::queue<GLES::Shader*>              mDiscardShaderQueue;        ///< Discard queue of shaders
+  std::queue<GLES::Sampler*>             mDiscardSamplerQueue;       ///< Discard queue of samplers
+  std::queue<const GLES::CommandBuffer*> mDiscardCommandBufferQueue; ///< Discard queue of command buffers
+  std::queue<GLES::Framebuffer*>         mCreateFramebufferQueue;    ///< Create queue for framebuffer resource
+  std::queue<GLES::Framebuffer*>         mDiscardFramebufferQueue;   ///< Discard queue for framebuffer resource
 
   std::queue<GLES::CommandBuffer*> mCommandQueue; ///< we may have more in the future
 
   using TextureUpdateRequest = std::pair<TextureUpdateInfo, TextureUpdateSourceInfo>;
   std::queue<TextureUpdateRequest> mTextureUpdateRequests;
 
-  std::unique_ptr<GLES::Context> mContext{nullptr}; ///< Context object handling command buffers execution
+  std::queue<const GLES::Texture*> mTextureMipmapGenerationRequests; ///< Queue for texture mipmap generation requests
+
+  GLES::Context*                 mCurrentContext{nullptr}; ///< The current context
+  std::unique_ptr<GLES::Context> mContext{nullptr};        ///< Context object handling command buffers execution
+  using SurfaceContextPair = std::pair<Dali::RenderSurfaceInterface*, std::unique_ptr<GLES::Context>>;
+  std::vector<SurfaceContextPair> mSurfaceContexts; ///< Vector of surface context objects handling command buffers execution
 
   std::unique_ptr<GLES::PipelineCache> mPipelineCache{nullptr}; ///< Internal pipeline cache
 
-  uint32_t mTextureUploadTotalCPUMemoryUsed {0u};
+  GLES::GLESVersion mGLESVersion{GLES::GLESVersion::GLES_20}; ///< Runtime supported GLES version
+  uint32_t          mTextureUploadTotalCPUMemoryUsed{0u};
 
   bool mIsShuttingDown{false}; ///< Indicates whether the controller is shutting down
+
+  // todo: to be removed after renderpass
+  const Graphics::Framebuffer* currentFramebuffer{nullptr};
 };
 
 } // namespace Graphics
diff --git a/dali/internal/graphics/gles-impl/egl-sync-object.cpp b/dali/internal/graphics/gles-impl/egl-sync-object.cpp
new file mode 100644 (file)
index 0000000..14410b4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2021 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.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles-impl/egl-sync-object.h>
+
+// EXTERNAL HEADERS
+
+// INTERNAL HEADERS
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+#include <dali/internal/graphics/gles/egl-sync-implementation.h>
+
+namespace Dali::Graphics::EGL
+{
+SyncObject::SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: SyncObjectResource(createInfo, controller),
+  mEglSyncImplementation(controller.GetEglSyncImplementation()),
+  mEglSyncObject(nullptr)
+{
+}
+
+SyncObject::~SyncObject()
+{
+}
+
+void SyncObject::DestroyResource()
+{
+}
+
+bool SyncObject::InitializeResource()
+{
+  // Initialized not from a resource queue, but from a command.
+  mEglSyncObject = static_cast<Internal::Adaptor::EglSyncObject*>(mEglSyncImplementation.CreateSyncObject());
+  return true;
+}
+
+void SyncObject::DiscardResource()
+{
+  // Called from custom deleter.
+  // Don't use discard queue, drop immediately.
+  mEglSyncImplementation.DestroySyncObject(mEglSyncObject);
+  mEglSyncObject = nullptr;
+}
+
+bool SyncObject::IsSynced()
+{
+  if(mEglSyncObject)
+  {
+    return mEglSyncObject->IsSynced();
+  }
+  return false;
+}
+
+} // namespace Dali::Graphics::EGL
diff --git a/dali/internal/graphics/gles-impl/egl-sync-object.h b/dali/internal/graphics/gles-impl/egl-sync-object.h
new file mode 100644 (file)
index 0000000..d014a7f
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef DALI_GRAPHICS_EGL_SYNC_OBJECT_H
+#define DALI_GRAPHICS_EGL_SYNC_OBJECT_H
+
+/*
+ * Copyright (c) 2021 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.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/gles-impl/gles-graphics-resource.h>
+
+namespace Dali::Internal::Adaptor
+{
+class EglSyncImplementation;
+class EglSyncObject;
+} // namespace Dali::Internal::Adaptor
+
+namespace Dali::Graphics::EGL
+{
+using SyncObjectResource = GLES::Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
+
+class SyncObject : public SyncObjectResource
+{
+public:
+  /**
+   * @brief Constructor
+   * @param[in] createInfo Valid createInfo structure
+   * @param[in] controller Reference to the controller
+   */
+  SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
+
+  /**
+   * @brief Destructor
+   */
+  ~SyncObject() override;
+
+  /**
+   * @brief Called when GL resources are destroyed
+   */
+  void DestroyResource() override;
+
+  /**
+   * @brief Called when initializing the resource
+   *
+   * @return True on success
+   */
+  bool InitializeResource() override;
+
+  /**
+   * @brief Called when UniquePtr<> on client-side dies
+   */
+  void DiscardResource() override;
+
+  /**
+   * Determine if the synchronisation object has been signalled.
+   *
+   * @return false if the sync object has not been signalled, true if it has been signalled (and
+   * can now be destroyed)
+   */
+  bool IsSynced() override;
+
+private:
+  Internal::Adaptor::EglSyncImplementation& mEglSyncImplementation;
+  Internal::Adaptor::EglSyncObject*         mEglSyncObject;
+};
+
+} // namespace Dali::Graphics::EGL
+
+#endif //DALI_GRAPHICS_EGL_SYNC_OBJECT_H
index 09df141..84481fd 100644 (file)
@@ -2,6 +2,8 @@
 # module: graphics, backend: gles-impl
 SET( adaptor_graphics_gles_src_files ${adaptor_graphics_gles_src_files}
     ${adaptor_graphics_dir}/gles-impl/egl-graphics-controller.cpp
+    ${adaptor_graphics_dir}/gles-impl/egl-graphics-controller-debug.cpp
+    ${adaptor_graphics_dir}/gles-impl/egl-sync-object.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-buffer.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-command-buffer.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-debug.cpp
@@ -18,5 +20,5 @@ SET( adaptor_graphics_gles_src_files ${adaptor_graphics_gles_src_files}
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-texture.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-graphics-pipeline-cache.cpp
     ${adaptor_graphics_dir}/gles-impl/gles-context.cpp
+    ${adaptor_graphics_dir}/gles-impl/gles-sync-object.cpp
 )
-
index f7cf80d..974869a 100644 (file)
  */
 
 #include "gles-context.h"
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
 #include <dali/integration-api/gl-abstraction.h>
 #include <dali/integration-api/gl-defines.h>
+#include <dali/internal/graphics/common/graphics-interface.h>
+
 #include "egl-graphics-controller.h"
 #include "gles-graphics-buffer.h"
 #include "gles-graphics-pipeline.h"
 #include "gles-graphics-program.h"
+#include "gles-graphics-render-pass.h"
+#include "gles-graphics-render-target.h"
 
 namespace Dali::Graphics::GLES
 {
@@ -55,6 +60,10 @@ struct Context::Impl
   // Currently bound UBOs (check if it's needed per program!)
   std::vector<UniformBufferBindingDescriptor> mCurrentUBOBindings{};
   UniformBufferBindingDescriptor              mCurrentStandaloneUBOBinding{};
+
+  // Current render pass and render target
+  const GLES::RenderTarget* mCurrentRenderTarget{nullptr};
+  const GLES::RenderPass*   mCurrentRenderPass{nullptr};
 };
 
 Context::Context(EglGraphicsController& controller)
@@ -87,6 +96,11 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
   ResolveUniformBuffers();
 
   // Bind textures
+  // Map binding# to sampler location
+  const auto program = static_cast<const GLES::Program*>(mImpl->mCurrentPipeline->GetCreateInfo().programState->program);
+
+  const auto& reflection = program->GetReflection();
+  const auto& samplers   = reflection.GetSamplers();
   for(const auto& binding : mImpl->mCurrentTextureBindings)
   {
     auto texture = const_cast<GLES::Texture*>(static_cast<const GLES::Texture*>(binding.texture));
@@ -102,6 +116,13 @@ void Context::Flush(bool reset, const GLES::DrawCallDescriptor& drawCall)
 
     texture->Bind(binding);
     texture->Prepare(); // @todo also non-const.
+
+    if(binding.binding < samplers.size()) // binding maps to texture unit. (texture bindings should also be in binding order)
+    {
+      // Offset is set to the lexical offset within the frag shader, map it to the texture unit
+      // @todo Explicitly set the texture unit through the graphics interface
+      gl.Uniform1i(samplers[binding.binding].location, samplers[binding.binding].offset);
+    }
   }
 
   // for each attribute bind vertices
@@ -310,7 +331,7 @@ void Context::ResolveStandaloneUniforms()
 
   auto extraInfos = reflection.GetStandaloneUniformExtraInfo();
 
-  const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress());
+  const auto ptr = reinterpret_cast<const char*>(mImpl->mCurrentStandaloneUBOBinding.buffer->GetCPUAllocatedAddress()) + mImpl->mCurrentStandaloneUBOBinding.offset;
 
   for(const auto& info : extraInfos)
   {
@@ -403,9 +424,166 @@ void Context::ResolveStandaloneUniforms()
   }
 }
 
+void Context::BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin)
+{
+  auto& renderPass   = *renderPassBegin.renderPass;
+  auto& renderTarget = *renderPassBegin.renderTarget;
+
+  const auto& targetInfo = renderTarget.GetCreateInfo();
+
+  auto& gl = *mImpl->mController.GetGL();
+
+  if(targetInfo.surface)
+  {
+    // Bind surface FB
+    gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
+  }
+  else if(targetInfo.framebuffer)
+  {
+    // bind framebuffer and swap.
+    renderTarget.GetFramebuffer()->Bind();
+  }
+
+  // clear (ideally cache the setup)
+
+  // In GL we assume that the last attachment is depth/stencil (we may need
+  // to cache extra information inside GLES RenderTarget if we want to be
+  // more specific in case of MRT)
+
+  const auto& attachments = *renderPass.GetCreateInfo().attachments;
+  const auto& color0      = attachments[0];
+  GLuint      mask        = 0;
+  if(color0.loadOp == AttachmentLoadOp::CLEAR)
+  {
+    mask |= GL_COLOR_BUFFER_BIT;
+
+    // Set clear color (todo: cache it!)
+    // Something goes wrong here if Alpha mask is GL_TRUE
+    gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+    gl.ClearColor(renderPassBegin.clearValues[0].color.r,
+                  renderPassBegin.clearValues[0].color.g,
+                  renderPassBegin.clearValues[0].color.b,
+                  renderPassBegin.clearValues[0].color.a);
+  }
+
+  // check for depth stencil
+  if(attachments.size() > 1)
+  {
+    const auto& depthStencil = attachments.back();
+    if(depthStencil.loadOp == AttachmentLoadOp::CLEAR)
+    {
+      gl.DepthMask(true);
+      mask |= GL_DEPTH_BUFFER_BIT;
+    }
+    if(depthStencil.stencilLoadOp == AttachmentLoadOp::CLEAR)
+    {
+      gl.StencilMask(0xFF);
+      mask |= GL_STENCIL_BUFFER_BIT;
+    }
+  }
+
+  gl.Enable(GL_SCISSOR_TEST);
+  gl.Scissor(renderPassBegin.renderArea.x, renderPassBegin.renderArea.y, renderPassBegin.renderArea.width, renderPassBegin.renderArea.height);
+  gl.Clear(mask);
+  gl.Disable(GL_SCISSOR_TEST);
+
+  mImpl->mCurrentRenderPass   = &renderPass;
+  mImpl->mCurrentRenderTarget = &renderTarget;
+}
+
+void Context::EndRenderPass()
+{
+  if(mImpl->mCurrentRenderTarget)
+  {
+    if(mImpl->mCurrentRenderTarget->GetFramebuffer())
+    {
+      auto& gl = *mImpl->mController.GetGL();
+      gl.Flush();
+    }
+  }
+}
+
 void Context::ClearState()
 {
   mImpl->mCurrentTextureBindings.clear();
 }
 
+void Context::ColorMask(bool enabled)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.ColorMask(enabled, enabled, enabled, enabled);
+}
+
+void Context::ClearStencilBuffer()
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.Clear(GL_STENCIL_BUFFER_BIT);
+}
+
+void Context::ClearDepthBuffer()
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.Clear(GL_DEPTH_BUFFER_BIT);
+}
+
+void Context::SetStencilTestEnable(bool stencilEnable)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  if(stencilEnable)
+  {
+    gl.Enable(GL_STENCIL_TEST);
+  }
+  else
+  {
+    gl.Disable(GL_STENCIL_TEST);
+  }
+}
+
+void Context::StencilMask(uint32_t writeMask)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.StencilMask(writeMask);
+}
+
+void Context::StencilFunc(Graphics::CompareOp compareOp,
+                          uint32_t            reference,
+                          uint32_t            compareMask)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.StencilFunc(GLCompareOp(compareOp).op, reference, compareMask);
+}
+
+void Context::StencilOp(Graphics::StencilOp failOp,
+                        Graphics::StencilOp depthFailOp,
+                        Graphics::StencilOp passOp)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.StencilOp(GLStencilOp(failOp).op, GLStencilOp(depthFailOp).op, GLStencilOp(passOp).op);
+}
+
+void Context::SetDepthCompareOp(Graphics::CompareOp compareOp)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.DepthFunc(GLCompareOp(compareOp).op);
+}
+
+void Context::SetDepthTestEnable(bool depthTestEnable)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  if(depthTestEnable)
+  {
+    gl.Enable(GL_DEPTH_TEST);
+  }
+  else
+  {
+    gl.Disable(GL_DEPTH_TEST);
+  }
+}
+
+void Context::SetDepthWriteEnable(bool depthWriteEnable)
+{
+  auto& gl = *mImpl->mController.GetGL();
+  gl.DepthMask(depthWriteEnable);
+}
+
 } // namespace Dali::Graphics::GLES
index cc4e243..c9df90f 100644 (file)
@@ -27,8 +27,8 @@ class EglGraphicsController;
 namespace GLES
 {
 class Pipeline;
-class Texture;
-
+class RenderPass;
+class RenderTarget;
 /**
  * @brief Context represents single GLES context
  */
@@ -121,6 +121,37 @@ public:
    */
   void ResolveStandaloneUniforms();
 
+  /**
+   * @brief Begins render pass for sepcified render target
+   *
+   * @param[in] renderPass render pass object to begin
+   * @param[in] renderTarget render target to be drawn onto
+   */
+  void BeginRenderPass(const BeginRenderPassDescriptor& renderPassBegin);
+
+  /**
+   * @brief Ends render pass
+   *
+   * Ending render pass is necessary in order to ensure
+   * proper implicit synchronization is in place
+   */
+  void EndRenderPass();
+
+  void ColorMask(bool enabled);
+  void ClearStencilBuffer();
+  void ClearDepthBuffer();
+  void SetStencilTestEnable(bool stencilEnable);
+  void StencilMask(uint32_t writeMask);
+  void StencilFunc(Graphics::CompareOp compareOp,
+                   uint32_t            reference,
+                   uint32_t            compareMask);
+  void StencilOp(Graphics::StencilOp failOp,
+                 Graphics::StencilOp depthFailOp,
+                 Graphics::StencilOp passOp);
+  void SetDepthCompareOp(Graphics::CompareOp compareOp);
+  void SetDepthTestEnable(bool depthTestEnable);
+  void SetDepthWriteEnable(bool depthWriteEnable);
+
 private:
   /**
    * @brief Clear current state
index 8cb90b1..b79607b 100644 (file)
 // INTERNAL INCLUDES
 #include "egl-graphics-controller.h"
 #include "gles-graphics-buffer.h"
+#include "gles-graphics-framebuffer.h"
 #include "gles-graphics-pipeline.h"
+#include "gles-graphics-render-pass.h"
+#include "gles-graphics-render-target.h"
 #include "gles-graphics-texture.h"
 
 namespace Dali::Graphics::GLES
@@ -121,24 +124,36 @@ void CommandBuffer::BindIndexBuffer(const Graphics::Buffer& buffer,
 }
 
 void CommandBuffer::BeginRenderPass(
-  Graphics::RenderPass&   renderPass,
-  Graphics::RenderTarget& renderTarget,
-  Extent2D                renderArea,
+  Graphics::RenderPass*   renderPass,
+  Graphics::RenderTarget* renderTarget,
+  Rect2D                  renderArea,
   std::vector<ClearValue> clearValues)
 {
+  mCommands.emplace_back(CommandType::BEGIN_RENDERPASS);
+  auto& cmd                        = mCommands.back();
+  cmd.beginRenderPass.renderPass   = static_cast<GLES::RenderPass*>(renderPass);
+  cmd.beginRenderPass.renderTarget = static_cast<GLES::RenderTarget*>(renderTarget);
+  cmd.beginRenderPass.renderArea   = renderArea;
+  cmd.beginRenderPass.clearValues  = clearValues;
 }
 
-/**
- * @brief Ends current render pass
- *
- * This command must be issued in order to finalize the render pass.
- * It's up to the implementation whether anything has to be done but
- * the Controller may use end RP marker in order to resolve resource
- * dependencies (for example, to know when target texture is ready
- * before passing it to another render pass).
- */
-void CommandBuffer::EndRenderPass()
+void CommandBuffer::EndRenderPass(Graphics::SyncObject* syncObject)
+{
+  mCommands.emplace_back(CommandType::END_RENDERPASS);
+  auto& cmd = mCommands.back();
+
+  cmd.endRenderPass.syncObject = static_cast<GLES::SyncObject*>(syncObject);
+}
+
+void CommandBuffer::ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers)
 {
+  mCommands.emplace_back(CommandType::EXECUTE_COMMAND_BUFFERS);
+  auto& cmd = mCommands.back();
+  cmd.executeCommandBuffers.buffers.reserve(commandBuffers.size());
+  for(auto&& item : commandBuffers)
+  {
+    cmd.executeCommandBuffers.buffers.emplace_back(static_cast<const GLES::CommandBuffer*>(item));
+  }
 }
 
 void CommandBuffer::Draw(
@@ -216,6 +231,80 @@ void CommandBuffer::SetViewportEnable(bool value)
   // There is no GL equivalent
 }
 
+void CommandBuffer::SetColorMask(bool enabled)
+{
+  mCommands.emplace_back(CommandType::SET_COLOR_MASK);
+  auto& cmd = mCommands.back().colorMask;
+  ;
+  cmd.enabled = enabled;
+}
+
+void CommandBuffer::ClearStencilBuffer()
+{
+  mCommands.emplace_back(CommandType::CLEAR_STENCIL_BUFFER);
+}
+
+void CommandBuffer::SetStencilTestEnable(bool stencilEnable)
+{
+  mCommands.emplace_back(CommandType::SET_STENCIL_TEST_ENABLE);
+  mCommands.back().stencilTest.enabled = stencilEnable;
+}
+
+void CommandBuffer::SetStencilWriteMask(uint32_t writeMask)
+{
+  mCommands.emplace_back(CommandType::SET_STENCIL_WRITE_MASK);
+  mCommands.back().stencilWriteMask.mask = writeMask;
+}
+
+void CommandBuffer::SetStencilOp(Graphics::StencilOp failOp,
+                                 Graphics::StencilOp passOp,
+                                 Graphics::StencilOp depthFailOp)
+{
+  mCommands.emplace_back(CommandType::SET_STENCIL_OP);
+  auto& cmd       = mCommands.back().stencilOp;
+  cmd.failOp      = failOp;
+  cmd.passOp      = passOp;
+  cmd.depthFailOp = depthFailOp;
+}
+
+void CommandBuffer::SetStencilFunc(Graphics::CompareOp compareOp,
+                                   uint32_t            reference,
+                                   uint32_t            compareMask)
+{
+  mCommands.emplace_back(CommandType::SET_STENCIL_FUNC);
+  auto& cmd       = mCommands.back().stencilFunc;
+  cmd.compareOp   = compareOp;
+  cmd.compareMask = compareMask;
+  cmd.reference   = reference;
+}
+
+void CommandBuffer::SetDepthCompareOp(Graphics::CompareOp compareOp)
+{
+  mCommands.emplace_back(CommandType::SET_DEPTH_COMPARE_OP);
+  mCommands.back().depth.compareOp = compareOp;
+}
+
+void CommandBuffer::SetDepthTestEnable(bool depthTestEnable)
+{
+  mCommands.emplace_back(CommandType::SET_DEPTH_TEST_ENABLE);
+  mCommands.back().depth.testEnabled = depthTestEnable;
+}
+void CommandBuffer::SetDepthWriteEnable(bool depthWriteEnable)
+{
+  mCommands.emplace_back(CommandType::SET_DEPTH_WRITE_ENABLE);
+  mCommands.back().depth.writeEnabled = depthWriteEnable;
+}
+void CommandBuffer::ClearDepthBuffer()
+{
+  mCommands.emplace_back(CommandType::CLEAR_DEPTH_BUFFER);
+}
+
+void CommandBuffer::PresentRenderTarget(GLES::RenderTarget* renderTarget)
+{
+  mCommands.emplace_back(CommandType::PRESENT_RENDER_TARGET);
+  mCommands.back().presentRenderTarget.targetToPresent = renderTarget;
+}
+
 [[nodiscard]] const std::vector<Command>& CommandBuffer::GetCommands() const
 {
   return mCommands;
@@ -237,4 +326,4 @@ void CommandBuffer::DiscardResource()
   GetController().DiscardResource(this);
 }
 
-} // namespace Dali::Graphics::GLES
\ No newline at end of file
+} // namespace Dali::Graphics::GLES
index cad69bd..f539103 100644 (file)
 // INTERNAL INCLUDES
 #include "gles-graphics-resource.h"
 #include "gles-graphics-types.h"
+#include "gles-sync-object.h"
 
 namespace Dali::Graphics::GLES
 {
-class Texture;
 class Pipeline;
-
+class RenderPass;
+class Framebuffer;
+class CommandBuffer;
 enum class CommandType
 {
   FLUSH,
@@ -46,7 +48,21 @@ enum class CommandType
   DRAW_INDEXED_INDIRECT,
   SET_SCISSOR,
   SET_SCISSOR_TEST,
-  SET_VIEWPORT
+  SET_VIEWPORT,
+  BEGIN_RENDERPASS,
+  END_RENDERPASS,
+  EXECUTE_COMMAND_BUFFERS,
+  PRESENT_RENDER_TARGET,
+  SET_COLOR_MASK,
+  CLEAR_STENCIL_BUFFER,
+  CLEAR_DEPTH_BUFFER,
+  SET_STENCIL_TEST_ENABLE,
+  SET_STENCIL_WRITE_MASK,
+  SET_STENCIL_OP,
+  SET_STENCIL_FUNC,
+  SET_DEPTH_COMPARE_OP,
+  SET_DEPTH_TEST_ENABLE,
+  SET_DEPTH_WRITE_ENABLE,
 };
 
 /**
@@ -80,6 +96,12 @@ struct Command
         new(&bindTextures) decltype(bindTextures);
         break;
       }
+      case CommandType::BEGIN_RENDERPASS:
+      {
+        // run destructor
+        new(&beginRenderPass) decltype(beginRenderPass);
+        break;
+      }
       default:
       {
       }
@@ -100,6 +122,12 @@ struct Command
         InvokeDestructor(bindTextures);
         break;
       }
+      case CommandType::BEGIN_RENDERPASS:
+      {
+        // run destructor
+        InvokeDestructor(beginRenderPass);
+        break;
+      }
       default:
       {
       }
@@ -164,6 +192,21 @@ struct Command
         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
         break;
       }
+      case CommandType::BEGIN_RENDERPASS:
+      {
+        new(&beginRenderPass) BeginRenderPassDescriptor(rhs.beginRenderPass);
+        break;
+      }
+      case CommandType::END_RENDERPASS:
+      {
+        endRenderPass.syncObject = rhs.endRenderPass.syncObject;
+        break;
+      }
+      case CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        executeCommandBuffers = rhs.executeCommandBuffers;
+        break;
+      }
       case CommandType::FLUSH:
       {
         // Nothing to do
@@ -184,12 +227,70 @@ struct Command
         viewport.region = rhs.viewport.region;
         break;
       }
+      case CommandType::PRESENT_RENDER_TARGET:
+      {
+        presentRenderTarget = rhs.presentRenderTarget;
+        break;
+      }
+      case CommandType::SET_COLOR_MASK:
+      {
+        colorMask.enabled = rhs.colorMask.enabled;
+        break;
+      }
+      case CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        break;
+      }
+      case CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        break;
+      }
+      case CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        stencilTest.enabled = rhs.stencilTest.enabled;
+        break;
+      }
+      case CommandType::SET_STENCIL_FUNC:
+      {
+        stencilFunc.compareMask = rhs.stencilFunc.compareMask;
+        stencilFunc.compareOp   = rhs.stencilFunc.compareOp;
+        stencilFunc.reference   = rhs.stencilFunc.reference;
+        break;
+      }
+      case CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        stencilWriteMask.mask = rhs.stencilWriteMask.mask;
+        break;
+      }
+      case CommandType::SET_STENCIL_OP:
+      {
+        stencilOp.failOp      = rhs.stencilOp.failOp;
+        stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
+        stencilOp.passOp      = rhs.stencilOp.passOp;
+        break;
+      }
+
+      case CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        depth.compareOp = rhs.depth.compareOp;
+        break;
+      }
+      case CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        depth.testEnabled = rhs.depth.testEnabled;
+        break;
+      }
+      case CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        depth.writeEnabled = rhs.depth.writeEnabled;
+        break;
+      }
     }
     type = rhs.type;
   }
 
   /**
-   * @brief Copy constructor
+   * @brief Move constructor
    * @param[in] rhs Command
    */
   Command(Command&& rhs) noexcept
@@ -246,6 +347,21 @@ struct Command
         draw.drawIndexedIndirect = rhs.draw.drawIndexedIndirect;
         break;
       }
+      case CommandType::BEGIN_RENDERPASS:
+      {
+        new(&beginRenderPass) BeginRenderPassDescriptor(std::move(rhs.beginRenderPass));
+        break;
+      }
+      case CommandType::END_RENDERPASS:
+      {
+        endRenderPass.syncObject = rhs.endRenderPass.syncObject;
+        break;
+      }
+      case CommandType::EXECUTE_COMMAND_BUFFERS:
+      {
+        executeCommandBuffers = std::move(rhs.executeCommandBuffers);
+        break;
+      }
       case CommandType::FLUSH:
       {
         // Nothing to do
@@ -266,6 +382,64 @@ struct Command
         viewport.region = rhs.viewport.region;
         break;
       }
+      case CommandType::PRESENT_RENDER_TARGET:
+      {
+        presentRenderTarget = rhs.presentRenderTarget;
+        break;
+      }
+      case CommandType::SET_COLOR_MASK:
+      {
+        colorMask.enabled = rhs.colorMask.enabled;
+        break;
+      }
+      case CommandType::CLEAR_STENCIL_BUFFER:
+      {
+        break;
+      }
+      case CommandType::CLEAR_DEPTH_BUFFER:
+      {
+        break;
+      }
+      case CommandType::SET_STENCIL_TEST_ENABLE:
+      {
+        stencilTest.enabled = rhs.stencilTest.enabled;
+        break;
+      }
+      case CommandType::SET_STENCIL_FUNC:
+      {
+        stencilFunc.compareMask = rhs.stencilFunc.compareMask;
+        stencilFunc.compareOp   = rhs.stencilFunc.compareOp;
+        stencilFunc.reference   = rhs.stencilFunc.reference;
+        break;
+      }
+      case CommandType::SET_STENCIL_WRITE_MASK:
+      {
+        stencilWriteMask.mask = rhs.stencilWriteMask.mask;
+        break;
+      }
+      case CommandType::SET_STENCIL_OP:
+      {
+        stencilOp.failOp      = rhs.stencilOp.failOp;
+        stencilOp.depthFailOp = rhs.stencilOp.depthFailOp;
+        stencilOp.passOp      = rhs.stencilOp.passOp;
+        break;
+      }
+
+      case CommandType::SET_DEPTH_COMPARE_OP:
+      {
+        depth.compareOp = rhs.depth.compareOp;
+        break;
+      }
+      case CommandType::SET_DEPTH_TEST_ENABLE:
+      {
+        depth.testEnabled = rhs.depth.testEnabled;
+        break;
+      }
+      case CommandType::SET_DEPTH_WRITE_ENABLE:
+      {
+        depth.writeEnabled = rhs.depth.writeEnabled;
+        break;
+      }
     }
     type = rhs.type;
   }
@@ -324,6 +498,60 @@ struct Command
     {
       Graphics::Viewport region;
     } viewport;
+
+    struct BeginRenderPassDescriptor
+      beginRenderPass;
+
+    struct
+    {
+      Graphics::SyncObject* syncObject;
+    } endRenderPass;
+
+    struct
+    {
+      std::vector<const GLES::CommandBuffer*> buffers;
+    } executeCommandBuffers;
+
+    struct
+    {
+      GLES::RenderTarget* targetToPresent;
+    } presentRenderTarget;
+
+    struct
+    {
+      Graphics::CompareOp compareOp;
+      bool                testEnabled;
+      bool                writeEnabled;
+    } depth;
+
+    struct
+    {
+      Graphics::StencilOp failOp;
+      Graphics::StencilOp passOp;
+      Graphics::StencilOp depthFailOp;
+    } stencilOp;
+
+    struct
+    {
+      uint32_t mask;
+    } stencilWriteMask;
+
+    struct
+    {
+      uint32_t            compareMask;
+      Graphics::CompareOp compareOp;
+      uint32_t            reference;
+    } stencilFunc;
+
+    struct
+    {
+      bool enabled;
+    } stencilTest;
+
+    struct
+    {
+      bool enabled;
+    } colorMask;
   };
 };
 
@@ -336,49 +564,78 @@ public:
 
   ~CommandBuffer() override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindVertexBuffers
+   */
   void BindVertexBuffers(uint32_t                             firstBinding,
                          std::vector<const Graphics::Buffer*> buffers,
                          std::vector<uint32_t>                offsets) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindUniformBuffers
+   */
   void BindUniformBuffers(const std::vector<Graphics::UniformBufferBinding>& bindings) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindPipeline
+   */
   void BindPipeline(const Graphics::Pipeline& pipeline) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindTextures
+   */
   void BindTextures(std::vector<TextureBinding>& textureBindings) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindSamplers
+   */
   void BindSamplers(std::vector<SamplerBinding>& samplerBindings) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindPushConstants
+   */
   void BindPushConstants(void*    data,
                          uint32_t size,
                          uint32_t binding) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BindIndexBuffer
+   */
   void BindIndexBuffer(const Graphics::Buffer& buffer,
                        uint32_t                offset,
                        Format                  format) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::BeginRenderPass
+   */
   void BeginRenderPass(
-    Graphics::RenderPass&   renderPass,
-    Graphics::RenderTarget& renderTarget,
-    Extent2D                renderArea,
+    Graphics::RenderPass*   renderPass,
+    Graphics::RenderTarget* renderTarget,
+    Rect2D                  renderArea,
     std::vector<ClearValue> clearValues) override;
 
   /**
-   * @brief Ends current render pass
-   *
-   * This command must be issued in order to finalize the render pass.
-   * It's up to the implementation whether anything has to be done but
-   * the Controller may use end RP marker in order to resolve resource
-   * dependencies (for example, to know when target texture is ready
-   * before passing it to another render pass).
+   * @copydoc Dali::Graphics::CommandBuffer::EndRenderPass
+   */
+  void EndRenderPass(Graphics::SyncObject* syncObject) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::ExecuteCommandBuffers
    */
-  void EndRenderPass() override;
+  void ExecuteCommandBuffers(std::vector<const Graphics::CommandBuffer*>&& commandBuffers) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::Draw
+   */
   void Draw(
     uint32_t vertexCount,
     uint32_t instanceCount,
     uint32_t firstVertex,
     uint32_t firstInstance) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::DrawIndexed
+   */
   void DrawIndexed(
     uint32_t indexCount,
     uint32_t instanceCount,
@@ -386,31 +643,123 @@ public:
     int32_t  vertexOffset,
     uint32_t firstInstance) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::DrawIndexedIndirect
+   */
   void DrawIndexedIndirect(
     Graphics::Buffer& buffer,
     uint32_t          offset,
     uint32_t          drawCount,
     uint32_t          stride) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::Reset
+   */
   void Reset() override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetScissor
+   */
   void SetScissor(Graphics::Rect2D value) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetScissorTestEnable
+   */
   void SetScissorTestEnable(bool value) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetViewport
+   */
   void SetViewport(Viewport value) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetViewportEnable
+   */
   void SetViewportEnable(bool value) override;
 
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetColorMask
+   */
+  void SetColorMask(bool enabled) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::ClearStencilBuffer
+   */
+  void ClearStencilBuffer() override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetStencilTestEnable
+   */
+  void SetStencilTestEnable(bool stencilEnable) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetStencilWriteMask
+   */
+  void SetStencilWriteMask(uint32_t writeMask) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetStencilOp
+   */
+  void SetStencilOp(Graphics::StencilOp failOp,
+                    Graphics::StencilOp passOp,
+                    Graphics::StencilOp depthFailOp) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetStencilFunc
+   */
+  void SetStencilFunc(Graphics::CompareOp compareOp,
+                      uint32_t            reference,
+                      uint32_t            compareMask) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetDepthCompareOp
+   */
+  void SetDepthCompareOp(Graphics::CompareOp compareOp) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetDepthTestEnable
+   */
+  void SetDepthTestEnable(bool depthTestEnable) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::SetDepthWriteEnable
+   */
+  void SetDepthWriteEnable(bool depthWriteEnable) override;
+
+  /**
+   * @copydoc Dali::Graphics::CommandBuffer::ClearDepthBuffer
+   */
+  void ClearDepthBuffer() override;
+
+  /**
+   * @brief Presents specified render target
+   *
+   * @param[in] renderTarget Valid pointer to a RenderTarget
+   *
+   * It's internal command that schedules presentation of
+   * specified render target.
+   */
+  void PresentRenderTarget(GLES::RenderTarget* renderTarget);
+
   [[nodiscard]] const std::vector<Command>& GetCommands() const;
 
+  /**
+   * @brief Destroy the associated resources
+   */
   void DestroyResource() override;
+
+  /**
+   * @brief Initialize associated resources
+   */
   bool InitializeResource() override;
 
+  /**
+   * @brief Add this resource to the discard queue
+   */
   void DiscardResource() override;
 
 private:
-  std::vector<Command> mCommands;
+  std::vector<Command> mCommands; ///< List of commands in this command buffer
 };
 } // namespace Dali::Graphics::GLES
 
index 6869bd9..2e52934 100644 (file)
 
 // CLASS HEADER
 #include "gles-graphics-framebuffer.h"
+
+// external headers
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+// Internal headers
+#include <dali/internal/graphics/gles-impl/gles-graphics-texture.h>
+#include "egl-graphics-controller.h"
+
+namespace Dali::Graphics::GLES
+{
+namespace
+{
+const GLenum COLOR_ATTACHMENTS[] =
+  {
+    GL_COLOR_ATTACHMENT0,
+    GL_COLOR_ATTACHMENT1,
+    GL_COLOR_ATTACHMENT2,
+    GL_COLOR_ATTACHMENT3,
+    GL_COLOR_ATTACHMENT4,
+    GL_COLOR_ATTACHMENT5,
+    GL_COLOR_ATTACHMENT6,
+    GL_COLOR_ATTACHMENT7,
+};
+
+struct DEPTH_STENCIL_ATTACHMENT_TYPE
+{
+  constexpr explicit DEPTH_STENCIL_ATTACHMENT_TYPE(Graphics::Format textureFormat)
+  {
+    switch(textureFormat)
+    {
+      case Graphics::Format::D16_UNORM:
+      case Graphics::Format::D32_SFLOAT:
+      case Graphics::Format::X8_D24_UNORM_PACK32:
+      {
+        attachment = GL_DEPTH_ATTACHMENT;
+        break;
+      }
+
+      case Graphics::Format::S8_UINT: // Probably won't work as a standalone texture.
+      {
+        attachment = GL_STENCIL_ATTACHMENT;
+        break;
+      }
+
+      case Graphics::Format::D16_UNORM_S8_UINT:
+      case Graphics::Format::D24_UNORM_S8_UINT:
+      case Graphics::Format::D32_SFLOAT_S8_UINT:
+      {
+        attachment = GL_DEPTH_STENCIL_ATTACHMENT;
+        break;
+      }
+      default:
+      {
+        attachment = GL_NONE;
+        break;
+      }
+    }
+  }
+  Dali::GLenum attachment{GL_NONE};
+};
+
+} // anonymous namespace
+
+Framebuffer::Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: FramebufferResource(createInfo, controller)
+{
+  // Add framebuffer to the Resource queue
+  mController.AddFramebuffer(*this);
+}
+
+Framebuffer::~Framebuffer() = default;
+
+bool Framebuffer::InitializeResource()
+{
+  auto gl = mController.GetGL();
+  if(gl && !mInitialized)
+  {
+    mInitialized = true;
+
+    gl->GenFramebuffers(1, &mFramebufferId);
+    gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+
+    for(Graphics::ColorAttachment& attachment : mCreateInfo.colorAttachments)
+    {
+      AttachTexture(attachment.texture, COLOR_ATTACHMENTS[attachment.attachmentId], attachment.layerId, attachment.levelId);
+    }
+
+    // @todo is this per framebuffer, or more immediate state that needs setting when framebuffer changed?
+    gl->DrawBuffers(mCreateInfo.colorAttachments.size(), COLOR_ATTACHMENTS);
+
+    if(mCreateInfo.depthStencilAttachment.depthTexture)
+    {
+      // Create a depth or depth/stencil render target.
+      auto depthTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.depthTexture);
+      auto attachmentId = DEPTH_STENCIL_ATTACHMENT_TYPE(depthTexture->GetCreateInfo().format).attachment;
+
+      gl->GenRenderbuffers(1, &mDepthBufferId);
+      gl->BindRenderbuffer(GL_RENDERBUFFER, mDepthBufferId);
+      gl->RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mCreateInfo.size.width, mCreateInfo.size.height);
+      gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mDepthBufferId);
+
+      AttachTexture(depthTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.depthLevel);
+    }
+
+    if(mCreateInfo.depthStencilAttachment.stencilTexture)
+    {
+      auto stencilTexture = static_cast<const GLES::Texture*>(mCreateInfo.depthStencilAttachment.stencilTexture);
+      auto attachmentId   = DEPTH_STENCIL_ATTACHMENT_TYPE(stencilTexture->GetCreateInfo().format).attachment;
+
+      // Create a stencil render target.
+      gl->GenRenderbuffers(1, &mStencilBufferId);
+      gl->BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferId);
+      gl->RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mCreateInfo.size.width, mCreateInfo.size.height);
+      gl->FramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentId, GL_RENDERBUFFER, mStencilBufferId);
+
+      AttachTexture(stencilTexture, attachmentId, 0, mCreateInfo.depthStencilAttachment.stencilLevel);
+    }
+    gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
+  }
+
+  return mInitialized;
+}
+
+void Framebuffer::DestroyResource()
+{
+  auto gl = mController.GetGL();
+  if(gl && mInitialized)
+  {
+    if(mDepthBufferId)
+    {
+      gl->DeleteRenderbuffers(1, &mDepthBufferId);
+    }
+    if(mStencilBufferId)
+    {
+      gl->DeleteRenderbuffers(1, &mStencilBufferId);
+    }
+
+    gl->DeleteFramebuffers(1, &mFramebufferId);
+    mFramebufferId = 0u;
+    mInitialized   = false;
+  }
+}
+
+void Framebuffer::DiscardResource()
+{
+  mController.DiscardResource(this);
+}
+
+void Framebuffer::Bind() const
+{
+  auto gl = mController.GetGL();
+  gl->BindFramebuffer(GL_FRAMEBUFFER, mFramebufferId);
+}
+
+void Framebuffer::AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId)
+{
+  auto gl = mController.GetGL();
+  if(gl)
+  {
+    auto graphicsTexture = static_cast<const GLES::Texture*>(texture);
+    if(graphicsTexture->GetCreateInfo().textureType == Graphics::TextureType::TEXTURE_2D)
+    {
+      gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, graphicsTexture->GetGlTarget(), graphicsTexture->GetGLTexture(), levelId);
+    }
+    else
+    {
+      gl->FramebufferTexture2D(GL_FRAMEBUFFER, attachmentId, GL_TEXTURE_CUBE_MAP_POSITIVE_X + layerId, graphicsTexture->GetGLTexture(), levelId);
+    }
+  }
+}
+
+uint32_t Framebuffer::GetGlFramebufferId() const
+{
+  return mFramebufferId;
+}
+
+uint32_t Framebuffer::GetGlDepthBufferId() const
+{
+  return mDepthBufferId;
+}
+
+uint32_t Framebuffer::GetGlStencilBufferId() const
+{
+  return mStencilBufferId;
+}
+
+} //namespace Dali::Graphics::GLES
index 784d3bd..b48af2c 100644 (file)
@@ -37,44 +37,58 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-  : FramebufferResource(createInfo, controller)
-  {
-  }
+  Framebuffer(const Graphics::FramebufferCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
 
   /**
    * @brief Destructor
    */
-  ~Framebuffer() override = default;
+  ~Framebuffer() override;
 
   /**
    * @brief Called when GL resources are destroyed
    */
-  void DestroyResource() override
-  {
-    // TODO: Implement destroying the resource
-  }
+  void DestroyResource() override;
 
   /**
    * @brief Called when initializing the resource
    *
    * @return True on success
    */
-  bool InitializeResource() override
-  {
-    // TODO: Implement initializing resource
-    return {};
-  }
+  bool InitializeResource() override;
 
   /**
    * @brief Called when UniquePtr<> on client-side dies
    */
-  void DiscardResource() override
-  {
-    // TODO: Implement moving to the discard queue
-  }
+  void DiscardResource() override;
+
+  /**
+   * Used to bind the framebuffer, e.g. when offscreen changes
+   */
+  void Bind() const;
+
+  [[nodiscard]] uint32_t GetGlFramebufferId() const;
+
+  [[nodiscard]] uint32_t GetGlDepthBufferId() const;
+
+  [[nodiscard]] uint32_t GetGlStencilBufferId() const;
+
+private:
+  /**
+   * Attach a texture to the specified attachment point
+   * @param[in] texture The texture to bind
+   * @param[in] attachmentId The attachment point to bind it to
+   * @param[in] layerId The texture layer (e.g. for cubemap)
+   * @param[in] levelId The texture mipmap level
+   */
+  void AttachTexture(const Graphics::Texture* texture, uint32_t attachmentId, uint32_t layerId, uint32_t levelId);
+
+private:
+  uint32_t mFramebufferId{0u};
+  uint32_t mDepthBufferId{0u};
+  uint32_t mStencilBufferId{0u};
+  bool     mInitialized{false};
 };
 
 } // namespace Dali::Graphics::GLES
 
-#endif
\ No newline at end of file
+#endif
index ad98fb0..f9a7d16 100644 (file)
@@ -65,13 +65,12 @@ enum class StateLookupIndex : uint32_t
 {
   COLOR_BLEND_STATE_BIT    = 0,
   VIEWPORT_STATE_BIT       = 1,
-  FRAMEBUFFER_STATE_BIT    = 2,
-  BASE_PIPELINE_STATE_BIT  = 3,
-  DEPTH_STENCIL_STATE_BIT  = 4,
-  RASTERIZATION_STATE_BIT  = 5,
-  VERTEX_INPUT_STATE_BIT   = 6,
-  INPUT_ASSEMBLY_STATE_BIT = 7,
-  MAX_STATE                = 8
+  BASE_PIPELINE_STATE_BIT  = 2,
+  DEPTH_STENCIL_STATE_BIT  = 3,
+  RASTERIZATION_STATE_BIT  = 4,
+  VERTEX_INPUT_STATE_BIT   = 5,
+  INPUT_ASSEMBLY_STATE_BIT = 6,
+  MAX_STATE                = 7
 };
 
 /**
@@ -169,12 +168,6 @@ void InitialiseStateCompareLookupTable()
              lvp.scissor == rvp.scissor &&
              lvp.scissorTestEnable == rvp.scissorTestEnable;
     },
-    [](const auto* lhs, const auto* rhs) -> bool // framebufferState
-    {
-      const auto& lfb = *lhs->framebufferState;
-      const auto& rfb = *rhs->framebufferState;
-      return lfb.framebuffer == rfb.framebuffer;
-    },
     [](const auto* lhs, const auto* rhs) -> bool // basePipeline
     {
       return lhs->basePipeline == rhs->basePipeline;
@@ -232,7 +225,6 @@ inline uint32_t GetStateBitmask(const PipelineCreateInfo& info)
   uint32_t mask{0u};
   mask |= bool(info.colorBlendState) << int(StateLookupIndex::COLOR_BLEND_STATE_BIT);
   mask |= bool(info.viewportState) << int(StateLookupIndex::VIEWPORT_STATE_BIT);
-  mask |= bool(info.framebufferState) << int(StateLookupIndex::FRAMEBUFFER_STATE_BIT);
   mask |= bool(info.basePipeline) << int(StateLookupIndex::BASE_PIPELINE_STATE_BIT);
   mask |= bool(info.depthStencilState) << int(StateLookupIndex::DEPTH_STENCIL_STATE_BIT);
   mask |= bool(info.rasterizationState) << int(StateLookupIndex::RASTERIZATION_STATE_BIT);
index 8cc9491..603039b 100644 (file)
@@ -45,7 +45,6 @@ struct PipelineImpl::PipelineState
   DepthStencilState  depthStencilState;
   ProgramState       programState;
   ViewportState      viewportState;
-  FramebufferState   framebufferState;
   RasterizationState rasterizationState;
   VertexInputState   vertexInputState;
   InputAssemblyState inputAssemblyState;
@@ -65,7 +64,6 @@ PipelineImpl::PipelineImpl(const Graphics::PipelineCreateInfo& createInfo, Graph
   CopyStateIfSet(createInfo.vertexInputState, mPipelineState->vertexInputState, &mCreateInfo.vertexInputState);
   CopyStateIfSet(createInfo.rasterizationState, mPipelineState->rasterizationState, &mCreateInfo.rasterizationState);
   CopyStateIfSet(createInfo.programState, mPipelineState->programState, &mCreateInfo.programState);
-  CopyStateIfSet(createInfo.framebufferState, mPipelineState->framebufferState, &mCreateInfo.framebufferState);
   CopyStateIfSet(createInfo.colorBlendState, mPipelineState->colorBlendState, &mCreateInfo.colorBlendState);
   CopyStateIfSet(createInfo.depthStencilState, mPipelineState->depthStencilState, &mCreateInfo.depthStencilState);
   CopyStateIfSet(createInfo.programState, mPipelineState->programState, &mCreateInfo.programState);
index 86a26b7..26c4352 100644 (file)
@@ -94,7 +94,36 @@ bool SortUniformExtraInfoByLocation(Dali::Graphics::GLES::Reflection::UniformExt
   return a.location < b.location;
 }
 
-} // namespace
+struct StringSize
+{
+  const char* const mString;
+  const uint32_t    mLength;
+
+  template<uint32_t kLength>
+  constexpr StringSize(const char (&string)[kLength])
+  : mString(string),
+    mLength(kLength - 1) // remove terminating null; N.B. there should be no other null.
+  {
+  }
+
+  operator const char*() const
+  {
+    return mString;
+  }
+};
+
+bool operator==(const StringSize& lhs, const char* rhs)
+{
+  return strncmp(lhs.mString, rhs, lhs.mLength) == 0;
+}
+
+const char* const    DELIMITERS = " \t\n";
+constexpr StringSize UNIFORM{"uniform"};
+constexpr StringSize SAMPLER_PREFIX{"sampler"};
+constexpr StringSize SAMPLER_TYPES[]   = {"2D", "Cube", "ExternalOES"};
+constexpr auto       END_SAMPLER_TYPES = SAMPLER_TYPES + std::extent<decltype(SAMPLER_TYPES)>::value;
+
+} // anonymous namespace
 
 namespace Dali::Graphics::GLES
 {
@@ -194,9 +223,10 @@ void Reflection::BuildUniformReflection()
     }
 
     uniformInfo.uniformClass = IsSampler(type) ? Dali::Graphics::UniformClass::COMBINED_IMAGE_SAMPLER : Dali::Graphics::UniformClass::UNIFORM;
-    uniformInfo.location     = IsSampler(type) ? 0 : location;
-    uniformInfo.binding      = IsSampler(type) ? location : 0;
+    uniformInfo.location     = location; //IsSampler(type) ? 0 : location;
+    uniformInfo.binding      = 0;        // IsSampler(type) ? location : 0;
     uniformInfo.bufferIndex  = 0;
+    uniformInfo.offset       = 0;
 
     if(IsSampler(type))
     {
@@ -219,7 +249,7 @@ void Reflection::BuildUniformReflection()
 
   if(mUniformOpaques.size() > 1)
   {
-    std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), SortUniformInfoByLocation);
+    SortOpaques();
   }
 
   // Calculate the uniform offset
@@ -490,21 +520,23 @@ bool Reflection::GetNamedUniform(const std::string& name, Dali::Graphics::Unifor
         return true;
       }
     }
-    index++;
+    ++index;
   }
 
   // check samplers
+  index = 0u;
   for(auto&& uniform : mUniformOpaques)
   {
     if(uniform.name == name)
     {
       out.uniformClass = Graphics::UniformClass::COMBINED_IMAGE_SAMPLER;
-      out.binding      = uniform.binding;
+      out.binding      = 0;
       out.name         = name;
-      out.offset       = 0;
-      out.location     = uniform.location;
+      out.offset       = index;            // lexical location in shader
+      out.location     = uniform.location; // uniform location mapping
       return true;
     }
+    ++index;
   }
 
   return false;
@@ -553,4 +585,78 @@ Graphics::ShaderLanguage Reflection::GetLanguage() const
   return version;
 }
 
+void Reflection::SortOpaques()
+{
+  //Determine declaration order of each sampler
+  auto& programCreateInfo = mProgram.GetCreateInfo();
+
+  std::vector<uint8_t> data;
+  std::string          fragShader;
+
+  for(auto& shaderState : *programCreateInfo.shaderState)
+  {
+    if(shaderState.pipelineStage == PipelineStage::FRAGMENT_SHADER)
+    {
+      auto* shader           = static_cast<const GLES::Shader*>(shaderState.shader);
+      auto& shaderCreateInfo = shader->GetCreateInfo();
+      data.resize(shaderCreateInfo.sourceSize + 1);
+      std::memcpy(&data[0], shaderCreateInfo.sourceData, shaderCreateInfo.sourceSize);
+      data[shaderCreateInfo.sourceSize] = 0;
+      fragShader                        = std::string(reinterpret_cast<char*>(&data[0]));
+      break;
+    }
+  }
+
+  if(!fragShader.empty())
+  {
+    char*            shaderStr       = strdup(fragShader.c_str());
+    char*            uniform         = strstr(shaderStr, UNIFORM);
+    int              samplerPosition = 0;
+    std::vector<int> samplerPositions(mUniformOpaques.size(), -1);
+
+    while(uniform)
+    {
+      char* outerToken = strtok_r(uniform + UNIFORM.mLength, ";", &uniform);
+
+      char* nextPtr = nullptr;
+      char* token   = strtok_r(outerToken, DELIMITERS, &nextPtr);
+      while(token)
+      {
+        if(SAMPLER_PREFIX == token)
+        {
+          token += SAMPLER_PREFIX.mLength;
+          if(std::find(SAMPLER_TYPES, END_SAMPLER_TYPES, token) != END_SAMPLER_TYPES)
+          {
+            bool found(false);
+            token = strtok_r(nullptr, DELIMITERS, &nextPtr);
+
+            for(uint32_t i = 0; i < static_cast<uint32_t>(mUniformOpaques.size()); ++i)
+            {
+              if(samplerPositions[i] == -1 &&
+                 strncmp(token, mUniformOpaques[i].name.c_str(), mUniformOpaques[i].name.size()) == 0)
+              {
+                samplerPositions[i] = mUniformOpaques[i].offset = samplerPosition++;
+                found                                           = true;
+                break;
+              }
+            }
+
+            if(!found)
+            {
+              DALI_LOG_ERROR("Sampler uniform %s declared but not used in the shader\n", token);
+            }
+            break;
+          }
+        }
+
+        token = strtok_r(nullptr, DELIMITERS, &nextPtr);
+      }
+
+      uniform = strstr(uniform, UNIFORM);
+    }
+    free(shaderStr);
+  }
+  std::sort(mUniformOpaques.begin(), mUniformOpaques.end(), [](const UniformInfo& a, const UniformInfo& b) { return a.offset < b.offset; });
+}
+
 } // namespace Dali::Graphics::GLES
index c54c505..3a4a781 100644 (file)
@@ -210,11 +210,11 @@ public:
       arraySize(arraySize),
       type(type){};
 
-    uint32_t location; ///< Location of uniform
-    uint32_t size;     ///< size of uniform
-    uint32_t offset;   ///< offset of uniform within UBO
+    uint32_t location;  ///< Location of uniform
+    uint32_t size;      ///< size of uniform
+    uint32_t offset;    ///< offset of uniform within UBO
     uint32_t arraySize; ///< number of array elements (1 for non-arrays)
-    GLenum   type;     ///< type of uniform
+    GLenum   type;      ///< type of uniform
   };
 
   /**
@@ -239,6 +239,11 @@ public:
    */
   void BuildUniformBlockReflection();
 
+  /**
+   * Sort the samplers by their lexical location in the frag shader source code.
+   */
+  void SortOpaques();
+
 protected:
   Reflection(Reflection&&) = default;
   Reflection& operator=(Reflection&&) = default;
index a5e0a25..bb5d680 100644 (file)
 
 // CLASS HEADER
 #include "gles-graphics-render-pass.h"
+
+namespace Dali::Graphics::GLES
+{
+struct RenderPass::Impl
+{
+  Impl()  = default;
+  ~Impl() = default;
+
+  std::vector<AttachmentDescription> attachments;
+};
+
+RenderPass::RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: RenderPassResource(createInfo, controller)
+{
+  mImpl = std::make_unique<Impl>();
+
+  // copy attachment description
+  if(createInfo.attachments)
+  {
+    mImpl->attachments.insert(mImpl->attachments.end(), createInfo.attachments->begin(), createInfo.attachments->end());
+    mCreateInfo.attachments = &mImpl->attachments;
+  }
+}
+
+} // namespace Dali::Graphics::GLES
index 53cc572..1186f61 100644 (file)
@@ -37,10 +37,7 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-  : RenderPassResource(createInfo, controller)
-  {
-  }
+  RenderPass(const Graphics::RenderPassCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
 
   /**
    * @brief Destructor
@@ -73,6 +70,10 @@ public:
   {
     // TODO: Implement moving to the discard queue
   }
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> mImpl{nullptr};
 };
 
 } // namespace Dali::Graphics::GLES
index 090bb71..efdaeb2 100644 (file)
 
 // CLASS HEADER
 #include "gles-graphics-render-target.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/adaptor-framework/render-surface-interface.h>
+#include "egl-graphics-controller.h"
+#include "gles-graphics-framebuffer.h"
+
+namespace Dali::Graphics::GLES
+{
+struct RenderTarget::Impl
+{
+  Impl(EglGraphicsController& controller)
+  : controller(controller){};
+
+  ~Impl() = default;
+
+  EglGraphicsController& controller;
+};
+
+RenderTarget::RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: RenderTargetResource(createInfo, controller)
+{
+  mImpl = std::make_unique<Impl>(controller);
+
+  if(createInfo.surface)
+  {
+    controller.CreateSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(createInfo.surface));
+  }
+}
+
+RenderTarget::~RenderTarget()
+{
+  if(mCreateInfo.surface)
+  {
+    mImpl->controller.DeleteSurfaceContext(static_cast<Dali::RenderSurfaceInterface*>(mCreateInfo.surface));
+  }
+}
+
+GLES::Framebuffer* RenderTarget::GetFramebuffer() const
+{
+  return static_cast<GLES::Framebuffer*>(mCreateInfo.framebuffer);
+}
+
+Surface* RenderTarget::GetSurface() const
+{
+  return mCreateInfo.surface;
+}
+
+} // namespace Dali::Graphics::GLES
\ No newline at end of file
index 57169d8..6a9fcab 100644 (file)
@@ -27,6 +27,7 @@
 
 namespace Dali::Graphics::GLES
 {
+class Framebuffer;
 using RenderTargetResource = Resource<Graphics::RenderTarget, Graphics::RenderTargetCreateInfo>;
 
 class RenderTarget : public RenderTargetResource
@@ -37,15 +38,12 @@ public:
    * @param[in] createInfo Valid createInfo structure
    * @param[in] controller Reference to the controller
    */
-  RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-  : RenderTargetResource(createInfo, controller)
-  {
-  }
+  RenderTarget(const Graphics::RenderTargetCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
 
   /**
    * @brief Destructor
    */
-  ~RenderTarget() override = default;
+  ~RenderTarget() override;
 
   /**
    * @brief Called when GL resources are destroyed
@@ -73,6 +71,20 @@ public:
   {
     // TODO: Implement moving to the discard queue
   }
+
+  /**
+   * @brief Returns framebuffer associated with the render target
+   */
+  GLES::Framebuffer* GetFramebuffer() const;
+
+  /**
+   * @brief Returns surface associated with the render target
+   */
+  Surface* GetSurface() const;
+
+private:
+  struct Impl;
+  std::unique_ptr<Impl> mImpl{nullptr};
 };
 
 } // namespace Dali::Graphics::GLES
index cf91080..a2c9617 100644 (file)
@@ -43,6 +43,49 @@ const int32_t DALI_MAGNIFY_DEFAULT = GL_LINEAR;
 
 namespace Dali::Graphics::GLES
 {
+struct ColorConversion
+{
+  Format srcFormat;
+  Format destFormat;
+  std::vector<uint8_t> (*pConversionFunc)(const void*, uint32_t, uint32_t, uint32_t, uint32_t);
+  void (*pConversionWriteFunc)(const void*, uint32_t, uint32_t, uint32_t, uint32_t, void*);
+};
+
+inline void WriteRGB32ToRGBA32(const void* pData, uint32_t sizeInBytes, uint32_t width, uint32_t height, uint32_t rowStride, void* pOutput)
+{
+  auto inData  = reinterpret_cast<const uint8_t*>(pData);
+  auto outData = reinterpret_cast<uint8_t*>(pOutput);
+  auto outIdx  = 0u;
+  for(auto i = 0u; i < sizeInBytes; i += 3)
+  {
+    outData[outIdx]     = inData[i];
+    outData[outIdx + 1] = inData[i + 1];
+    outData[outIdx + 2] = inData[i + 2];
+    outData[outIdx + 3] = 0xff;
+    outIdx += 4;
+  }
+}
+
+/**
+ * Converts RGB to RGBA
+ */
+inline std::vector<uint8_t> ConvertRGB32ToRGBA32(const void* pData, uint32_t sizeInBytes, uint32_t width, uint32_t height, uint32_t rowStride)
+{
+  std::vector<uint8_t> rgbaBuffer{};
+  rgbaBuffer.resize(width * height * 4);
+  WriteRGB32ToRGBA32(pData, sizeInBytes, width, height, rowStride, &rgbaBuffer[0]);
+  return rgbaBuffer;
+}
+
+/**
+ * Format conversion table
+ */
+static const std::vector<ColorConversion> COLOR_CONVERSION_TABLE = {
+  {Format::R8G8B8_UNORM, Format::R8G8B8A8_UNORM, ConvertRGB32ToRGBA32, WriteRGB32ToRGBA32}};
+
+/**
+ * Constructor
+ */
 Texture::Texture(const Graphics::TextureCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
 : TextureResource(createInfo, controller)
 {
@@ -127,7 +170,8 @@ bool Texture::InitializeTexture()
 
   GLuint texture{0};
 
-  mGlTarget = GLTextureTarget(mCreateInfo.textureType).target;
+  mGlTarget     = GLTextureTarget(mCreateInfo.textureType).target;
+  mIsCompressed = Graphics::GLES::FormatCompression(mCreateInfo.format).compressed;
 
   switch(mCreateInfo.textureType)
   {
@@ -144,24 +188,93 @@ bool Texture::InitializeTexture()
         gl->BindTexture(GL_TEXTURE_2D, texture);
 
         // Allocate memory for the texture
-        gl->TexImage2D(GL_TEXTURE_2D,
-                       0,
-                       format.format,
-                       mCreateInfo.size.width,
-                       mCreateInfo.size.height,
-                       0,
-                       format.format,
-                       format.type,
-                       (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+        if(!mIsCompressed)
+        {
+          gl->TexImage2D(GL_TEXTURE_2D,
+                         0,
+                         format.internalFormat,
+                         mCreateInfo.size.width,
+                         mCreateInfo.size.height,
+                         0,
+                         format.format,
+                         format.type,
+                         (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+        }
+        else
+        {
+          gl->CompressedTexImage2D(GL_TEXTURE_2D,
+                                   0,
+                                   format.internalFormat,
+                                   mCreateInfo.size.width,
+                                   mCreateInfo.size.height,
+                                   0,
+                                   mCreateInfo.dataSize,
+                                   (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+        }
 
         // Clear staging buffer if there was any
         mStagingBuffer.clear();
-
         mTextureId = texture;
 
         // Default texture filtering (to be set later via command buffer binding)
         gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
         gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
+        gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+      }
+      break;
+    }
+    // Texture Cubemap
+    case Graphics::TextureType::TEXTURE_CUBEMAP:
+    {
+      Graphics::GLES::GLTextureFormatType format(mCreateInfo.format);
+
+      if(format.format && format.type)
+      {
+        // Bind texture
+        gl->GenTextures(1, &texture);
+        gl->BindTexture(GL_TEXTURE_CUBE_MAP, texture);
+        gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
+
+        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, Graphics::GLES::GLSamplerFilterAndMipMapMode(Graphics::SamplerFilter::LINEAR, SamplerMipmapMode::NONE));
+        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_WRAP_DEFAULT);
+        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_WRAP_DEFAULT);
+
+        // Allocate memory for the texture
+        for(uint32_t i = 0; i < 6; ++i)
+        {
+          if(!mIsCompressed)
+          {
+            gl->TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+                           0,
+                           format.internalFormat,
+                           mCreateInfo.size.width,
+                           mCreateInfo.size.height,
+                           0,
+                           format.format,
+                           format.type,
+                           (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+          }
+          else
+          {
+            gl->CompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
+                                     0,
+                                     format.internalFormat,
+                                     mCreateInfo.size.width,
+                                     mCreateInfo.size.height,
+                                     0,
+                                     mCreateInfo.dataSize,
+                                     (mCreateInfo.data ? mStagingBuffer.data() : nullptr));
+          }
+        }
+
+        // Clear staging buffer if there was any
+        mStagingBuffer.clear();
+
+        mTextureId = texture;
+
+        gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
       }
       break;
     }
@@ -217,7 +330,6 @@ void Texture::Bind(const TextureBinding& binding) const
     const auto& samplerCreateInfo = sampler->GetCreateInfo();
 
     auto mipMapMode = samplerCreateInfo.mipMapMode;
-    mipMapMode      = Graphics::SamplerMipmapMode::NONE; // @todo Remove when mip-map generation is supported
 
     gl->TexParameteri(mGlTarget, GL_TEXTURE_MIN_FILTER, GLSamplerFilterAndMipMapMode(samplerCreateInfo.minFilter, mipMapMode).glFilter);
     gl->TexParameteri(mGlTarget, GL_TEXTURE_MAG_FILTER, GLSamplerFilter(samplerCreateInfo.magFilter).glFilter);
@@ -239,6 +351,11 @@ void Texture::Bind(const TextureBinding& binding) const
       gl->TexParameteri(mGlTarget, GL_TEXTURE_WRAP_R, GL_WRAP_DEFAULT);
     }
   }
+
+  if(mMaxMipMapLevel)
+  {
+    gl->TexParameteri(mGlTarget, GL_TEXTURE_MAX_LEVEL, mMaxMipMapLevel);
+  }
 }
 
 void Texture::Prepare()
@@ -258,4 +375,31 @@ void Texture::Prepare()
   }
 }
 
+/**
+ * This function tests whether format is supported by the driver. If possible it applies
+ * format conversion to suitable supported pixel format.
+ */
+bool Texture::TryConvertPixelData(const void* pData, Graphics::Format srcFormat, Graphics::Format destFormat, uint32_t sizeInBytes, uint32_t width, uint32_t height, std::vector<uint8_t>& outputBuffer)
+{
+  // No need to convert
+  if(srcFormat == destFormat)
+  {
+    return false;
+  }
+
+  auto it = std::find_if(COLOR_CONVERSION_TABLE.begin(), COLOR_CONVERSION_TABLE.end(), [&](auto& item) {
+    return item.srcFormat == srcFormat && item.destFormat == destFormat;
+  });
+
+  // No suitable format, return empty array
+  if(it == COLOR_CONVERSION_TABLE.end())
+  {
+    return false;
+  }
+  auto begin = reinterpret_cast<const uint8_t*>(pData);
+
+  outputBuffer = std::move(it->pConversionFunc(begin, sizeInBytes, width, height, 0u));
+  return !outputBuffer.empty();
+}
+
 } // namespace Dali::Graphics::GLES
index c6e46dc..dc7d921 100644 (file)
@@ -88,15 +88,63 @@ public:
    */
   void Prepare();
 
-protected:
+  /**
+   * @brief Returns the GL Target
+   * @return the Gl target
+   */
+  [[nodiscard]] GLenum GetGlTarget() const
+  {
+    return mGlTarget;
+  }
+
+  /**
+   * @brief Sets the maximum mipmap level
+   * @param[in] maxMipMapLevel The maximum mipmap level
+   */
+  void SetMaxMipMapLevel(const uint32_t maxMipMapLevel)
+  {
+    mMaxMipMapLevel = maxMipMapLevel;
+  }
+
+  /**
+   * @brief Returns the maximum mipmap level
+   * @return The maximum mipmap level
+   */
+  [[nodiscard]] uint32_t GetMaxMipMapLevel() const
+  {
+    return mMaxMipMapLevel;
+  }
+
+  /**
+   * @param pData  Input data
+   * @param sizeInBytes Size of the input data in bytes
+   * @param width  Width of the output buffer
+   * @param height height of the output buffer
+   * @param outputBuffer The buffer to write to
+   * @return true if converted, or false otherwise
+   */
+  bool TryConvertPixelData(const void* pData, Graphics::Format srcFormat, Graphics::Format destFormat, uint32_t sizeInBytes, uint32_t width, uint32_t height, std::vector<uint8_t>& outputBuffer);
+
+  bool InitializeNativeImage();
+
+  bool InitializeTexture();
+
+  Format ValidateFormat(Format sourceFormat);
+
+  bool IsCompressed()
+  {
+    return mIsCompressed;
+  }
+
 private:
   std::vector<char> mStagingBuffer;
   uint32_t          mTextureId{0u};
   GLenum            mGlTarget{0u};
+  uint32_t          mMaxMipMapLevel{0u};
   void*             mGLOwnerContext{nullptr};
-  bool              InitializeNativeImage();
-  bool              InitializeTexture();
+  bool              mIsCompressed{false};
 };
+
 } // namespace Dali::Graphics::GLES
 
 #endif
index b8b6fcd..35893c8 100644 (file)
@@ -9,6 +9,10 @@
 namespace Dali::Graphics::GLES
 {
 class Buffer;
+class RenderPass;
+class RenderTarget;
+class Framebuffer;
+
 // Conversion functions
 /**
  * Stucture delivers format and type that can be used
@@ -544,7 +548,7 @@ struct GLTextureFormatType
       case Graphics::Format::R16G16B16_SFLOAT:
       {
         // GLES 3.0 floating point formats.
-        Assign(GL_RGB, GL_HALF_FLOAT);
+        AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_HALF_FLOAT); // DALi uses compact internal format
         break;
       }
       case Graphics::Format::R16G16B16A16_UNORM:
@@ -624,8 +628,7 @@ struct GLTextureFormatType
       }
       case Graphics::Format::R32G32B32_SFLOAT:
       {
-        // GLES 3.0 floating point formats.
-        Assign(GL_RGB, GL_FLOAT);
+        AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_FLOAT); // DALi uses compact internal format
         break;
       }
       case Graphics::Format::R32G32B32A32_UINT:
@@ -703,6 +706,11 @@ struct GLTextureFormatType
         Assign(0, 0);
         break;
       }
+      case Graphics::Format::R11G11B10_UFLOAT_PACK32:
+      {
+        AssignInternal(GL_RGB, GL_R11F_G11F_B10F, GL_FLOAT);
+        break;
+      }
       case Graphics::Format::B10G11R11_UFLOAT_PACK32:
       {
         Assign(0, 0);
@@ -727,7 +735,7 @@ struct GLTextureFormatType
       case Graphics::Format::D32_SFLOAT:
       {
         // GLES 3.0 depth and stencil formats
-        Assign(GL_DEPTH_COMPONENT, GL_FLOAT);
+        AssignInternal(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT32F, GL_FLOAT);
         break;
       }
       case Graphics::Format::S8_UINT:
@@ -743,7 +751,7 @@ struct GLTextureFormatType
       case Graphics::Format::D24_UNORM_S8_UINT:
       {
         // GLES 3.0 depth and stencil formats
-        Assign(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
+        AssignInternal(GL_DEPTH_STENCIL, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8);
         break;
       }
       case Graphics::Format::D32_SFLOAT_S8_UINT:
@@ -1104,14 +1112,87 @@ struct GLTextureFormatType
 
   constexpr inline void Assign(uint32_t f, uint32_t t)
   {
-    format = f;
-    type   = t;
+    format         = f;
+    internalFormat = f;
+    type           = t;
+  }
+  constexpr inline void AssignInternal(uint32_t f, uint32_t i, uint32_t t)
+  {
+    format         = f;
+    internalFormat = i;
+    type           = t;
   }
 
   uint32_t format{0};
+  uint32_t internalFormat{0};
   uint32_t type{0};
 };
 
+struct FormatCompression
+{
+  /**
+   * Constuctor from Graphics::Format
+   * @param value
+   */
+  constexpr explicit FormatCompression(Graphics::Format value)
+  {
+    switch(value)
+    {
+      case Graphics::Format::ETC2_R8G8B8_UNORM_BLOCK:
+      case Graphics::Format::ETC2_R8G8B8_SRGB_BLOCK:
+      case Graphics::Format::ETC2_R8G8B8A1_UNORM_BLOCK:
+      case Graphics::Format::ETC2_R8G8B8A1_SRGB_BLOCK:
+      case Graphics::Format::ETC2_R8G8B8A8_UNORM_BLOCK:
+      case Graphics::Format::ETC2_R8G8B8A8_SRGB_BLOCK:
+      case Graphics::Format::EAC_R11_UNORM_BLOCK:
+      case Graphics::Format::EAC_R11_SNORM_BLOCK:
+      case Graphics::Format::EAC_R11G11_UNORM_BLOCK:
+      case Graphics::Format::EAC_R11G11_SNORM_BLOCK:
+      case Graphics::Format::ASTC_4x4_UNORM_BLOCK:
+      case Graphics::Format::ASTC_4x4_SRGB_BLOCK:
+      case Graphics::Format::ASTC_5x4_UNORM_BLOCK:
+      case Graphics::Format::ASTC_5x4_SRGB_BLOCK:
+      case Graphics::Format::ASTC_5x5_UNORM_BLOCK:
+      case Graphics::Format::ASTC_5x5_SRGB_BLOCK:
+      case Graphics::Format::ASTC_6x5_UNORM_BLOCK:
+      case Graphics::Format::ASTC_6x5_SRGB_BLOCK:
+      case Graphics::Format::ASTC_6x6_UNORM_BLOCK:
+      case Graphics::Format::ASTC_6x6_SRGB_BLOCK:
+      case Graphics::Format::ASTC_8x5_UNORM_BLOCK:
+      case Graphics::Format::ASTC_8x5_SRGB_BLOCK:
+      case Graphics::Format::ASTC_8x6_UNORM_BLOCK:
+      case Graphics::Format::ASTC_8x6_SRGB_BLOCK:
+      case Graphics::Format::ASTC_8x8_UNORM_BLOCK:
+      case Graphics::Format::ASTC_8x8_SRGB_BLOCK:
+      case Graphics::Format::ASTC_10x5_UNORM_BLOCK:
+      case Graphics::Format::ASTC_10x5_SRGB_BLOCK:
+      case Graphics::Format::ASTC_10x6_UNORM_BLOCK:
+      case Graphics::Format::ASTC_10x6_SRGB_BLOCK:
+      case Graphics::Format::ASTC_10x8_UNORM_BLOCK:
+      case Graphics::Format::ASTC_10x8_SRGB_BLOCK:
+      case Graphics::Format::ASTC_10x10_UNORM_BLOCK:
+      case Graphics::Format::ASTC_10x10_SRGB_BLOCK:
+      case Graphics::Format::ASTC_12x10_UNORM_BLOCK:
+      case Graphics::Format::ASTC_12x10_SRGB_BLOCK:
+      case Graphics::Format::ASTC_12x12_UNORM_BLOCK:
+      case Graphics::Format::ASTC_12x12_SRGB_BLOCK:
+      case Graphics::Format::PVRTC1_2BPP_UNORM_BLOCK_IMG:
+      case Graphics::Format::PVRTC1_4BPP_UNORM_BLOCK_IMG:
+      case Graphics::Format::PVRTC2_2BPP_UNORM_BLOCK_IMG:
+      case Graphics::Format::PVRTC2_4BPP_UNORM_BLOCK_IMG:
+      case Graphics::Format::PVRTC1_2BPP_SRGB_BLOCK_IMG:
+      case Graphics::Format::PVRTC1_4BPP_SRGB_BLOCK_IMG:
+      case Graphics::Format::PVRTC2_2BPP_SRGB_BLOCK_IMG:
+      case Graphics::Format::PVRTC2_4BPP_SRGB_BLOCK_IMG:
+        compressed = true;
+        break;
+      default:
+        break;
+    }
+  }
+  bool compressed{false};
+};
+
 struct GLSamplerFilter
 {
   constexpr explicit GLSamplerFilter(Graphics::SamplerFilter filter)
@@ -1331,6 +1412,76 @@ struct GLAddressMode
   GLenum texParameter{GL_CLAMP_TO_EDGE};
 };
 
+struct GLCompareOp
+{
+  constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
+  {
+    switch(compareOp)
+    {
+      case Graphics::CompareOp::NEVER:
+        op = GL_NEVER;
+        break;
+      case Graphics::CompareOp::LESS:
+        op = GL_LESS;
+        break;
+      case Graphics::CompareOp::EQUAL:
+        op = GL_EQUAL;
+        break;
+      case Graphics::CompareOp::LESS_OR_EQUAL:
+        op = GL_LEQUAL;
+        break;
+      case Graphics::CompareOp::GREATER:
+        op = GL_GREATER;
+        break;
+      case Graphics::CompareOp::NOT_EQUAL:
+        op = GL_NOTEQUAL;
+        break;
+      case Graphics::CompareOp::GREATER_OR_EQUAL:
+        op = GL_GEQUAL;
+        break;
+      case Graphics::CompareOp::ALWAYS:
+        op = GL_ALWAYS;
+        break;
+    }
+  }
+  GLenum op{GL_LESS};
+};
+
+struct GLStencilOp
+{
+  constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
+  {
+    switch(stencilOp)
+    {
+      case Graphics::StencilOp::KEEP:
+        op = GL_KEEP;
+        break;
+      case Graphics::StencilOp::ZERO:
+        op = GL_ZERO;
+        break;
+      case Graphics::StencilOp::REPLACE:
+        op = GL_REPLACE;
+        break;
+      case Graphics::StencilOp::INCREMENT_AND_CLAMP:
+        op = GL_INCR;
+        break;
+      case Graphics::StencilOp::DECREMENT_AND_CLAMP:
+        op = GL_DECR;
+        break;
+      case Graphics::StencilOp::INVERT:
+        op = GL_INVERT;
+        break;
+      case Graphics::StencilOp::INCREMENT_AND_WRAP:
+        op = GL_INCR_WRAP;
+        break;
+      case Graphics::StencilOp::DECREMENT_AND_WRAP:
+        op = GL_DECR_WRAP;
+        break;
+    }
+  }
+  GLenum op{GL_KEEP};
+};
+
 /**
  * @brief Descriptor of single buffer binding within
  * command buffer.
@@ -1866,6 +2017,17 @@ enum class GLESVersion
   GLES_32 = 32
 };
 
+/**
+ * The descriptor of BeginRenderPass command
+ */
+struct BeginRenderPassDescriptor
+{
+  const GLES::RenderPass*   renderPass{};
+  const GLES::RenderTarget* renderTarget{};
+  Rect2D                    renderArea{};
+  std::vector<ClearValue>   clearValues{};
+};
+
 } // namespace Dali::Graphics::GLES
 
 #endif //DALI_GRAPHICS_API_TYPES_H
diff --git a/dali/internal/graphics/gles-impl/gles-sync-object.cpp b/dali/internal/graphics/gles-impl/gles-sync-object.cpp
new file mode 100644 (file)
index 0000000..f44fdc3
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 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.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/gles-impl/gles-sync-object.h>
+
+// EXTERNAL HEADERS
+
+// INTERNAL HEADERS
+#include <dali/internal/graphics/gles-impl/egl-graphics-controller.h>
+
+namespace Dali::Graphics::GLES
+{
+SyncObject::SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: SyncObjectResource(createInfo, controller),
+  mGlSyncObject(0)
+{
+}
+
+SyncObject::~SyncObject()
+{
+}
+
+void SyncObject::DestroyResource()
+{
+}
+
+bool SyncObject::InitializeResource()
+{
+  // Initialized not from a resource queue, but from a command.
+  auto gl = mController.GetGL();
+  if(gl)
+  {
+    mGlSyncObject = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+  }
+  return true;
+}
+
+void SyncObject::DiscardResource()
+{
+  // Called from custom deleter.
+  // Don't use discard queue, drop immediately.
+  auto gl = mController.GetGL();
+  if(gl)
+  {
+    gl->DeleteSync(mGlSyncObject);
+  }
+  mGlSyncObject = 0;
+}
+
+bool SyncObject::IsSynced()
+{
+  auto gl = mController.GetGL();
+  if(gl && mGlSyncObject)
+  {
+    GLenum result = gl->ClientWaitSync(mGlSyncObject, 0, 0ull);
+    return result == GL_ALREADY_SIGNALED || result == GL_CONDITION_SATISFIED;
+  }
+  return false;
+}
+
+} // namespace Dali::Graphics::GLES
diff --git a/dali/internal/graphics/gles-impl/gles-sync-object.h b/dali/internal/graphics/gles-impl/gles-sync-object.h
new file mode 100644 (file)
index 0000000..32a89f6
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef DALI_GRAPHICS_GLES_SYNC_OBJECT_H
+#define DALI_GRAPHICS_GLES_SYNC_OBJECT_H
+
+/*
+ * Copyright (c) 2021 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.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-sync-object-create-info.h>
+#include <dali/graphics-api/graphics-sync-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/graphics/gles-impl/gles-graphics-resource.h>
+
+namespace Dali::Internal::Adaptor
+{
+class EglSyncImplementation;
+class EglSyncObject;
+} // namespace Dali::Internal::Adaptor
+
+namespace Dali::Graphics::GLES
+{
+using SyncObjectResource = Resource<Graphics::SyncObject, Graphics::SyncObjectCreateInfo>;
+
+class SyncObject : public SyncObjectResource
+{
+public:
+  /**
+   * @brief Constructor
+   * @param[in] createInfo Valid createInfo structure
+   * @param[in] controller Reference to the controller
+   */
+  SyncObject(const Graphics::SyncObjectCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
+
+  /**
+   * @brief Destructor
+   */
+  ~SyncObject() override;
+
+  /**
+   * @brief Called when GL resources are destroyed
+   */
+  void DestroyResource() override;
+
+  /**
+   * @brief Called when initializing the resource
+   *
+   * @return True on success
+   */
+  bool InitializeResource() override;
+
+  /**
+   * @brief Called when UniquePtr<> on client-side dies
+   */
+  void DiscardResource() override;
+
+  /**
+   * Determine if the synchronisation object has been signalled.
+   *
+   * @return false if the sync object has not been signalled, true if it has been signalled (and
+   * can now be destroyed)
+   */
+  bool IsSynced() override;
+
+private:
+  GLsync mGlSyncObject;
+};
+
+} // namespace Dali::Graphics::GLES
+
+#endif //DALI_GRAPHICS_GLES_SYNC_OBJECT_H
index f92af32..4c2e45c 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/integration-api/gl-defines.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/graphics/common/graphics-interface.h>
 #include "egl-graphics-controller.h"
 #include "gles-graphics-buffer.h"
 
@@ -44,7 +45,7 @@ Memory2::Memory2(const Graphics::MapTextureInfo& mapInfo, EglGraphicsController&
 
 Memory2::~Memory2()
 {
-  //Unlock(true);
+  Unlock(true);
 }
 
 void* Memory2::LockRegion(uint32_t offset, uint32_t size)
@@ -56,14 +57,14 @@ void* Memory2::LockRegion(uint32_t offset, uint32_t size)
     auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
     if(buffer->IsCPUAllocated())
     {
-      using Ptr = char*;
-      mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
+      using Ptr           = char*;
+      mMappedPointer      = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
       mIsAllocatedLocally = false;
     }
     else
     {
-      auto retval    = malloc(size);
-      mMappedPointer = retval;
+      auto retval         = malloc(size);
+      mMappedPointer      = retval;
       mIsAllocatedLocally = true;
     }
   }
@@ -76,7 +77,7 @@ void Memory2::Unlock(bool flush)
   auto gl = mController.GetGL();
 
   // for buffer...
-  if(mMapObjectType == MapObjectType::BUFFER&& mMappedPointer)
+  if(mMapObjectType == MapObjectType::BUFFER && mMappedPointer)
   {
     auto buffer = static_cast<GLES::Buffer*>(mMapBufferInfo.buffer);
     if(!buffer->IsCPUAllocated())
index 7085276..8b3908d 100644 (file)
@@ -23,6 +23,7 @@
 #include <dali/integration-api/gl-defines.h>
 
 // INTERNAL INCLUDES
+#include <dali/internal/graphics/common/graphics-interface.h>
 #include "egl-graphics-controller.h"
 
 namespace Dali::Graphics::GLES
@@ -56,8 +57,8 @@ void* Memory3::LockRegion(uint32_t offset, uint32_t size)
 
     if(buffer->IsCPUAllocated())
     {
-      using Ptr = char*;
-      return Ptr(buffer->GetCPUAllocatedAddress()) + offset;
+      using Ptr      = char*;
+      mMappedPointer = Ptr(buffer->GetCPUAllocatedAddress()) + offset;
     }
     else
     {
@@ -91,6 +92,8 @@ void Memory3::Unlock(bool flush)
   {
     Flush();
   }
+
+  mMappedPointer = nullptr;
 }
 
 void Memory3::Flush()
index e1dd665..d19f824 100644 (file)
@@ -62,6 +62,8 @@ void EglGraphics::SetGlesVersion(const int32_t glesVersion)
   }
 
   mGLES->SetGlesVersion(glesVersion);
+
+  mGraphicsController.SetGLESVersion(static_cast<Graphics::GLES::GLESVersion>(glesVersion));
 }
 
 void EglGraphics::SetIsSurfacelessContextSupported(const bool isSupported)
@@ -71,6 +73,8 @@ void EglGraphics::SetIsSurfacelessContextSupported(const bool isSupported)
 
 void EglGraphics::ActivateResourceContext()
 {
+  mGraphicsController.ActivateResourceContext();
+
   if(mEglImplementation && mEglImplementation->IsSurfacelessContextSupported())
   {
     // Make the shared surfaceless context as current before rendering
@@ -78,6 +82,17 @@ void EglGraphics::ActivateResourceContext()
   }
 }
 
+void EglGraphics::ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface)
+{
+  mGraphicsController.ActivateSurfaceContext(surface);
+
+  if(surface)
+  {
+    surface->InitializeGraphics();
+    surface->MakeContextCurrent();
+  }
+}
+
 void EglGraphics::SetFirstFrameAfterResume()
 {
   if(mEglImplementation)
@@ -91,7 +106,7 @@ void EglGraphics::Initialize()
   EglInitialize();
 
   // Sync and context helper require EGL to be initialized first (can't execute in the constructor)
-  mGraphicsController.Initialize(*mEglSync.get(), *mEglContextHelper.get());
+  mGraphicsController.Initialize(*mEglSync.get(), *mEglContextHelper.get(), *this);
 }
 
 void EglGraphics::Initialize(bool depth, bool stencil, bool partialRendering, int msaa)
index 30f6e58..8c8d80c 100644 (file)
@@ -84,6 +84,13 @@ public:
   void ActivateResourceContext() override;
 
   /**
+   * Activate the surface context
+   *
+   * @param[in] surface The surface whose context to be switched to.
+   */
+  void ActivateSurfaceContext(Dali::RenderSurfaceInterface* surface) override;
+
+  /**
    * Inform graphics interface that this is the first frame after a resume.
    * (For debug only)
    */
index 24f2434..8398c1b 100644 (file)
@@ -113,7 +113,7 @@ void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
   mEglImplementation = eglImpl;
 }
 
-Integration::GlSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
 {
   DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
   if(mSyncInitialized == false)
@@ -121,12 +121,12 @@ Integration::GlSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObj
     InitializeEglSync();
   }
 
-  EglSyncObject* syncObject = new EglSyncObject(*mEglImplementation);
+  auto* syncObject = new EglSyncObject(*mEglImplementation);
   mSyncObjects.PushBack(syncObject);
   return syncObject;
 }
 
-void EglSyncImplementation::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
 {
   DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
 
@@ -143,8 +143,7 @@ void EglSyncImplementation::DestroySyncObject(Integration::GlSyncAbstraction::Sy
       break;
     }
   }
-  EglSyncObject* eglSyncObject = static_cast<EglSyncObject*>(syncObject);
-  delete eglSyncObject;
+  delete static_cast<EglSyncObject*>(syncObject);
 }
 
 void EglSyncImplementation::InitializeEglSync()
@@ -204,21 +203,16 @@ void EglSyncImplementation::Initialize(EglImplementation* eglImpl)
   mEglImplementation = eglImpl;
 }
 
-Integration::GlSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
+Integration::GraphicsSyncAbstraction::SyncObject* EglSyncImplementation::CreateSyncObject()
 {
   DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
   return new EglSyncObject(*mEglImplementation);
 }
 
-void EglSyncImplementation::DestroySyncObject(Integration::GlSyncAbstraction::SyncObject* syncObject)
+void EglSyncImplementation::DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject)
 {
   DALI_ASSERT_ALWAYS(mEglImplementation && "Sync Implementation not initialized");
-
-  // The abstraction's virtual destructor is protected, so that Core can't delete the sync objects
-  // directly (This object also needs removing from the mSyncObject container in the ARM
-  // implementation above). We therefore need to cast to the actual implementation object first.
-  EglSyncObject* eglSyncObject = static_cast<EglSyncObject*>(syncObject);
-  delete eglSyncObject;
+  delete static_cast<EglSyncObject*>(syncObject);
 }
 
 void EglSyncImplementation::InitializeEglSync()
index 218e647..6a29ca9 100644 (file)
  */
 
 // EXTERNAL INCLUDES
-#include <dali/integration-api/gl-sync-abstraction.h>
-#include <dali/internal/graphics/common/egl-include.h>
 #include <dali/public-api/common/dali-vector.h>
 
 // INTERNAL INCLUDES
 #include <dali/public-api/dali-adaptor-common.h>
 
+#include <dali/integration-api/graphics-sync-abstraction.h>
+#include <dali/internal/graphics/common/egl-include.h>
+
 namespace Dali
 {
 namespace Internal
@@ -34,7 +35,7 @@ namespace Adaptor
 {
 class EglImplementation;
 
-class EglSyncObject : public Integration::GlSyncAbstraction::SyncObject
+class EglSyncObject : public Integration::GraphicsSyncAbstraction::SyncObject
 {
 public:
   /**
@@ -47,9 +48,6 @@ public:
    */
   virtual ~EglSyncObject();
 
-  /**
-   * @copydoc Dali::Integration::GlSyncAbstraction::SyncObject::IsSynced()
-   */
   bool IsSynced() override;
 
 private:
@@ -62,14 +60,13 @@ private:
 };
 
 /**
- * GlSyncImplementation is a concrete implementation for GlSyncAbstraction.
  * It provides fence syncing for resources such as FrameBuffers using EGL extensions
  *
  * Sync objects are created in the render thread after a render instruction
  * has been processed (i.e. GL draw calls have completed for a given FB), and
- * tested in the update
+ * tested in the update thread.
  */
-class EglSyncImplementation : public Integration::GlSyncAbstraction
+class EglSyncImplementation : public Integration::GraphicsSyncAbstraction
 {
 public:
   /**
@@ -80,7 +77,7 @@ public:
   /**
    * Destructor
    */
-  virtual ~EglSyncImplementation();
+  ~EglSyncImplementation();
 
   /**
    * Initialize the sync object with the Egl implementation.
@@ -89,14 +86,14 @@ public:
   void Initialize(EglImplementation* impl);
 
   /**
-   * @copydoc Dali::Integration::GlSyncAbstraction::CreateSyncObject()
+   * Create a sync object that can be polled
    */
-  SyncObject* CreateSyncObject() override;
+  Integration::GraphicsSyncAbstraction::SyncObject* CreateSyncObject() override;
 
   /**
-   * @copydoc Dali::Integration::GlSyncAbstraction::DestroySyncObject()
+   * Destroy a sync object
    */
-  void DestroySyncObject(SyncObject* syncObject) override;
+  void DestroySyncObject(Integration::GraphicsSyncAbstraction::SyncObject* syncObject) override;
 
 private:
   /**
index dbf492c..8c7139d 100644 (file)
 #include <dali/internal/imaging/common/loader-astc.h>
 #include <dali/internal/imaging/common/loader-bmp.h>
 #include <dali/internal/imaging/common/loader-gif.h>
-#include <dali/internal/imaging/common/loader-webp.h>
 #include <dali/internal/imaging/common/loader-ico.h>
 #include <dali/internal/imaging/common/loader-jpeg.h>
 #include <dali/internal/imaging/common/loader-ktx.h>
 #include <dali/internal/imaging/common/loader-png.h>
 #include <dali/internal/imaging/common/loader-wbmp.h>
+#include <dali/internal/imaging/common/loader-webp.h>
 #include <dali/internal/system/common/file-reader.h>
 
 using namespace Dali::Integration;
index 9c3f526..e4c3fe0 100644 (file)
@@ -328,6 +328,7 @@ bool HasChannel(Dali::Pixel::Format pixelFormat, Channel channel)
     case Dali::Pixel::BGR8888:
     case Dali::Pixel::RGB16F:
     case Dali::Pixel::RGB32F:
+    case Dali::Pixel::R11G11B10F:
     {
       return (channel == RED || channel == GREEN || channel == BLUE);
     }
index 41618eb..75417e4 100644 (file)
@@ -38,7 +38,7 @@ namespace Adaptor
 {
 namespace
 {
-const char* SAMPLER_TYPE    = "samplerExternalOES";
+const char* SAMPLER_TYPE = "samplerExternalOES";
 
 // clang-format off
 tbm_format FORMATS_BLENDING_REQUIRED[] = {
index 689741c..7f72939 100644 (file)
@@ -38,7 +38,7 @@ namespace
 {
 #define TBM_SURFACE_QUEUE_SIZE 3
 
-const char* SAMPLER_TYPE    = "samplerExternalOES";
+const char* SAMPLER_TYPE = "samplerExternalOES";
 
 // clang-format off
 int FORMATS_BLENDING_REQUIRED[] = {
index 19bf14d..b37e1ad 100644 (file)
@@ -23,7 +23,7 @@
 \r
 // Need to undef the following constants as they are defined in one of the headers in Windows.h but used in DALi (via debug.h)\r
 #undef TRANSPARENT // Used in constants.h\r
-#undef CopyMemory // Used in dali-vector.h\r
+#undef CopyMemory  // Used in dali-vector.h\r
 \r
 #include <dali/integration-api/debug.h>\r
 \r
index d708d85..e6e93fc 100644 (file)
@@ -387,7 +387,8 @@ uint32_t FontClient::GetNumberOfPointsPerOneUnitOfPointSize() const
   {
     return mPlugin->GetNumberOfPointsPerOneUnitOfPointSize();
   }
-  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  ;
 }
 
 FT_FaceRec_* FontClient::GetFreetypeFace(FontId fontId)
index 07eea78..80abee5 100644 (file)
@@ -233,7 +233,7 @@ public:
    */
   Size GetMaximumTextAtlasSize() const;
 
-   /**
+  /**
    * @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
    */
   Size GetDefaultTextAtlasSize() const;
index 60deca8..f8aa87a 100644 (file)
@@ -169,17 +169,16 @@ bool IsFitIntoAtlas(FT_Face& ftFace, int& error, const unsigned int& horizontalD
   bool isFit = false;
 
   error = FT_Set_Char_Size(ftFace,
-                      0,
-                      requestedPointSize,
-                      horizontalDpi,
-                      verticalDpi);
+                           0,
+                           requestedPointSize,
+                           horizontalDpi,
+                           verticalDpi);
 
-  if( error == FT_Err_Ok)
+  if(error == FT_Err_Ok)
   {
     //Check width and height of block for requestedPointSize
     //If the width or height is greater than the maximum-size then decrement by one unit of point-size.
-    if( static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height
-      && (static_cast<float>(ftFace->size->metrics.ascender)-static_cast<float>(ftFace->size->metrics.descender))* FROM_266 <= maxSizeFitInAtlas.width)
+    if(static_cast<float>(ftFace->size->metrics.height) * FROM_266 <= maxSizeFitInAtlas.height && (static_cast<float>(ftFace->size->metrics.ascender) - static_cast<float>(ftFace->size->metrics.descender)) * FROM_266 <= maxSizeFitInAtlas.width)
     {
       isFit = true;
     }
@@ -202,8 +201,8 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi,
 {
   //To improve performance of sequential search. This code is applying Exponential search then followed by Binary search.
   const uint32_t& pointSizePerOneUnit = TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
-  bool canFitInAtlas;
-  int error; // FreeType error code.
+  bool            canFitInAtlas;
+  int             error; // FreeType error code.
 
   canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
   if(FT_Err_Ok != error)
@@ -216,16 +215,16 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi,
     //Exponential search
     uint32_t exponentialDecrement = 1;
 
-    while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit*exponentialDecrement)
+    while(!canFitInAtlas && requestedPointSize > pointSizePerOneUnit * exponentialDecrement)
     {
-      requestedPointSize-=(pointSizePerOneUnit*exponentialDecrement);
+      requestedPointSize -= (pointSizePerOneUnit * exponentialDecrement);
       canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
       if(FT_Err_Ok != error)
       {
         return error;
       }
 
-      exponentialDecrement*=2;
+      exponentialDecrement *= 2;
     }
 
     //Binary search
@@ -234,9 +233,9 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi,
 
     if(canFitInAtlas)
     {
-      exponentialDecrement/=2;
+      exponentialDecrement /= 2;
       minPointSize = requestedPointSize;
-      maxPointSize = requestedPointSize + (pointSizePerOneUnit*exponentialDecrement);
+      maxPointSize = requestedPointSize + (pointSizePerOneUnit * exponentialDecrement);
     }
     else
     {
@@ -246,8 +245,8 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi,
 
     while(minPointSize < maxPointSize)
     {
-      requestedPointSize = ((maxPointSize/pointSizePerOneUnit - minPointSize/pointSizePerOneUnit)/2) * pointSizePerOneUnit + minPointSize;
-      canFitInAtlas = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
+      requestedPointSize = ((maxPointSize / pointSizePerOneUnit - minPointSize / pointSizePerOneUnit) / 2) * pointSizePerOneUnit + minPointSize;
+      canFitInAtlas      = IsFitIntoAtlas(ftFace, error, horizontalDpi, verticalDpi, maxSizeFitInAtlas, requestedPointSize);
       if(FT_Err_Ok != error)
       {
         return error;
@@ -273,7 +272,6 @@ int SearchOnProperPointSize(FT_Face& ftFace, const unsigned int& horizontalDpi,
   return error;
 }
 
-
 FontClient::Plugin::FallbackCacheItem::FallbackCacheItem(FontDescription&& font, FontList* fallbackFonts, CharacterSetList* characterSets)
 : fontDescription{std::move(font)},
   fallbackFonts{fallbackFonts},
@@ -2038,11 +2036,10 @@ bool FontClient::Plugin::SetCurrentMaximumBlockSizeFitInAtlas(const Size& curren
   const Size&     maxTextAtlasSize = TextAbstraction::FontClient::MAX_TEXT_ATLAS_SIZE;
   const uint16_t& padding          = TextAbstraction::FontClient::PADDING_TEXT_ATLAS_BLOCK;
 
-  if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding
-      && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
+  if(currentMaximumBlockSizeFitInAtlas.width <= maxTextAtlasSize.width - padding && currentMaximumBlockSizeFitInAtlas.height <= maxTextAtlasSize.height - padding)
   {
     mCurrentMaximumBlockSizeFitInAtlas = currentMaximumBlockSizeFitInAtlas;
-    isChanged = true;
+    isChanged                          = true;
   }
 
   return isChanged;
@@ -2050,10 +2047,10 @@ bool FontClient::Plugin::SetCurrentMaximumBlockSizeFitInAtlas(const Size& curren
 
 uint32_t FontClient::Plugin::GetNumberOfPointsPerOneUnitOfPointSize() const
 {
-  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;;
+  return TextAbstraction::FontClient::NUMBER_OF_POINTS_PER_ONE_UNIT_OF_POINT_SIZE;
+  ;
 }
 
-
 void FontClient::Plugin::InitSystemFonts()
 {
   DALI_LOG_INFO(gLogFilter, Debug::General, "-->FontClient::Plugin::InitSystemFonts\n");
@@ -2375,9 +2372,9 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
         //If the block size cannot fit into atlas size, then the system cannot draw block.
         //This is workaround to avoid issue in advance
         //Decrementing point-size until arriving to maximum allowed block size.
-        auto requestedPointSizeBackup= requestedPointSize;
-        const Size& maxSizeFitInAtlas = GetCurrentMaximumBlockSizeFitInAtlas();
-        error = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
+        auto        requestedPointSizeBackup = requestedPointSize;
+        const Size& maxSizeFitInAtlas        = GetCurrentMaximumBlockSizeFitInAtlas();
+        error                                = SearchOnProperPointSize(ftFace, mDpiHorizontal, mDpiVertical, maxSizeFitInAtlas, requestedPointSize);
 
         if(requestedPointSize != requestedPointSizeBackup)
         {
@@ -2386,11 +2383,11 @@ FontId FontClient::Plugin::CreateFont(const FontPath& path,
       }
       else
       {
-         error = FT_Set_Char_Size(ftFace,
-                               0,
-                               requestedPointSize,
-                               mDpiHorizontal,
-                               mDpiVertical);
+        error = FT_Set_Char_Size(ftFace,
+                                 0,
+                                 requestedPointSize,
+                                 mDpiHorizontal,
+                                 mDpiVertical);
       }
 
       if(FT_Err_Ok == error)
index fb3569a..acd4be1 100644 (file)
@@ -405,7 +405,7 @@ struct FontClient::Plugin
    */
   Size GetMaximumTextAtlasSize() const;
 
-   /**
+  /**
    * @copydoc Dali::TextAbstraction::FontClient::GetDefaultTextAtlasSize()
    */
   Size GetDefaultTextAtlasSize() const;
@@ -685,7 +685,7 @@ private:
 
   bool mDefaultFontDescriptionCached : 1; ///< Whether the default font is cached or not
 
-  bool mIsAtlasLimitationEnabled : 1; ///< Whether the validation on maximum atlas block size, then reduce block size to fit into it is enabled or not.
+  bool    mIsAtlasLimitationEnabled : 1;      ///< Whether the validation on maximum atlas block size, then reduce block size to fit into it is enabled or not.
   Vector2 mCurrentMaximumBlockSizeFitInAtlas; ///< The current maximum size (width, height) of text-atlas-block.
 };
 
index c105e39..b5002fc 100644 (file)
@@ -115,9 +115,9 @@ private:
    */
   enum class AnimationFormat
   {
-     NONE = 0,
-     JSON,
-     RIVE
+    NONE = 0,
+    JSON,
+    RIVE
   };
 
   /**
index 8283c30..95a1366 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_WINDOWSYSTEM_COMMON_GL_WINDOW_RENDER_THREAD_H
 
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
@@ -265,13 +265,13 @@ private:
   int                           mScreenRotationAngle; ///< The angle of screen rotation angle
 
   // To manage the render/main thread
-  ConditionalWait                 mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
-  volatile unsigned int           mDestroyRenderThread;       ///< Stop render thread. It means this rendter thread will be destoried.
-  volatile unsigned int           mPauseRenderThread;         ///< Sleep render thread by pause.
-  volatile unsigned int           mRenderingMode;             ///< Rendering Mode, 0: continuous, 1:OnDemad
-  volatile unsigned int           mRequestRenderOnce;         ///< Request rendering once
-  volatile unsigned int           mSurfaceStatus;             ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
-  volatile unsigned int           mPostRendering;             ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
+  ConditionalWait       mRenderThreadWaitCondition; ///< The wait condition for the update-render-thread.
+  volatile unsigned int mDestroyRenderThread;       ///< Stop render thread. It means this rendter thread will be destoried.
+  volatile unsigned int mPauseRenderThread;         ///< Sleep render thread by pause.
+  volatile unsigned int mRenderingMode;             ///< Rendering Mode, 0: continuous, 1:OnDemad
+  volatile unsigned int mRequestRenderOnce;         ///< Request rendering once
+  volatile unsigned int mSurfaceStatus;             ///< When surface is changed as resized or rotated, this flag is set. 0: No changed, 1:resized, 2:window rotation, 4:screen rotation
+  volatile unsigned int mPostRendering;             ///< Whether post-rendering is taking place (set by the event & render threads, read by the render-thread).
 
   uint64_t mDefaultFrameDurationNanoseconds; ///< Default duration of a frame (used for sleeping if not enough time elapsed). Not protected by lock, but written to rarely so not worth adding a lock when reading.
 
index 659ad2c..9e43d8d 100644 (file)
@@ -133,7 +133,6 @@ WindowBase::UpdatePositionSizeType& WindowBase::UpdatePositionSizeSignal()
   return mUpdatePositionSizeSignal;
 }
 
-
 } // namespace Adaptor
 
 } // namespace Internal
index ddb2993..a2b7ce4 100644 (file)
@@ -466,7 +466,6 @@ protected:
   KeyboardRepeatSettingsChangedSignalType mKeyboardRepeatSettingsChangedSignal;
   WindowRedrawRequestSignalType           mWindowRedrawRequestSignal;
   UpdatePositionSizeType                  mUpdatePositionSizeSignal;
-
 };
 
 } // namespace Adaptor
index 7f6c29f..4a7a8e7 100644 (file)
@@ -429,6 +429,8 @@ void WindowRenderSurface::StartRender()
 
 bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
 {
+  mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+
   Dali::Integration::Scene::FrameCallbackContainer callbacks;
 
   Dali::Integration::Scene scene = mScene.GetHandle();
@@ -493,8 +495,6 @@ bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect
     }
   }
 
-  MakeContextCurrent();
-
   /**
     * wl_egl_window_tizen_set_rotation(SetEglWindowRotation)                -> PreRotation
     * wl_egl_window_tizen_set_buffer_transform(SetEglWindowBufferTransform) -> Screen Rotation
@@ -504,7 +504,7 @@ bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect
     *          because output transform event should be occured before egl window is not created.
     */
 
-  if(resizingSurface || mDefaultScreenRotationAvailable)
+  if(mIsResizing || mDefaultScreenRotationAvailable)
   {
     int totalAngle = (mWindowRotationAngle + mScreenRotationAngle) % 360;
 
@@ -551,12 +551,20 @@ bool WindowRenderSurface::PreRender(bool resizingSurface, const std::vector<Rect
     mDefaultScreenRotationAvailable = false;
   }
 
-  SetBufferDamagedRects(damagedRects, clippingRect);
+  SetBufferDamagedRects(mDamagedRects, clippingRect);
+
+  if(clippingRect.IsEmpty())
+  {
+    mDamagedRects.clear();
+  }
+
+  // This is now done when the render pass for the render surface begins
+  //  MakeContextCurrent();
 
   return true;
 }
 
-void WindowRenderSurface::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void WindowRenderSurface::PostRender()
 {
   // Inform the gl implementation that rendering has finished before informing the surface
   auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
@@ -565,37 +573,29 @@ void WindowRenderSurface::PostRender(bool renderToFbo, bool replacingSurface, bo
     GlImplementation& mGLES = eglGraphics->GetGlesInterface();
     mGLES.PostRender();
 
-    if(renderToFbo)
+    if(mIsResizing)
     {
-      mGLES.Flush();
-      mGLES.Finish();
-    }
-    else
-    {
-      if(resizingSurface)
+      if(!mWindowRotationFinished)
       {
-        if(!mWindowRotationFinished)
+        if(mThreadSynchronization)
         {
-          if(mThreadSynchronization)
-          {
-            // Enable PostRender flag
-            mThreadSynchronization->PostRenderStarted();
-          }
+          // Enable PostRender flag
+          mThreadSynchronization->PostRenderStarted();
+        }
 
-          DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n");
+        DALI_LOG_RELEASE_INFO("WindowRenderSurface::PostRender: Trigger rotation event\n");
 
-          mRotationTrigger->Trigger();
+        mRotationTrigger->Trigger();
 
-          if(mThreadSynchronization)
-          {
-            // Wait until the event-thread complete the rotation event processing
-            mThreadSynchronization->PostRenderWaitForCompletion();
-          }
+        if(mThreadSynchronization)
+        {
+          // Wait until the event-thread complete the rotation event processing
+          mThreadSynchronization->PostRenderWaitForCompletion();
         }
       }
     }
 
-    SwapBuffers(damagedRects);
+    SwapBuffers(mDamagedRects);
 
     if(mRenderNotification)
     {
index d2584f1..2661adc 100644 (file)
@@ -166,7 +166,7 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+  void PostRender() override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()
@@ -301,7 +301,8 @@ private: // Data
   int                                    mScreenRotationAngle;
   uint32_t                               mDpiHorizontal;
   uint32_t                               mDpiVertical;
-  bool                                   mOwnSurface; ///< Whether we own the surface (responsible for deleting it)
+  std::vector<Rect<int>>                 mDamagedRects{}; ///< Keeps collected damaged render items rects for one render pass
+  bool                                   mOwnSurface;     ///< Whether we own the surface (responsible for deleting it)
   bool                                   mWindowRotationFinished;
   bool                                   mScreenRotationFinished;
   bool                                   mResizeFinished;
index 7587ece..4fe0a30 100644 (file)
@@ -1016,8 +1016,8 @@ void WindowBaseEcoreWl2::OnConfiguration(void* data, int type, void* event)
     // When window is just moved or window is resized by client application,
     // The configure notification event's size will be 0.
     // If new size is 0, the resized work should be skip.
-    int newWidth = mWindowPositionSize.width;
-    int newHeight = mWindowPositionSize.height;
+    int  newWidth    = mWindowPositionSize.width;
+    int  newHeight   = mWindowPositionSize.height;
     bool windowMoved = false, windowResized = false;
 
     if(ev->x != mWindowPositionSize.x || ev->y != mWindowPositionSize.y)
@@ -1028,8 +1028,8 @@ void WindowBaseEcoreWl2::OnConfiguration(void* data, int type, void* event)
     if(tempWidth != 0 && tempHeight != 0 && (tempWidth != mWindowPositionSize.width || tempHeight != mWindowPositionSize.height))
     {
       windowResized = true;
-      newWidth = tempWidth;
-      newHeight = tempHeight;
+      newWidth      = tempWidth;
+      newHeight     = tempHeight;
     }
 
     if(windowMoved || windowResized)
index ecdc4e2..b752013 100644 (file)
@@ -220,18 +220,28 @@ void NativeRenderSurfaceEcoreWl::StartRender()
 
 bool NativeRenderSurfaceEcoreWl::PreRender(bool resizingSurface, const std::vector<Rect<int>>& damagedRects, Rect<int>& clippingRect)
 {
+  if(!clippingRect.IsEmpty())
+  {
+    mDamagedRects.assign(damagedRects.begin(), damagedRects.end());
+  }
+  else
+  {
+    mDamagedRects.clear();
+  }
+
   //TODO: Need to support partial update
-  MakeContextCurrent();
+  // This is now done when the render pass for the render surface begins
+  //  MakeContextCurrent();
   return true;
 }
 
-void NativeRenderSurfaceEcoreWl::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void NativeRenderSurfaceEcoreWl::PostRender()
 {
   auto eglGraphics = static_cast<Internal::Adaptor::EglGraphics*>(mGraphics);
   if(eglGraphics)
   {
     Internal::Adaptor::EglImplementation& eglImpl = eglGraphics->GetEglImplementation();
-    eglImpl.SwapBuffers(mEGLSurface, damagedRects);
+    eglImpl.SwapBuffers(mEGLSurface, mDamagedRects);
   }
 
   if(mRenderNotification)
index da93899..f33588e 100644 (file)
@@ -118,7 +118,7 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+  void PostRender() override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()
@@ -171,6 +171,7 @@ private: // Data
   ColorDepth                            mColorDepth;
   tbm_format                            mTbmFormat;
   bool                                  mOwnSurface;
+  std::vector<Rect<int>>                mDamagedRects{}; ///< Keeps collected damaged render items rects for one render pass
 
   tbm_surface_queue_h             mTbmQueue;
   ThreadSynchronizationInterface* mThreadSynchronization; ///< A pointer to the thread-synchronization
index 1aa2b46..c79fd3b 100644 (file)
@@ -229,7 +229,7 @@ bool PixmapRenderSurfaceEcoreX::PreRender(bool, const std::vector<Rect<int>>&, R
   return true;
 }
 
-void PixmapRenderSurfaceEcoreX::PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects)
+void PixmapRenderSurfaceEcoreX::PostRender()
 {
   auto eglGraphics = static_cast<EglGraphics*>(mGraphics);
 
index c9a6906..4970520 100644 (file)
@@ -122,7 +122,7 @@ public: // from Dali::RenderSurfaceInterface
   /**
    * @copydoc Dali::RenderSurfaceInterface::PostRender()
    */
-  void PostRender(bool renderToFbo, bool replacingSurface, bool resizingSurface, const std::vector<Rect<int>>& damagedRects) override;
+  void PostRender() override;
 
   /**
    * @copydoc Dali::RenderSurfaceInterface::StopRender()
index 872bd1a..7bcc796 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.