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