Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-queue-impl-tizen.cpp
1 /*
2  * Copyright (c) 2018 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/imaging/tizen/native-image-source-queue-impl-tizen.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/gl-defines.h>
24 #include <tbm_surface_internal.h>
25
26 // INTERNAL INCLUDES
27 #include <dali/internal/graphics/common/egl-image-extensions.h>
28 #include <dali/internal/graphics/gles/egl-graphics.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30
31 namespace Dali
32 {
33
34 namespace Internal
35 {
36
37 namespace Adaptor
38 {
39
40 namespace
41 {
42 #define TBM_SURFACE_QUEUE_SIZE  3
43
44 const char* FRAGMENT_PREFIX = "#extension GL_OES_EGL_image_external:require\n";
45 const char* SAMPLER_TYPE = "samplerExternalOES";
46
47 int FORMATS_BLENDING_REQUIRED[] = {
48   TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
49   TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
50   TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
51   TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
52   TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
53   TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
54   TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
55   TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
56   TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
57 };
58
59 const int NUM_FORMATS_BLENDING_REQUIRED = 18;
60
61 }
62
63 NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New( uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue )
64 {
65   NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen( width, height, depth, nativeImageSourceQueue );
66   DALI_ASSERT_DEBUG( image && "NativeImageSourceQueueTizen allocation failed." );
67
68   if( image )
69   {
70     image->Initialize( depth );
71   }
72
73   return image;
74 }
75
76 NativeImageSourceQueueTizen::NativeImageSourceQueueTizen( uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue )
77 : mMutex(),
78   mWidth( width ),
79   mHeight( height ),
80   mTbmQueue( NULL ),
81   mConsumeSurface( NULL ),
82   mEglImages(),
83   mEglGraphics( NULL ),
84   mEglImageExtensions( NULL ),
85   mOwnTbmQueue( false ),
86   mBlendingRequired( false )
87 {
88   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
89
90   GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
91   mEglGraphics = static_cast<EglGraphics *>(graphics);
92
93   mTbmQueue = GetSurfaceFromAny( nativeImageSourceQueue );
94
95   if( mTbmQueue != NULL )
96   {
97     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
98     mWidth = tbm_surface_queue_get_width( mTbmQueue );
99     mHeight = tbm_surface_queue_get_height( mTbmQueue );
100   }
101 }
102
103 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
104 {
105   if( mOwnTbmQueue )
106   {
107     if( mTbmQueue != NULL )
108     {
109       tbm_surface_queue_destroy( mTbmQueue );
110     }
111   }
112 }
113
114 void NativeImageSourceQueueTizen::Initialize( Dali::NativeImageSourceQueue::ColorDepth depth )
115 {
116   if( mWidth == 0 || mHeight == 0 )
117   {
118     return;
119   }
120
121   if( mTbmQueue == NULL )
122   {
123     int format = TBM_FORMAT_ARGB8888;
124
125     switch( depth )
126     {
127       case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
128       case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
129       {
130         format = TBM_FORMAT_ARGB8888;
131         mBlendingRequired = true;
132         break;
133       }
134       case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
135       {
136         format = TBM_FORMAT_RGB888;
137         mBlendingRequired = false;
138         break;
139       }
140       default:
141       {
142         DALI_LOG_WARNING( "Wrong color depth.\n" );
143         return;
144       }
145     }
146
147     mTbmQueue = tbm_surface_queue_create( TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0 );
148
149     mOwnTbmQueue = true;
150   }
151 }
152
153 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
154 {
155   if( source.Empty() )
156   {
157     return NULL;
158   }
159
160   if( source.GetType() == typeid( tbm_surface_queue_h ) )
161   {
162     return AnyCast< tbm_surface_queue_h >( source );
163   }
164   else
165   {
166     return NULL;
167   }
168 }
169
170 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
171 {
172   return Any( mTbmQueue );
173 }
174
175 void NativeImageSourceQueueTizen::SetSize( uint32_t width, uint32_t height )
176 {
177   Dali::Mutex::ScopedLock lock( mMutex );
178
179   tbm_surface_queue_reset( mTbmQueue, width, height, tbm_surface_queue_get_format( mTbmQueue ) );
180
181   mWidth = width;
182   mHeight = height;
183
184   ResetEglImageList();
185 }
186
187 bool NativeImageSourceQueueTizen::GlExtensionCreate()
188 {
189   mEglImageExtensions = mEglGraphics->GetImageExtensions();
190   DALI_ASSERT_DEBUG( mEglImageExtensions );
191
192   return true;
193 }
194
195 void NativeImageSourceQueueTizen::GlExtensionDestroy()
196 {
197   Dali::Mutex::ScopedLock lock( mMutex );
198
199   ResetEglImageList();
200 }
201
202 uint32_t NativeImageSourceQueueTizen::TargetTexture()
203 {
204   return 0;
205 }
206
207 void NativeImageSourceQueueTizen::PrepareTexture()
208 {
209   Dali::Mutex::ScopedLock lock( mMutex );
210
211   tbm_surface_h oldSurface = mConsumeSurface;
212
213   if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
214   {
215     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
216     {
217       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
218       return;
219     }
220
221     if( oldSurface )
222     {
223       if( tbm_surface_internal_is_valid( oldSurface ) )
224       {
225         tbm_surface_queue_release( mTbmQueue, oldSurface );
226       }
227     }
228
229     if( mConsumeSurface )
230     {
231       bool existing = false;
232       for( auto&& iter : mEglImages )
233       {
234         if( iter.first == mConsumeSurface )
235         {
236           // Find the surface in the existing list
237           existing = true;
238           mEglImageExtensions->TargetTextureKHR( iter.second );
239           break;
240         }
241       }
242
243       if( !existing )
244       {
245         // Push the surface
246         tbm_surface_internal_ref( mConsumeSurface );
247
248         void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
249         mEglImageExtensions->TargetTextureKHR( eglImageKHR );
250
251         mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
252       }
253     }
254   }
255 }
256
257 const char* NativeImageSourceQueueTizen::GetCustomFragmentPreFix()
258 {
259   return FRAGMENT_PREFIX;
260 }
261
262 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename()
263 {
264   return SAMPLER_TYPE;
265 }
266
267 int NativeImageSourceQueueTizen::GetEglImageTextureTarget()
268 {
269   return GL_TEXTURE_EXTERNAL_OES;
270 }
271
272 void NativeImageSourceQueueTizen::ResetEglImageList()
273 {
274   if( mConsumeSurface )
275   {
276     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
277     {
278       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
279     }
280     mConsumeSurface = NULL;
281   }
282
283   for( auto&& iter : mEglImages )
284   {
285     mEglImageExtensions->DestroyImageKHR( iter.second );
286
287     tbm_surface_internal_unref( iter.first );
288   }
289   mEglImages.clear();
290 }
291
292 bool NativeImageSourceQueueTizen::CheckBlending( int format )
293 {
294   for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
295   {
296     if( format == FORMATS_BLENDING_REQUIRED[i] )
297     {
298       return true;
299     }
300   }
301
302   return false;
303 }
304
305 } // namespace Adaptor
306
307 } // namespace internal
308
309 } // namespace Dali