DirectRendering with DrawableView support and list of used resources 11/276111/8
authorAdam Bialogonski <adam.b@samsung.com>
Wed, 6 Jul 2022 10:40:40 +0000 (11:40 +0100)
committerAdam Bialogonski <adam.b@samsung.com>
Wed, 6 Jul 2022 10:41:27 +0000 (11:41 +0100)
- Added GLESNativeInfo inner struct (in NativeDrawInfo) to extract shared context
- The native draw can use list of textures and buffers that the callback will use
- The used resources are being passed into the callback so it can access DALi objects

Change-Id: I6b162c0741d95ab3698185d05e2a78f4b0ab02f7

automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp
automated-tests/src/dali/utc-Dali-DrawableActor.cpp
dali/graphics-api/graphics-command-buffer.h
dali/graphics-api/graphics-types.h
dali/internal/render/common/render-algorithms.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/render/renderers/render-renderer.h
dali/internal/render/renderers/render-texture.h
dali/public-api/file.list
dali/public-api/signals/render-callback.cpp [deleted file]
dali/public-api/signals/render-callback.h

index 6a8eab4..fc176e5 100644 (file)
@@ -32,6 +32,8 @@
 #include <iostream>
 #include <sstream>
 
+#include <any>
+
 namespace Dali
 {
 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
@@ -696,6 +698,13 @@ void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& com
       case CommandType::DRAW_NATIVE:
       {
         auto info = &cmd.data.draw.drawNative.drawNativeInfo;
+
+        if(info->glesNativeInfo.eglSharedContextStoragePointer)
+        {
+          auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
+          *anyContext      = reinterpret_cast<void*>(0x12345678u);
+        }
+
         CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
         break;
       }
index e413029..f200991 100644 (file)
@@ -28,6 +28,19 @@ struct DrawableObject
     return false;
   }
 
+  bool RenderWithTextures(const RenderCallbackInput& inputData)
+  {
+    // Store the size of rendered area
+    size = inputData.size;
+
+    auto count = inputData.textureBindings.size();
+
+    // test whether number of textures matches 1
+    DALI_TEST_EQUALS(count, 1, TEST_LOCATION);
+
+    return false;
+  }
+
   Size size{};
 };
 
@@ -78,7 +91,40 @@ int UtcDaliDrawableActor1P(void)
   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;
+}
+
+int UtcRenderCallbackTextureBindingP(void)
+{
+  tet_infoline("Testing RenderCallback texture bindings");
+  TestApplication application;
+
+  DrawableObject drawable{};
+
+  auto callback = RenderCallback::New<DrawableObject>(&drawable, &DrawableObject::RenderWithTextures);
+
+  // Prepare texture
+  Texture   texture   = Texture::New(Dali::TextureType::TEXTURE_2D, Pixel::Format::RGBA8888, 512, 512);
+  auto*     data      = reinterpret_cast<uint8_t*>(malloc(512 * 512 * 4));
+  PixelData pixelData = PixelData::New(data, 512 * 512 * 4, 512, 512, Pixel::Format::RGBA8888, PixelData::ReleaseFunction::FREE);
+  texture.Upload(pixelData);
+
+  std::vector<Texture> texturesToBind;
+  texturesToBind.push_back(texture);
+  callback->BindTextureResources(texturesToBind);
+
+  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)
   DALI_TEST_EQUALS(drawable.size, Size(100, 100), TEST_LOCATION);
 
   END_TEST;
index 61dd8df..800583f 100644 (file)
@@ -98,10 +98,30 @@ enum class DrawNativeAPI
 
 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
+  DrawNativeAPI       api;      ///< API used by the callback
+  Dali::CallbackBase* callback; ///< Callback pointer
+
+  /**
+   * The call allows binding the resource so they can be passed into the callback
+   * Each resource will pass API specific data (for example GL texture and buffer ids)
+   */
+  Graphics::Texture** textureList;  ///< Textures to be used by the call
+  uint32_t            textureCount; ///< Number of texture used by the callback
+  Graphics::Buffer**  bufferList;   ///< Buffers to be used by the call
+  uint32_t            bufferCount;  ///< Number of buffers used by the callback
+
+  /**
+   * The GLES api specific structure that stores pointers to objects to be filled when requested
+   * by caller. The structure cointains void* to avoid creating any complex constructors and keep
+   * the class trivial.
+   */
+  struct GLESNativeInfo
+  {
+    void* eglSharedContextStoragePointer; ///< Indicates the storage object to pass the shared context, must be null if not in use
+  } glesNativeInfo;
+
+  void* userData; ///< Data passed into the callback (unspecified type, callback should decode it)
+  void* reserved; ///< Reserved for internal use
 };
 
 /**
index 2ce4b5a..e75e449 100644 (file)
@@ -994,6 +994,7 @@ struct TextureProperties
   bool     packed;                   ///< Texture is packed
   Extent2D extent2D;                 ///< Size of texture
   bool     directWriteAccessEnabled; ///< Direct write access (mappable textures)
+  uint32_t nativeHandle;             ///< Native texture handle
 };
 
 /**
index efcb575..ff82cd3 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.
@@ -463,6 +463,17 @@ inline void RenderAlgorithms::SetupScissorClipping(
       commandBuffer.SetScissor(Rect2DFromClippingBox(useScissorBox, orientation, graphicsViewport));
     }
   }
+  else
+  {
+    // If there is render callback on the Renderer we need to calculate the scissor box and provide it to the
+    // callback so it may be clipped
+    if(item.mRenderer->GetRenderCallback())
+    {
+      // store clipping box inside the render callback input structure
+      auto& input       = item.mRenderer->GetRenderCallbackInput();
+      input.clippingBox = ClippingBox(RenderItem::CalculateViewportSpaceAABB(item.mModelViewMatrix, item.mSize, mViewportRectangle.width, mViewportRectangle.height));
+    }
+  }
 }
 
 inline void RenderAlgorithms::SetupClipping(const RenderItem&                   item,
index b481a8a..80dbc6f 100644 (file)
@@ -22,6 +22,7 @@
 #include <dali/graphics-api/graphics-types.h>
 #include <dali/integration-api/debug.h>
 #include <dali/internal/common/image-sampler.h>
+#include <dali/internal/event/rendering/texture-impl.h>
 #include <dali/internal/render/common/render-instruction.h>
 #include <dali/internal/render/data-providers/node-data-provider.h>
 #include <dali/internal/render/data-providers/uniform-map-data-provider.h>
@@ -447,11 +448,36 @@ bool Renderer::Render(Graphics::CommandBuffer&                             comma
     info.api      = Graphics::DrawNativeAPI::GLES;
     info.callback = &static_cast<Dali::CallbackBase&>(*mRenderCallback);
     info.userData = &mRenderCallbackInput;
-    info.reserved = nullptr;
+
+    // Set storage for the context to be used
+    info.glesNativeInfo.eglSharedContextStoragePointer = &mRenderCallbackInput.eglContext;
+    info.reserved                                      = nullptr;
+
+    auto& textureResources = mRenderCallback->GetTextureResources();
+
+    if(!textureResources.empty())
+    {
+      mRenderCallbackTextureBindings.clear();
+      mRenderCallbackInput.textureBindings.resize(textureResources.size());
+      auto i = 0u;
+      for(auto& texture : textureResources)
+      {
+        auto& textureImpl     = GetImplementation(texture);
+        auto  graphicsTexture = textureImpl.GetRenderObject()->GetGraphicsObject();
+
+        const auto& properties = mGraphicsController->GetTextureProperties(*graphicsTexture);
+
+        mRenderCallbackTextureBindings.emplace_back(graphicsTexture);
+        mRenderCallbackInput.textureBindings[i] = properties.nativeHandle;
+      }
+      info.textureCount = mRenderCallbackTextureBindings.size();
+      info.textureList  = mRenderCallbackTextureBindings.data();
+    }
 
     // pass render callback input
     mRenderCallbackInput.size       = size;
     mRenderCallbackInput.projection = projectionMatrix;
+
     Matrix::Multiply(mRenderCallbackInput.mvp, modelViewMatrix, projectionMatrix);
 
     // submit draw
index 1523aa4..b99ac4e 100644 (file)
@@ -400,6 +400,15 @@ public:
   }
 
   /**
+   * Returns internal RenderCallbackInput structure
+   * @return Valid reference to the RenderCallbackInput
+   */
+  RenderCallbackInput& GetRenderCallbackInput()
+  {
+    return mRenderCallbackInput;
+  }
+
+  /**
    * Write the renderer's sort attributes to the passed in reference
    *
    * @param[out] sortAttributes
@@ -589,6 +598,7 @@ private:
   std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; // Devel stuff
   RenderCallback*                               mRenderCallback{nullptr};
   RenderCallbackInput                           mRenderCallbackInput{};
+  std::vector<Graphics::Texture*>               mRenderCallbackTextureBindings{};
 };
 
 } // namespace Render
index ea8cd13..a3945d8 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_RENDER_TEXTURE_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.
index 97af7b0..33c8153 100644 (file)
@@ -82,7 +82,6 @@ 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
diff --git a/dali/public-api/signals/render-callback.cpp b/dali/public-api/signals/render-callback.cpp
deleted file mode 100644 (file)
index 1e55e2b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-* 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>
index 64f0a18..cc7b8a6 100644 (file)
 
 // INTERNAL INCLUDES
 #include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/rect.h>
 #include <dali/public-api/math/vector2.h>
+#include <dali/public-api/rendering/texture.h>
 #include <dali/public-api/signals/callback.h>
 
 // EXTERNAL INCLUDES
+#include <any>
 #include <memory>
+#include <utility>
+#include <vector>
 
 namespace Dali
 {
@@ -36,23 +41,32 @@ namespace Dali
  *
  * RenderCallbackInput inherits from Graphics::NativeDrawInput
  *
- * @SINCE_2_1.14
+ * @SINCE_2_1.30
  */
-struct RenderCallbackInput
+struct DALI_CORE_API RenderCallbackInput
 {
-  Matrix mvp;
-  Matrix projection;
-  Size   size;
+  Matrix                mvp;
+  Matrix                projection;
+  Size                  size;
+  Rect<int32_t>         clippingBox;
+  std::vector<uint32_t> textureBindings;
+
+  std::any eglContext; ///< Storage for EGL Context
 };
 
 /**
- * @class DrawableCallback
+ * @class RenderCallback
+ *
+ * RenderCallback is used by the direct rendering feature and allows injecting
+ * custom render code (using native API such as GL directly) into the DALi
+ * rendering stream. The RenderCallback will be executed within own context (unless
+ * native API is context-less) to maintain state separation from DALi render state.
  *
  * The class wraps CallbackBase object ensuring its type-safe assignment
  *
  * @SINCE_2_1.14
  */
-class RenderCallback
+class DALI_CORE_API RenderCallback
 {
 public:
   /**
@@ -101,6 +115,33 @@ public:
   }
 
   /**
+   * @brief Binds DALi textures to the callback
+   *
+   * The textures that are bound to the callback will be passed upon
+   * callback execution providing native handles (like GL name) so they
+   * can be used alongside with custom GL code.
+   *
+   * Binding texture does not affect lifecycle and it's up to the client-side
+   * to make sure the resource is alive when used inside the callback.
+   *
+   * @param[in] textures List of DALi textures to be bound to the callback
+   * @SINCE_2_1.30
+   */
+  void BindTextureResources(std::vector<Dali::Texture> textures)
+  {
+    mTextureResources = std::move(textures);
+  }
+
+  /**
+   * @brief Returns list of DALi textures bound to the callback
+   *
+   * @return list of textures
+   */
+  [[nodiscard]] const std::vector<Dali::Texture>& GetTextureResources() const
+  {
+    return mTextureResources;
+  }
+  /**
    * @brief Explicit cast operator
    *
    * @SINCE_2_1.14
@@ -111,8 +152,26 @@ public:
     return *mCallback;
   }
 
+  /**
+   * @brief Returns input data passed to the callback upon execution
+   *
+   * The input data will be filled by the DALi and Graphics backend
+   * providing DALi rendering related data (such as clipping box) as well as
+   * Graphics native API related data (like EGLContext for GL).
+   *
+   * @SINCE_2_1.30
+   * @return Valid RenderCallbackInput structure
+   */
+  RenderCallbackInput& GetRenderCallbackInput()
+  {
+    return mRenderCallbackInput;
+  }
+
 private:
   std::unique_ptr<CallbackBase> mCallback; //< Callback base object
+  RenderCallbackInput           mRenderCallbackInput;
+
+  std::vector<Dali::Texture> mTextureResources{};
 };
 } // namespace Dali