Revert "[3.0] TC fail because of tbm surface is not supporting specific color depth"
[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( true ),
69   mTbmsurface( NULL ),
70   mBlendingRequired( false ),
71   mColorDepth( depth ),
72   mEglImageKHR( NULL ),
73   mEglImageExtensions( NULL )
74 {
75   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
76   EglFactory& eglFactory = Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory();
77   mEglImageExtensions = eglFactory.GetImageExtensions();
78   DALI_ASSERT_DEBUG( mEglImageExtensions );
79
80   mTbmsurface = GetSurfaceFromAny( nativeImageSource );
81
82   if( mTbmsurface != NULL )
83   {
84     mWidth = tbm_surface_get_width( mTbmsurface );
85     mHeight = tbm_surface_get_height( mTbmsurface );
86   }
87 }
88
89 void NativeImageSource::Initialize()
90 {
91   if( mTbmsurface != NULL )
92   {
93     mOwnTbmsurface = false;
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." );
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 }
148
149 tbm_surface_h NativeImageSource::GetSurfaceFromAny( Any source ) const
150 {
151   if( source.Empty() )
152   {
153     return NULL;
154   }
155
156   if( source.GetType() == typeid( tbm_surface_h ) )
157   {
158     return AnyCast< tbm_surface_h >( source );
159   }
160   else
161   {
162     return NULL;
163   }
164 }
165
166 NativeImageSource::~NativeImageSource()
167 {
168   if( mOwnTbmsurface && mTbmsurface != NULL )
169   {
170     if( tbm_surface_destroy( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
171     {
172       DALI_LOG_ERROR( "Failed to destroy tbm_surface" );
173     }
174   }
175 }
176
177 Any NativeImageSource::GetNativeImageSource() const
178 {
179   return Any( mTbmsurface );
180 }
181
182 bool NativeImageSource::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
183 {
184   if( mTbmsurface != NULL )
185   {
186     tbm_surface_info_s surface_info;
187
188     if( tbm_surface_map( mTbmsurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE )
189     {
190       DALI_LOG_ERROR( "Fail to map tbm_surface" );
191
192       width = 0;
193       height = 0;
194
195       return false;
196     }
197
198     tbm_format format = surface_info.format;
199     uint32_t stride = surface_info.planes[0].stride;
200     unsigned char* ptr = surface_info.planes[0].ptr;
201
202     width = mWidth;
203     height = mHeight;
204     size_t lineSize;
205     size_t offset;
206     size_t cOffset;
207
208     switch( format )
209     {
210       case TBM_FORMAT_RGB888:
211       {
212         lineSize = width*3;
213         pixelFormat = Pixel::RGB888;
214         pixbuf.resize( lineSize*height );
215         unsigned char* bufptr = &pixbuf[0];
216
217         for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
218         {
219           for( unsigned int c = 0; c < width; ++c )
220           {
221             cOffset = c*3;
222             offset = cOffset + r*stride;
223             *(bufptr) = ptr[offset+2];
224             *(bufptr+cOffset+1) = ptr[offset+1];
225             *(bufptr+cOffset+2) = ptr[offset];
226           }
227         }
228         break;
229       }
230       case TBM_FORMAT_RGBA8888:
231       {
232         lineSize = width*4;
233         pixelFormat = Pixel::RGBA8888;
234         pixbuf.resize( lineSize*height );
235         unsigned char* bufptr = &pixbuf[0];
236
237         for( unsigned int r = 0; r < height; ++r, bufptr += lineSize )
238         {
239           for( unsigned int c = 0; c < width; ++c )
240           {
241             cOffset = c*4;
242             offset = cOffset + r*stride;
243             *(bufptr) = ptr[offset+3];
244             *(bufptr+cOffset+1) = ptr[offset+2];
245             *(bufptr+cOffset+2) = ptr[offset+1];
246             *(bufptr+cOffset+3) = ptr[offset];
247           }
248         }
249         break;
250       }
251       default:
252       {
253         DALI_LOG_WARNING( "Tbm surface has unsupported pixel format." );
254
255         pixbuf.resize( 0 );
256         width = 0;
257         height = 0;
258
259         return false;
260       }
261     }
262
263     if( tbm_surface_unmap( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
264     {
265       DALI_LOG_ERROR( "Fail to unmap tbm_surface" );
266     }
267
268     return true;
269   }
270
271   DALI_LOG_WARNING( "TBM surface does not exist." );
272
273   width = 0;
274   height = 0;
275
276   return false;
277 }
278
279 bool NativeImageSource::EncodeToFile(const std::string& filename) const
280 {
281   std::vector< unsigned char > pixbuf;
282   unsigned int width(0), height(0);
283   Pixel::Format pixelFormat;
284
285   if(GetPixels(pixbuf, width, height, pixelFormat))
286   {
287     return Dali::EncodeToFile(&pixbuf[0], filename, pixelFormat, width, height);
288   }
289   return false;
290 }
291
292 void NativeImageSource::SetSource( Any source )
293 {
294   if( mOwnTbmsurface && mTbmsurface != NULL )
295   {
296     if( tbm_surface_destroy( mTbmsurface ) != TBM_SURFACE_ERROR_NONE )
297     {
298       DALI_LOG_ERROR( "Failed to destroy tbm_surface" );
299     }
300
301     mTbmsurface = NULL;
302   }
303
304   mTbmsurface = GetSurfaceFromAny( source );
305   mOwnTbmsurface = false;
306
307   if( mTbmsurface != NULL )
308   {
309     mWidth = tbm_surface_get_width( mTbmsurface );
310     mHeight = tbm_surface_get_height( mTbmsurface );
311   }
312 }
313
314 bool NativeImageSource::GlExtensionCreate()
315 {
316   if( mEglImageKHR != NULL )
317   {
318     GlExtensionDestroy();
319   }
320
321   // casting from an unsigned int to a void *, which should then be cast back
322   // to an unsigned int in the driver.
323   EGLClientBuffer eglBuffer = reinterpret_cast< EGLClientBuffer > (mTbmsurface);
324
325   mEglImageKHR = mEglImageExtensions->CreateImageKHR( eglBuffer );
326
327   return mEglImageKHR != NULL;
328 }
329
330 void NativeImageSource::GlExtensionDestroy()
331 {
332   mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
333
334   mEglImageKHR = NULL;
335 }
336
337 unsigned int NativeImageSource::TargetTexture()
338 {
339   mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
340
341   return 0;
342 }
343
344 int NativeImageSource::GetPixelDepth(Dali::NativeImageSource::ColorDepth depth) const
345 {
346   switch (depth)
347   {
348     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
349     {
350       // ToDo: Get the default screen depth
351       return 32;
352     }
353     case Dali::NativeImageSource::COLOR_DEPTH_8:
354     {
355       return 8;
356     }
357     case Dali::NativeImageSource::COLOR_DEPTH_16:
358     {
359       return 16;
360     }
361     case Dali::NativeImageSource::COLOR_DEPTH_24:
362     {
363       return 24;
364     }
365     case Dali::NativeImageSource::COLOR_DEPTH_32:
366     {
367       return 32;
368     }
369     default:
370     {
371       DALI_ASSERT_DEBUG(0 && "unknown color enum");
372       return 0;
373     }
374   }
375 }
376
377 const char* NativeImageSource::GetCustomFragmentPreFix()
378 {
379   return FRAGMENT_PREFIX;
380 }
381
382 const char* NativeImageSource::GetCustomSamplerTypename()
383 {
384   return SAMPLER_TYPE;
385 }
386
387 } // namespace Adaptor
388
389 } // namespace internal
390
391 } // namespace Dali