Let we support to release pixel data memory automatically after upload finished.
Change-Id: I809289ca5124ba5672a5f87ba1f5772511b5054b
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) 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.
END_TEST;
}
-int UtcDaliPixelDataReleasePixelDataBuffer(void)
+int UtcDaliPixelDataGetPixelDataBuffer(void)
{
TestApplication application;
DALI_TEST_CHECK(pixelData.GetStride() == stride);
DALI_TEST_CHECK(pixelData.GetPixelFormat() == Pixel::L8);
- Dali::Integration::PixelDataBuffer pixelDataBuffer = Dali::Integration::ReleasePixelDataBuffer(pixelData);
+ Dali::Integration::PixelDataBuffer pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
- DALI_TEST_CHECK(!pixelData);
+ DALI_TEST_CHECK(pixelData);
DALI_TEST_EQUALS(pixelDataBuffer.bufferSize, bufferSize, TEST_LOCATION);
DALI_TEST_EQUALS(pixelDataBuffer.buffer[0], static_cast<uint8_t>('a'), TEST_LOCATION);
- // Release memory by our self.
- delete[] pixelDataBuffer.buffer;
-
END_TEST;
}
-int UtcDaliPixelDataGetPixelDataBuffer(void)
+int UtcDaliPixelDataReleasePixelDataBuffer(void)
{
TestApplication application;
DALI_TEST_CHECK(pixelData.GetStride() == stride);
DALI_TEST_CHECK(pixelData.GetPixelFormat() == Pixel::L8);
+ Dali::Integration::ReleasePixelDataBuffer(pixelData);
+
Dali::Integration::PixelDataBuffer pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+ DALI_TEST_CHECK(pixelDataBuffer.buffer == nullptr);
+
+ END_TEST;
+}
+
+int UtcDaliPixelDataNewPixelDataWithReleaseAfterUpload(void)
+{
+ TestApplication application;
+
+ uint32_t width = 10u;
+ uint32_t height = 10u;
+ uint32_t stride = 12u;
+ uint32_t bufferSize = stride * height * Pixel::GetBytesPerPixel(Pixel::L8);
+ uint8_t* buffer = new uint8_t[bufferSize];
+ buffer[0] = 'a';
+
+ PixelData pixelData = Dali::Integration::NewPixelDataWithReleaseAfterUpload(buffer, bufferSize, width, height, stride, Pixel::L8, PixelData::DELETE_ARRAY);
+
DALI_TEST_CHECK(pixelData);
+ DALI_TEST_CHECK(pixelData.GetWidth() == width);
+ DALI_TEST_CHECK(pixelData.GetHeight() == height);
+ DALI_TEST_CHECK(pixelData.GetStride() == stride);
+ DALI_TEST_CHECK(pixelData.GetPixelFormat() == Pixel::L8);
+ DALI_TEST_EQUALS(Dali::Integration::IsPixelDataReleaseAfterUpload(pixelData), true, TEST_LOCATION);
+
+ Dali::Integration::PixelDataBuffer pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
DALI_TEST_EQUALS(pixelDataBuffer.bufferSize, bufferSize, TEST_LOCATION);
DALI_TEST_EQUALS(pixelDataBuffer.buffer[0], static_cast<uint8_t>('a'), TEST_LOCATION);
/*
- * 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-test-suite-utils.h>
#include <dali/devel-api/rendering/texture-devel.h>
+#include <dali/integration-api/pixel-data-integ.h>
#include <dali/integration-api/texture-integ.h>
#include <dali/public-api/dali-core.h>
#include <test-native-image.h>
END_TEST;
}
+int UtcDaliTextureUpload09(void)
+{
+ TestApplication application;
+
+ //Create the texture
+ uint32_t width(64u);
+ uint32_t height(64u);
+ 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 bufferSize(width * height * 4u);
+ uint8_t* buffer = reinterpret_cast<uint8_t*>(malloc(bufferSize));
+ buffer[0] = 'a';
+
+ PixelData pixelData = Dali::Integration::NewPixelDataWithReleaseAfterUpload(buffer, bufferSize, width, height, 0u, Pixel::RGBA8888, PixelData::FREE);
+ DALI_TEST_CHECK(pixelData);
+
+ Dali::Integration::PixelDataBuffer pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+
+ DALI_TEST_EQUALS(pixelDataBuffer.bufferSize, bufferSize, TEST_LOCATION);
+ DALI_TEST_EQUALS(pixelDataBuffer.buffer[0], static_cast<uint8_t>('a'), TEST_LOCATION);
+
+ texture.Upload(pixelData);
+
+ 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()));
+ }
+
+ // Check whether the buffer become nullptr after texture uploaded.
+ pixelDataBuffer = Dali::Integration::GetPixelDataBuffer(pixelData);
+
+ DALI_TEST_CHECK(pixelDataBuffer.buffer == nullptr);
+
+ END_TEST;
+}
+
int UtcDaliTextureUploadSubPixelData01(void)
{
TestApplication application;
/*
- * 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.
namespace Dali::Integration
{
-PixelDataBuffer ReleasePixelDataBuffer(Dali::PixelData& pixelData)
+void ReleasePixelDataBuffer(Dali::PixelData pixelData)
{
- Internal::PixelData& pixelDataImpl = GetImplementation(pixelData);
- PixelDataBuffer pixelDataBuffer = pixelDataImpl.ReleasePixelDataBuffer();
- pixelData.Reset();
- return pixelDataBuffer;
+ Internal::PixelData& pixelDataImpl = GetImplementation(pixelData);
+ pixelDataImpl.ReleasePixelDataBuffer();
}
PixelDataBuffer GetPixelDataBuffer(const Dali::PixelData& pixelData)
PixelDataBuffer pixelDataBuffer = pixelDataImpl.GetPixelDataBuffer();
return pixelDataBuffer;
}
+
+Dali::PixelData NewPixelDataWithReleaseAfterUpload(uint8_t* buffer,
+ uint32_t bufferSize,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ Pixel::Format pixelFormat,
+ PixelData::ReleaseFunction releaseFunction)
+{
+ IntrusivePtr<Internal::PixelData> internal = Internal::PixelData::New(buffer, bufferSize, width, height, stride, pixelFormat, releaseFunction, true);
+ return PixelData(internal.Get());
+}
+
+bool IsPixelDataReleaseAfterUpload(const Dali::PixelData& pixelData)
+{
+ const Internal::PixelData& pixelDataImpl = GetImplementation(pixelData);
+ return pixelDataImpl.IsPixelDataReleaseAfterUpload();
+}
} // namespace Dali::Integration
#define DALI_PIXEL_DATA_INTEG_H
/*
- * 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.
*/
struct PixelDataBuffer
{
- uint8_t* buffer;
- uint32_t bufferSize;
- Dali::PixelData::ReleaseFunction releaseFunction;
+ uint8_t* buffer;
+ uint32_t bufferSize;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
- PixelDataBuffer(uint8_t* buffer,
- uint32_t bufferSize,
- Dali::PixelData::ReleaseFunction releaseFunction)
+ PixelDataBuffer(uint8_t* buffer,
+ uint32_t bufferSize,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride = 0)
: buffer(buffer),
bufferSize(bufferSize),
- releaseFunction(releaseFunction)
+ width(width),
+ height(height),
+ stride(stride)
{
}
};
/**
- * Get the buffer from a pixel data object, zero it in the pixel data object
- * and release the handle.
- * @param[in,out] pixelData The pixel data object to take the buffer from
- * @return the buffer and the data release mechanism
+ * Release the buffer from a pixel data object, zero it in the pixel data object.
+ * @param[in] pixelData The pixel data object to take the buffer from
*/
-DALI_CORE_API PixelDataBuffer ReleasePixelDataBuffer(Dali::PixelData& pixelData);
+DALI_CORE_API void ReleasePixelDataBuffer(Dali::PixelData pixelData);
/**
* Get the buffer from a pixel data object.
*/
DALI_CORE_API PixelDataBuffer GetPixelDataBuffer(const Dali::PixelData& pixelData);
+/**
+ * Creates a PixelData object which will release the buffer automatically after upload to texture.
+ * @return The pixel data object.
+ */
+DALI_CORE_API Dali::PixelData NewPixelDataWithReleaseAfterUpload(uint8_t* buffer,
+ uint32_t bufferSize,
+ uint32_t width,
+ uint32_t height,
+ uint32_t stride,
+ Pixel::Format pixelFormat,
+ PixelData::ReleaseFunction releaseFunction);
+
+/**
+ * Get whether we need to release pixel data after texture upload or not.
+ * @note This function can be called from another thread. Be careful about thread safety.
+ * @param[in] pixelData The pixel data object to get the release policy.
+ * @return True if we need to release pixel data after texture upload. False otherwise.
+ */
+DALI_CORE_API bool IsPixelDataReleaseAfterUpload(const Dali::PixelData& pixelData);
+
} // namespace Dali::Integration
#endif // DALI_PIXEL_DATA_INTEG_H
/*
- * 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.
uint32_t height,
uint32_t stride,
Pixel::Format pixelFormat,
- Dali::PixelData::ReleaseFunction releaseFunction)
+ Dali::PixelData::ReleaseFunction releaseFunction,
+ bool releaseAfterUpload)
: mBuffer(buffer),
mBufferSize(bufferSize),
mWidth(width),
mHeight(height),
mStride(stride),
mPixelFormat(pixelFormat),
- mReleaseFunction(releaseFunction)
+ mReleaseFunction(releaseFunction),
+ mReleaseAfterUpload(releaseAfterUpload)
{
DALI_LOG_INFO(gPixelDataLogFilter, Debug::Concise, "Allocated PixelData of size %u\n", bufferSize);
#if defined(DEBUG_ENABLED)
PixelData::~PixelData()
{
- if(mBuffer)
- {
- if(mReleaseFunction == Dali::PixelData::FREE)
- {
- free(mBuffer);
- }
- else
- {
- delete[] mBuffer;
- }
-#if defined(DEBUG_ENABLED)
- gPixelDataAllocationTotal -= mBufferSize;
-#endif
- }
+ ReleasePixelDataBuffer();
}
PixelDataPtr PixelData::New(uint8_t* buffer,
uint32_t height,
uint32_t stride,
Pixel::Format pixelFormat,
- Dali::PixelData::ReleaseFunction releaseFunction)
+ Dali::PixelData::ReleaseFunction releaseFunction,
+ bool releaseAfterUpload)
{
- return new PixelData(buffer, bufferSize, width, height, stride, pixelFormat, releaseFunction);
+ return new PixelData(buffer, bufferSize, width, height, stride, pixelFormat, releaseFunction, releaseAfterUpload);
}
uint32_t PixelData::GetWidth() const
return mBufferSize;
}
-Dali::Integration::PixelDataBuffer PixelData::ReleasePixelDataBuffer()
+void PixelData::ReleasePixelDataBuffer()
{
- Dali::Integration::PixelDataBuffer pixelDataBuffer(mBuffer, mBufferSize, mReleaseFunction);
- mBuffer = nullptr;
- return pixelDataBuffer;
+ if(mBuffer)
+ {
+ if(mReleaseFunction == Dali::PixelData::FREE)
+ {
+ free(mBuffer);
+ }
+ else
+ {
+ delete[] mBuffer;
+ }
+ mBuffer = nullptr;
+#if defined(DEBUG_ENABLED)
+ gPixelDataAllocationTotal -= mBufferSize;
+#endif
+ }
}
Dali::Integration::PixelDataBuffer PixelData::GetPixelDataBuffer() const
{
- Dali::Integration::PixelDataBuffer pixelDataBuffer(mBuffer, mBufferSize, mReleaseFunction);
+ Dali::Integration::PixelDataBuffer pixelDataBuffer(mBuffer, mBufferSize, mWidth, mHeight, mStride);
return pixelDataBuffer;
}
#define DALI_INTERNAL_PIXEL_DATA_H
/*
- * 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.
* @param [in] stride Buffer stride in pixels, 0 means the buffer is tightly packed
* @param [in] pixelFormat The pixel format
* @param [in] releaseFunction The function used to release the memory.
+ * @param [in] releaseAfterUpload Whether we release buffer after texture upload or not.
*/
static PixelDataPtr New(uint8_t* buffer,
uint32_t bufferSize,
uint32_t height,
uint32_t stride,
Pixel::Format pixelFormat,
- Dali::PixelData::ReleaseFunction releaseFunction);
+ Dali::PixelData::ReleaseFunction releaseFunction,
+ bool releaseAfterUpload);
/**
* @brief Constructor.
*
- * @param [in] buffer The raw pixel data.
- * @param [in] bufferSize The size of the buffer in bytes
- * @param [in] width Buffer width in pixels
- * @param [in] height Buffer height in pixels
- * @param [in] stride Buffer stride in pixels, 0 means the buffer is tightly packed
- * @param [in] pixelFormat The pixel format
- * @param [in] releaseFunction The function used to release the memory.
+ * @param [in] buffer The raw pixel data.
+ * @param [in] bufferSize The size of the buffer in bytes
+ * @param [in] width Buffer width in pixels
+ * @param [in] height Buffer height in pixels
+ * @param [in] stride Buffer stride in pixels, 0 means the buffer is tightly packed
+ * @param [in] pixelFormat The pixel format
+ * @param [in] releaseFunction The function used to release the memory.
+ * @param [in] releaseAfterUpload Whether we release buffer after texture upload or not.
*/
PixelData(uint8_t* buffer,
uint32_t bufferSize,
uint32_t height,
uint32_t stride,
Pixel::Format pixelFormat,
- Dali::PixelData::ReleaseFunction releaseFunction);
+ Dali::PixelData::ReleaseFunction releaseFunction,
+ bool releaseAfterUpload);
protected:
/**
uint32_t GetBufferSize() const;
/**
- * Return the buffer pointer and reset the internal buffer to zero.
- * @return The buffer pointer and associated data.
+ * Release the buffer data and reset the internal buffer to zero.
*/
- Dali::Integration::PixelDataBuffer ReleasePixelDataBuffer();
+ void ReleasePixelDataBuffer();
/**
* Return the buffer pointer.
Dali::Integration::PixelDataBuffer GetPixelDataBuffer() const;
/**
+ * Get whether we need to release pixel data after texture upload or not.
+ * @note This function can be called from another thread. Be careful.
+ * @return True if we need to release pixel data after texture upload. False otherwise.
+ */
+ bool IsPixelDataReleaseAfterUpload() const
+ {
+ return mReleaseAfterUpload;
+ }
+
+ /**
* @copydoc PixelData::GetStride()
*/
uint32_t GetStride() const;
Pixel::Format mPixelFormat; ///< Pixel format
Dali::PixelData::ReleaseFunction mReleaseFunction; ///< Function for releasing memory
+ const bool mReleaseAfterUpload;
+
#if defined(DEBUG_ENABLED)
static uint32_t gPixelDataAllocationTotal;
#endif
/*
- * 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.
Pixel::Format pixelFormat,
ReleaseFunction releaseFunction)
{
- IntrusivePtr<Internal::PixelData> internal = Internal::PixelData::New(buffer, bufferSize, width, height, 0, pixelFormat, releaseFunction);
+ IntrusivePtr<Internal::PixelData> internal = Internal::PixelData::New(buffer, bufferSize, width, height, 0, pixelFormat, releaseFunction, false);
return PixelData(internal.Get());
}
Pixel::Format pixelFormat,
ReleaseFunction releaseFunction)
{
- IntrusivePtr<Internal::PixelData> internal = Internal::PixelData::New(buffer, bufferSize, width, height, stride, pixelFormat, releaseFunction);
+ IntrusivePtr<Internal::PixelData> internal = Internal::PixelData::New(buffer, bufferSize, width, height, stride, pixelFormat, releaseFunction, false);
return PixelData(internal.Get());
}