Updates for NativeImageInterface
[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     if( !mTbmQueue )
149     {
150       DALI_LOG_ERROR( "NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue );
151       return;
152     }
153
154     mOwnTbmQueue = true;
155   }
156 }
157
158 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
159 {
160   if( source.Empty() )
161   {
162     return NULL;
163   }
164
165   if( source.GetType() == typeid( tbm_surface_queue_h ) )
166   {
167     return AnyCast< tbm_surface_queue_h >( source );
168   }
169   else
170   {
171     return NULL;
172   }
173 }
174
175 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
176 {
177   return Any( mTbmQueue );
178 }
179
180 void NativeImageSourceQueueTizen::SetSize( uint32_t width, uint32_t height )
181 {
182   Dali::Mutex::ScopedLock lock( mMutex );
183
184   tbm_surface_queue_reset( mTbmQueue, width, height, tbm_surface_queue_get_format( mTbmQueue ) );
185
186   mWidth = width;
187   mHeight = height;
188
189   ResetEglImageList();
190 }
191
192 void NativeImageSourceQueueTizen::IgnoreSourceImage()
193 {
194   Dali::Mutex::ScopedLock lock( mMutex );
195   tbm_surface_h surface;
196
197   if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
198   {
199     if( tbm_surface_queue_acquire( mTbmQueue, &surface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
200     {
201       DALI_LOG_ERROR( "NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n" );
202       return;
203     }
204
205     if( tbm_surface_internal_is_valid( surface ) )
206     {
207       tbm_surface_queue_release( mTbmQueue, surface );
208     }
209   }
210 }
211
212 bool NativeImageSourceQueueTizen::CreateResource()
213 {
214   mEglImageExtensions = mEglGraphics->GetImageExtensions();
215   DALI_ASSERT_DEBUG( mEglImageExtensions );
216
217   return true;
218 }
219
220 void NativeImageSourceQueueTizen::DestroyResource()
221 {
222   Dali::Mutex::ScopedLock lock( mMutex );
223
224   ResetEglImageList();
225 }
226
227 uint32_t NativeImageSourceQueueTizen::TargetTexture()
228 {
229   return 0;
230 }
231
232 void NativeImageSourceQueueTizen::PrepareTexture()
233 {
234   Dali::Mutex::ScopedLock lock( mMutex );
235
236   tbm_surface_h oldSurface = mConsumeSurface;
237
238   if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
239   {
240     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
241     {
242       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
243       return;
244     }
245
246     if( oldSurface )
247     {
248       if( tbm_surface_internal_is_valid( oldSurface ) )
249       {
250         tbm_surface_queue_release( mTbmQueue, oldSurface );
251       }
252     }
253
254     if( mConsumeSurface )
255     {
256       bool existing = false;
257       for( auto&& iter : mEglImages )
258       {
259         if( iter.first == mConsumeSurface )
260         {
261           // Find the surface in the existing list
262           existing = true;
263           mEglImageExtensions->TargetTextureKHR( iter.second );
264           break;
265         }
266       }
267
268       if( !existing )
269       {
270         // Push the surface
271         tbm_surface_internal_ref( mConsumeSurface );
272
273         void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
274         mEglImageExtensions->TargetTextureKHR( eglImageKHR );
275
276         mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
277       }
278     }
279   }
280 }
281
282 const char* NativeImageSourceQueueTizen::GetCustomFragmentPrefix() const
283 {
284   return FRAGMENT_PREFIX;
285 }
286
287 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
288 {
289   return SAMPLER_TYPE;
290 }
291
292 int NativeImageSourceQueueTizen::GetTextureTarget() const
293 {
294   return GL_TEXTURE_EXTERNAL_OES;
295 }
296
297 Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
298 {
299   return nullptr;
300 }
301
302 bool NativeImageSourceQueueTizen::SourceChanged() const
303 {
304   return false;
305 }
306
307
308
309 void NativeImageSourceQueueTizen::ResetEglImageList()
310 {
311   if( mConsumeSurface )
312   {
313     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
314     {
315       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
316     }
317     mConsumeSurface = NULL;
318   }
319
320   for( auto&& iter : mEglImages )
321   {
322     mEglImageExtensions->DestroyImageKHR( iter.second );
323
324     tbm_surface_internal_unref( iter.first );
325   }
326   mEglImages.clear();
327 }
328
329 bool NativeImageSourceQueueTizen::CheckBlending( int format )
330 {
331   for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
332   {
333     if( format == FORMATS_BLENDING_REQUIRED[i] )
334     {
335       return true;
336     }
337   }
338
339   return false;
340 }
341
342 } // namespace Adaptor
343
344 } // namespace internal
345
346 } // namespace Dali