From 8f1f192ac7a965c0021b38b225904a0a3c42348f Mon Sep 17 00:00:00 2001 From: "Eunki, Hong" Date: Mon, 8 Jan 2024 10:21:12 +0900 Subject: [PATCH] Make PixelData flag that we release buffer after texture upload Let we support to release pixel data memory automatically after upload finished. And also, let we make new PixelBuffer::Convert API with this flag. Change-Id: I9537da4d10a59bdb4c6cd12ea3d62463455399a3 Signed-off-by: Eunki, Hong --- .../test-graphics-texture.cpp | 59 ++++++++++++++++++++-- .../src/dali-adaptor/utc-Dali-PixelBuffer.cpp | 54 +++++++++++++++++++- dali/devel-api/adaptor-framework/pixel-buffer.cpp | 10 ++-- dali/devel-api/adaptor-framework/pixel-buffer.h | 16 +++++- .../graphics/gles-impl/egl-graphics-controller.cpp | 24 ++++++--- dali/internal/imaging/common/pixel-buffer-impl.cpp | 48 +++++++++++++----- dali/internal/imaging/common/pixel-buffer-impl.h | 5 +- 7 files changed, 181 insertions(+), 35 deletions(-) diff --git a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp index 30a759d..4950bbd 100644 --- a/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp +++ b/automated-tests/src/dali-adaptor/dali-test-suite-utils/test-graphics-texture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -15,6 +15,7 @@ */ #include "test-graphics-texture.h" +#include #include #include @@ -935,26 +936,74 @@ void TestGraphicsTexture::Update(Graphics::TextureUpdateInfo updateInfo, Graphic updateInfo.srcExtent2D.width != (mCreateInfo.size.width / (1 << updateInfo.level)) || updateInfo.srcExtent2D.height != (mCreateInfo.size.height / (1 << updateInfo.level))); + uint8_t* pixels = nullptr; + bool releasePixels = false; + + switch(source.sourceType) + { + case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA: + { + auto pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData); + + pixels = pixelDataBuffer.buffer; + releasePixels = Dali::Integration::IsPixelDataReleaseAfterUpload(source.pixelDataSource.pixelData) && updateInfo.srcOffset == 0u; + break; + } + case Graphics::TextureUpdateSourceInfo::Type::MEMORY: + { + pixels = reinterpret_cast(source.memorySource.memory); + releasePixels = true; + break; + } + default: + { + // TODO : Implement here + break; + } + } + if(!isSubImage) { if(!mIsCompressed) { - mGlAbstraction.TexImage2D(target, updateInfo.level, mGlInternalFormat, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, 0, mGlFormat, mPixelDataType, source.memorySource.memory); + mGlAbstraction.TexImage2D(target, updateInfo.level, mGlInternalFormat, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, 0, mGlFormat, mPixelDataType, pixels); } else { - mGlAbstraction.CompressedTexImage2D(target, updateInfo.level, mGlInternalFormat, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, 0, updateInfo.srcSize, source.memorySource.memory); + mGlAbstraction.CompressedTexImage2D(target, updateInfo.level, mGlInternalFormat, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, 0, updateInfo.srcSize, pixels); } } else { if(!mIsCompressed) { - mGlAbstraction.TexSubImage2D(target, updateInfo.level, updateInfo.dstOffset2D.x, updateInfo.dstOffset2D.y, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, mGlFormat, mPixelDataType, source.memorySource.memory); + mGlAbstraction.TexSubImage2D(target, updateInfo.level, updateInfo.dstOffset2D.x, updateInfo.dstOffset2D.y, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, mGlFormat, mPixelDataType, pixels); } else { - mGlAbstraction.CompressedTexSubImage2D(target, updateInfo.level, updateInfo.dstOffset2D.x, updateInfo.dstOffset2D.y, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, mGlFormat, updateInfo.srcSize, source.memorySource.memory); + mGlAbstraction.CompressedTexSubImage2D(target, updateInfo.level, updateInfo.dstOffset2D.x, updateInfo.dstOffset2D.y, updateInfo.srcExtent2D.width, updateInfo.srcExtent2D.height, mGlFormat, updateInfo.srcSize, pixels); + } + } + + if(releasePixels && pixels != nullptr) + { + switch(source.sourceType) + { + case Graphics::TextureUpdateSourceInfo::Type::PIXEL_DATA: + { + Dali::Integration::ReleasePixelDataBuffer(source.pixelDataSource.pixelData); + break; + } + case Graphics::TextureUpdateSourceInfo::Type::MEMORY: + { + free(reinterpret_cast(pixels)); + break; + } + default: + { + // TODO : Implement here + break; + } } } } diff --git a/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp b/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp index 2c74145..e435ed7 100644 --- a/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp +++ b/automated-tests/src/dali-adaptor/utc-Dali-PixelBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -244,7 +244,7 @@ int UtcDaliPixelBufferNew01N(void) END_TEST; } -int UtcDaliPixelBufferConvert(void) +int UtcDaliPixelBufferConvert01(void) { TestApplication application; TestGlAbstraction& gl = application.GetGlAbstraction(); @@ -294,6 +294,56 @@ int UtcDaliPixelBufferConvert(void) END_TEST; } +int UtcDaliPixelBufferConvert02(void) +{ + TestApplication application; + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& textureTrace = gl.GetTextureTrace(); + textureTrace.Enable(true); + + Devel::PixelBuffer pixbuf = Devel::PixelBuffer::New(10, 10, Pixel::RGB565); + FillCheckerboard(pixbuf); + + { + Devel::PixelBuffer pixbufPrime = pixbuf; // store a second handle to the data + + Dali::PixelData pixelData = Devel::PixelBuffer::Convert(pixbuf, true); + DALI_TEST_CHECK(!pixbuf); + + // check the buffer in the second handle is empty + DALI_TEST_CHECK(pixbufPrime.GetBuffer() == NULL); + + DALI_TEST_CHECK(pixelData); + DALI_TEST_EQUALS(pixelData.GetWidth(), 10, TEST_LOCATION); + DALI_TEST_EQUALS(pixelData.GetHeight(), 10, TEST_LOCATION); + DALI_TEST_EQUALS(pixelData.GetStride(), 10, TEST_LOCATION); + DALI_TEST_EQUALS(pixelData.GetPixelFormat(), Pixel::RGB565, TEST_LOCATION); + + // Try drawing it + Texture t = Texture::New(TextureType::TEXTURE_2D, Pixel::RGB565, 10, 10); + t.Upload(pixelData); + TextureSet ts = TextureSet::New(); + ts.SetTexture(0, t); + Geometry g = CreateQuadGeometry(); + Shader s = Shader::New("v", "f"); + Renderer r = Renderer::New(g, s); + r.SetTextures(ts); + Actor a = Actor::New(); + a.AddRenderer(r); + a.SetProperty(Actor::Property::SIZE, Vector2(10, 10)); + a.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER); + application.GetScene().Add(a); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(textureTrace.FindMethod("BindTexture"), true, TEST_LOCATION); + + // Let secondary scope destroy pixbufPrime + } + + END_TEST; +} + int UtcDaliPixelBufferGetWidth(void) { TestApplication application; diff --git a/dali/devel-api/adaptor-framework/pixel-buffer.cpp b/dali/devel-api/adaptor-framework/pixel-buffer.cpp index e391463..4000b4f 100644 --- a/dali/devel-api/adaptor-framework/pixel-buffer.cpp +++ b/dali/devel-api/adaptor-framework/pixel-buffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -39,8 +39,12 @@ PixelBuffer PixelBuffer::New(uint32_t width, Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer) { - Dali::PixelData pixelData = - Internal::Adaptor::PixelBuffer::Convert(GetImplementation(pixelBuffer)); + return Convert(pixelBuffer, false); +} + +Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload) +{ + Dali::PixelData pixelData = Internal::Adaptor::PixelBuffer::Convert(GetImplementation(pixelBuffer), releaseAfterUpload); pixelBuffer.Reset(); return pixelData; } diff --git a/dali/devel-api/adaptor-framework/pixel-buffer.h b/dali/devel-api/adaptor-framework/pixel-buffer.h index 40f3eae..2d768c0 100644 --- a/dali/devel-api/adaptor-framework/pixel-buffer.h +++ b/dali/devel-api/adaptor-framework/pixel-buffer.h @@ -2,7 +2,7 @@ #define DALI_PIXEL_BUFFER_H /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -128,6 +128,20 @@ public: static PixelData Convert(PixelBuffer& pixelBuffer); /** + * Convert to a pixel data and release the pixelBuffer's object. + * This handle is left empty. + * + * @warning Any other handles that keep a reference to this object + * will be left with no buffer, trying to access it will return NULL. + * + * @SINCE_2_3.6 + * @param[in,out] pixelBuffer + * @param[in] releaseAfterUpload Whether converted PixelData released after upload or not. + * @return a new PixelData which takes ownership of the PixelBuffer's buffer. + */ + static PixelData Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload); + + /** * Copy the data from this object into a new PixelData object, which could be * used for uploading to a texture. * @return a new PixelData object containing a copy of this pixel buffer's data. diff --git a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp index b211897..fef6d60 100644 --- a/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp +++ b/dali/internal/graphics/gles-impl/egl-graphics-controller.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -748,17 +748,19 @@ void EglGraphicsController::ProcessTextureUpdateQueue() info.srcExtent2D.width != (createInfo.size.width / (1 << info.level)) || info.srcExtent2D.height != (createInfo.size.height / (1 << info.level))); - uint8_t* sourceBuffer; + uint8_t* sourceBuffer = nullptr; + bool sourceBufferReleaseRequired = false; if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY) { - sourceBuffer = reinterpret_cast(source.memorySource.memory); + sourceBuffer = reinterpret_cast(source.memorySource.memory); + sourceBufferReleaseRequired = true; } else { - // Get buffer of PixelData Dali::Integration::PixelDataBuffer pixelBufferData = Dali::Integration::GetPixelDataBuffer(source.pixelDataSource.pixelData); - sourceBuffer = pixelBufferData.buffer + info.srcOffset; + sourceBuffer = pixelBufferData.buffer + info.srcOffset; + sourceBufferReleaseRequired = Dali::Integration::IsPixelDataReleaseAfterUpload(source.pixelDataSource.pixelData) && info.srcOffset == 0u; } auto sourceStride = info.srcStride; @@ -847,10 +849,16 @@ void EglGraphicsController::ProcessTextureUpdateQueue() } } - if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY) + if(sourceBufferReleaseRequired && sourceBuffer != nullptr) { - // free staging memory - free(source.memorySource.memory); + if(source.sourceType == Graphics::TextureUpdateSourceInfo::Type::MEMORY) + { + free(reinterpret_cast(sourceBuffer)); + } + else + { + Dali::Integration::ReleasePixelDataBuffer(source.pixelDataSource.pixelData); + } } break; } diff --git a/dali/internal/imaging/common/pixel-buffer-impl.cpp b/dali/internal/imaging/common/pixel-buffer-impl.cpp index 31b7f0f..3afdce5 100644 --- a/dali/internal/imaging/common/pixel-buffer-impl.cpp +++ b/dali/internal/imaging/common/pixel-buffer-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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. @@ -19,6 +19,7 @@ #include // EXTERNAL INCLUDES +#include #include #include @@ -102,23 +103,37 @@ PixelBufferPtr PixelBuffer::New(uint8_t* buffer, return new PixelBuffer(buffer, bufferSize, width, height, stride, pixelFormat); } -Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer) +Dali::PixelData PixelBuffer::Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload) { #if defined(DEBUG_ENABLED) gPixelBufferAllocationTotal -= pixelBuffer.mBufferSize; #endif - Dali::PixelData pixelData = Dali::PixelData::New(pixelBuffer.mBuffer, - pixelBuffer.mBufferSize, - pixelBuffer.mWidth, - pixelBuffer.mHeight, - pixelBuffer.mStride, - pixelBuffer.mPixelFormat, - Dali::PixelData::FREE); - pixelBuffer.mBuffer = NULL; - pixelBuffer.mWidth = 0; - pixelBuffer.mHeight = 0; - pixelBuffer.mBufferSize = 0; - pixelBuffer.mStride = 0; + Dali::PixelData pixelData; + if(releaseAfterUpload) + { + pixelData = Dali::Integration::NewPixelDataWithReleaseAfterUpload(pixelBuffer.mBuffer, + pixelBuffer.mBufferSize, + pixelBuffer.mWidth, + pixelBuffer.mHeight, + pixelBuffer.mStride, + pixelBuffer.mPixelFormat, + Dali::PixelData::FREE); + } + else + { + pixelData = Dali::PixelData::New(pixelBuffer.mBuffer, + pixelBuffer.mBufferSize, + pixelBuffer.mWidth, + pixelBuffer.mHeight, + pixelBuffer.mStride, + pixelBuffer.mPixelFormat, + Dali::PixelData::FREE); + } + pixelBuffer.mBuffer = NULL; + pixelBuffer.mWidth = 0; + pixelBuffer.mHeight = 0; + pixelBuffer.mBufferSize = 0; + pixelBuffer.mStride = 0; return pixelData; } @@ -240,6 +255,7 @@ void PixelBuffer::ReleaseBuffer() gPixelBufferAllocationTotal -= mBufferSize; #endif free(mBuffer); + mBuffer = nullptr; } } @@ -325,6 +341,10 @@ bool PixelBuffer::Rotate(Degree angle) pixelsOut = nullptr; mBufferSize = mWidth * mHeight * pixelSize; mStride = mWidth; // The buffer is tightly packed. + +#if defined(DEBUG_ENABLED) + gPixelBufferAllocationTotal += mBufferSize; +#endif } return success; diff --git a/dali/internal/imaging/common/pixel-buffer-impl.h b/dali/internal/imaging/common/pixel-buffer-impl.h index 45ff5dd..d9898bf 100644 --- a/dali/internal/imaging/common/pixel-buffer-impl.h +++ b/dali/internal/imaging/common/pixel-buffer-impl.h @@ -2,7 +2,7 @@ #define DALI_INTERNAL_ADAPTOR_PIXEL_BUFFER_H /* - * Copyright (c) 2022 Samsung Electronics Co., Ltd. + * Copyright (c) 2024 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,9 +76,10 @@ public: * The new object takes ownership of the buffer data, and the * mBuffer pointer is reset to NULL. * @param[in] pixelBuffer The buffer to convert + * @param[in] releaseAfterUpload Whether converted PixelData released after upload or not. * @return the pixelData */ - static Dali::PixelData Convert(PixelBuffer& pixelBuffer); + static Dali::PixelData Convert(PixelBuffer& pixelBuffer, bool releaseAfterUpload); /** * @brief Constructor. -- 2.7.4