2 * Copyright (c) 2021 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>
33 LoadingTask::LoadingTask(uint32_t id, Dali::AnimatedImageLoading animatedImageLoading, uint32_t frameIndex)
40 orientationCorrection(),
41 preMultiplyOnLoad(DevelAsyncImageLoader::PreMultiplyOnLoad::OFF),
46 animatedImageLoading(animatedImageLoading),
47 frameIndex(frameIndex)
51 LoadingTask::LoadingTask(uint32_t id, const VisualUrl& url, ImageDimensions dimensions, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, bool orientationCorrection, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
55 dimensions(dimensions),
56 fittingMode(fittingMode),
57 samplingMode(samplingMode),
58 orientationCorrection(orientationCorrection),
59 preMultiplyOnLoad(preMultiplyOnLoad),
64 animatedImageLoading(),
69 LoadingTask::LoadingTask(uint32_t id, Devel::PixelBuffer pixelBuffer, Devel::PixelBuffer maskPixelBuffer, float contentScale, bool cropToMask, DevelAsyncImageLoader::PreMultiplyOnLoad preMultiplyOnLoad)
70 : pixelBuffer(pixelBuffer),
76 orientationCorrection(),
77 preMultiplyOnLoad(preMultiplyOnLoad),
79 maskPixelBuffer(maskPixelBuffer),
80 contentScale(contentScale),
81 cropToMask(cropToMask),
82 animatedImageLoading(),
87 void LoadingTask::Load()
89 if(animatedImageLoading)
91 pixelBuffer = animatedImageLoading.LoadFrame(frameIndex);
93 else if(url.IsLocalResource())
95 pixelBuffer = Dali::LoadImageFromFile(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
99 pixelBuffer = Dali::DownloadImageSynchronously(url.GetUrl(), dimensions, fittingMode, samplingMode, orientationCorrection);
104 DALI_LOG_ERROR("LoadingTask::Load: Loading is failed: %s\n", url.GetUrl().c_str());
108 void LoadingTask::ApplyMask()
110 pixelBuffer.ApplyMask(maskPixelBuffer, contentScale, cropToMask);
113 void LoadingTask::MultiplyAlpha()
115 if(pixelBuffer && Pixel::HasAlpha(pixelBuffer.GetPixelFormat()))
117 if(preMultiplyOnLoad == DevelAsyncImageLoader::PreMultiplyOnLoad::ON)
119 pixelBuffer.MultiplyColorByAlpha();
124 ImageLoadThread::ImageLoadThread(EventThreadCallback* trigger)
126 mLogFactory(Dali::Adaptor::Get().GetLogFactory())
130 ImageLoadThread::~ImageLoadThread()
132 // add an empty task would stop the thread from conditional wait.
139 for(auto&& iter : mLoadQueue)
145 for(auto&& iter : mCompleteQueue)
149 mCompleteQueue.Clear();
152 void ImageLoadThread::Run()
154 SetThreadName("ImageLoadThread");
155 mLogFactory.InstallLogFunction();
157 while(LoadingTask* task = NextTaskToProcess())
159 if(!task->isMaskTask)
167 task->MultiplyAlpha();
169 AddCompletedTask(task);
173 void ImageLoadThread::AddTask(LoadingTask* task)
175 bool wasEmpty = false;
177 // Lock while adding task to the queue
178 ConditionalWait::ScopedLock lock(mConditionalWait);
179 wasEmpty = mLoadQueue.Empty();
180 mLoadQueue.PushBack(task);
185 // wake up the image loading thread
186 mConditionalWait.Notify();
190 LoadingTask* ImageLoadThread::NextCompletedTask()
192 // Lock while popping task out from the queue
193 Mutex::ScopedLock lock(mMutex);
195 if(mCompleteQueue.Empty())
200 Vector<LoadingTask*>::Iterator next = mCompleteQueue.Begin();
201 LoadingTask* nextTask = *next;
202 mCompleteQueue.Erase(next);
207 bool ImageLoadThread::CancelTask(uint32_t loadingTaskId)
209 // Lock while remove task from the queue
210 ConditionalWait::ScopedLock lock(mConditionalWait);
212 for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
214 if((*iter)->id == loadingTaskId)
217 mLoadQueue.Erase(iter);
225 void ImageLoadThread::CancelAll()
227 // Lock while remove task from the queue
228 ConditionalWait::ScopedLock lock(mConditionalWait);
230 for(Vector<LoadingTask*>::Iterator iter = mLoadQueue.Begin(); iter != mLoadQueue.End(); ++iter)
237 LoadingTask* ImageLoadThread::NextTaskToProcess()
239 // Lock while popping task out from the queue
240 ConditionalWait::ScopedLock lock(mConditionalWait);
242 while(mLoadQueue.Empty())
244 mConditionalWait.Wait(lock);
247 Vector<LoadingTask*>::Iterator next = mLoadQueue.Begin();
248 LoadingTask* nextTask = *next;
249 mLoadQueue.Erase(next);
254 void ImageLoadThread::AddCompletedTask(LoadingTask* task)
256 // Lock while adding task to the queue
257 Mutex::ScopedLock lock(mMutex);
258 mCompleteQueue.PushBack(task);
260 // wake up the main thread
264 } // namespace Internal
266 } // namespace Toolkit