24f87f8fde88402216871a09c9823873e52f8672
[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( unsigned int width, unsigned int 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( unsigned int width, unsigned int height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue )
77 : mWidth( width ),
78   mHeight( height ),
79   mTbmQueue( NULL ),
80   mConsumeSurface( NULL ),
81   mEglImages(),
82   mEglFactory( NULL ),
83   mEglImageExtensions( NULL ),
84   mOwnTbmQueue( false ),
85   mBlendingRequired( false )
86 {
87   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
88   mEglFactory = &( Adaptor::GetImplementation( Adaptor::Get() ).GetEGLFactory() );
89
90   mTbmQueue = GetSurfaceFromAny( nativeImageSourceQueue );
91
92   if( mTbmQueue != NULL )
93   {
94     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
95     mWidth = tbm_surface_queue_get_width( mTbmQueue );
96     mHeight = tbm_surface_queue_get_height( mTbmQueue );
97   }
98 }
99
100 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
101 {
102   if( mOwnTbmQueue )
103   {
104     DestroyQueue();
105   }
106 }
107
108 void NativeImageSourceQueueTizen::Initialize( Dali::NativeImageSourceQueue::ColorDepth depth )
109 {
110   if( mTbmQueue != NULL || mWidth == 0 || mHeight == 0 )
111   {
112     return;
113   }
114
115   int format = TBM_FORMAT_ARGB8888;
116
117   switch( depth )
118   {
119     case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
120     case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
121     {
122       format = TBM_FORMAT_ARGB8888;
123       mBlendingRequired = true;
124       break;
125     }
126     case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
127     {
128       format = TBM_FORMAT_RGB888;
129       mBlendingRequired = false;
130       break;
131     }
132     default:
133     {
134       DALI_LOG_WARNING( "Wrong color depth.\n" );
135       return;
136     }
137   }
138
139   mTbmQueue = tbm_surface_queue_create( TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0 );
140
141   mOwnTbmQueue = true;
142 }
143
144 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
145 {
146   if( source.Empty() )
147   {
148     return NULL;
149   }
150
151   if( source.GetType() == typeid( tbm_surface_queue_h ) )
152   {
153     return AnyCast< tbm_surface_queue_h >( source );
154   }
155   else
156   {
157     return NULL;
158   }
159 }
160
161 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
162 {
163   return Any( mTbmQueue );
164 }
165
166 void NativeImageSourceQueueTizen::SetSource( Any source )
167 {
168   if( mOwnTbmQueue )
169   {
170     DestroyQueue();
171   }
172
173   mTbmQueue = GetSurfaceFromAny( source );
174
175   if( mTbmQueue != NULL )
176   {
177     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
178     mWidth = tbm_surface_queue_get_width( mTbmQueue );
179     mHeight = tbm_surface_queue_get_height( mTbmQueue );
180   }
181 }
182
183 bool NativeImageSourceQueueTizen::GlExtensionCreate()
184 {
185   mEglImageExtensions = mEglFactory->GetImageExtensions();
186   DALI_ASSERT_DEBUG( mEglImageExtensions );
187
188   return true;
189 }
190
191 void NativeImageSourceQueueTizen::GlExtensionDestroy()
192 {
193   for( auto&& iter : mEglImages )
194   {
195     mEglImageExtensions->DestroyImageKHR( iter.second );
196
197     tbm_surface_internal_unref( iter.first );
198   }
199   mEglImages.clear();
200 }
201
202 unsigned int NativeImageSourceQueueTizen::TargetTexture()
203 {
204   return 0;
205 }
206
207 void NativeImageSourceQueueTizen::PrepareTexture()
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::DestroyQueue()
275 {
276   if( mConsumeSurface )
277   {
278     tbm_surface_internal_unref( mConsumeSurface );
279
280     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
281     {
282       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
283     }
284   }
285
286   if( mTbmQueue != NULL )
287   {
288     tbm_surface_queue_destroy( mTbmQueue );
289   }
290
291   mTbmQueue = NULL;
292   mOwnTbmQueue = false;
293 }
294
295 bool NativeImageSourceQueueTizen::CheckBlending( int format )
296 {
297   for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
298   {
299     if( format == FORMATS_BLENDING_REQUIRED[i] )
300     {
301       return true;
302     }
303   }
304
305   return false;
306 }
307
308 } // namespace Adaptor
309
310 } // namespace internal
311
312 } // namespace Dali