e7fa5548325730be4ea103c58b6dceb68a698527
[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 bool NativeImageSourceQueueTizen::GlExtensionCreate()
193 {
194   mEglImageExtensions = mEglGraphics->GetImageExtensions();
195   DALI_ASSERT_DEBUG( mEglImageExtensions );
196
197   return true;
198 }
199
200 void NativeImageSourceQueueTizen::GlExtensionDestroy()
201 {
202   Dali::Mutex::ScopedLock lock( mMutex );
203
204   ResetEglImageList();
205 }
206
207 uint32_t NativeImageSourceQueueTizen::TargetTexture()
208 {
209   return 0;
210 }
211
212 void NativeImageSourceQueueTizen::PrepareTexture()
213 {
214   Dali::Mutex::ScopedLock lock( mMutex );
215
216   tbm_surface_h oldSurface = mConsumeSurface;
217
218   if( tbm_surface_queue_can_acquire( mTbmQueue, 0 ) )
219   {
220     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
221     {
222       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
223       return;
224     }
225
226     if( oldSurface )
227     {
228       if( tbm_surface_internal_is_valid( oldSurface ) )
229       {
230         tbm_surface_queue_release( mTbmQueue, oldSurface );
231       }
232     }
233
234     if( mConsumeSurface )
235     {
236       bool existing = false;
237       for( auto&& iter : mEglImages )
238       {
239         if( iter.first == mConsumeSurface )
240         {
241           // Find the surface in the existing list
242           existing = true;
243           mEglImageExtensions->TargetTextureKHR( iter.second );
244           break;
245         }
246       }
247
248       if( !existing )
249       {
250         // Push the surface
251         tbm_surface_internal_ref( mConsumeSurface );
252
253         void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
254         mEglImageExtensions->TargetTextureKHR( eglImageKHR );
255
256         mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
257       }
258     }
259   }
260 }
261
262 const char* NativeImageSourceQueueTizen::GetCustomFragmentPreFix()
263 {
264   return FRAGMENT_PREFIX;
265 }
266
267 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename()
268 {
269   return SAMPLER_TYPE;
270 }
271
272 int NativeImageSourceQueueTizen::GetEglImageTextureTarget()
273 {
274   return GL_TEXTURE_EXTERNAL_OES;
275 }
276
277 void NativeImageSourceQueueTizen::ResetEglImageList()
278 {
279   if( mConsumeSurface )
280   {
281     if( tbm_surface_internal_is_valid( mConsumeSurface ) )
282     {
283       tbm_surface_queue_release( mTbmQueue, mConsumeSurface );
284     }
285     mConsumeSurface = NULL;
286   }
287
288   for( auto&& iter : mEglImages )
289   {
290     mEglImageExtensions->DestroyImageKHR( iter.second );
291
292     tbm_surface_internal_unref( iter.first );
293   }
294   mEglImages.clear();
295 }
296
297 bool NativeImageSourceQueueTizen::CheckBlending( int format )
298 {
299   for( int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i )
300   {
301     if( format == FORMATS_BLENDING_REQUIRED[i] )
302     {
303       return true;
304     }
305   }
306
307   return false;
308 }
309
310 } // namespace Adaptor
311
312 } // namespace internal
313
314 } // namespace Dali