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 <eunkiki.hong@samsung.com>
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;
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<unsigned char*>(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<unsigned char*>(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;
mNativeImage(),
mSize(size),
mType(type),
- mFormat(format)
+ mFormat(format),
+ mUseUploadedParameter(mSize.GetWidth() == 0u && mSize.GetHeight() == 0u && mFormat == Pixel::INVALID)
{
}
mNativeImage(nativeImageInterface),
mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
mType(TextureType::TEXTURE_2D),
- mFormat(Pixel::RGB888)
+ mFormat(Pixel::RGB888),
+ mUseUploadedParameter(false)
{
}
constexpr auto max_value = std::numeric_limits<uint16_t>::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");
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)
{
{
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<uint32_t>(mSize.GetWidth()) >> mipmap)) ||
+ (yOffset + height > (static_cast<uint32_t>(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<uint32_t>(dataXOffset),
static_cast<uint32_t>(dataYOffset),
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
Integration::StencilBufferAvailable stencilBufferAvailable; ///< Whether the stencil buffer is available
Integration::PartialUpdateAvailable partialUpdateAvailable; ///< Whether the partial update is available
- std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
- Vector<Graphics::Texture*> boundTextures; ///< The textures bound for rendering
- Vector<Graphics::Texture*> textureDependencyList; ///< The dependency list of bound textures
- Vector<Render::TextureKey> updatedTextures{}; ///< The updated texture list
+ std::unique_ptr<Dali::ThreadPool> threadPool; ///< The thread pool
+ Vector<Graphics::Texture*> boundTextures; ///< The textures bound for rendering
+ Vector<Render::TextureKey> 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;
// 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
#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.
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();
mHeight(size.GetHeight()),
mType(type),
mHasAlpha(HasAlpha(format)),
- mUpdated(true)
+ mUpdated(true),
+ mUseUploadedParameter(mWidth == 0u && mHeight == 0u && mPixelFormat == Pixel::INVALID)
{
}
mHeight(static_cast<uint16_t>(nativeImageInterface->GetHeight())), // ignoring overflow, not happening in practice
mType(TextureType::TEXTURE_2D),
mHasAlpha(nativeImageInterface->RequiresBlending()),
- mUpdated(true)
+ mUpdated(true),
+ mUseUploadedParameter(false)
{
}
{
DALI_ASSERT_ALWAYS(!mNativeImage);
- if(!mGraphicsTexture)
- {
- Create(static_cast<Graphics::TextureUsageFlags>(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)
{
* srcOffset = A).offsetByte;
* srcSize = ( C).offsetByte - A).offsetByte );
*/
- const uint32_t bytePerPixel = Pixel::GetBytesPerPixel(pixelData->GetPixelFormat());
- const uint32_t dataStrideByte = (srcStride ? srcStride : static_cast<uint32_t>(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<uint32_t>(params.dataWidth) * bytePerPixel;
+ const uint32_t dataWidthByte = static_cast<uint32_t>(uploadedDataWidth) * bytePerPixel;
srcOffset = params.dataYOffset * dataStrideByte + dataXOffsetByte;
- srcSize = static_cast<uint32_t>(params.dataHeight) * dataStrideByte - (dataStrideByte - dataWidthByte);
+ srcSize = static_cast<uint32_t>(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::TextureUsageFlags>(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<uint16_t>(params.xOffset, params.yOffset, params.width, params.height);
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();
}
/**
+ * 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
*/
*/
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<Graphics::Texture> mGraphicsTexture;
Render::Sampler mSampler; ///< The current sampler state
Rect<uint16_t> 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
/*
- * 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.
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);
#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.
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