2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/rendering/texture-impl.h> // Dali::Internal::Texture
22 #include <dali/integration-api/render-controller.h>
23 #include <dali/internal/event/common/stage-impl.h>
24 #include <dali/internal/update/manager/update-manager.h>
30 TexturePtr Texture::New(TextureType::Type type, Pixel::Format format, uint32_t width, uint32_t height)
32 constexpr auto max_value = std::numeric_limits<uint16_t>::max();
33 DALI_ASSERT_ALWAYS((width < max_value) && (height < max_value) && "Size out of range");
34 TexturePtr texture(new Texture(type, format, ImageDimensions(width, height)));
35 texture->Initialize();
39 TexturePtr Texture::New(NativeImageInterface& nativeImageInterface)
41 TexturePtr texture(new Texture(&nativeImageInterface));
42 texture->Initialize();
44 // Request event processing and update forcely.
45 texture->mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
46 texture->mEventThreadServices.ForceNextUpdate();
50 Render::TextureKey Texture::GetRenderTextureKey() const
55 Texture::Texture(TextureType::Type type, Pixel::Format format, ImageDimensions size)
56 : mEventThreadServices(EventThreadServices::Get()),
65 Texture::Texture(NativeImageInterfacePtr nativeImageInterface)
66 : mEventThreadServices(EventThreadServices::Get()),
68 mNativeImage(nativeImageInterface),
69 mSize(nativeImageInterface->GetWidth(), nativeImageInterface->GetHeight()),
70 mType(TextureType::TEXTURE_2D),
71 mFormat(Pixel::RGB888)
75 void Texture::Initialize()
77 if(EventThreadServices::IsCoreRunning())
81 mTextureKey = Render::Texture::NewKey(mNativeImage);
85 mTextureKey = Render::Texture::NewKey(mType, mFormat, mSize);
88 AddTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
94 if(EventThreadServices::IsCoreRunning() && mTextureKey)
96 RemoveTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
100 bool Texture::Upload(PixelDataPtr pixelData)
102 return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), 0u, 0u, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight());
105 bool Texture::Upload(PixelDataPtr pixelData,
113 return UploadSubPixelData(pixelData, 0u, 0u, pixelData->GetWidth(), pixelData->GetHeight(), layer, mipmap, xOffset, yOffset, width, height);
116 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
117 uint32_t dataXOffset,
118 uint32_t dataYOffset,
122 return UploadSubPixelData(pixelData, dataXOffset, dataYOffset, dataWidth, dataHeight, 0u, 0u, 0u, 0u, dataWidth, dataHeight);
125 bool Texture::UploadSubPixelData(PixelDataPtr pixelData,
126 uint32_t dataXOffset,
127 uint32_t dataYOffset,
137 constexpr auto max_value = std::numeric_limits<uint16_t>::max();
138 DALI_ASSERT_ALWAYS(layer < max_value &&
139 mipmap < max_value &&
140 xOffset < max_value &&
141 yOffset < max_value &&
143 height < max_value &&
144 dataWidth < max_value &&
145 dataHeight < max_value &&
146 "Parameter value out of range");
149 if(EventThreadServices::IsCoreRunning() && mTextureKey)
153 DALI_LOG_ERROR("OpenGL ES does not support uploading data to native texture\n");
157 uint32_t pixelDataSize = dataWidth * dataHeight;
158 if(pixelData->GetBuffer() == nullptr || pixelDataSize == 0)
160 DALI_LOG_ERROR("PixelData is empty\n");
164 Pixel::Format pixelDataFormat = pixelData->GetPixelFormat();
165 if((pixelDataFormat == mFormat) || ((pixelDataFormat == Pixel::RGB888) && (mFormat == Pixel::RGBA8888)))
167 if(pixelDataSize < width * height)
169 DALI_LOG_ERROR("PixelData of an incorrect size when trying to update texture\n");
171 else if(Pixel::IsCompressed(mFormat) &&
172 ((dataXOffset != 0) ||
173 (dataYOffset != 0) ||
174 (dataWidth != pixelData->GetWidth()) ||
175 (dataHeight != pixelData->GetHeight())))
177 DALI_LOG_ERROR("Compressed pixel format don't support SubPixelData upload\n");
179 else if((dataXOffset + dataWidth > pixelData->GetWidth()) ||
180 (dataYOffset + dataHeight > pixelData->GetHeight()))
182 DALI_LOG_ERROR("PixelData of an incorrect subsize when trying to update texture\n");
184 else if((xOffset + width > (mSize.GetWidth() / (1u << mipmap))) ||
185 (yOffset + height > (mSize.GetHeight() / (1u << mipmap))))
187 DALI_LOG_ERROR("Texture update area out of bounds\n");
191 //Parameters are correct. Send message to upload data to the texture
192 UploadParams params = {static_cast<uint32_t>(dataXOffset),
193 static_cast<uint32_t>(dataYOffset),
194 static_cast<uint16_t>(dataWidth),
195 static_cast<uint16_t>(dataHeight),
196 static_cast<uint16_t>(layer),
197 static_cast<uint16_t>(mipmap),
198 static_cast<uint16_t>(xOffset),
199 static_cast<uint16_t>(yOffset),
200 static_cast<uint16_t>(width),
201 static_cast<uint16_t>(height)};
202 UploadTextureMessage(mEventThreadServices.GetUpdateManager(), mTextureKey, pixelData, params);
204 // Request event processing and update forcely
205 mEventThreadServices.GetRenderController().RequestProcessEventsOnIdle(true);
206 mEventThreadServices.ForceNextUpdate();
213 DALI_LOG_ERROR("Bad format\n");
222 void Texture::GenerateMipmaps()
224 if(EventThreadServices::IsCoreRunning() && mTextureKey)
226 GenerateMipmapsMessage(mEventThreadServices.GetUpdateManager(), mTextureKey);
230 uint32_t Texture::GetWidth() const
232 return mSize.GetWidth();
235 uint32_t Texture::GetHeight() const
237 return mSize.GetHeight();
240 Pixel::Format Texture::GetPixelFormat() const
245 bool Texture::IsNative() const
247 return static_cast<bool>(mNativeImage);
250 bool Texture::ApplyNativeFragmentShader(std::string& shader)
252 bool modified = false;
253 if(mNativeImage && !shader.empty())
255 modified = mNativeImage->ApplyNativeFragmentShader(shader);
261 } // namespace Internal