4593bc7b777a02866f6163435a5365dc38a644ce
[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 namespace Dali
24 {
25 namespace Toolkit
26 {
27 namespace Internal
28 {
29 namespace
30 {
31 const bool ENABLE_ORIENTATION_CORRECTION(true);
32 } // namespace
33
34 FixedImageCache::FixedImageCache(
35   TextureManager& textureManager, UrlList& urlList, ImageCache::FrameReadyObserver& observer, unsigned int batchSize)
36 : ImageCache(textureManager, observer, batchSize),
37   mImageUrls(urlList),
38   mFront(0u)
39 {
40   mReadyFlags.reserve(mImageUrls.size());
41   LoadBatch();
42 }
43
44 FixedImageCache::~FixedImageCache()
45 {
46   if(mTextureManagerAlive)
47   {
48     for(std::size_t i = 0; i < mImageUrls.size(); ++i)
49     {
50       mTextureManager.Remove(mImageUrls[i].mTextureId, this);
51     }
52   }
53 }
54
55 TextureSet FixedImageCache::Frame(uint32_t frameIndex)
56 {
57   while(frameIndex > mFront)
58   {
59     ++mFront;
60     if(mFront >= mImageUrls.size())
61     {
62       mFront = 0;
63     }
64     LoadBatch();
65   }
66
67   mFront = frameIndex;
68
69   TextureSet textureSet;
70   if(IsFrontReady() == true)
71   {
72     textureSet = GetFrontTextureSet();
73   }
74   else
75   {
76     mWaitingForReadyFrame = true;
77   }
78
79   return textureSet;
80 }
81
82 TextureSet FixedImageCache::FirstFrame()
83 {
84   TextureSet textureSet = GetFrontTextureSet();
85
86   if(!textureSet)
87   {
88     mWaitingForReadyFrame = true;
89   }
90
91   return textureSet;
92 }
93
94 TextureSet FixedImageCache::NextFrame()
95 {
96   TextureSet textureSet = Frame((mFront + 1) % mImageUrls.size());
97
98   return textureSet;
99 }
100
101 uint32_t FixedImageCache::GetFrameInterval(uint32_t frameIndex) const
102 {
103   return 0u;
104 }
105
106 int32_t FixedImageCache::GetCurrentFrameIndex() const
107 {
108   return static_cast<int32_t>(mFront);
109 }
110
111 int32_t FixedImageCache::GetTotalFrameCount() const
112 {
113   return mImageUrls.size();
114 }
115
116 bool FixedImageCache::IsFrontReady() const
117 {
118   return (mReadyFlags.size() > 0 && mReadyFlags[mFront] == true);
119 }
120
121 void FixedImageCache::LoadBatch()
122 {
123   // Try and load up to mBatchSize images, until the cache is filled.
124   // Once the cache is filled, mUrlIndex exceeds mImageUrls size and
125   // no more images are loaded.
126   bool frontFrameReady = IsFrontReady();
127
128   for(unsigned int i = 0; i < mBatchSize && mUrlIndex < mImageUrls.size(); ++i)
129   {
130     std::string& url = mImageUrls[mUrlIndex].mUrl;
131
132     mReadyFlags.push_back(false);
133
134     // Note, if the image is already loaded, then UploadComplete will get called
135     // from within this method. This means it won't yet have a texture id, so we
136     // need to account for this inside the UploadComplete method using mRequestingLoad.
137     mRequestingLoad = true;
138
139     bool                               synchronousLoading = false;
140     bool                               atlasingStatus     = false;
141     bool                               loadingStatus      = false;
142     TextureManager::MaskingDataPointer maskInfo           = nullptr;
143     AtlasUploadObserver*               atlasObserver      = nullptr;
144     ImageAtlasManagerPtr               imageAtlasManager  = nullptr;
145     Vector4                            textureRect;
146     Dali::ImageDimensions              textureRectSize;
147     auto                               preMultiply = TextureManager::MultiplyOnLoad::LOAD_WITHOUT_MULTIPLY;
148
149     mTextureManager.LoadTexture(
150       url, ImageDimensions(), FittingMode::SCALE_TO_FILL, SamplingMode::BOX_THEN_LINEAR, maskInfo, synchronousLoading, mImageUrls[mUrlIndex].mTextureId, textureRect, textureRectSize, atlasingStatus, loadingStatus, Dali::WrapMode::Type::DEFAULT, Dali::WrapMode::Type::DEFAULT, this, atlasObserver, imageAtlasManager, ENABLE_ORIENTATION_CORRECTION, TextureManager::ReloadPolicy::CACHED, preMultiply);
151
152     if(loadingStatus == false) // not loading, means it's already ready.
153     {
154       SetImageFrameReady(mImageUrls[mUrlIndex].mTextureId);
155     }
156     mRequestingLoad = false;
157     ++mUrlIndex;
158   }
159
160   CheckFrontFrame(frontFrameReady);
161 }
162
163 void FixedImageCache::SetImageFrameReady(TextureManager::TextureId textureId)
164 {
165   for(std::size_t i = 0; i < mImageUrls.size(); ++i)
166   {
167     if(mImageUrls[i].mTextureId == textureId)
168     {
169       mReadyFlags[i] = true;
170       break;
171     }
172   }
173 }
174
175 TextureSet FixedImageCache::GetFrontTextureSet() const
176 {
177   return mTextureManager.GetTextureSet(mImageUrls[mFront].mTextureId);
178 }
179
180 void FixedImageCache::CheckFrontFrame(bool wasReady)
181 {
182   if(mWaitingForReadyFrame && wasReady == false && IsFrontReady())
183   {
184     mWaitingForReadyFrame = false;
185     mObserver.FrameReady(GetFrontTextureSet());
186   }
187 }
188
189 void FixedImageCache::UploadComplete(
190   bool           loadSuccess,
191   int32_t        textureId,
192   TextureSet     textureSet,
193   bool           useAtlasing,
194   const Vector4& atlasRect,
195   bool           preMultiplied)
196 {
197   bool frontFrameReady = IsFrontReady();
198
199   if(!mRequestingLoad)
200   {
201     SetImageFrameReady(textureId);
202
203     CheckFrontFrame(frontFrameReady);
204   }
205   else
206   {
207     // UploadComplete has been called from within RequestLoad. TextureManager must
208     // therefore already have the texture cached, so make the texture ready.
209     // (Use the last texture, as the texture id hasn't been assigned yet)
210     mReadyFlags.back() = true;
211   }
212 }
213
214 void FixedImageCache::LoadComplete(
215   bool               loadSuccess,
216   Devel::PixelBuffer pixelBuffer,
217   const VisualUrl&   url,
218   bool               preMultiplied)
219 {
220   // LoadComplete is called if this TextureUploadObserver requested to load
221   // an image that will be returned as a type of PixelBuffer by using a method
222   // TextureManager::LoadPixelBuffer.
223 }
224
225 } //namespace Internal
226 } //namespace Toolkit
227 } //namespace Dali