- 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
#include <iostream>
#include <sstream>
+#include <any>
+
namespace Dali
{
std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
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;
}
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{};
};
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;
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
};
/**
bool packed; ///< Texture is packed
Extent2D extent2D; ///< Size of texture
bool directWriteAccessEnabled; ///< Direct write access (mappable textures)
+ uint32_t nativeHandle; ///< Native texture handle
};
/**
/*
- * 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.
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,
#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>
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
}
/**
+ * 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
std::vector<Dali::DevelRenderer::DrawCommand> mDrawCommands; // Devel stuff
RenderCallback* mRenderCallback{nullptr};
RenderCallbackInput mRenderCallbackInput{};
+ std::vector<Graphics::Texture*> mRenderCallbackTextureBindings{};
};
} // namespace Render
#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.
${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
+++ /dev/null
-/*
-* 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>
// 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
{
*
* 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:
/**
}
/**
+ * @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
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