[3.0] Added missing newline chars to logging commands
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / native-image-source-impl-tizen.cpp
1 /*
2  * Copyright (c) 2014 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 "native-image-source-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <cstring>
24
25 // INTERNAL INCLUDES
26 #include <gl/egl-image-extensions.h>
27 #include <gl/egl-factory.h>
28 #include <adaptor-impl.h>
29 #include <render-surface.h>
30
31 // Allow this to be encoded and saved:
32 #include <platform-abstractions/tizen/resource-loader/resource-loader.h>
33 #include <bitmap-saver.h>
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace Adaptor
42 {
43
44 namespace
45 {
46 const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
47 const char* SAMPLER_TYPE = "samplerExternalOES";
48 }
49
50 using Dali::Integration::PixelBuffer;
51
52 NativeImageSource* NativeImageSource::New(unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
53 {
54   NativeImageSource* image = new NativeImageSource( width, height, depth, nativeImageSource );
55   DALI_ASSERT_DEBUG( image && "NativeImageSource allocation failed." );
56
57   if( image )
58   {
59     image->Initialize();
60   }
61
62   return image;
63 }
64
65 NativeImageSource::NativeImageSource( unsigned int width, unsigned int height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource )
66 : mWidth( width ),
67   mHeight( height ),
68   mOwnTbmsurface( false ),
69   mTbmsurface( NULL ),
70   mBlendingRequired( false ),
71   mColorDepth( depth ),
72   mEglImageKHR( NULL ),
73   mEglImageExtensions( NULL ),
74   mSetSource( false )
75 {
76   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
77   EglFactory& eglFactory = Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory();
78   mEglImageExtensions = eglFactory.GetImageExtensions();
79   DALI_ASSERT_DEBUG( mEglImageExtensions );
80
81   mTbmsurface = GetSurfaceFromAny( nativeImageSource );
82
83   if( mTbmsurface != NULL )
84   {
85     mWidth = tbm_surface_get_width( mTbmsurface );
86     mHeight = tbm_surface_get_height( mTbmsurface );
87   }
88 }
89
90 void NativeImageSource::Initialize()
91 {
92   if( mTbmsurface != NULL || mWidth == 0 || mHeight == 0 )
93   {
94     return;
95   }
96
97   tbm_format format = TBM_FORMAT_RGB888;
98   int depth = 0;
99
100   switch( mColorDepth )
101   {
102     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
103     {
104       format = TBM_FORMAT_RGBA8888;
105       depth = 32;
106       break;
107     }
108     case Dali::NativeImageSource::COLOR_DEPTH_8:
109     {
110       format = TBM_FORMAT_C8;
111       depth = 8;
112       break;
113     }
114     case Dali::NativeImageSource::COLOR_DEPTH_16:
115     {
116       format = TBM_FORMAT_RGB565;
117       depth = 16;
118       break;
119     }
120     case Dali::NativeImageSource::COLOR_DEPTH_24:
121     {
122       format = TBM_FORMAT_RGB888;
123       depth = 24;
124       break;
125     }
126     case Dali::NativeImageSource::COLOR_DEPTH_32:
127     {
128       format = TBM_FORMAT_RGBA8888;
129       depth = 32;
130       break;
131     }
132     default:
133     {
134       DALI_LOG_WARNING( "Wrong color depth.\n" );
135       return;
136     }
137   }
138
139   // set whether blending is required according to pixel format based on the depth
140   /* default pixel format is RGB888
141      If depth = 8, Pixel::A8;
142      If depth = 16, Pixel::RGB565;
143      If depth = 32, Pixel::RGBA8888 */
144   mBlendingRequired = ( depth == 32 || depth == 8 );
145
146   mTbmsurface = tbm_surface_create( mWidth, mHeight, format );
147   mOwnTbmsurface = true;
148 }
149
150 tbm_surface_h NativeImageSource::GetSurfaceFromAny( Any source ) const
151 {
152   if( source.Empty() )
153   {
154     return NULL;
155   }
156
157   if( source.GetType() == typeid( tbm_surface_h ) )
158   {
159     return AnyCast< tbm_surface_h >( source );
160   }
161   else
162   {
163     return NULL;
164   }
165 }
166
167 NativeImageSource::~NativeImageSource()
168 {
169   if( mOwnTbmsurface && mTbmsurface != NULL )
170   {
171     if( tbm_surface_destroy( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
172     {
173       DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
174     }
175   }
176 }
177
178 Any NativeImageSource::GetNativeImageSource() const
179 {
180   return Any( mTbmsurface );
181 }
182
183 bool NativeImageSource::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
184 {
185   if( mTbmsurface != NULL )
186   {
187     tbm_surface_info_s surface_info;
188
189     if( tbm_surface_map( mTbmsurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE )
190     {
191       DALI_LOG_ERROR( "Fail to map tbm_surface\n" );
192
193       width = 0;
194       height = 0;
195
196       return false;
197     }
198
199     tbm_format format = surface_info.format;
200     uint32_t stride = surface_info.planes[0].stride;
201     unsigned char* ptr = surface_info.planes[0].ptr;
202
203     width = mWidth;
204     height = mHeight;
205     size_t lineSize;
206     size_t offset;
207     size_t cOffset;
208
209     switch( format )
210     {
211       case TBM_FORMAT_RGB888:
212       {
213         lineSize = width*3;
214         pixelFormat = Pixel::RGB888;
215         pixbuf.resize( lineSize*height );
216         unsigned char* bufptr = &pixbuf[0];
217
218         for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
219         {
220           for( unsigned int c = 0; c < width; ++c )
221           {
222             cOffset = c*3;
223             offset = cOffset + r*stride;
224             *(bufptr) = ptr[offset+2];
225             *(bufptr+cOffset+1) = ptr[offset+1];
226             *(bufptr+cOffset+2) = ptr[offset];
227           }
228         }
229         break;
230       }
231       case TBM_FORMAT_RGBA8888:
232       {
233         lineSize = width*4;
234         pixelFormat = Pixel::RGBA8888;
235         pixbuf.resize( lineSize*height );
236         unsigned char* bufptr = &pixbuf[0];
237
238         for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
239         {
240           for( unsigned int c = 0; c < width; ++c )
241           {
242             cOffset = c*4;
243             offset = cOffset + r*stride;
244             *(bufptr) = ptr[offset+3];
245             *(bufptr+cOffset+1) = ptr[offset+2];
246             *(bufptr+cOffset+2) = ptr[offset+1];
247             *(bufptr+cOffset+3) = ptr[offset];
248           }
249         }
250         break;
251       }
252       default:
253       {
254         DALI_LOG_WARNING( "Tbm surface has unsupported pixel format.\n" );
255
256         pixbuf.resize( 0 );
257         width = 0;
258         height = 0;
259
260         return false;
261       }
262     }
263
264     if( tbm_surface_unmap( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
265     {
266       DALI_LOG_ERROR( "Fail to unmap tbm_surface\n" );
267     }
268
269     return true;
270   }
271
272   DALI_LOG_WARNING( "TBM surface does not exist.\n" );
273
274   width = 0;
275   height = 0;
276
277   return false;
278 }
279
280 bool NativeImageSource::EncodeToFile(const std::string& filename) const
281 {
282   std::vector< unsigned char > pixbuf;
283   unsigned int width(0), height(0);
284   Pixel::Format pixelFormat;
285
286   if(GetPixels(pixbuf, width, height, pixelFormat))
287   {
288     return Dali::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
289   }
290   return false;
291 }
292
293 void NativeImageSource::SetSource( Any source )
294 {
295   if( mOwnTbmsurface && mTbmsurface != NULL )
296   {
297     if( tbm_surface_destroy( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
298     {
299       DALI_LOG_ERROR( "Failed to destroy tbm_surface\n" );
300     }
301
302     mTbmsurface = NULL;
303     mOwnTbmsurface = false;
304   }
305
306   mTbmsurface = GetSurfaceFromAny( source );
307   mSetSource = true;
308
309   if( mTbmsurface != NULL )
310   {
311     mWidth = tbm_surface_get_width( mTbmsurface );
312     mHeight = tbm_surface_get_height( mTbmsurface );
313   }
314
315   if( mEglImageKHRContainer.Size() > 2 )
316   {
317     mEglImageExtensions->DestroyImageKHR(mEglImageKHRContainer[0]);
318     mEglImageKHRContainer.Erase( mEglImageKHRContainer.Begin() );
319   }
320
321   mEglImageKHRContainer.PushBack( mEglImageKHR );
322 }
323
324 bool NativeImageSource::IsColorDepthSupported( Dali::NativeImageSource::ColorDepth colorDepth )
325 {
326   uint32_t* formats;
327   uint32_t formatNum;
328   tbm_format format = TBM_FORMAT_RGB888;
329
330   switch( colorDepth )
331   {
332     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
333     {
334       format = TBM_FORMAT_RGBA8888;
335       break;
336     }
337     case Dali::NativeImageSource::COLOR_DEPTH_8:
338     {
339       format = TBM_FORMAT_C8;
340       break;
341     }
342     case Dali::NativeImageSource::COLOR_DEPTH_16:
343     {
344       format = TBM_FORMAT_RGB565;
345       break;
346     }
347     case Dali::NativeImageSource::COLOR_DEPTH_24:
348     {
349       format = TBM_FORMAT_RGB888;
350       break;
351     }
352     case Dali::NativeImageSource::COLOR_DEPTH_32:
353     {
354       format = TBM_FORMAT_RGBA8888;
355       break;
356     }
357   }
358
359   if( tbm_surface_query_formats( &formats, &formatNum ) )
360   {
361     for( unsigned int i = 0; i < formatNum; i++ )
362     {
363       if( formats[i] == format )
364       {
365         free( formats );
366         return true;
367       }
368     }
369   }
370
371   free( formats );
372   return false;
373 }
374
375 bool NativeImageSource::GlExtensionCreate()
376 {
377   // casting from an unsigned int to a void *, which should then be cast back
378   // to an unsigned int in the driver.
379   EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer > (mTbmsurface);
380
381   mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );
382
383   return mEglImageKHR != NULL;
384 }
385
386 void NativeImageSource::GlExtensionDestroy()
387 {
388   mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
389
390   mEglImageKHR = NULL;
391 }
392
393 unsigned int NativeImageSource::TargetTexture()
394 {
395   mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
396
397   return 0;
398 }
399
400 void NativeImageSource::PrepareTexture()
401 {
402   if( mSetSource && GlExtensionCreate() )
403   {
404     TargetTexture();
405     mSetSource = false;
406   }
407 }
408
409 int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
410 {
411   switch (depth)
412   {
413     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
414     {
415       // ToDo: Get the default screen depth
416       return 32;
417     }
418     case Dali::NativeImageSource::COLOR_DEPTH_8:
419     {
420       return 8;
421     }
422     case Dali::NativeImageSource::COLOR_DEPTH_16:
423     {
424       return 16;
425     }
426     case Dali::NativeImageSource::COLOR_DEPTH_24:
427     {
428       return 24;
429     }
430     case Dali::NativeImageSource::COLOR_DEPTH_32:
431     {
432       return 32;
433     }
434     default:
435     {
436       DALI_ASSERT_DEBUG(0 && "unknown color enum");
437       return 0;
438     }
439   }
440 }
441
442 const char* NativeImageSource::GetCustomFragmentPreFix()
443 {
444   return FRAGMENT_PREFIX;
445 }
446
447 const char* NativeImageSource::GetCustomSamplerTypename()
448 {
449   return SAMPLER_TYPE;
450 }
451
452 } // namespace Adaptor
453
454 } // namespace internal
455
456 } // namespace Dali