2 * Copyright (c) 2024 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-toolkit/internal/image-loader/fast-track-loading-task.h>
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/adaptor-framework/texture-upload-manager.h>
24 #include <dali/integration-api/debug.h>
25 #include <dali/integration-api/texture-integ.h>
26 #include <dali/integration-api/trace.h>
27 #include <dali/public-api/common/vector-wrapper.h>
44 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_IMAGE_PERFORMANCE_MARKER, false);
47 uint64_t GetNanoseconds()
49 // Get the time of a monotonic clock since its epoch.
50 auto epoch = std::chrono::steady_clock::now().time_since_epoch();
51 auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(epoch);
52 return static_cast<uint64_t>(duration.count());
56 constexpr uint32_t CHROMINANCE_U_INDEX = 1u;
57 constexpr uint32_t CHROMINANCE_V_INDEX = 2u;
59 Dali::PixelData GetDummyChrominanceUPixelData()
61 static Dali::PixelData pixelDataU = PixelData::New(new uint8_t[2]{0x00, 0x00}, 2, 1, 2, Pixel::L8, PixelData::DELETE_ARRAY);
65 Dali::PixelData GetDummyChrominanceVPixelData()
67 static Dali::PixelData pixelDataV = PixelData::New(new uint8_t[2]{0x00, 0x00}, 2, 2, 1, Pixel::L8, PixelData::DELETE_ARRAY);
73 FastTrackLoadingTask::FastTrackLoadingTask(const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes, CallbackBase* callback)
74 : AsyncTask(MakeCallback(this, &FastTrackLoadingTask::OnComplete), url.GetProtocolType() == VisualUrl::ProtocolType::REMOTE ? AsyncTask::PriorityType::LOW : AsyncTask::PriorityType::HIGH),
77 mDimensions(dimensions),
78 mFittingMode(fittingMode),
79 mSamplingMode(samplingMode),
80 mPreMultiplyOnLoad(preMultiplyOnLoad),
82 mTextureUploadManager(Dali::Devel::TextureUploadManager::Get()),
85 mOrientationCorrection(orientationCorrection),
87 mLoadPlanesAvaliable(loadPlanes),
88 mPremultiplied(false),
91 mCallback = std::unique_ptr<CallbackBase>(callback);
95 FastTrackLoadingTask::~FastTrackLoadingTask()
99 void FastTrackLoadingTask::PrepareTexture()
101 const uint32_t requiredTexturesCount = mLoadPlanesAvaliable ? 3u : 1u;
103 mTextures.resize(requiredTexturesCount);
104 mImageInformations.resize(requiredTexturesCount);
105 for(uint32_t index = 0u; index < requiredTexturesCount; ++index)
107 mTextures[index] = mTextureUploadManager.GenerateTexture2D();
109 mImageInformations[index].resourceId = Integration::GetTextureResourceId(mTextures[index]);
112 if(mLoadPlanesAvaliable)
114 // Create static dummy chrominance pixel data now, for thread safety.
115 [[maybe_unused]] auto pixelDataU = GetDummyChrominanceUPixelData();
116 [[maybe_unused]] auto pixelDataV = GetDummyChrominanceVPixelData();
120 void FastTrackLoadingTask::OnComplete(AsyncTaskPtr task)
124 for(uint32_t index = 0u; index < mImageInformations.size(); ++index)
126 Dali::Integration::SetTextureSize(mTextures[index], Dali::ImageDimensions(mImageInformations[index].width, mImageInformations[index].height));
127 Dali::Integration::SetTexturePixelFormat(mTextures[index], mImageInformations[index].format);
129 if(mLoadPlanesAvaliable && !mPlanesLoaded)
131 // We will not use ChrominanceU and ChrominanceV texture anymore.
132 mTextures.resize(1u);
142 CallbackBase::Execute(*mCallback, FastTrackLoadingTaskPtr(reinterpret_cast<FastTrackLoadingTask*>(task.Get())));
146 // Called by worker thread
148 void FastTrackLoadingTask::Process()
154 bool FastTrackLoadingTask::IsReady()
159 void FastTrackLoadingTask::Load()
162 uint64_t mStartTimeNanoSceonds = 0;
163 uint64_t mEndTimeNanoSceonds = 0;
164 if(gTraceFilter && gTraceFilter->IsTraceEnabled())
166 mStartTimeNanoSceonds = GetNanoseconds();
167 std::ostringstream oss;
168 oss << "[u:" << mUrl.GetEllipsedUrl() << "]";
169 // DALI_TRACE_BEGIN(gTraceFilter, "DALI_IMAGE_FAST_TRACK_UPLOADING_TASK"); ///< TODO : Open it if we can control trace log level
170 DALI_LOG_RELEASE_INFO("BEGIN: DALI_IMAGE_FAST_TRACK_UPLOADING_TASK %s", oss.str().c_str());
174 Devel::PixelBuffer pixelBuffer;
175 std::vector<Devel::PixelBuffer> pixelBuffers;
177 if(mUrl.IsValid() && mUrl.IsLocalResource())
179 if(mLoadPlanesAvaliable)
181 Dali::LoadImagePlanesFromFile(mUrl.GetUrl(), pixelBuffers, mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
185 pixelBuffer = Dali::LoadImageFromFile(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
188 else if(mUrl.IsValid())
190 pixelBuffer = Dali::DownloadImageSynchronously(mUrl.GetUrl(), mDimensions, mFittingMode, mSamplingMode, mOrientationCorrection);
195 pixelBuffers.emplace_back(std::move(pixelBuffer));
198 if(pixelBuffers.empty())
200 mLoadSuccess = false;
201 DALI_LOG_ERROR("FastTrackLoadingTask::Load: Loading is failed: ResourceId : %d url : [%s]\n", mImageInformations[0u].resourceId, mUrl.GetUrl().c_str());
205 mPixelData.resize(pixelBuffers.size());
208 MultiplyAlpha(pixelBuffers[0]);
210 for(auto&& pixelBuffer : pixelBuffers)
212 mPixelData[index++] = Dali::Devel::PixelBuffer::Convert(pixelBuffer);
215 if(pixelBuffers.size() > 1u)
217 mPlanesLoaded = true;
219 else if(mLoadPlanesAvaliable && pixelBuffers.size() == 1u && mTextures.size() == 3u) ///< Case when we prepare three textures to render YUV, but loaded image is not YUV.
221 // Dummy pixel data for fake shader that we don't use actual YUV format.
222 // To fake shader, let we use indivisual sizes of texture for U and V.
223 mPixelData.resize(3u);
224 mPixelData[CHROMINANCE_U_INDEX] = GetDummyChrominanceUPixelData();
225 mPixelData[CHROMINANCE_V_INDEX] = GetDummyChrominanceVPixelData();
228 if(DALI_UNLIKELY(mPixelData.size() != mImageInformations.size()))
230 DALI_LOG_ERROR("FastTrackLoadingTask::Load: Undefined case. pixelBuffers.size() : %zu, image size : %zu, ResourceId : %d, url : [%s]\n", pixelBuffers.size(), mImageInformations.size(), mImageInformations[0u].resourceId, mUrl.GetUrl().c_str());
231 mLoadSuccess = false;
236 if(gTraceFilter && gTraceFilter->IsTraceEnabled())
238 mEndTimeNanoSceonds = GetNanoseconds();
239 std::ostringstream oss;
240 oss << std::fixed << std::setprecision(3);
242 oss << "d:" << static_cast<float>(mEndTimeNanoSceonds - mStartTimeNanoSceonds) / 1000000.0f << "ms ";
243 oss << "b:" << pixelBuffers.size() << " ";
244 if(!mPixelData.empty())
246 oss << "s:" << mPixelData[0].GetWidth() << "x" << mPixelData[0].GetHeight() << " ";
247 oss << "p:" << mPremultiplied << " ";
249 oss << "u:" << mUrl.GetEllipsedUrl() << "]";
250 // DALI_TRACE_END(gTraceFilter, "DALI_IMAGE_FAST_TRACK_UPLOADING_TASK"); ///< TODO : Open it if we can control trace log level
251 DALI_LOG_RELEASE_INFO("END: DALI_IMAGE_FAST_TRACK_UPLOADING_TASK %s", oss.str().c_str());
256 void FastTrackLoadingTask::MultiplyAlpha(Dali::Devel::PixelBuffer pixelBuffer)
258 if(mPreMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON && Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
260 pixelBuffer.MultiplyColorByAlpha();
261 mPremultiplied = pixelBuffer.IsAlphaPreMultiplied();
265 void FastTrackLoadingTask::UploadToTexture()
269 DALI_ASSERT_DEBUG(mPixelData.size() == mImageInformations.size());
272 for(auto&& pixelData : mPixelData)
274 mImageInformations[index].width = pixelData.GetWidth();
275 mImageInformations[index].height = pixelData.GetHeight();
276 mImageInformations[index].format = pixelData.GetPixelFormat();
278 mTextureUploadManager.RequestUpload(mImageInformations[index].resourceId, pixelData);
289 } // namespace Internal
291 } // namespace Toolkit