Refactoring Animated image visual
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / animated-image / fixed-image-cache.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 // CLASS HEADER
18 #include <dali-toolkit/internal/visuals/animated-image/fixed-image-cache.h>
19
20 // INTERNAL HEADERS
21 #include <dali-toolkit/internal/visuals/image-atlas-manager.h> // For ImageAtlasManagerPtr
22
23 // EXTERNAL HEADERS
24 #include <dali/integration-api/debug.h>
25
26 namespace Dali
27 {
28 namespace Toolkit
29 {
30 namespace Internal
31 {
32 namespace
33 {
34 constexpr bool ENABLE_ORIENTATION_CORRECTION(true);
35 constexpr uint32_t FIRST_FRAME_INDEX = 0u;
36 } // namespace
37
38 FixedImageCache::FixedImageCache(
39   TextureManager& textureManager, UrlList& urlList, ImageCache::FrameReadyObserver& observer, uint32_t batchSize, uint32_t interval)
40 : ImageCache(textureManager, observer, batchSize, interval),
41   mImageUrls(urlList),
42   mFront(FIRST_FRAME_INDEX)
43 {
44   mReadyFlags.reserve(mImageUrls.size());
45 }
46
47 FixedImageCache::~FixedImageCache()
48 {
49   ClearCache();
50 }
51
52 TextureSet FixedImageCache::Frame(uint32_t frameIndex)
53 {
54   TextureSet textureSet;
55   if(frameIndex >= mImageUrls.size())
56   {
57     DALI_LOG_ERROR("Wrong frameIndex requested.\n");
58     return textureSet;
59   }
60
61   while(mReadyFlags.size() < mImageUrls.size() &&
62         (frameIndex > mFront || mReadyFlags.empty()))
63   {
64     ++mFront;
65     LoadBatch();
66   }
67
68   mFront = frameIndex;
69
70   if(IsFrontReady() && mLoadState != TextureManager::LoadState::LOAD_FAILED)
71   {
72     textureSet = GetFrontTextureSet();
73   }
74
75   return textureSet;
76 }
77
78 TextureSet FixedImageCache::FirstFrame()
79 {
80   TextureSet textureSet = Frame(FIRST_FRAME_INDEX);
81
82   return textureSet;
83 }
84
85 uint32_t FixedImageCache::GetFrameInterval(uint32_t frameIndex) const
86 {
87   return mInterval;
88 }
89
90 int32_t FixedImageCache::GetCurrentFrameIndex() const
91 {
92   return static_cast<int32_t>(mFront);
93 }
94
95 int32_t FixedImageCache::GetTotalFrameCount() const
96 {
97   return mImageUrls.size();
98 }
99
100 bool FixedImageCache::IsFrontReady() const
101 {
102   return (mReadyFlags.size() > 0 && mReadyFlags[mFront] == true);
103 }
104
105 void FixedImageCache::LoadBatch()
106 {
107   // Try and load up to mBatchSize images, until the cache is filled.
108   // Once the cache is filled, no more images are loaded.
109   for(unsigned int i = 0; i < mBatchSize && mReadyFlags.size() < mImageUrls.size(); ++i)
110   {
111     uint32_t frameIndex = mReadyFlags.size();
112     std::string& url = mImageUrls[frameIndex].mUrl;
113
114     mReadyFlags.push_back(false);
115
116     // Note, if the image is already loaded, then LoadComplete will get called
117     // from within this method. This means it won't yet have a texture id, so we
118     // need to account for this inside the LoadComplete method using mRequestingLoad.
119     mRequestingLoad = true;
120     mLoadState = TextureManager::LoadState::LOADING;
121
122     bool                               synchronousLoading = false;
123     bool                               atlasingStatus     = false;
124     bool                               loadingStatus      = false;
125     TextureManager::MaskingDataPointer maskInfo           = nullptr;
126     AtlasUploadObserver*               atlasObserver      = nullptr;
127     ImageAtlasManagerPtr               imageAtlasManager  = nullptr;
128     Vector4                            textureRect;
129     Dali::ImageDimensions              textureRectSize;
130     auto                               preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
131
132     mTextureManager.LoadTexture(
133       url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, maskInfo, synchronousLoading, mImageUrls[frameIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
134
135     mRequestingLoad = false;
136   }
137 }
138
139 TextureSet FixedImageCache::GetFrontTextureSet() const
140 {
141   return mTextureManager.GetTextureSet(mImageUrls[mFront].mTextureId);
142 }
143
144 void FixedImageCache::CheckFrontFrame(bool wasReady)
145 {
146   if(wasReady == false && IsFrontReady())
147   {
148     mObserver.FrameReady(GetFrontTextureSet(), mInterval);
149   }
150 }
151
152 void FixedImageCache::ClearCache()
153 {
154   if(mTextureManagerAlive)
155   {
156     for(std::size_t i = 0; i < mImageUrls.size(); ++i)
157     {
158       mTextureManager.Remove(mImageUrls[i].mTextureId, this);
159       mImageUrls[i].mTextureId = TextureManager::INVALID_TEXTURE_ID;
160     }
161   }
162   mReadyFlags.clear();
163   mLoadState = TextureManager::LoadState::NOT_STARTED;
164 }
165
166 void FixedImageCache::LoadComplete(bool loadSuccess, TextureInformation textureInformation)
167 {
168   if(loadSuccess)
169   {
170     mLoadState = TextureManager::LoadState::LOAD_FINISHED;
171     bool frontFrameReady = IsFrontReady();
172     if(!mRequestingLoad)
173     {
174       for(std::size_t i = 0; i < mImageUrls.size(); ++i)
175       {
176         if(mImageUrls[i].mTextureId == textureInformation.textureId)
177         {
178           mReadyFlags[i] = true;
179           break;
180         }
181       }
182     }
183     else
184     {
185       mReadyFlags.back() = true;
186     }
187     CheckFrontFrame(frontFrameReady);
188   }
189   else
190   {
191     mLoadState = TextureManager::LoadState::LOAD_FAILED;
192     mObserver.FrameReady(TextureSet(), 0);
193   }
194 }
195
196 } //namespace Internal
197 } //namespace Toolkit
198 } //namespace Dali