Changed SceneHolder's RenderTarget initialization 71/268271/5
authorDavid Steele <david.steele@samsung.com>
Fri, 17 Dec 2021 17:24:15 +0000 (17:24 +0000)
committerDavid Steele <david.steele@samsung.com>
Fri, 21 Jan 2022 11:54:57 +0000 (11:54 +0000)
SceneHolder currently generates Graphics::RenderTarget in the wrong
thread (Event thread) which can cause crashes in EglController if
there is a heavy load, as Surface/Context pair vector can be modified
in one thread whilst being read in another.

Instead, set up the RenderTarget create info struct, and pass that
through the existing messages instead of RenderTarget. When the
SceneGraph::Scene gets it's second stage Initialize() method
called (by RenderManager), then use that CreateInfo struct to create
the RenderTarget. All modifications to the queues/vectors are now done
in the same thread, and should prevent crashes.

Change-Id: I6d33590ed85085f26c84c5d798abca48dd8affba
Signed-off-by: David Steele <david.steele@samsung.com>
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h
automated-tests/src/dali/utc-Dali-Scene.cpp
dali/integration-api/scene.cpp
dali/integration-api/scene.h
dali/internal/event/common/scene-impl.cpp
dali/internal/event/common/scene-impl.h
dali/internal/update/common/scene-graph-scene.cpp
dali/internal/update/common/scene-graph-scene.h

index 440270a..2862284 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -82,8 +82,9 @@ void TestApplication::CreateScene()
   // Create render target for the scene
   Graphics::RenderTargetCreateInfo rtInfo{};
   rtInfo.SetExtent({mSurfaceWidth, mSurfaceHeight});
-  mRenderTarget = mGraphicsController.CreateRenderTarget(rtInfo, nullptr);
-  mScene.SetSurfaceRenderTarget(mRenderTarget.get());
+  rtInfo.SetSurface(&mSurfaceWidth); // Can point to anything, really.
+
+  mScene.SetSurfaceRenderTarget(rtInfo);
 }
 
 void TestApplication::InitializeCore()
index fb2afda..3ed6b56 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -1028,9 +1028,11 @@ void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
  */
 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
 {
+  auto*                       rt = static_cast<const TestGraphicsRenderTarget*>(renderTarget);
   TraceCallStack::NamedParams namedParams;
   namedParams["renderTarget"] << std::hex << renderTarget;
-  mCallStack.PushCall("PresentRenderTarget", "", namedParams);
+  namedParams["surface"] << std::hex << rt->mCreateInfo.surface;
+  mCallStack.PushCall("PresentRenderTarget", namedParams.str(), namedParams);
 }
 
 /**
@@ -1237,7 +1239,10 @@ 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", "");
+  TraceCallStack::NamedParams namedParams;
+  namedParams["surface"] << std::hex << renderTargetCreateInfo.surface;
+  mCallStack.PushCall("CreateRenderTarget", namedParams.str(), namedParams);
+
   return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
 }
 
index 7631630..6f720c5 100644 (file)
@@ -2,7 +2,7 @@
 #define TEST_TRACE_CALL_STACK_H
 
 /*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 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.
@@ -121,6 +121,25 @@ public:
       }
     }
 
+    const std::ostringstream& operator[](std::string name) const
+    {
+      static std::ostringstream empty;
+      auto                      iter = mParams.begin();
+      for(; iter != mParams.end(); ++iter)
+      {
+        if(!iter->parameterName.compare(name))
+        {
+          break;
+        }
+      }
+
+      if(iter != mParams.end())
+      {
+        return iter->value;
+      }
+      return empty;
+    }
+
     std::string str() const
     {
       std::ostringstream out;
index a65463e..a573a0b 100644 (file)
@@ -33,27 +33,6 @@ namespace
 {
 const std::string DEFAULT_DEVICE_NAME("hwKeyboard");
 
-const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
-  attribute mediump vec2     aPosition;\n
-    uniform mediump mat4     uModelView;\n
-      uniform mediump mat4   uProjection;\n
-        uniform mediump vec3 uSize;\n void main()\n {
-          \n
-            mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
-          \n
-            vertexPosition.xyz *= uSize;
-          \n
-            gl_Position = uProjection * uModelView * vertexPosition;
-          \n
-        }\n);
-
-const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
-  uniform lowp vec4 uColor;\n void main()\n {
-    \n
-      gl_FragColor = uColor;
-    \n
-  }\n);
-
 // Functor for EventProcessingFinished signal
 struct EventProcessingFinishedFunctor
 {
@@ -1128,8 +1107,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle0(void)
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  Texture image = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u);
-  Actor   actor = CreateRenderableActor(image, VERTEX_SHADER, FRAGMENT_SHADER);
+  Actor actor = CreateRenderableActor();
   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
   actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
   actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
@@ -1137,11 +1115,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle0(void)
   application.GetScene().Add(actor);
 
   application.SendNotification();
-  application.Render(0);
-
-  Matrix      projection;
-  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
-  camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projection);
 
   damagedRects.clear();
   application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
@@ -1173,24 +1146,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle0(void)
   // It should be changed.
   DALI_TEST_EQUALS(orientation, 0, TEST_LOCATION);
 
-  // Check uniform
-  Quaternion rotationAngle(Dali::ANGLE_0, Vector3::ZAXIS);
-  Matrix     rotation, newProjection;
-  rotation.SetIdentity();
-  rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
-  Matrix::Multiply(newProjection, projection, rotation);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
-  // Change actor size to trigger rendering
-  actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f));
-
-  // Render again
-  application.SendNotification();
-  application.Render(0);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
   END_TEST;
 }
 
@@ -1218,8 +1173,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle90(void)
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  Texture image = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u);
-  Actor   actor = CreateRenderableActor(image, VERTEX_SHADER, FRAGMENT_SHADER);
+  Actor actor = CreateRenderableActor();
   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
   actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
   actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
@@ -1227,11 +1181,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle90(void)
   application.GetScene().Add(actor);
 
   application.SendNotification();
-  application.Render(0);
-
-  Matrix      projection;
-  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
-  camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projection);
 
   damagedRects.clear();
   application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
@@ -1270,24 +1219,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle90(void)
   // It should be changed.
   DALI_TEST_EQUALS(orientation, 90, TEST_LOCATION);
 
-  // Check uniform
-  Quaternion rotationAngle(Dali::ANGLE_90, Vector3::ZAXIS);
-  Matrix     rotation, newProjection;
-  rotation.SetIdentity();
-  rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
-  Matrix::Multiply(newProjection, projection, rotation);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
-  // Change actor size to trigger rendering
-  actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f));
-
-  // Render again
-  application.SendNotification();
-  application.Render(0);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
   END_TEST;
 }
 
@@ -1315,8 +1246,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle180(void)
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  Texture image = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u);
-  Actor   actor = CreateRenderableActor(image, VERTEX_SHADER, FRAGMENT_SHADER);
+  Actor actor = CreateRenderableActor();
   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
   actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
   actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
@@ -1324,11 +1254,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle180(void)
   application.GetScene().Add(actor);
 
   application.SendNotification();
-  application.Render(0);
-
-  Matrix      projection;
-  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
-  camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projection);
 
   damagedRects.clear();
   application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
@@ -1367,24 +1292,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle180(void)
   // It should be changed.
   DALI_TEST_EQUALS(orientation, 180, TEST_LOCATION);
 
-  // Check uniform
-  Quaternion rotationAngle(Dali::ANGLE_180, Vector3::ZAXIS);
-  Matrix     rotation, newProjection;
-  rotation.SetIdentity();
-  rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
-  Matrix::Multiply(newProjection, projection, rotation);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
-  // Change actor size to trigger rendering
-  actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f));
-
-  // Render again
-  application.SendNotification();
-  application.Render(0);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
   END_TEST;
 }
 
@@ -1412,8 +1319,7 @@ int UtcDaliSceneSurfaceRotatedWithAngle270(void)
   clippingRect = TestApplication::DEFAULT_SURFACE_RECT;
   application.RenderWithPartialUpdate(damagedRects, clippingRect);
 
-  Texture image = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 4u, 4u);
-  Actor   actor = CreateRenderableActor(image, VERTEX_SHADER, FRAGMENT_SHADER);
+  Actor actor = CreateRenderableActor();
   actor.SetProperty(Actor::Property::ANCHOR_POINT, AnchorPoint::TOP_LEFT);
   actor.SetProperty(Actor::Property::POSITION, Vector3(16.0f, 16.0f, 0.0f));
   actor.SetProperty(Actor::Property::SIZE, Vector3(16.0f, 16.0f, 0.0f));
@@ -1421,11 +1327,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle270(void)
   application.GetScene().Add(actor);
 
   application.SendNotification();
-  application.Render(0);
-
-  Matrix      projection;
-  CameraActor camera = application.GetScene().GetRenderTaskList().GetTask(0u).GetCameraActor();
-  camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projection);
 
   damagedRects.clear();
   application.GetScene().SurfaceRotated(TestApplication::DEFAULT_SURFACE_WIDTH,
@@ -1464,24 +1365,6 @@ int UtcDaliSceneSurfaceRotatedWithAngle270(void)
   // It should be changed.
   DALI_TEST_EQUALS(orientation, 270, TEST_LOCATION);
 
-  // Check uniform
-  Quaternion rotationAngle(Dali::ANGLE_270, Vector3::ZAXIS);
-  Matrix     rotation, newProjection;
-  rotation.SetIdentity();
-  rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
-  Matrix::Multiply(newProjection, projection, rotation);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
-  // Change actor size to trigger rendering
-  actor.SetProperty(Actor::Property::SIZE, Vector3(32.0f, 32.0f, 0.0f));
-
-  // Render again
-  application.SendNotification();
-  application.Render(0);
-
-  DALI_TEST_CHECK(application.GetGlAbstraction().CheckUniformValue("uProjection", newProjection));
-
   END_TEST;
 }
 
@@ -1676,6 +1559,51 @@ int UtcDaliSceneEnsureReplacedSurfaceKeepsClearColor(void)
   END_TEST;
 }
 
+int UtcDaliSceneEnsureRenderTargetRecreated(void)
+{
+  tet_infoline("Ensure render target is re-created when surface replaced ");
+
+  TestApplication application;
+
+  // Create a new scene and set the background color of the main scene
+  auto defaultScene = application.GetScene();
+  defaultScene.SetBackgroundColor(Color::BLUE);
+
+  auto actor = CreateRenderableActor();
+  defaultScene.Add(actor);
+
+  auto& graphicsController = application.GetGraphicsController();
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack&                    graphicsCallStack = graphicsController.mCallStack;
+  TraceCallStack::NamedParams        empty{};
+  const TraceCallStack::NamedParams* matching = graphicsCallStack.FindLastMatch("PresentRenderTarget", empty);
+  DALI_TEST_CHECK(matching != nullptr);
+
+  graphicsCallStack.Reset();
+
+  int                              fakeSurface1;
+  Graphics::RenderTargetCreateInfo createInfo{};
+  createInfo.SetSurface(&fakeSurface1).SetExtent(Graphics::Extent2D{480u, 800u});
+  defaultScene.SetSurfaceRenderTarget(createInfo);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack::NamedParams query1;
+  query1["surface"] << std::hex << &fakeSurface1;
+  const TraceCallStack::NamedParams* matching2 = graphicsCallStack.FindLastMatch("CreateRenderTarget", query1);
+  DALI_TEST_CHECK(matching2 != nullptr);
+
+  const TraceCallStack::NamedParams* matching3 = graphicsCallStack.FindLastMatch("PresentRenderTarget", empty);
+  DALI_TEST_CHECK(matching3 != nullptr);
+  DALI_TEST_EQUALS((*matching3)["surface"].str(), query1["surface"].str(), TEST_LOCATION);
+
+  END_TEST;
+}
+
 int UtcDaliSceneEmptySceneRendering(void)
 {
   tet_infoline("Ensure not rendering before a Renderer is added");
index 8fb7a7c..a5e6236 100644 (file)
@@ -124,9 +124,9 @@ void Scene::Discard()
   GetImplementation(*this).Discard();
 }
 
-void Scene::SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget)
+void Scene::SetSurfaceRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo)
 {
-  GetImplementation(*this).SetSurfaceRenderTarget(renderTarget);
+  GetImplementation(*this).SetSurfaceRenderTarget(renderTargetCreateInfo);
 }
 
 Integration::Scene Scene::Get(Actor actor)
index d137773..ad41479 100644 (file)
@@ -22,6 +22,8 @@
 #include <memory>
 
 // INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-controller.h>
+#include <dali/graphics-api/graphics-render-target-create-info.h>
 #include <dali/public-api/common/vector-wrapper.h>
 #include <dali/public-api/math/vector2.h>
 #include <dali/public-api/math/vector4.h>
@@ -225,9 +227,9 @@ public:
   /**
    * @brief Sets the render target for the surface.
    *
-   * @param[in] renderTarget The render target for the surface
+   * @param[in] renderTarget The render target create info for the surface
    */
-  void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget);
+  void SetSurfaceRenderTarget(const Graphics::RenderTargetCreateInfo& createInfo);
 
   /**
    * @brief Retrieve the Scene that the given actor belongs to.
index ba88152..0cd81c8 100644 (file)
@@ -332,11 +332,11 @@ void Scene::SetRotationCompletedAcknowledgement()
   SetRotationCompletedAcknowledgementMessage(tls->GetEventThreadServices(), *mSceneObject);
 }
 
-void Scene::SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget)
+void Scene::SetSurfaceRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo)
 {
   // Send the surface render target to SceneGraph::Scene
   ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
-  SetSurfaceRenderTargetMessage(tls->GetEventThreadServices(), *mSceneObject, renderTarget);
+  SetSurfaceRenderTargetCreateInfoMessage(tls->GetEventThreadServices(), *mSceneObject, renderTargetCreateInfo);
 }
 
 bool Scene::EmitKeyEventGeneratedSignal(const Dali::KeyEvent& event)
index 34ab1a8..67606d7 100644 (file)
@@ -218,7 +218,7 @@ public:
   /**
    * @copydoc Dali::Integration::Scene::SetSurfaceRenderTarget
    */
-  void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget);
+  void SetSurfaceRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo);
 
   /**
    * Used by the EventProcessor to emit key event signals.
index 1ad1c93..9360c32 100644 (file)
@@ -46,6 +46,11 @@ Scene::~Scene()
 
 void Scene::Initialize(Graphics::Controller& graphicsController, Integration::DepthBufferAvailable depthBufferAvailable, Integration::StencilBufferAvailable stencilBufferAvailable)
 {
+  mGraphicsController = &graphicsController;
+
+  // Create the render target for the surface. It should already have been sent via message.
+  mRenderTarget = mGraphicsController->CreateRenderTarget(mRenderTargetCreateInfo, std::move(mRenderTarget));
+
   // Create the render pass for the surface
   std::vector<Graphics::AttachmentDescription> attachmentDescriptions;
 
@@ -187,6 +192,22 @@ std::vector<DirtyRect>& Scene::GetItemsDirtyRects()
   return mItemsDirtyRects;
 }
 
+void Scene::SetSurfaceRenderTargetCreateInfo(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo)
+{
+  if(mRenderTarget != nullptr &&
+     mRenderTargetCreateInfo.surface != renderTargetCreateInfo.surface)
+  {
+    // Only recreate if the surface has changed.
+    mRenderTargetCreateInfo = renderTargetCreateInfo;
+    mRenderTarget           = mGraphicsController->CreateRenderTarget(renderTargetCreateInfo, std::move(mRenderTarget));
+  }
+  else
+  {
+    // 2nd Stage initialization happens in RenderManager, not UpdateManager, so is delayed.
+    mRenderTargetCreateInfo = renderTargetCreateInfo;
+  }
+}
+
 } // namespace SceneGraph
 
 } // namespace Internal
index f1f0f5a..d8c8643 100644 (file)
@@ -216,10 +216,7 @@ public:
    *
    * @param[in] renderTarget The render target.
    */
-  void SetSurfaceRenderTarget(Graphics::RenderTarget* renderTarget)
-  {
-    mRenderTarget = renderTarget;
-  }
+  void SetSurfaceRenderTargetCreateInfo(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo);
 
   /**
    * Get the render target created for the scene
@@ -228,7 +225,7 @@ public:
    */
   [[nodiscard]] Graphics::RenderTarget* GetSurfaceRenderTarget() const
   {
-    return mRenderTarget;
+    return mRenderTarget.get();
   }
 
   /**
@@ -271,6 +268,8 @@ private:
 
   RenderInstructionContainer mInstructions; ///< Render instructions for the scene
 
+  Graphics::Controller* mGraphicsController; ///< Graphics controller
+
   Dali::Integration::Scene::FrameCallbackContainer mFrameRenderedCallbacks;  ///< Frame rendered callbacks
   Dali::Integration::Scene::FrameCallbackContainer mFramePresentedCallbacks; ///< Frame presented callbacks
 
@@ -283,14 +282,16 @@ private:
 
   // Render pass and render target
 
+  Graphics::RenderTargetCreateInfo mRenderTargetCreateInfo; // Passed in by message before 2nd stage Initialization happens.
+
   /**
    * Render pass is created on fly depending on Load and Store operations
    * The default render pass (most likely to be used) is the load = CLEAR
    * and store = STORE for color attachment.
    */
-  Graphics::UniquePtr<Graphics::RenderPass> mRenderPass{nullptr};        ///< The render pass created to render the surface
-  Graphics::UniquePtr<Graphics::RenderPass> mRenderPassNoClear{nullptr}; ///< The render pass created to render the surface without clearing color
-  Graphics::RenderTarget*                   mRenderTarget{nullptr};      ///< This is created in the event thread when surface is created/resized/replaced
+  Graphics::UniquePtr<Graphics::RenderPass>   mRenderPass{nullptr};        ///< The render pass created to render the surface
+  Graphics::UniquePtr<Graphics::RenderPass>   mRenderPassNoClear{nullptr}; ///< The render pass created to render the surface without clearing color
+  Graphics::UniquePtr<Graphics::RenderTarget> mRenderTarget{nullptr};      ///< This is created in Update/Render thread when surface is created/resized/replaced
 
   std::vector<Graphics::ClearValue>                  mClearValues{};     ///< Clear colors
   std::vector<Dali::Internal::SceneGraph::DirtyRect> mItemsDirtyRects{}; ///< Dirty rect list
@@ -352,15 +353,15 @@ inline void SetRotationCompletedAcknowledgementMessage(EventThreadServices& even
   new(slot) LocalType(&scene, &Scene::SetRotationCompletedAcknowledgement);
 }
 
-inline void SetSurfaceRenderTargetMessage(EventThreadServices& eventThreadServices, const Scene& scene, Graphics::RenderTarget* renderTarget)
+inline void SetSurfaceRenderTargetCreateInfoMessage(EventThreadServices& eventThreadServices, const Scene& scene, const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo)
 {
-  using LocalType = MessageValue1<Scene, Graphics::RenderTarget*>;
+  using LocalType = MessageValue1<Scene, Graphics::RenderTargetCreateInfo>;
 
   // Reserve some memory inside the message queue
   uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
 
   // Construct message in the message queue memory; note that delete should not be called on the return value
-  new(slot) LocalType(&scene, &Scene::SetSurfaceRenderTarget, renderTarget);
+  new(slot) LocalType(&scene, &Scene::SetSurfaceRenderTargetCreateInfo, renderTargetCreateInfo);
 }
 
 } // namespace SceneGraph