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