From b6ee5cd3e04f63cff74010745da721d1e5ca6246 Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Tue, 12 Jul 2022 22:46:45 +0900 Subject: [PATCH] Upload PixelData's sub image to Texture Add API to upload subimage of inputed PixelData. It will be useful when we want to make multiple tiling textures with one single big PixelData. Change-Id: Ia07ddc96cdaf7006239a21a307dbb0995c755bb4 Signed-off-by: Eunki, Hong --- automated-tests/src/dali/utc-Dali-Pixel.cpp | 88 ++++++++++ automated-tests/src/dali/utc-Dali-Texture.cpp | 194 +++++++++++++++++++++- dali/devel-api/rendering/texture-devel.cpp | 30 +++- dali/devel-api/rendering/texture-devel.h | 56 ++++++- dali/internal/event/rendering/texture-impl.cpp | 49 +++++- dali/internal/event/rendering/texture-impl.h | 40 ++++- dali/internal/render/renderers/render-texture.cpp | 51 +++++- dali/public-api/images/pixel.cpp | 77 +++++++++ dali/public-api/images/pixel.h | 9 + 9 files changed, 573 insertions(+), 21 deletions(-) diff --git a/automated-tests/src/dali/utc-Dali-Pixel.cpp b/automated-tests/src/dali/utc-Dali-Pixel.cpp index 6eb1948..8e991e9 100644 --- a/automated-tests/src/dali/utc-Dali-Pixel.cpp +++ b/automated-tests/src/dali/utc-Dali-Pixel.cpp @@ -43,6 +43,94 @@ static void TestPixelEnumSize(const int size) "The Pixel::Format enum may have had new formats added. Expand the test cases to include them."); } +int UtcDaliPixelIsCompressed(void) +{ + TestApplication application; + + tet_infoline("UtcDaliPixelIsCompressed"); + + TestPixelEnumSize(62); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::INVALID) == false); // For completeness + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::L8) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB565) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB888) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB8888) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGR8888) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGR565) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_R11_EAC) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SIGNED_R11_EAC) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RG11_EAC) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SIGNED_RG11_EAC) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_ETC2) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ETC2) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_ETC1) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1) == true); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::A8) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::LA88) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA5551) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA4444) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGBA8888) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA8888) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA5551) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::BGRA4444) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA8_ETC2_EAC) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) == true); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_4x4_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_5x4_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_5x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_6x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_6x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_8x8_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x8_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_10x10_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_12x10_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_RGBA_ASTC_12x12_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR) == true); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR) == true); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB16F) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::RGB32F) == false); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_UNSIGNED_INT) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_FLOAT) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::DEPTH_STENCIL) == false); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::R11G11B10F) == false); + + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::CHROMINANCE_U) == false); + DALI_TEST_CHECK(Pixel::IsCompressed(Pixel::CHROMINANCE_V) == false); + + END_TEST; +} + +int UtcDaliPixelIsCompressedN(void) +{ + DALI_TEST_EQUALS(Pixel::IsCompressed(Pixel::Format(123123123123)), false, TEST_LOCATION); + END_TEST; +} + int UtcDaliPixelHasAlpha(void) { TestApplication application; diff --git a/automated-tests/src/dali/utc-Dali-Texture.cpp b/automated-tests/src/dali/utc-Dali-Texture.cpp index 5de38f2..b16d10b 100644 --- a/automated-tests/src/dali/utc-Dali-Texture.cpp +++ b/automated-tests/src/dali/utc-Dali-Texture.cpp @@ -206,9 +206,9 @@ int UtcDaliTextureUpload01(void) //Upload part of the texture callStack.Reset(); - bufferSize = width * height * 2; + bufferSize = width * height; buffer = reinterpret_cast(malloc(bufferSize)); - PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); + PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width / 2, height / 2, Pixel::RGBA8888, PixelData::FREE); texture.Upload(pixelDataSubImage, 0u, 0u, width / 2, height / 2, width / 2, height / 2); application.SendNotification(); application.Render(); @@ -382,7 +382,7 @@ int UtcDaliTextureUpload03(void) bufferSize = widthMipmap1 * heightMipmap1 * 4; buffer = reinterpret_cast(malloc(bufferSize)); - PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); + PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, widthMipmap1, heightMipmap1, Pixel::RGBA8888, PixelData::FREE); texture.Upload(pixelDataMipmap1, 0u, 1u, 0u, 0u, widthMipmap1, heightMipmap1); application.SendNotification(); application.Render(); @@ -425,7 +425,7 @@ int UtcDaliTextureUpload04(void) bufferSize = widthMipmap1 * heightMipmap1 * 4; buffer = reinterpret_cast(malloc(bufferSize)); - PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, width, height, Pixel::RGBA8888, PixelData::FREE); + PixelData pixelDataMipmap1 = PixelData::New(buffer, bufferSize, widthMipmap1, heightMipmap1, Pixel::RGBA8888, PixelData::FREE); texture.Upload(pixelDataMipmap1, CubeMapLayer::NEGATIVE_X, 1u, 0u, 0u, widthMipmap1, heightMipmap1); application.SendNotification(); application.Render(); @@ -534,9 +534,9 @@ int UtcDaliTextureUpload05(void) //Upload part of the texture callStack.Reset(); - bufferSize = width * height * 2; + bufferSize = width * height; buffer = reinterpret_cast(malloc(bufferSize)); - PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width, height, COMPRESSED_PIXEL_FORMATS[index], PixelData::FREE); + PixelData pixelDataSubImage = PixelData::New(buffer, bufferSize, width / 2, height / 2, COMPRESSED_PIXEL_FORMATS[index], PixelData::FREE); texture.Upload(pixelDataSubImage, 0u, 0u, width / 2, height / 2, width / 2, height / 2); application.SendNotification(); application.Render(); @@ -654,6 +654,188 @@ int UtcDaliTextureUpload07(void) END_TEST; } +int UtcDaliTextureUploadSubPixelData01(void) +{ + TestApplication application; + + //Create the texture + unsigned int width(64); + unsigned int height(64); + Texture texture = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, width, height); + + application.GetGlAbstraction().EnableTextureCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace(); + + //Upload data to the texture + callStack.Reset(); + + uint32_t bufferWidth = width * 2; + uint32_t bufferHeight = height * 2; + uint32_t bufferXOffset = width; + uint32_t bufferYOffset = height; + + unsigned int bufferSize(bufferWidth * bufferHeight * 4); + unsigned char* buffer = reinterpret_cast(malloc(bufferSize)); + PixelData pixelData = PixelData::New(buffer, bufferSize, bufferWidth, bufferHeight, Pixel::RGBA8888, PixelData::FREE); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data + { + std::stringstream out; + out << GL_TEXTURE_2D << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + + //Upload part of the texture + callStack.Reset(); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width / 2, height / 2, 0u, 0u, width / 2, height / 2, width / 2, height / 2); + application.SendNotification(); + application.Render(); + + //TexSubImage2D should be called to upload the data + { + std::stringstream out; + out << GL_TEXTURE_2D << ", " << 0u << ", " << width / 2 << ", " << height / 2 << ", " << width / 2 << ", " << height / 2; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexSubImage2D", out.str().c_str())); + } + + END_TEST; +} + +int UtcDaliTextureUploadSubPixelData02(void) +{ + TestApplication application; + + //Create the texture + unsigned int width(64); + unsigned int height(64); + Texture texture = CreateTexture(TextureType::TEXTURE_CUBE, Pixel::RGBA8888, width, height); + + application.GetGlAbstraction().EnableTextureCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace(); + + tet_infoline("TexImage2D should be called six times with a null pointer to reserve storage for the six textures of the cube map"); + for(unsigned int i(0); i < 6; ++i) + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_POSITIVE_X + i << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + + uint32_t bufferWidth = width * 2; + uint32_t bufferHeight = height * 2; + uint32_t bufferXOffset = width; + uint32_t bufferYOffset = height; + + unsigned int bufferSize(bufferWidth * bufferHeight * 4); + unsigned char* buffer = reinterpret_cast(malloc(bufferSize)); + PixelData pixelData = PixelData::New(buffer, bufferSize, bufferWidth, bufferHeight, Pixel::RGBA8888, PixelData::FREE); + + //Upload data to the POSITIVE_X face of the texture + { + callStack.Reset(); + + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_X, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the POSITIVE_X face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_POSITIVE_X << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + //Upload data to the NEGATIVE_X face of the texture + { + callStack.Reset(); + + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_X, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the NEGATIVE_X face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_NEGATIVE_X << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + //Upload data to the POSITIVE_Y face of the texture + { + callStack.Reset(); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_Y, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the POSITIVE_Y face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_POSITIVE_Y << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + //Upload data to the NEGATIVE_Y face of the texture + { + callStack.Reset(); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_Y, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the NEGATIVE_Y face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_NEGATIVE_Y << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + //Upload data to the POSITIVE_Z face of the texture + { + callStack.Reset(); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::POSITIVE_Z, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the POSITIVE_Z face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_POSITIVE_Z << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + //Upload data to the NEGATIVE_Z face of the texture + { + callStack.Reset(); + DevelTexture::UploadSubPixelData(texture, pixelData, bufferXOffset, bufferYOffset, width, height, CubeMapLayer::NEGATIVE_Z, 0u, 0u, 0u, width, height); + application.SendNotification(); + application.Render(); + + //TexImage2D should be called to upload the data to the NEGATIVE_Z face + { + std::stringstream out; + out << GL_TEXTURE_CUBE_MAP_NEGATIVE_Z << ", " << 0u << ", " << width << ", " << height; + DALI_TEST_CHECK(callStack.FindMethodAndParams("TexImage2D", out.str().c_str())); + } + } + + END_TEST; +} + int UtcDaliTextureUploadPixelFormats(void) { TestApplication application; diff --git a/dali/devel-api/rendering/texture-devel.cpp b/dali/devel-api/rendering/texture-devel.cpp index d56cae6..010a51f 100644 --- a/dali/devel-api/rendering/texture-devel.cpp +++ b/dali/devel-api/rendering/texture-devel.cpp @@ -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. @@ -33,5 +33,33 @@ bool ApplyNativeFragmentShader(Dali::Texture texture, std::string& shader) return impl.ApplyNativeFragmentShader(shader); } +bool UploadSubPixelData(Texture texture, + PixelData pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight) +{ + Internal::PixelData& internalPixelData = GetImplementation(pixelData); + return GetImplementation(texture).UploadSubPixelData(&internalPixelData, dataXOffset, dataYOffset, dataWidth, dataHeight); +} + +bool UploadSubPixelData(Texture texture, + PixelData pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight, + uint32_t layer, + uint32_t mipmap, + uint32_t xOffset, + uint32_t yOffset, + uint32_t width, + uint32_t height) +{ + Internal::PixelData& internalPixelData = GetImplementation(pixelData); + return GetImplementation(texture).UploadSubPixelData(&internalPixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, layer, mipmap, xOffset, yOffset, width, height); +} + } // namespace DevelTexture } // namespace Dali diff --git a/dali/devel-api/rendering/texture-devel.h b/dali/devel-api/rendering/texture-devel.h index 0204a41..9c071e0 100644 --- a/dali/devel-api/rendering/texture-devel.h +++ b/dali/devel-api/rendering/texture-devel.h @@ -2,7 +2,7 @@ #define DALI_TEXTURE_DEVEL_H /* - * 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. @@ -44,6 +44,60 @@ bool DALI_CORE_API IsNative(Dali::Texture texture); */ bool DALI_CORE_API ApplyNativeFragmentShader(Dali::Texture texture, std::string& shader); +/** + * @brief Uploads data to the texture from a PixelData object. + * @note Compressed type doesn't support this API. + * @note Upload does not upsample or downsample pixel data to fit the specified rectangular area in the texture. + * + * @SINCE_2_1.33 + * @param[in] texture The texture will be uploaded + * @param[in] pixelData The pixelData object + * @param[in] dataXOffset Specifies an horizontal offset of the rectangular area in the pixelData that will be updated + * @param[in] dataYOffset Specifies a vertical offset of the rectangular area in the pixelData that will be updated + * @param[in] dataWidth Specifies the width of the rectangular area in the pixelData that will be updated + * @param[in] dataHeight Specifies the height of the rectangular area in the pixelData that will be updated + * @return True if the PixelData object has compatible pixel format and fits within the texture, false otherwise + */ +bool DALI_CORE_API UploadSubPixelData(Dali::Texture texture, + Dali::PixelData pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight); + +/** + * @brief Uploads data to the texture from a PixelData object. + * @note Compressed type doesn't support this API. + * @note Upload does not upsample or downsample pixel data to fit the specified rectangular area in the texture. + * + * @SINCE_2_1.33 + * @param[in] texture The texture will be uploaded + * @param[in] pixelData The pixelData object + * @param[in] dataXOffset Specifies an horizontal offset of the rectangular area in the pixelData that will be updated + * @param[in] dataYOffset Specifies a vertical offset of the rectangular area in the pixelData that will be updated + * @param[in] dataWidth Specifies the width of the rectangular area in the pixelData that will be updated + * @param[in] dataHeight Specifies the height of the rectangular area in the pixelData that will be updated + * @param[in] layer Specifies the layer of a cube map or array texture (Unused for 2D textures). @see CubeMapLayer + * @param[in] mipmap Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image + * @param[in] xOffset Specifies an horizontal offset of the rectangular area in the texture that will be updated + * @param[in] yOffset Specifies a vertical offset of the rectangular area in the texture that will be updated + * @param[in] width Specifies the width of the rectangular area in the texture that will be updated + * @param[in] height Specifies the height of the rectangular area in the texture that will be updated + * @return True if the PixelData object has compatible pixel format and fits within the texture, false otherwise + */ +bool DALI_CORE_API UploadSubPixelData(Dali::Texture texture, + Dali::PixelData pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight, + uint32_t layer, + uint32_t mipmap, + uint32_t xOffset, + uint32_t yOffset, + uint32_t width, + uint32_t height); + } // namespace DevelTexture } // namespace Dali diff --git a/dali/internal/event/rendering/texture-impl.cpp b/dali/internal/event/rendering/texture-impl.cpp index b6c5cc9..d386150 100644 --- a/dali/internal/event/rendering/texture-impl.cpp +++ b/dali/internal/event/rendering/texture-impl.cpp @@ -100,7 +100,7 @@ Texture::~Texture() bool Texture::Upload(PixelDataPtr pixelData) { - return Upload(pixelData, 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight()); + return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight()); } bool Texture::Upload(PixelDataPtr pixelData, @@ -111,6 +111,30 @@ bool Texture::Upload(PixelDataPtr pixelData, uint32_t width, uint32_t height) { + return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), layer, mipmap, xOffset, yOffset, width, height); +} + +bool Texture::UploadSubPixelData(PixelDataPtr pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight) +{ + return UploadSubPixelData(pixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, 0u, 0u, 0u, 0u, dataWidth, dataHeight); +} + +bool Texture::UploadSubPixelData(PixelDataPtr pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight, + uint32_t layer, + uint32_t mipmap, + uint32_t xOffset, + uint32_t yOffset, + uint32_t width, + uint32_t height) +{ constexpr auto max_value = std::numeric_limits::max(); DALI_ASSERT_ALWAYS(layer < max_value && mipmap < max_value && @@ -118,6 +142,8 @@ bool Texture::Upload(PixelDataPtr pixelData, yOffset < max_value && width < max_value && height < max_value && + dataWidth < max_value && + dataHeight < max_value && "Parameter value out of range"); bool result(false); @@ -129,7 +155,7 @@ bool Texture::Upload(PixelDataPtr pixelData, } else { - uint32_t pixelDataSize = pixelData->GetWidth() * pixelData->GetHeight(); + uint32_t pixelDataSize = dataWidth * dataHeight; if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0) { DALI_LOG_ERROR("PixelData is empty\n"); @@ -143,6 +169,19 @@ bool Texture::Upload(PixelDataPtr pixelData, { DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n"); } + else if(Pixel::IsCompressed(mFormat) && + ((dataXOffset != 0) || + (dataYOffset != 0) || + (dataWidth != pixelData->GetWidth()) || + (dataHeight != pixelData->GetHeight()))) + { + DALI_LOG_ERROR("Compressed pixel format don't support SubPixelData upload\n"); + } + else if((dataXOffset + dataWidth > pixelData->GetWidth()) || + (dataYOffset + dataHeight > pixelData->GetHeight())) + { + 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)))) { @@ -151,7 +190,11 @@ bool Texture::Upload(PixelDataPtr pixelData, else { //Parameters are correct. Send message to upload data to the texture - UploadParams params = {static_cast(layer), + UploadParams params = {static_cast(dataXOffset), + static_cast(dataYOffset), + static_cast(dataWidth), + static_cast(dataHeight), + static_cast(layer), static_cast(mipmap), static_cast(xOffset), static_cast(yOffset), diff --git a/dali/internal/event/rendering/texture-impl.h b/dali/internal/event/rendering/texture-impl.h index 84faac6..c00e663 100644 --- a/dali/internal/event/rendering/texture-impl.h +++ b/dali/internal/event/rendering/texture-impl.h @@ -48,12 +48,16 @@ public: */ struct UploadParams { - uint16_t layer; ///< Specifies the layer of a cube map or array texture - uint16_t mipmap; ///< Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image. - uint16_t xOffset; ///< Specifies a texel offset in the x direction within the texture array. - uint16_t yOffset; ///< Specifies a texel offset in the y direction within the texture array. - uint16_t width; ///< Specifies the width of the texture subimage - uint16_t height; ///< Specifies the height of the texture subimage. + uint32_t dataXOffset; ///< Specifies a pixeldata offset in the x direction within the pixeldata buffer. + uint32_t dataYOffset; ///< Specifies a pixeldata offset in the y direction within the pixeldata buffer. + uint16_t dataWidth; ///< Specifies the width of the pixeldata subimage. + uint16_t dataHeight; ///< Specifies the height of the pixeldata subimage. + uint16_t layer; ///< Specifies the layer of a cube map or array texture + uint16_t mipmap; ///< Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap reduction image. + uint16_t xOffset; ///< Specifies a texel offset in the x direction within the texture array. + uint16_t yOffset; ///< Specifies a texel offset in the y direction within the texture array. + uint16_t width; ///< Specifies the width of the texture subimage + uint16_t height; ///< Specifies the height of the texture subimage. }; /** @@ -98,6 +102,30 @@ public: uint32_t height); /** + * @copydoc Dali::Texture::UploadSubPixelData() + */ + bool UploadSubPixelData(PixelDataPtr pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight); + + /** + * @copydoc Dali::Texture::UploadSubPixelData() + */ + bool UploadSubPixelData(PixelDataPtr pixelData, + uint32_t dataXOffset, + uint32_t dataYOffset, + uint32_t dataWidth, + uint32_t dataHeight, + uint32_t layer, + uint32_t mipmap, + uint32_t xOffset, + uint32_t yOffset, + uint32_t width, + uint32_t height); + + /** * @copydoc Dali::Texture::GenerateMipmaps() */ void GenerateMipmaps(); diff --git a/dali/internal/render/renderers/render-texture.cpp b/dali/internal/render/renderers/render-texture.cpp index b0fca79..f2bc5a3 100644 --- a/dali/internal/render/renderers/render-texture.cpp +++ b/dali/internal/render/renderers/render-texture.cpp @@ -286,15 +286,58 @@ void Texture::Upload(PixelDataPtr pixelData, const Internal::Texture::UploadPara } Graphics::TextureUpdateInfo info{}; + + const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat()); + const uint32_t srcStride = pixelData->GetStride(); + uint32_t srcOffset = 0u; + uint32_t srcSize = pixelData->GetBufferSize(); + + const bool requiredSubPixelData = (!Pixel::IsCompressed(pixelData->GetPixelFormat())) && + ((params.dataXOffset != 0) || + (params.dataYOffset != 0) || + (params.dataWidth != pixelData->GetWidth()) || + (params.dataHeight != pixelData->GetHeight())); + + if(requiredSubPixelData) + { + /** + * TextureUpdateInfo use byte scaled offset / size. + * + * To make we only use sub-data of inputed PixelData, make srcOffset as 'start of SubPixelData. + * + * |---- dataStrideByte -----| + * |-----| <-- dataXOffsetByte + * ........................... + * ......A-----------+........ + * ......| |........ + * ......| |........ + * ......+-----------+C....... + * ......B.................... + * + * A) Start of SubPixelData. offsetByte = dataStrideByte * dataYOffset + dataXOffsetByte. + * B) offsetByte = A).offsetByte + dataStrideByte * dataHeight. Note, It can be out of original PixelData boundary. + * C) End of SubPixelData. offsetByte = B).offsetByte - dataStrideByte + dataWidthByte. + * + * srcOffset = A).offsetByte; + * srcSize = ( C).offsetByte - A).offsetByte ); + */ + const uint32_t dataStrideByte = (srcStride ? srcStride : static_cast(params.dataWidth)) * bytePerPixel; + const uint32_t dataXOffsetByte = params.dataXOffset * bytePerPixel; + const uint32_t dataWidthByte = static_cast(params.dataWidth) * bytePerPixel; + + srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte; + srcSize = static_cast(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte); + } + info.dstTexture = mGraphicsTexture.get(); info.dstOffset2D = {params.xOffset, params.yOffset}; info.layer = params.layer; info.level = params.mipmap; info.srcReference = 0; - info.srcExtent2D = {params.width, params.height}; - info.srcOffset = 0; - info.srcSize = pixelData->GetBufferSize(); - info.srcStride = pixelData->GetStride(); + info.srcExtent2D = {params.dataWidth, params.dataHeight}; + info.srcOffset = srcOffset; + info.srcSize = srcSize; + info.srcStride = srcStride; info.srcFormat = ConvertPixelFormat(pixelData->GetPixelFormat()); Graphics::TextureUpdateSourceInfo updateSourceInfo{}; diff --git a/dali/public-api/images/pixel.cpp b/dali/public-api/images/pixel.cpp index 90985a4..0dee73a 100644 --- a/dali/public-api/images/pixel.cpp +++ b/dali/public-api/images/pixel.cpp @@ -24,6 +24,83 @@ namespace Dali { +bool Pixel::IsCompressed(Format pixelformat) +{ + switch(pixelformat) + { + case COMPRESSED_R11_EAC: + case COMPRESSED_SIGNED_R11_EAC: + case COMPRESSED_RG11_EAC: + case COMPRESSED_SIGNED_RG11_EAC: + case COMPRESSED_RGB8_ETC2: + case COMPRESSED_SRGB8_ETC2: + case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case COMPRESSED_RGBA8_ETC2_EAC: + case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case COMPRESSED_RGB8_ETC1: + case COMPRESSED_RGB_PVRTC_4BPPV1: + case COMPRESSED_RGBA_ASTC_4x4_KHR: + case COMPRESSED_RGBA_ASTC_5x4_KHR: + case COMPRESSED_RGBA_ASTC_5x5_KHR: + case COMPRESSED_RGBA_ASTC_6x5_KHR: + case COMPRESSED_RGBA_ASTC_6x6_KHR: + case COMPRESSED_RGBA_ASTC_8x5_KHR: + case COMPRESSED_RGBA_ASTC_8x6_KHR: + case COMPRESSED_RGBA_ASTC_8x8_KHR: + case COMPRESSED_RGBA_ASTC_10x5_KHR: + case COMPRESSED_RGBA_ASTC_10x6_KHR: + case COMPRESSED_RGBA_ASTC_10x8_KHR: + case COMPRESSED_RGBA_ASTC_10x10_KHR: + case COMPRESSED_RGBA_ASTC_12x10_KHR: + case COMPRESSED_RGBA_ASTC_12x12_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: + case COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: + { + return true; + } + case INVALID: + case A8: + case L8: + case LA88: + case RGB565: + case BGR565: + case RGBA4444: + case BGRA4444: + case RGBA5551: + case BGRA5551: + case RGB888: + case RGB8888: + case BGR8888: + case RGBA8888: + case BGRA8888: + case RGB16F: + case RGB32F: + case DEPTH_UNSIGNED_INT: + case DEPTH_FLOAT: + case DEPTH_STENCIL: + case R11G11B10F: + case CHROMINANCE_U: + case CHROMINANCE_V: + { + return false; + } + } + return false; +} + bool Pixel::HasAlpha(Format pixelformat) { switch(pixelformat) diff --git a/dali/public-api/images/pixel.h b/dali/public-api/images/pixel.h index d62907d..ff07691 100644 --- a/dali/public-api/images/pixel.h +++ b/dali/public-api/images/pixel.h @@ -141,6 +141,15 @@ const Format FIRST_VALID_PIXEL_FORMAT = A8; const Format LAST_VALID_PIXEL_FORMAT = CHROMINANCE_V; /** + * @brief Whether specified pixel format is compressed or not. + * + * @SINCE_2_1.33 + * @param[in] pixelFormat The pixel format + * @return True if pixel format is compressed type. False otherwise. + */ +DALI_CORE_API bool IsCompressed(Format pixelFormat); + +/** * @brief Whether specified pixel format contains an alpha value. * * @SINCE_1_0.0 -- 2.7.4