From 27171a26226cd4758d41ca210112f53a0ee8d8e4 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Fri, 16 Jun 2023 16:22:25 +0900 Subject: [PATCH] Make Texture can use Uploaded data infomation Make new way to use Dali::Texture that don't know the destination size. For special case, if width and height are both 0, 0, and format is INVALID, let we make to use uploaded pixeldata's size and format. Change-Id: Ieec3f102d2568f3481344e164c5c29ff20c6a604 Signed-off-by: Eunki, Hong --- automated-tests/src/dali/utc-Dali-Texture.cpp | 84 ++++++++++++++++++++++ dali/internal/event/rendering/texture-impl.cpp | 25 ++++--- dali/internal/event/rendering/texture-impl.h | 2 + dali/internal/render/common/render-manager.cpp | 16 +---- .../render/renderers/render-frame-buffer.h | 11 +-- dali/internal/render/renderers/render-texture.cpp | 52 +++++++++----- dali/internal/render/renderers/render-texture.h | 40 +++++++---- dali/public-api/rendering/texture.cpp | 8 ++- dali/public-api/rendering/texture.h | 13 +++- 9 files changed, 186 insertions(+), 65 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Texture.cpp b/automated-tests/src/dali/utc-Dali-Texture.cpp index 3b63aa5..c817afa 100644 --- a/automated-tests/src/dali/utc-Dali-Texture.cpp +++ b/automated-tests/src/dali/utc-Dali-Texture.cpp @@ -70,6 +70,16 @@ int UtcDaliTextureNew03(void) END_TEST; } +int UtcDaliTextureNew04(void) +{ + TestApplication application; + + Texture texture = Texture::New(TextureType::TEXTURE_2D); + + DALI_TEST_CHECK(texture); + END_TEST; +} + int UtcDaliTextureCopyConstructor(void) { TestApplication application; @@ -653,6 +663,80 @@ int UtcDaliTextureUpload07(void) END_TEST; } +int UtcDaliTextureUpload08(void) +{ + TestApplication application; + + //Create the texture without pixel information + tet_infoline("Creating a Texure without any size/format information"); + Texture texture = Texture::New(TextureType::TEXTURE_2D); + + application.GetGlAbstraction().EnableTextureCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace(); + + tet_infoline("TexImage2D should not be called with a null pointer to reserve storage for the texture in the gpu"); + DALI_TEST_CHECK(!callStack.FindMethod("GenTextures")); + DALI_TEST_CHECK(!callStack.FindMethod("TexImage2D")); + + tet_infoline("Upload data to the texture"); + unsigned int width(64); + unsigned int height(64); + callStack.Reset(); + + tet_infoline("Creating a RGB pixel buffer and adding that to the texture to ensure it is handled correctly"); + unsigned int bufferSize(width * height * 3); + unsigned char* buffer = reinterpret_cast(malloc(bufferSize)); + PixelData pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGB888, PixelData::FREE); + texture.Upload(pixelData); + application.SendNotification(); + application.Render(); + + tet_infoline("GetWidth / GetHeight / GetPixelFormat will return uploaded value"); + DALI_TEST_EQUALS(texture.GetWidth(), width, TEST_LOCATION); + DALI_TEST_EQUALS(texture.GetHeight(), height, TEST_LOCATION); + DALI_TEST_EQUALS(texture.GetPixelFormat(), Pixel::RGB888, TEST_LOCATION); + + tet_infoline("TexImage2D should be called to upload the data"); + DALI_TEST_CHECK(callStack.FindMethod("GenTextures")); + { + std::stringstream out; + out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + + tet_infoline("Upload another data to the texture"); + width = 40; + height = 73; + callStack.Reset(); + + tet_infoline("Creating a RGB pixel buffer and adding that to the texture to ensure it is handled correctly"); + bufferSize = width * height * 4; + buffer = reinterpret_cast(malloc(bufferSize)); + pixelData = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); + texture.Upload(pixelData); + application.SendNotification(); + application.Render(); + + tet_infoline("TexImage2D should be generate new graphics, and be called to upload the data"); + DALI_TEST_CHECK(callStack.FindMethod("GenTextures")); + { + std::stringstream out; + out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + + tet_infoline("GetWidth / GetHeight / GetPixelFormat will return uploaded value"); + DALI_TEST_EQUALS(texture.GetWidth(), width, TEST_LOCATION); + DALI_TEST_EQUALS(texture.GetHeight(), height, TEST_LOCATION); + DALI_TEST_EQUALS(texture.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION); + + END_TEST; +} + int UtcDaliTextureUploadSubPixelData01(void) { TestApplication application; diff --git a/dali/internal/event/rendering/texture-impl.cpp b/dali/internal/event/rendering/texture-impl.cpp index c8a69b2..e582632 100644 --- a/dali/internal/event/rendering/texture-impl.cpp +++ b/dali/internal/event/rendering/texture-impl.cpp @@ -54,7 +54,8 @@ Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions s mNativeImage(), mSize(size), mType(type), - mFormat(format) + mFormat(format), + mUseUploadedParameter(mSize.GetWidth() == 0u && mSize.GetHeight() == 0u && mFormat == Pixel::INVALID) { } @@ -64,7 +65,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface) mNativeImage(nativeImageInterface), mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()), mType(TextureType::TEXTURE_2D), - mFormat(Pixel::RGB888) + mFormat(Pixel::RGB888), + mUseUploadedParameter(false) { } @@ -133,10 +135,8 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData, constexpr auto max_value = std::numeric_limits::max(); DALI_ASSERT_ALWAYS(layer < max_value && mipmap < max_value && - xOffset < max_value && - yOffset < max_value && - width < max_value && - height < max_value && + xOffset + width < max_value && + yOffset + height < max_value && dataWidth < max_value && dataHeight < max_value && "Parameter value out of range"); @@ -158,7 +158,7 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData, else { Pixel::Format pixelDataFormat = pixelData->GetPixelFormat(); - if((pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888))) + if((mUseUploadedParameter || pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888))) { if(pixelDataSize < width * height) { @@ -177,13 +177,20 @@ bool Texture::UploadSubPixelData(PixelDataPtr pixelData, { DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n"); } - else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) || - (yOffset + height > (mSize.GetHeight() / (1u << mipmap)))) + else if(!mUseUploadedParameter && + ((xOffset + width > (static_cast(mSize.GetWidth()) >> mipmap)) || + (yOffset + height > (static_cast(mSize.GetHeight()) >> mipmap)))) { DALI_LOG_ERROR("Texture update area out of bounds\n"); } else { + if(mUseUploadedParameter) + { + mSize = ImageDimensions(xOffset + width, yOffset + height); + mFormat = pixelDataFormat; + } + //Parameters are correct. Send message to upload data to the texture UploadParams params = {static_cast(dataXOffset), static_cast(dataYOffset), diff --git a/dali/internal/event/rendering/texture-impl.h b/dali/internal/event/rendering/texture-impl.h index 3f6166b..f97fd5a 100644 --- a/dali/internal/event/rendering/texture-impl.h +++ b/dali/internal/event/rendering/texture-impl.h @@ -194,6 +194,8 @@ private: // data ImageDimensions mSize; ///< Size of the texture Dali::TextureType::Type mType; ///< Texture type (cached) Pixel::Format mFormat; ///< Pixel format + + bool mUseUploadedParameter : 1; ///< Whether ths texture size and format depend on uploaded image or not. }; } // namespace Internal diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp index afef026..adb9ba0 100644 --- a/dali/internal/render/common/render-manager.cpp +++ b/dali/internal/render/common/render-manager.cpp @@ -202,10 +202,9 @@ struct RenderManager::Impl Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available - std::unique_ptr threadPool; ///< The thread pool - Vector boundTextures; ///< The textures bound for rendering - Vector textureDependencyList; ///< The dependency list of bound textures - Vector updatedTextures{}; ///< The updated texture list + std::unique_ptr threadPool; ///< The thread pool + Vector boundTextures; ///< The textures bound for rendering + Vector updatedTextures{}; ///< The updated texture list uint32_t frameCount{0u}; ///< The current frame count BufferIndex renderBufferIndex{SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX}; ///< The index of the buffer to read from; @@ -970,15 +969,6 @@ void RenderManager::RenderScene(Integration::RenderStatus& status, Integration:: // this ensures we will set view and projection matrix once per program per camera mImpl->programController.ResetProgramMatrices(); - if(instruction.mFrameBuffer) - { - // For each offscreen buffer, update the dependency list with the new texture id used by this frame buffer. - for(unsigned int i0 = 0, i1 = instruction.mFrameBuffer->GetColorAttachmentCount(); i0 < i1; ++i0) - { - mImpl->textureDependencyList.PushBack(instruction.mFrameBuffer->GetTexture(i0)); - } - } - if(!instruction.mIgnoreRenderToFbo && (instruction.mFrameBuffer != nullptr)) { // Offscreen buffer rendering diff --git a/dali/internal/render/renderers/render-frame-buffer.h b/dali/internal/render/renderers/render-frame-buffer.h index 097e703..e1eb657 100644 --- a/dali/internal/render/renderers/render-frame-buffer.h +++ b/dali/internal/render/renderers/render-frame-buffer.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_RENDER_FRAME_BUFFER_H /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -119,15 +119,6 @@ public: return mCreateInfo.colorAttachments.size(); } - /** - * @brief Get the texture bound to this frame buffer as color attachment @a index. - * @return The texture. - */ - Graphics::Texture* GetTexture(uint8_t index) - { - return mCreateInfo.colorAttachments[index].texture; - }; - Graphics::Framebuffer* GetGraphicsObject() { return mGraphicsObject.get(); diff --git a/dali/internal/render/renderers/render-texture.cpp b/dali/internal/render/renderers/render-texture.cpp index eb5c3cf..a38ede9 100644 --- a/dali/internal/render/renderers/render-texture.cpp +++ b/dali/internal/render/renderers/render-texture.cpp @@ -241,7 +241,8 @@ Texture::Texture(Type type, Pixel::Format format, ImageDimensions size) mHeight(size.GetHeight()), mType(type), mHasAlpha(HasAlpha(format)), - mUpdated(true) + mUpdated(true), + mUseUploadedParameter(mWidth == 0u && mHeight == 0u && mPixelFormat == Pixel::INVALID) { } @@ -255,7 +256,8 @@ Texture::Texture(NativeImageInterfacePtr nativeImageInterface) mHeight(static_cast(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice mType(TextureType::TEXTURE_2D), mHasAlpha(nativeImageInterface->RequiresBlending()), - mUpdated(true) + mUpdated(true), + mUseUploadedParameter(false) { } @@ -318,22 +320,20 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara { DALI_ASSERT_ALWAYS(!mNativeImage); - if(!mGraphicsTexture) - { - Create(static_cast(Graphics::TextureUsageFlagBits::SAMPLE)); - } - - Graphics::TextureUpdateInfo info{}; - const uint32_t srcStride = pixelData->GetStride(); uint32_t srcOffset = 0u; uint32_t srcSize = pixelData->GetBufferSize(); - const bool requiredSubPixelData = (!Pixel::IsCompressed(pixelData->GetPixelFormat())) && + // Cache uploaded data + const auto uploadedDataWidth = params.dataWidth; + const auto uploadedDataHeight = params.dataHeight; + const auto uploadedPixelFormat = pixelData->GetPixelFormat(); + + const bool requiredSubPixelData = (!Pixel::IsCompressed(uploadedPixelFormat)) && ((params.dataXOffset != 0) || (params.dataYOffset != 0) || - (params.dataWidth != pixelData->GetWidth()) || - (params.dataHeight != pixelData->GetHeight())); + (uploadedDataWidth != pixelData->GetWidth()) || + (uploadedDataHeight != pixelData->GetHeight())); if(requiredSubPixelData) { @@ -358,25 +358,41 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara * srcOffset = A).offsetByte; * srcSize = ( C).offsetByte - A).offsetByte ); */ - const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat()); - const uint32_t dataStrideByte = (srcStride ? srcStride : static_cast(params.dataWidth)) * bytePerPixel; + const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(uploadedPixelFormat); + const uint32_t dataStrideByte = (srcStride ? srcStride : pixelData->GetWidth()) * bytePerPixel; const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel; - const uint32_t dataWidthByte = static_cast(params.dataWidth) * bytePerPixel; + const uint32_t dataWidthByte = static_cast(uploadedDataWidth) * bytePerPixel; srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte; - srcSize = static_cast(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte); + srcSize = static_cast(uploadedDataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte); } + // Update render texture value as uploaded data. + if(mUseUploadedParameter) + { + mWidth = params.xOffset + uploadedDataWidth; + mHeight = params.yOffset + uploadedDataHeight; + mPixelFormat = uploadedPixelFormat; + } + + // Always create new graphics texture object if we use uploaded parameter as texture. + if(!mGraphicsTexture || mUseUploadedParameter) + { + Create(static_cast(Graphics::TextureUsageFlagBits::SAMPLE)); + } + + Graphics::TextureUpdateInfo info{}; + info.dstTexture = mGraphicsTexture.get(); info.dstOffset2D = {params.xOffset, params.yOffset}; info.layer = params.layer; info.level = params.mipmap; info.srcReference = 0; - info.srcExtent2D = {params.dataWidth, params.dataHeight}; + info.srcExtent2D = {uploadedDataWidth, uploadedDataHeight}; info.srcOffset = srcOffset; info.srcSize = srcSize; info.srcStride = srcStride; - info.srcFormat = ConvertPixelFormat(pixelData->GetPixelFormat()); + info.srcFormat = ConvertPixelFormat(uploadedPixelFormat); mUpdatedArea = Rect(params.xOffset, params.yOffset, params.width, params.height); diff --git a/dali/internal/render/renderers/render-texture.h b/dali/internal/render/renderers/render-texture.h index 2e4dcee..8895cfc 100644 --- a/dali/internal/render/renderers/render-texture.h +++ b/dali/internal/render/renderers/render-texture.h @@ -111,13 +111,6 @@ public: void Create(Graphics::TextureUsageFlags usage); /** - * Create a texture with a buffer if non-null - * @param[in] usage How texture will be used - * @param[in] buffer Buffer to copy - */ - void CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* buffer, uint32_t bufferSize); - - /** * Deletes the texture from the GPU */ void Destroy(); @@ -164,6 +157,15 @@ public: } /** + * Return the pixel format of the texture + * @return The pixel format of the texture data. + */ + Pixel::Format GetPixelFormat() const + { + return mPixelFormat; + } + + /** * Return the width of the texture * @return The width of the texture */ @@ -222,6 +224,14 @@ private: */ void ApplySampler(Render::Sampler* sampler); + /** + * Create a texture with a buffer if non-null + * @param[in] usage How texture will be used + * @param[in] buffer Buffer to copy + * @param[in] bufferSize Size of buffer to copy + */ + void CreateWithData(Graphics::TextureUsageFlags usage, uint8_t* buffer, uint32_t bufferSize); + private: Graphics::Controller* mGraphicsController; Graphics::UniquePtr mGraphicsTexture; @@ -230,12 +240,16 @@ private: Render::Sampler mSampler; ///< The current sampler state Rect mUpdatedArea{}; ///< Updated area of the texture - Pixel::Format mPixelFormat; ///< Pixel format of the texture - uint16_t mWidth; ///< Width of the texture - uint16_t mHeight; ///< Height of the texture - Type mType : 3; ///< Type of the texture - bool mHasAlpha : 1; ///< Whether the format has an alpha channel - bool mUpdated : 1; ///< Whether the texture is updated + + Pixel::Format mPixelFormat; ///< Pixel format of the texture + uint16_t mWidth; ///< Width of the texture + uint16_t mHeight; ///< Height of the texture + + Type mType : 3; ///< Type of the texture + bool mHasAlpha : 1; ///< Whether the format has an alpha channel + bool mUpdated : 1; ///< Whether the texture is updated + + bool mUseUploadedParameter : 1; ///< Whether ths texture size and format depend on uploaded image or not. }; } // namespace Render diff --git a/dali/public-api/rendering/texture.cpp b/dali/public-api/rendering/texture.cpp index 2f62053..2ba28e0 100644 --- a/dali/public-api/rendering/texture.cpp +++ b/dali/public-api/rendering/texture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -30,6 +30,12 @@ Texture Texture::New(TextureType::Type type, Pixel::Format format, uint32_t widt return Texture(texture.Get()); } +Texture Texture::New(TextureType::Type type) +{ + Internal::TexturePtr texture = Internal::Texture::New(type, Pixel::INVALID, 0u, 0u); + return Texture(texture.Get()); +} + Texture Texture::New(NativeImageInterface& nativeImageInterface) { Internal::TexturePtr texture = Internal::Texture::New(nativeImageInterface); diff --git a/dali/public-api/rendering/texture.h b/dali/public-api/rendering/texture.h index 9819677..11d973a 100644 --- a/dali/public-api/rendering/texture.h +++ b/dali/public-api/rendering/texture.h @@ -2,7 +2,7 @@ #define DALI_TEXTURE_H /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2023 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. @@ -86,6 +86,17 @@ public: static Texture New(TextureType::Type type, Pixel::Format format, uint32_t width, uint32_t height); /** + * @brief Creates a new Texture object with no informations. + * Texture will use Uploaded PixelData size and format. + * Before texture Upload is called, width, height and format return invalid values. + * + * @SINCE_2_2.34 + * @param[in] type The type of the texture + * @return A handle to a newly allocated Texture + */ + static Texture New(TextureType::Type type); + + /** * @brief Creates a new Texture object from a native image. * * @SINCE_1_1.43 -- 2.7.4