89a44c381701b8b71d21eb7d96938ea96a4ced96
[platform/core/uifw/dali-adaptor.git] / dali / internal / legacy / common / tizen-platform-abstraction.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
18 // CLASS HEADER
19 #include <dali/internal/legacy/common/tizen-platform-abstraction.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/bitmap.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/integration-api/resource-types.h>
25 #include <dali/public-api/signals/callback.h>
26 #include <dirent.h>
27 #include <algorithm>
28 #include <fstream>
29
30 // INTERNAL INCLUDES
31 #include <dali/devel-api/adaptor-framework/file-loader.h>
32 #include <dali/internal/adaptor/common/adaptor-impl.h>
33 #include <dali/internal/imaging/common/image-loader.h>
34 #include <dali/internal/imaging/common/pixel-buffer-impl.h>
35 #include <dali/internal/system/common/file-reader.h>
36
37 namespace Dali
38 {
39 namespace TizenPlatform
40 {
41 struct TizenPlatformAbstraction::TimerCallback : ConnectionTracker
42 {
43   Dali::Timer                   mTimer;
44   TizenPlatformAbstraction*     mOwner;
45   std::unique_ptr<CallbackBase> mCallback;
46   const uint32_t                mIdNumber;
47
48   static uint32_t sNextTimerId;
49
50   TimerCallback(TizenPlatformAbstraction* owner, CallbackBase* callback, uint32_t ms)
51   : mTimer(Dali::Timer::New(ms)),
52     mOwner(owner),
53     mCallback(std::unique_ptr<CallbackBase>(callback)),
54     mIdNumber(++sNextTimerId)
55   {
56     mTimer.TickSignal().Connect(this, &TimerCallback::Tick);
57     mTimer.Start();
58   }
59   ~TimerCallback()
60   {
61   }
62
63   bool Tick()
64   {
65     mOwner->RunTimerFunction(*this);
66     return false;
67   }
68 };
69
70 uint32_t TizenPlatformAbstraction::TimerCallback::sNextTimerId = 0;
71
72 TizenPlatformAbstraction::TizenPlatformAbstraction()
73 : mDataStoragePath(""),
74   mTimerPairsWaiting(),
75   mTimerPairsSpent()
76
77 {
78 }
79
80 TizenPlatformAbstraction::~TizenPlatformAbstraction()
81 {
82 }
83
84 ImageDimensions TizenPlatformAbstraction::GetClosestImageSize(const std::string& filename,
85                                                               ImageDimensions    size,
86                                                               FittingMode::Type  fittingMode,
87                                                               SamplingMode::Type samplingMode,
88                                                               bool               orientationCorrection)
89 {
90   return ImageLoader::GetClosestImageSize(filename, size, fittingMode, samplingMode, orientationCorrection);
91 }
92
93 ImageDimensions TizenPlatformAbstraction::GetClosestImageSize(Integration::ResourcePointer resourceBuffer,
94                                                               ImageDimensions              size,
95                                                               FittingMode::Type            fittingMode,
96                                                               SamplingMode::Type           samplingMode,
97                                                               bool                         orientationCorrection)
98 {
99   return ImageLoader::GetClosestImageSize(resourceBuffer, size, fittingMode, samplingMode, orientationCorrection);
100 }
101
102 Integration::ResourcePointer TizenPlatformAbstraction::LoadImageSynchronously(const Integration::BitmapResourceType& resource, const std::string& resourcePath)
103 {
104   return ImageLoader::LoadImageSynchronously(resource, resourcePath);
105 }
106
107 Integration::BitmapPtr TizenPlatformAbstraction::DecodeBuffer(const Integration::BitmapResourceType& resource, uint8_t* buffer, size_t size)
108 {
109   Integration::BitmapPtr   resultBitmap;
110   Dali::Devel::PixelBuffer bitmap;
111
112   Dali::Internal::Platform::FileReader fileReader(buffer, size);
113   FILE* const                          fp = fileReader.GetFile();
114   if(fp)
115   {
116     bool result = ImageLoader::ConvertStreamToBitmap(resource, "", fp, bitmap);
117     if(!result || !bitmap)
118     {
119       bitmap.Reset();
120       DALI_LOG_WARNING("Unable to decode bitmap supplied as in-memory blob.\n");
121     }
122     else
123     {
124       Integration::Bitmap::Profile profile{Integration::Bitmap::Profile::BITMAP_2D_PACKED_PIXELS};
125
126       // For backward compatibility the Bitmap must be created
127       auto retval = Integration::Bitmap::New(profile, Dali::ResourcePolicy::OWNED_DISCARD);
128
129       retval->GetPackedPixelsProfile()->ReserveBuffer(
130         bitmap.GetPixelFormat(),
131         bitmap.GetWidth(),
132         bitmap.GetHeight(),
133         bitmap.GetWidth(),
134         bitmap.GetHeight());
135
136       auto& impl = Dali::GetImplementation(bitmap);
137
138       std::copy(impl.GetBuffer(), impl.GetBuffer() + impl.GetBufferSize(), retval->GetBuffer());
139       resultBitmap.Reset(retval);
140     }
141   }
142
143   return resultBitmap;
144 }
145
146 bool TizenPlatformAbstraction::LoadShaderBinaryFile(const std::string& filename, Dali::Vector<unsigned char>& buffer) const
147 {
148   bool result = false;
149
150 #ifdef SHADERBIN_CACHE_ENABLED
151   std::string path;
152
153   // First check the system location where shaders are stored at install time:
154   path = DALI_SHADERBIN_DIR;
155   path += filename;
156   result = Dali::FileLoader::ReadFile(path, buffer);
157
158   // Fallback to the cache of shaders stored after previous runtime compilations:
159   // On desktop this looks in the current working directory that the app was launched from.
160   if(result == false)
161   {
162     path = mDataStoragePath;
163     path += filename;
164     result = Dali::FileLoader::ReadFile(path, buffer);
165   }
166 #endif
167
168   return result;
169 }
170
171 bool TizenPlatformAbstraction::SaveShaderBinaryFile(const std::string& filename, const unsigned char* buffer, unsigned int numBytes) const
172 {
173   bool result = false;
174
175 #ifdef SHADERBIN_CACHE_ENABLED
176
177   // Use the cache of shaders stored after previous runtime compilations:
178   // On desktop this looks in the current working directory that the app was launched from.
179   std::string path = mDataStoragePath;
180   path += filename;
181   result = SaveFile(path, buffer, numBytes);
182
183 #endif
184
185   return result;
186 }
187
188 void TizenPlatformAbstraction::SetDataStoragePath(const std::string& path)
189 {
190   mDataStoragePath = path;
191 }
192
193 uint32_t TizenPlatformAbstraction::StartTimer(uint32_t milliseconds, CallbackBase* callback)
194 {
195   TimerCallback* timerCallbackPtr = new TimerCallback(this, callback, milliseconds);
196
197   // Stick it in the list
198   mTimerPairsWaiting.push_back(std::unique_ptr<TimerCallback>(timerCallbackPtr));
199
200   return timerCallbackPtr->mIdNumber;
201 }
202
203 void TizenPlatformAbstraction::CancelTimer(uint32_t timerId)
204 {
205   auto iter = std::remove_if(
206     mTimerPairsWaiting.begin(), mTimerPairsWaiting.end(), [&timerId](std::unique_ptr<TimerCallback>& timerCallbackPtr) {
207       if(timerCallbackPtr->mIdNumber == timerId)
208       {
209         timerCallbackPtr->mTimer.Stop();
210         return true;
211       }
212       else
213       {
214         return false;
215       }
216     });
217
218   mTimerPairsWaiting.erase(iter, mTimerPairsWaiting.end());
219 }
220
221 void TizenPlatformAbstraction::RunTimerFunction(TimerCallback& timerPtr)
222 {
223   CallbackBase::Execute(*timerPtr.mCallback);
224
225   std::vector<std::unique_ptr<TimerCallback> >::iterator timerIter = std::find_if(mTimerPairsWaiting.begin(), mTimerPairsWaiting.end(), [&](std::unique_ptr<TimerCallback>& p) { return p.get() == &timerPtr; });
226
227   if(timerIter == std::end(mTimerPairsWaiting))
228   {
229     DALI_ASSERT_DEBUG(false);
230   }
231
232   // ...and move it
233   std::move(timerIter, timerIter + 1, std::back_inserter(mTimerPairsSpent));
234
235   mTimerPairsWaiting.erase(timerIter, timerIter + 1);
236
237   Dali::Adaptor::Get().AddIdle(MakeCallback(this, &TizenPlatformAbstraction::CleanupTimers), false);
238 }
239
240 void TizenPlatformAbstraction::CleanupTimers()
241 {
242   mTimerPairsSpent.clear();
243 }
244
245 TizenPlatformAbstraction* CreatePlatformAbstraction()
246 {
247   return new TizenPlatformAbstraction();
248 }
249
250 bool SaveFile(const std::string& filename, const unsigned char* buffer, unsigned int numBytes)
251 {
252   DALI_ASSERT_DEBUG(0 != filename.length());
253
254   bool result = false;
255
256   std::filebuf buf;
257   buf.open(filename.c_str(), std::ios::out | std::ios_base::trunc | std::ios::binary);
258   if(buf.is_open())
259   {
260     std::ostream stream(&buf);
261
262     // determine size of buffer
263     int length = static_cast<int>(numBytes);
264
265     // write contents of buffer to the file
266     stream.write(reinterpret_cast<const char*>(buffer), length);
267
268     if(!stream.bad())
269     {
270       result = true;
271     }
272   }
273
274   return result;
275 }
276
277 } // namespace TizenPlatform
278
279 } // namespace Dali