2 * Copyright (c) 2022 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 "image-load-thread.h"
22 #include <dali/devel-api/adaptor-framework/image-loading.h>
23 #include <dali/devel-api/adaptor-framework/thread-settings.h>
24 #include <dali/integration-api/adaptor-framework/adaptor.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/public-api/adaptor-framework/encoded-image-buffer.h>
34 LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
41 preMultiplyOnLoad(preMultiplyOnLoad),
44 animatedImageLoading(animatedImageLoading),
45 frameIndex(frameIndex),
46 orientationCorrection(),
53 LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad, bool loadPlanes)
57 dimensions(dimensions),
58 fittingMode(fittingMode),
59 samplingMode(samplingMode),
60 preMultiplyOnLoad(preMultiplyOnLoad),
63 animatedImageLoading(),
65 orientationCorrection(orientationCorrection),
68 loadPlanes(loadPlanes)
72 LoadingTask::LoadingTask(uint32_t id, const EncodedImageBuffer& encodedImageBuffer, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
74 encodedImageBuffer(encodedImageBuffer),
76 dimensions(dimensions),
77 fittingMode(fittingMode),
78 samplingMode(samplingMode),
79 preMultiplyOnLoad(preMultiplyOnLoad),
82 animatedImageLoading(),
84 orientationCorrection(orientationCorrection),
91 LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
98 preMultiplyOnLoad(preMultiplyOnLoad),
99 maskPixelBuffer(maskPixelBuffer),
100 contentScale(contentScale),
101 animatedImageLoading(),
103 orientationCorrection(),
105 cropToMask(cropToMask),
108 pixelBuffers.push_back(pixelBuffer);
111 void LoadingTask::Load()
113 Devel::PixelBuffer pixelBuffer;
114 if(animatedImageLoading)
116 pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
118 else if(encodedImageBuffer)
120 pixelBuffer = Dali::LoadImageFromBuffer(encodedImageBuffer.GetRawBuffer(), dimensions, fittingMode, samplingMode, orientationCorrection);
122 else if(url.IsValid() && url.IsLocalResource())
126 Dali::LoadImagePlanesFromFile(url.GetUrl(), pixelBuffers, dimensions, fittingMode, samplingMode, orientationCorrection);
130 pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
133 else if(url.IsValid())
135 pixelBuffer = Dali::DownloadImageSynchronously(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
140 pixelBuffers.push_back(pixelBuffer);
143 if(pixelBuffers.empty())
145 DALI_LOG_ERROR("LoadingTask::Load: Loading is failed: %s\n", url.GetUrl().c_str());
149 void LoadingTask::ApplyMask()
151 if(!pixelBuffers.empty())
153 pixelBuffers[0].ApplyMask(maskPixelBuffer, contentScale, cropToMask);
157 void LoadingTask::MultiplyAlpha()
159 if(!pixelBuffers.empty() && Pixel::HasAlpha(pixelBuffers[0].GetPixelFormat()))
161 if(preMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON)
163 pixelBuffers[0].MultiplyColorByAlpha();
168 ImageLoadThread::ImageLoadThread(EventThreadCallback* trigger)
170 mLogFactory(Dali::Adaptor::Get().GetLogFactory())
174 ImageLoadThread::~ImageLoadThread()
176 // add an empty task would stop the thread from conditional wait.
183 for(auto&& iter : mLoadQueue)
189 for(auto&& iter : mCompleteQueue)
193 mCompleteQueue.Clear();
196 void ImageLoadThread::Run()
198 SetThreadName("ImageLoadThread");
199 mLogFactory.InstallLogFunction();
201 while(LoadingTask* task = NextTaskToProcess())
203 if(!task->isMaskTask)
211 task->MultiplyAlpha();
213 AddCompletedTask(task);
217 void ImageLoadThread::AddTask(LoadingTask* task)
219 bool wasEmpty = false;
221 // Lock while adding task to the queue
222 ConditionalWait::ScopedLock lock(mConditionalWait);
223 wasEmpty = mLoadQueue.Empty();
224 mLoadQueue.PushBack(task);
229 // wake up the image loading thread
230 mConditionalWait.Notify();
234 LoadingTask* ImageLoadThread::NextCompletedTask()
236 // Lock while popping task out from the queue
237 Mutex::ScopedLock lock(mMutex);
239 if(mCompleteQueue.Empty())
244 Vector<LoadingTask*>::Iterator next = mCompleteQueue.Begin();
245 LoadingTask* nextTask = *next;
246 mCompleteQueue.Erase(next);
251 bool ImageLoadThread::CancelTask(uint32_t loadingTaskId)
253 // Lock while remove task from the queue
254 ConditionalWait::ScopedLock lock(mConditionalWait);
256 for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
258 if((*iter)->id == loadingTaskId)
261 mLoadQueue.Erase(iter);
269 void ImageLoadThread::CancelAll()
271 // Lock while remove task from the queue
272 ConditionalWait::ScopedLock lock(mConditionalWait);
274 for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
281 LoadingTask* ImageLoadThread::NextTaskToProcess()
283 // Lock while popping task out from the queue
284 ConditionalWait::ScopedLock lock(mConditionalWait);
286 while(mLoadQueue.Empty())
288 mConditionalWait.Wait(lock);
291 Vector<LoadingTask*>::Iterator next = mLoadQueue.Begin();
292 LoadingTask* nextTask = *next;
293 mLoadQueue.Erase(next);
298 void ImageLoadThread::AddCompletedTask(LoadingTask* task)
300 // Lock while adding task to the queue
301 Mutex::ScopedLock lock(mMutex);
302 mCompleteQueue.PushBack(task);
304 // wake up the main thread
308 } // namespace Internal
310 } // namespace Toolkit