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 <eunkiki.hong@samsung.com>
/*
- * 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.
*/
#include "test-graphics-texture.h"
+#include <dali/integration-api/pixel-data-integ.h>
#include <iostream>
#include <sstream>
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<uint8_t*>(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<void*>(pixels));
+ break;
+ }
+ default:
+ {
+ // TODO : Implement here
+ break;
+ }
}
}
}
/*
- * 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.
END_TEST;
}
-int UtcDaliPixelBufferConvert(void)
+int UtcDaliPixelBufferConvert01(void)
{
TestApplication application;
TestGlAbstraction& gl = application.GetGlAbstraction();
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;
/*
- * 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.
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;
}
#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.
*/
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.
/*
- * 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.
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<uint8_t*>(source.memorySource.memory);
+ sourceBuffer = reinterpret_cast<uint8_t*>(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;
}
}
- 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<void*>(sourceBuffer));
+ }
+ else
+ {
+ Dali::Integration::ReleasePixelDataBuffer(source.pixelDataSource.pixelData);
+ }
}
break;
}
/*
- * 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.
#include <dali/internal/imaging/common/pixel-buffer-impl.h>
// EXTERNAL INCLUDES
+#include <dali/integration-api/pixel-data-integ.h>
#include <stdlib.h>
#include <cstring>
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;
}
gPixelBufferAllocationTotal -= mBufferSize;
#endif
free(mBuffer);
+ mBuffer = nullptr;
}
}
pixelsOut = nullptr;
mBufferSize = mWidth * mHeight * pixelSize;
mStride = mWidth; // The buffer is tightly packed.
+
+#if defined(DEBUG_ENABLED)
+ gPixelBufferAllocationTotal += mBufferSize;
+#endif
}
return success;
#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.
* 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.