DirectRendering: 76/270676/20
authorAdam Bialogonski <adam.b@samsung.com>
Mon, 14 Mar 2022 16:46:44 +0000 (16:46 +0000)
committerAdam Bialogonski <adam.b@samsung.com>
Fri, 18 Mar 2022 15:45:08 +0000 (15:45 +0000)
- Added RenderCallback for native rendering
- Added new Graphics API command - DrawNative()
- Added DrawableActor

Change-Id: If286d6eddf0836c63227c870eb13e8bab252fda7

23 files changed:
automated-tests/src/dali/CMakeLists.txt
automated-tests/src/dali/dali-test-suite-utils/test-graphics-command-buffer.h
automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/utc-Dali-DrawableActor.cpp [new file with mode: 0644]
dali/graphics-api/graphics-command-buffer.h
dali/graphics-api/graphics-types.h
dali/internal/event/actors/drawable-actor-impl.cpp [new file with mode: 0644]
dali/internal/event/actors/drawable-actor-impl.h [new file with mode: 0644]
dali/internal/event/rendering/renderer-impl.cpp
dali/internal/event/rendering/renderer-impl.h
dali/internal/file.list
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/update/manager/render-instruction-processor.cpp
dali/internal/update/rendering/scene-graph-renderer.cpp
dali/internal/update/rendering/scene-graph-renderer.h
dali/public-api/actors/drawable-actor.cpp [new file with mode: 0644]
dali/public-api/actors/drawable-actor.h [new file with mode: 0644]
dali/public-api/file.list
dali/public-api/rendering/renderer.cpp
dali/public-api/rendering/renderer.h
dali/public-api/signals/render-callback.cpp [new file with mode: 0644]
dali/public-api/signals/render-callback.h [new file with mode: 0644]

index a6c8ac8..6f299d8 100644 (file)
@@ -26,6 +26,7 @@ SET(TC_SOURCES
         utc-Dali-CustomActor.cpp
         utc-Dali-Degree.cpp
         utc-Dali-DistanceField.cpp
+        utc-Dali-DrawableActor.cpp
         utc-Dali-Extents.cpp
         utc-Dali-FrameBuffer.cpp
         utc-Dali-FrameCallbackInterface.cpp
index 96b0021..407dade 100644 (file)
@@ -65,6 +65,7 @@ enum class CommandType
   SET_DEPTH_COMPARE_OP    = 1 << 24,
   SET_DEPTH_TEST_ENABLE   = 1 << 25,
   SET_DEPTH_WRITE_ENABLE  = 1 << 26,
+  DRAW_NATIVE             = 1 << 27,
 };
 
 std::ostream& operator<<(std::ostream& os, Graphics::StencilOp op);
@@ -123,7 +124,8 @@ struct DrawCallDescriptor
   {
     DRAW,
     DRAW_INDEXED,
-    DRAW_INDEXED_INDIRECT
+    DRAW_INDEXED_INDIRECT,
+    DRAW_NATIVE
   };
 
   Type type{}; ///< Type of the draw call
@@ -166,6 +168,11 @@ struct DrawCallDescriptor
       uint32_t                  drawCount;
       uint32_t                  stride;
     } drawIndexedIndirect;
+
+    struct
+    {
+      Graphics::DrawNativeInfo drawNativeInfo;
+    } drawNative;
   };
 };
 
@@ -265,6 +272,12 @@ struct Command
         data.bindUniformBuffers = rhs.data.bindUniformBuffers;
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        data.draw.type       = rhs.data.draw.type;
+        data.draw.drawNative = rhs.data.draw.drawNative;
+        break;
+      }
       case CommandType::DRAW:
       {
         data.draw.type = rhs.data.draw.type;
@@ -418,6 +431,12 @@ struct Command
         data.bindPipeline = rhs.data.bindPipeline;
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        data.draw.type       = rhs.data.draw.type;
+        data.draw.drawNative = rhs.data.draw.drawNative;
+        break;
+      }
       case CommandType::DRAW:
       {
         data.draw.type = rhs.data.draw.type;
@@ -800,6 +819,16 @@ public:
     mCallStack.PushCall("ExecuteCommandBuffers", "");
   }
 
+  void DrawNative(const Graphics::DrawNativeInfo* drawInfo)
+  {
+    mCommands.emplace_back();
+    mCommands.back().type         = CommandType::DRAW_NATIVE;
+    auto& cmd                     = mCommands.back().data.draw;
+    cmd.type                      = DrawCallDescriptor::Type::DRAW_NATIVE;
+    cmd.drawNative.drawNativeInfo = *drawInfo;
+    mCallStack.PushCall("DrawNative", "");
+  }
+
   void Draw(
     uint32_t vertexCount,
     uint32_t instanceCount,
index bedce18..6a8eab4 100644 (file)
@@ -693,6 +693,12 @@ void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& com
         BindPipeline(currentPipeline);
         break;
       }
+      case CommandType::DRAW_NATIVE:
+      {
+        auto info = &cmd.data.draw.drawNative.drawNativeInfo;
+        CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
+        break;
+      }
       case CommandType::DRAW:
       {
         if(currentPipeline)
diff --git a/automated-tests/src/dali/utc-Dali-DrawableActor.cpp b/automated-tests/src/dali/utc-Dali-DrawableActor.cpp
new file mode 100644 (file)
index 0000000..e13606e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ * 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/public-api/actors/drawable-actor.h>
+
+struct DrawableObject
+{
+  bool Render(const RenderCallbackInput& inputData)
+  {
+    // Store the size of rendered area
+    size = inputData.size;
+
+    return false;
+  }
+
+  Size size;
+};
+
+int UtcDaliDrawableActor1P(void)
+{
+  tet_infoline("Testing DrawableActor");
+  TestApplication application;
+
+  DrawableObject drawable{};
+
+  auto callback = RenderCallback::New<DrawableObject>(&drawable, &DrawableObject::Render);
+
+  DrawableActor drawableActor = DrawableActor::New(*callback);
+  application.GetScene().Add(drawableActor);
+
+  drawableActor.SetProperty(Actor::Property::SIZE, Vector2(100, 100));
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Check the size (whether callback has been called)
+  auto size(drawable.size);
+  DALI_TEST_EQUALS(drawable.size, Size(100, 100), TEST_LOCATION);
+
+  END_TEST;
+}
\ No newline at end of file
index 476dd78..61dd8df 100644 (file)
@@ -88,6 +88,22 @@ struct ClearValue
   };
 };
 
+// Native rendering (using native APIs)
+
+enum class DrawNativeAPI
+{
+  GLES,
+  UNDEFINED
+};
+
+struct DrawNativeInfo
+{
+  DrawNativeAPI       api;      //< API used by the callback
+  Dali::CallbackBase* callback; //< Callback pointer
+  void*               userData; //< Data passed into the callback (unspecified type, callback should decode it)
+  void*               reserved; //< Reserved for internal use
+};
+
 /**
  * @brief CommandBuffer contains a stream of commands to be executed
  * by the controller.
@@ -266,6 +282,21 @@ public:
     uint32_t stride) = 0;
 
   /**
+   * @brief Draws using native API (via callback)
+   *
+   * DrawNative should be use in order to acquire direct access to the
+   * graphics API like GL. Upon command execution, the backend will
+   * invoke given callback and pass API-specific arguments (for example,
+   * the GL callback will receive EGL context used for rendering).
+   *
+   * The client side must make sure the callback is valid for the
+   * time of execution.
+   *
+   * @param[in] drawInfo NativeDrawInfo structure
+   */
+  virtual void DrawNative(const DrawNativeInfo* drawInfo) = 0;
+
+  /**
    * @brief Resets CommandBuffer
    *
    * This function resets the command buffer and discards all previously
index 84f0fd3..2ce4b5a 100644 (file)
@@ -24,6 +24,8 @@
 #include <utility>
 #include <vector>
 
+#include <dali/public-api/signals/callback.h>
+
 namespace Dali
 {
 namespace Graphics
diff --git a/dali/internal/event/actors/drawable-actor-impl.cpp b/dali/internal/event/actors/drawable-actor-impl.cpp
new file mode 100644 (file)
index 0000000..01836e9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ * 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 "drawable-actor-impl.h"
+#include <dali/internal/event/rendering/renderer-impl.h>
+#include <dali/internal/update/nodes/node.h>
+
+namespace Dali::Internal
+{
+DrawableActorPtr DrawableActor::New(RenderCallback* renderCallback)
+{
+  return DrawableActorPtr(new DrawableActor(*CreateNode(), renderCallback));
+}
+
+DrawableActor::DrawableActor(const Internal::SceneGraph::Node& node, RenderCallback* renderCallback)
+: Actor(Actor::BASIC, node)
+{
+  auto rendererImpl = Internal::Renderer::New();
+
+  rendererImpl->SetProperty(DevelRenderer::Property::RENDERING_BEHAVIOR, DevelRenderer::Rendering::CONTINUOUSLY);
+
+  mRenderer = Dali::Renderer(rendererImpl.Get());
+  mRenderer.SetRenderCallback(renderCallback);
+  AddRenderer(*rendererImpl.Get());
+}
+
+} // namespace Dali::Internal
\ No newline at end of file
diff --git a/dali/internal/event/actors/drawable-actor-impl.h b/dali/internal/event/actors/drawable-actor-impl.h
new file mode 100644 (file)
index 0000000..9939ca8
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef DALI_INTERNAL_DRAWABLE_ACTOR_H
+#define DALI_INTERNAL_DRAWABLE_ACTOR_H
+
+/*
+ * 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.
+ * 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/event/actors/actor-impl.h>
+#include <dali/public-api/rendering/renderer.h>
+
+namespace Dali::Internal
+{
+namespace SceneGraph
+{
+class Node;
+}
+
+class DrawableActor;
+using DrawableActorPtr = IntrusivePtr<DrawableActor>;
+
+class DrawableActor : public Actor
+{
+public:
+  /**
+   * @brief Constructor of DrawableActor
+   *
+   * @param[in] node the scenegraph Node object
+   * @param[in] renderCallback the pointer to the CallbackBase object
+   */
+  explicit DrawableActor(const Internal::SceneGraph::Node& node, RenderCallback* renderCallback);
+
+  /**
+   * @brief Creates new instance of the DrawableActor implementation
+   *
+   * @param[in] renderCallback Pointer to a valid CallbackBase object
+   * @return managed pointer to the DrawableActor implementation
+   */
+  static DrawableActorPtr New(RenderCallback* renderCallback);
+
+private:
+  Dali::Renderer mRenderer; //< Drawable renderer with callback attached
+};
+
+} // namespace Dali::Internal
+
+#endif // DALI_INTERNAL_DRAWABLE_ACTOR_H
index fc9b85a..bf68b0e 100644 (file)
@@ -1180,6 +1180,13 @@ const Vector4& Renderer::GetBlendColor() const
   return Color::TRANSPARENT; // GL default
 }
 
+void Renderer::SetRenderCallback(RenderCallback* callback)
+{
+  Dali::Internal::SceneGraph::SetRenderCallbackMessage(GetEventThreadServices(),
+                                                       GetRendererSceneObject(),
+                                                       callback);
+}
+
 } // namespace Internal
 
 } // namespace Dali
index 17818ab..3a5ffa1 100644 (file)
@@ -211,6 +211,11 @@ public: // Default property extensions from Object
    */
   void AddDrawCommand(const Dali::DevelRenderer::DrawCommand& command);
 
+  /**
+   * @copydoc Dali::Renderer::SetRenderCallback()
+   */
+  void SetRenderCallback(RenderCallback* callback);
+
 protected: // implementation
   /**
    * @brief Constructor.
index 73911cc..c7ec680 100644 (file)
@@ -20,6 +20,7 @@ SET( internal_src_files
   ${internal_src_dir}/event/actors/actor-parent-impl.cpp
   ${internal_src_dir}/event/actors/actor-sizer.cpp
   ${internal_src_dir}/event/actors/custom-actor-internal.cpp
+  ${internal_src_dir}/event/actors/drawable-actor-impl.cpp
   ${internal_src_dir}/event/actors/layer-impl.cpp
   ${internal_src_dir}/event/actors/layer-list.cpp
   ${internal_src_dir}/event/actors/camera-actor-impl.cpp
index b76c15f..3a84873 100644 (file)
@@ -35,6 +35,7 @@
 #include <dali/internal/render/shaders/program.h>
 #include <dali/internal/render/shaders/render-shader.h>
 #include <dali/internal/update/common/uniform-map.h>
+#include <dali/public-api/signals/render-callback.h>
 
 namespace Dali::Internal
 {
@@ -441,6 +442,25 @@ bool Renderer::Render(Graphics::CommandBuffer&                             comma
     return false;
   }
 
+  // Check if there is render callback
+  if(mRenderCallback)
+  {
+    Graphics::DrawNativeInfo info{};
+    info.api      = Graphics::DrawNativeAPI::GLES;
+    info.callback = &static_cast<Dali::CallbackBase&>(*mRenderCallback);
+    info.userData = &mRenderCallbackInput;
+    info.reserved = nullptr;
+
+    // pass render callback input
+    mRenderCallbackInput.size       = size;
+    mRenderCallbackInput.projection = projectionMatrix;
+    Matrix::Multiply(mRenderCallbackInput.mvp, modelViewMatrix, projectionMatrix);
+
+    // submit draw
+    commandBuffer.DrawNative(&info);
+    return true;
+  }
+
   // Prepare commands
   std::vector<DevelRenderer::DrawCommand*> commands;
   for(auto& cmd : mDrawCommands)
@@ -800,7 +820,7 @@ bool Renderer::Updated(BufferIndex bufferIndex, const SceneGraph::NodeDataProvid
     return true;
   }
 
-  if(mShaderChanged || mGeometry->AttributesChanged())
+  if(mRenderCallback || mShaderChanged || mGeometry->AttributesChanged())
   {
     return true;
   }
@@ -868,6 +888,11 @@ Graphics::Pipeline& Renderer::PrepareGraphicsPipeline(
   return *pipelineResult.pipeline;
 }
 
+void Renderer::SetRenderCallback(RenderCallback* callback)
+{
+  mRenderCallback = callback;
+}
+
 } // namespace Render
 
 } // namespace Dali::Internal
index fe0e07e..eb7764c 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_RENDERER_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.
@@ -22,6 +22,7 @@
 #include <dali/public-api/math/matrix.h>
 #include <dali/public-api/math/vector4.h>
 #include <dali/public-api/rendering/texture-set.h>
+#include <dali/public-api/signals/render-callback.h>
 
 #include <dali/graphics-api/graphics-controller.h>
 #include <dali/integration-api/debug.h>
@@ -381,6 +382,23 @@ public:
               uint32_t                                             queueIndex);
 
   /**
+   * Sets RenderCallback object
+   *
+   * @param[in] callback Valid pointer to RenderCallback object
+   */
+  void SetRenderCallback(RenderCallback* callback);
+
+  /**
+   * Returns currently set RenderCallback object
+   *
+   * @return Valid pointer to RenderCallback object or nullptr
+   */
+  RenderCallback* GetRenderCallback()
+  {
+    return mRenderCallback;
+  }
+
+  /**
    * Write the renderer's sort attributes to the passed in reference
    *
    * @param[out] sortAttributes
@@ -563,6 +581,8 @@ private:
   bool                  mUpdated : 1;
 
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; // Devel stuff
+  RenderCallback*                               mRenderCallback{nullptr};
+  RenderCallbackInput                           mRenderCallbackInput{};
 };
 
 } // namespace Render
index ff4d120..1ff28a8 100644 (file)
@@ -194,7 +194,10 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
   Matrix  nodeModelViewMatrix(false);
   bool    nodeModelViewMatrixSet(false);
 
-  if(cull && renderable.mRenderer && !renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)
+  // Don't cull items which have render callback
+  bool hasRenderCallback = (renderable.mRenderer && renderable.mRenderer->GetRenderCallback());
+
+  if(cull && renderable.mRenderer && (hasRenderCallback || (!renderable.mRenderer->GetShader().HintEnabled(Dali::Shader::Hint::MODIFIES_GEOMETRY) && node->GetClippingMode() == ClippingMode::DISABLED)))
   {
     const Vector4& boundingSphere = node->GetBoundingSphere();
     inside                        = (boundingSphere.w > Math::MACHINE_EPSILON_1000) &&
@@ -222,10 +225,18 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
 
   if(inside)
   {
-    Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *node) : Renderer::OPAQUE;
+    bool skipRender(false);
+    bool isOpaque = true;
+    if(!hasRenderCallback)
+    {
+      Renderer::OpacityType opacityType = renderable.mRenderer ? renderable.mRenderer->GetOpacityType(updateBufferIndex, *node) : Renderer::OPAQUE;
+
+      // We can skip render when node is not clipping and transparent
+      skipRender = (opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
+
+      isOpaque = (opacityType == Renderer::OPAQUE);
+    }
 
-    // We can skip render when node is not clipping and transparent
-    const bool skipRender(opacityType == Renderer::TRANSPARENT && node->GetClippingMode() == ClippingMode::DISABLED);
     if(!skipRender)
     {
       // Get the next free RenderItem.
@@ -237,7 +248,7 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
       auto& partialRenderingCacheInfo = node->GetPartialRenderingData().GetCurrentCacheInfo();
 
       partialRenderingCacheInfo.node       = node;
-      partialRenderingCacheInfo.isOpaque   = (opacityType == Renderer::OPAQUE);
+      partialRenderingCacheInfo.isOpaque   = isOpaque;
       partialRenderingCacheInfo.renderer   = renderable.mRenderer;
       partialRenderingCacheInfo.color      = node->GetWorldColor(updateBufferIndex);
       partialRenderingCacheInfo.depthIndex = node->GetDepthIndex();
@@ -248,7 +259,7 @@ inline void AddRendererToRenderList(BufferIndex         updateBufferIndex,
       }
 
       item.mNode     = node;
-      item.mIsOpaque = (opacityType == Renderer::OPAQUE);
+      item.mIsOpaque = isOpaque;
       item.mColor    = node->GetColor(updateBufferIndex);
 
       item.mDepthIndex = 0;
index 7be96da..9e982a8 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.
@@ -116,7 +116,8 @@ enum Flags
   RESEND_STENCIL_OPERATION_ON_Z_PASS = 1 << 17,
   RESEND_WRITE_TO_COLOR_BUFFER       = 1 << 18,
   RESEND_SHADER                      = 1 << 19,
-  RESEND_DRAW_COMMANDS               = 1 << 20
+  RESEND_DRAW_COMMANDS               = 1 << 20,
+  RESEND_SET_RENDER_CALLBACK         = 1 << 21
 };
 
 } // Anonymous namespace
@@ -367,6 +368,13 @@ bool Renderer::PrepareRender(BufferIndex updateBufferIndex)
       new(slot) DerivedType(mRenderer, &Render::Renderer::SetShaderChanged, true);
     }
 
+    if(mResendFlag & RESEND_SET_RENDER_CALLBACK)
+    {
+      using DerivedType = MessageValue1<Render::Renderer, Dali::RenderCallback*>;
+      uint32_t* slot    = mSceneController->GetRenderQueue().ReserveMessageSlot(updateBufferIndex, sizeof(DerivedType));
+      new(slot) DerivedType(mRenderer, &Render::Renderer::SetRenderCallback, mRenderCallback);
+    }
+
     mResendFlag = 0;
   }
 
@@ -601,6 +609,12 @@ void Renderer::SetStencilOperationOnZPass(StencilOperation::Type stencilOperatio
   mResendFlag |= RESEND_STENCIL_OPERATION_ON_Z_PASS;
 }
 
+void Renderer::SetRenderCallback(RenderCallback* callback)
+{
+  mRenderCallback = callback;
+  mResendFlag |= RESEND_SET_RENDER_CALLBACK;
+}
+
 const Render::Renderer::StencilParameters& Renderer::GetStencilParameters() const
 {
   return mStencilParameters;
index d818dcd..b7c1aef 100644 (file)
@@ -381,6 +381,23 @@ public:
     return *this;
   };
 
+  /**
+   * Sets RenderCallback object
+   *
+   * @param[in] callback Valid pointer to RenderCallback object
+   */
+  void SetRenderCallback(RenderCallback* callback);
+
+  /**
+   * Returns currently set RenderCallback pointer
+   *
+   * @return RenderCallback pointer or nullptr
+   */
+  RenderCallback* GetRenderCallback()
+  {
+    return mRenderCallback;
+  }
+
 public: // Implementation of ConnectionChangePropagator
   /**
    * @copydoc ConnectionChangePropagator::AddObserver
@@ -488,6 +505,7 @@ private:
   bool                           mPremultipledAlphaEnabled : 1; ///< Flag indicating whether the Pre-multiplied Alpha Blending is required
 
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands;
+  Dali::RenderCallback*                         mRenderCallback{nullptr};
 
 public:
   AnimatableProperty<float> mOpacity;    ///< The opacity value
@@ -749,6 +767,16 @@ inline void SetDrawCommandsMessage(EventThreadServices& eventThreadServices, con
   new(slot) LocalType(&renderer, &Renderer::SetDrawCommands, pDrawCommands, size);
 }
 
+inline void SetRenderCallbackMessage(EventThreadServices& eventThreadServices, const Renderer& renderer, Dali::RenderCallback* callback)
+{
+  using LocalType = MessageValue1<Renderer, Dali::RenderCallback*>;
+
+  // Reserve some memory inside the message queue
+  uint32_t* slot = eventThreadServices.ReserveMessageSlot(sizeof(LocalType));
+
+  new(slot) LocalType(&renderer, &Renderer::SetRenderCallback, callback);
+}
+
 } // namespace SceneGraph
 } // namespace Internal
 } // namespace Dali
diff --git a/dali/public-api/actors/drawable-actor.cpp b/dali/public-api/actors/drawable-actor.cpp
new file mode 100644 (file)
index 0000000..b789c26
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ * 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/public-api/actors/drawable-actor.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/drawable-actor-impl.h>
+
+using DrawableActorImpl = Dali::Internal::DrawableActor;
+
+namespace Dali
+{
+DrawableActor DrawableActor::New(RenderCallback& callback)
+{
+  auto internal = Internal::DrawableActor::New(&callback);
+  return DrawableActor(internal.Get());
+}
+
+DrawableActor::DrawableActor(Internal::DrawableActor* internal)
+: Actor(internal)
+{
+}
+
+} // namespace Dali
\ No newline at end of file
diff --git a/dali/public-api/actors/drawable-actor.h b/dali/public-api/actors/drawable-actor.h
new file mode 100644 (file)
index 0000000..72a94c2
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef DALI_DRAWABLE_ACTOR_H
+#define DALI_DRAWABLE_ACTOR_H
+
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/signals/render-callback.h>
+
+// EXTERNAL INCLUDES
+#include <memory>
+
+namespace Dali
+{
+namespace Internal
+{
+class DrawableActor;
+}
+
+/**
+ * @class DrawableActor
+ *
+ * DrawableActor is a special type of Actor that allows attaching
+ * DrawableCallback in order to pass custom native graphics API
+ * calls (like GLES).
+ *
+ * @SINCE_2_1.15
+ */
+class DALI_CORE_API DrawableActor : public Actor
+{
+public:
+  /**
+   * @brief Creates new DrawableActor instance
+   *
+   * @SINCE_2_1.15
+   * @param[in] callback Reference to the valid DrawableCallback object
+   * @return Handle to the new DrawableActor
+   */
+  static DrawableActor New(RenderCallback& callback);
+
+  /**
+   * @brief Constructor
+   *
+   * @SINCE_2_1.15
+   */
+  DrawableActor() = default;
+
+private:
+  explicit DrawableActor(Internal::DrawableActor* internal);
+};
+} // namespace Dali
+
+#endif // DALI_DRAWABLE_ACTOR_H
index 70d8684..a3b27bf 100644 (file)
@@ -7,6 +7,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/actors/camera-actor.cpp
   ${public_api_src_dir}/actors/custom-actor.cpp
   ${public_api_src_dir}/actors/custom-actor-impl.cpp
+  ${public_api_src_dir}/actors/drawable-actor.cpp
   ${public_api_src_dir}/actors/layer.cpp
   ${public_api_src_dir}/animation/animation.cpp
   ${public_api_src_dir}/animation/alpha-function.cpp
@@ -80,6 +81,7 @@ SET( public_api_src_files
   ${public_api_src_dir}/signals/signal-slot-observers.cpp
   ${public_api_src_dir}/signals/base-signal.cpp
   ${public_api_src_dir}/signals/functor-delegate.cpp
+  ${public_api_src_dir}/signals/render-callback.cpp
   ${public_api_src_dir}/object/type-info.cpp
   ${public_api_src_dir}/object/type-registry.cpp
   ${public_api_src_dir}/object/weak-handle.cpp
@@ -99,6 +101,7 @@ SET( public_api_core_actors_header_files
   ${public_api_src_dir}/actors/camera-actor.h
   ${public_api_src_dir}/actors/custom-actor.h
   ${public_api_src_dir}/actors/custom-actor-impl.h
+  ${public_api_src_dir}/actors/drawable-actor.h
   ${public_api_src_dir}/actors/draw-mode.h
   ${public_api_src_dir}/actors/layer.h
   ${public_api_src_dir}/actors/sampling.h
@@ -241,6 +244,7 @@ SET( public_api_core_signals_header_files
   ${public_api_src_dir}/signals/signal-slot-connections.h
   ${public_api_src_dir}/signals/signal-slot-observers.h
   ${public_api_src_dir}/signals/slot-delegate.h
+  ${public_api_src_dir}/signals/render-callback.h
 )
 
 
index f857986..15b2df3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 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.
@@ -76,6 +76,11 @@ void Renderer::SetShader(Shader& shader)
   GetImplementation(*this).SetShader(GetImplementation(shader));
 }
 
+void Renderer::SetRenderCallback(RenderCallback* callback)
+{
+  GetImplementation(*this).SetRenderCallback(callback);
+}
+
 Shader Renderer::GetShader() const
 {
   return Dali::Shader(GetImplementation(*this).GetShader().Get());
index d434f72..21e2b24 100644 (file)
@@ -26,6 +26,8 @@
 
 namespace Dali
 {
+class RenderCallback;
+
 /**
  * @addtogroup dali_core_rendering_effects
  * @{
@@ -544,6 +546,14 @@ public:
    */
   Shader GetShader() const;
 
+  /**
+   * @brief Sets RenderCallback to be used for native rendering
+   *
+   * @SINCE_2_1.15
+   * @param[in] callback Pointer to a valid RenderCallback object
+   */
+  void SetRenderCallback(RenderCallback* callback);
+
 public:
   /// @cond internal
   /**
diff --git a/dali/public-api/signals/render-callback.cpp b/dali/public-api/signals/render-callback.cpp
new file mode 100644 (file)
index 0000000..1e55e2b
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+* 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.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*/
+
+#include <dali/public-api/signals/render-callback.h>
diff --git a/dali/public-api/signals/render-callback.h b/dali/public-api/signals/render-callback.h
new file mode 100644 (file)
index 0000000..64f0a18
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef DALI_RENDER_CALLBACK_H
+#define DALI_RENDER_CALLBACK_H
+
+/*
+ * 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.
+ * 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.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/signals/callback.h>
+
+// EXTERNAL INCLUDES
+#include <memory>
+
+namespace Dali
+{
+/**
+ * @class RenderCallbackInput
+ *
+ * This structure contains data to be passed into the RenderCallback
+ * functor.
+ *
+ * RenderCallbackInput inherits from Graphics::NativeDrawInput
+ *
+ * @SINCE_2_1.14
+ */
+struct RenderCallbackInput
+{
+  Matrix mvp;
+  Matrix projection;
+  Size   size;
+};
+
+/**
+ * @class DrawableCallback
+ *
+ * The class wraps CallbackBase object ensuring its type-safe assignment
+ *
+ * @SINCE_2_1.14
+ */
+class RenderCallback
+{
+public:
+  /**
+   * Templated member function type
+   */
+  template<class T>
+  using FuncType = bool (T::*)(const RenderCallbackInput&);
+
+  /**
+   * @brief Constructor of RenderCallback
+   *
+   * @param[in] object Object to invoke
+   * @param[in] func Member function to invoke
+   *
+   * @SINCE_2_1.14
+   */
+  template<class T>
+  RenderCallback(T* object, FuncType<T> func)
+  : mCallback(MakeCallback(object, func))
+  {
+  }
+
+  /**
+   * @brief Creates new instance of RenderCallback
+   *
+   * @SINCE_2_1.14
+   * @param[in] object Object to invoke
+   * @param[in] func Member function to invoke
+   * @return Unique pointer to the RenderCallback instance
+   */
+  template<class T>
+  static std::unique_ptr<RenderCallback> New(T* object, FuncType<T> func)
+  {
+    return std::make_unique<RenderCallback>(object, func);
+  }
+
+  /**
+   * @brief Explicit cast operator
+   *
+   * @SINCE_2_1.14
+   * @return casts RenderCallback to CallbackBase object
+   */
+  explicit operator CallbackBase*()
+  {
+    return mCallback.get();
+  }
+
+  /**
+   * @brief Explicit cast operator
+   *
+   * @SINCE_2_1.14
+   * @return casts RenderCallback to CallbackBase object
+   */
+  explicit operator CallbackBase&()
+  {
+    return *mCallback;
+  }
+
+private:
+  std::unique_ptr<CallbackBase> mCallback; //< Callback base object
+};
+} // namespace Dali
+
+#endif // DALI_RENDER_CALLBACK_H