[4.0] Change NativeImageSourceQueue
[platform/core/uifw/dali-adaptor.git] / adaptors / 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 <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 <gl/egl-image-extensions.h>
28 #include <gl/egl-factory.h>
29 #include <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   mEglFactory( NULL ),
84   mEglImageExtensions( NULL ),
85   mOwnTbmQueue( false ),
86   mBlendingRequired( false )
87 {
88   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
89   mEglFactory = &( Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory() );
90
91   mTbmQueue = GetSurfaceFromAny( nativeImageSourceQueue );
92
93   if( mTbmQueue != NULL )
94   {
95     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
96     mWidth = tbm_surface_queue_get_width( mTbmQueue );
97     mHeight = tbm_surface_queue_get_height( mTbmQueue );
98   }
99 }
100
101 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
102 {
103   if( mOwnTbmQueue )
104   {
105     if( mTbmQueue != NULL )
106     {
107       tbm_surface_queue_destroy( mTbmQueue );
108     }
109   }
110 }
111
112 void NativeImageSourceQueueTizen::Initialize( Dali::NativeImageSourceQueue::ColorDepth depth )
113 {
114   if( mWidth == 0 || mHeight == 0 )
115   {
116     return;
117   }
118
119   if( mTbmQueue == NULL )
120   {
121     int format = TBM_FORMAT_ARGB8888;
122
123     switch( depth )
124     {
125       case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
126       case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
127       {
128         format = TBM_FORMAT_ARGB8888;
129         mBlendingRequired = true;
130         break;
131       }
132       case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
133       {
134         format = TBM_FORMAT_RGB888;
135         mBlendingRequired = false;
136         break;
137       }
138       default:
139       {
140         DALI_LOG_WARNING( "Wrong color depth.\n" );
141         return;
142       }
143     }
144
145     mTbmQueue = tbm_surface_queue_create( TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0 );
146
147     mOwnTbmQueue = true;
148   }
149 }
150
151 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
152 {
153   if( source.Empty() )
154   {
155     return NULL;
156   }
157
158   if( source.GetType() == typeid( tbm_surface_queue_h ) )
159   {
160     return AnyCast< tbm_surface_queue_h >( source );
161   }
162   else
163   {
164     return NULL;
165   }
166 }
167
168 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
169 {
170   return Any( mTbmQueue );
171 }
172
173 void NativeImageSourceQueueTizen::SetSize( uint32_t width, uint32_t height )
174 {
175   Dali::Mutex::ScopedLock lock( mMutex );
176
177   tbm_surface_queue_reset( mTbmQueue, width, height, tbm_surface_queue_get_format( mTbmQueue ) );
178
179   mWidth = width;
180   mHeight = height;
181
182   ResetEglImageList();
183 }
184
185 bool NativeImageSourceQueueTizen::GlExtensionCreate()
186 {
187   mEglImageExtensions = mEglFactory->GetImageExtensions();
188   DALI_ASSERT_DEBUG( mEglImageExtensions );
189
190   return true;
191 }
192
193 void NativeImageSourceQueueTizen::GlExtensionDestroy()
194 {
195   Dali::Mutex::ScopedLock lock( mMutex );
196
197   ResetEglImageList();
198 }
199
200 uint32_t NativeImageSourceQueueTizen::TargetTexture()
201 {
202   return 0;
203 }
204
205 void NativeImageSourceQueueTizen::PrepareTexture()
206 {
207   Dali::Mutex::ScopedLock lock( mMutex );
208
209   tbm_surface_h oldSurface = mConsumeSurface;
210
211   if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
212   {
213     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
214     {
215       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
216       return;
217     }
218
219     if( oldSurface )
220     {
221       if( tbm_surface_internal_is_valid( oldSurface ) )
222       {
223         tbm_surface_queue_release( mTbmQueue, oldSurface );
224       }
225     }
226
227     if( mConsumeSurface )
228     {
229       bool existing = false;
230       for( auto&& iter : mEglImages )
231       {
232         if( iter.first == mConsumeSurface )
233         {
234           // Find the surface in the existing list
235           existing = true;
236           mEglImageExtensions->TargetTextureKHR( iter.second );
237           break;
238         }
239       }
240
241       if( !existing )
242       {
243         // Push the surface
244         tbm_surface_internal_ref( mConsumeSurface );
245
246         void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
247         mEglImageExtensions->TargetTextureKHR( eglImageKHR );
248
249         mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
250       }
251     }
252   }
253 }
254
255 const char* NativeImageSourceQueueTizen::GetCustomFragmentPreFix()
256 {
257   return FRAGMENT_PREFIX;
258 }
259
260 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename()
261 {
262   return SAMPLER_TYPE;
263 }
264
265 int NativeImageSourceQueueTizen::GetEglImageTextureTarget()
266 {
267   return GL_TEXTURE_EXTERNAL_OES;
268 }
269
270 void NativeImageSourceQueueTizen::SetDestructorNotification(void* notification)
271 {
272 }
273
274 void NativeImageSourceQueueTizen::ResetEglImageList()
275 {
276   if( mConsumeSurface )
277   {
278     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
279     {
280       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
281     }
282     mConsumeSurface = NULL;
283   }
284
285   for( auto&& iter : mEglImages )
286   {
287     mEglImageExtensions->DestroyImageKHR( iter.second );
288
289     tbm_surface_internal_unref( iter.first );
290   }
291   mEglImages.clear();
292 }
293
294 bool NativeImageSourceQueueTizen::CheckBlending( int format )
295 {
296   for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
297   {
298     if( format == FORMATS_BLENDING_REQUIRED[i] )
299     {
300       return true;
301     }
302   }
303
304   return false;
305 }
306
307 } // namespace Adaptor
308
309 } // namespace internal
310
311 } // namespace Dali