Separate out Render Helper
[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/gles20/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( 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   mEglImageExtensions( NULL ),
83   mOwnTbmQueue( false ),
84   mBlendingRequired( false )
85 {
86   DALI_ASSERT_ALWAYS( Adaptor::IsAvailable() );
87
88   GraphicsInterface* graphics = &( Adaptor::GetImplementation( Adaptor::Get() ).GetGraphicsInterface() );
89   auto eglGraphics = static_cast<EglGraphics *>(graphics);
90
91   mEglImageExtensions = eglGraphics->GetImageExtensions();
92
93   DALI_ASSERT_DEBUG( mEglImageExtensions );
94
95   mTbmQueue = GetSurfaceFromAny( nativeImageSourceQueue );
96
97   if( mTbmQueue != NULL )
98   {
99     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
100     mWidth = tbm_surface_queue_get_width( mTbmQueue );
101     mHeight = tbm_surface_queue_get_height( mTbmQueue );
102   }
103 }
104
105 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
106 {
107   if( mOwnTbmQueue )
108   {
109     DestroyQueue();
110   }
111 }
112
113 void NativeImageSourceQueueTizen::Initialize( Dali::NativeImageSourceQueue::ColorDepth depth )
114 {
115   if( mTbmQueue != NULL || mWidth == 0 || mHeight == 0 )
116   {
117     return;
118   }
119
120   int format = TBM_FORMAT_ARGB8888;
121
122   switch( depth )
123   {
124     case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
125     case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
126     {
127       format = TBM_FORMAT_ARGB8888;
128       mBlendingRequired = true;
129       break;
130     }
131     case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
132     {
133       format = TBM_FORMAT_RGB888;
134       mBlendingRequired = false;
135       break;
136     }
137     default:
138     {
139       DALI_LOG_WARNING( "Wrong color depth.\n" );
140       return;
141     }
142   }
143
144   mTbmQueue = tbm_surface_queue_create( TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0 );
145
146   mOwnTbmQueue = true;
147 }
148
149 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny( Any source ) const
150 {
151   if( source.Empty() )
152   {
153     return NULL;
154   }
155
156   if( source.GetType() == typeid( tbm_surface_queue_h ) )
157   {
158     return AnyCast< tbm_surface_queue_h >( source );
159   }
160   else
161   {
162     return NULL;
163   }
164 }
165
166 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
167 {
168   return Any( mTbmQueue );
169 }
170
171 void NativeImageSourceQueueTizen::SetSource( Any source )
172 {
173   if( mOwnTbmQueue )
174   {
175     DestroyQueue();
176   }
177
178   mTbmQueue = GetSurfaceFromAny( source );
179
180   if( mTbmQueue != NULL )
181   {
182     mBlendingRequired = CheckBlending( tbm_surface_queue_get_format( mTbmQueue ) );
183     mWidth = tbm_surface_queue_get_width( mTbmQueue );
184     mHeight = tbm_surface_queue_get_height( mTbmQueue );
185   }
186 }
187
188 bool NativeImageSourceQueueTizen::GlExtensionCreate()
189 {
190   return true;
191 }
192
193 void NativeImageSourceQueueTizen::GlExtensionDestroy()
194 {
195   for( auto&& iter : mEglImages )
196   {
197     mEglImageExtensions->DestroyImageKHR( iter.second );
198
199     tbm_surface_internal_unref( iter.first );
200   }
201   mEglImages.clear();
202 }
203
204 unsigned int NativeImageSourceQueueTizen::TargetTexture()
205 {
206   return 0;
207 }
208
209 void NativeImageSourceQueueTizen::PrepareTexture()
210 {
211   tbm_surface_h oldSurface = mConsumeSurface;
212
213   bool needToWait = ( mConsumeSurface == NULL ) ? true : false;
214
215   if( tbm_surface_queue_can_acquire( mTbmQueue, needToWait ) )
216   {
217     if( tbm_surface_queue_acquire( mTbmQueue, &mConsumeSurface ) != TBM_SURFACE_QUEUE_ERROR_NONE )
218     {
219       DALI_LOG_ERROR( "Failed to aquire a tbm_surface\n" );
220       return;
221     }
222   }
223
224   if( oldSurface && oldSurface != mConsumeSurface )
225   {
226     if( tbm_surface_internal_is_valid( oldSurface ) )
227     {
228       tbm_surface_queue_release( mTbmQueue, oldSurface );
229     }
230   }
231
232   if( mConsumeSurface )
233   {
234     bool existing = false;
235     for( auto&& iter : mEglImages )
236     {
237       if( iter.first == mConsumeSurface )
238       {
239         // Find the surface in the existing list
240         existing = true;
241         mEglImageExtensions->TargetTextureKHR( iter.second );
242         break;
243       }
244     }
245
246     if( !existing )
247     {
248       // Push the surface
249       tbm_surface_internal_ref( mConsumeSurface );
250
251       void* eglImageKHR = mEglImageExtensions->CreateImageKHR( reinterpret_cast< EGLClientBuffer >( mConsumeSurface ) );
252       mEglImageExtensions->TargetTextureKHR( eglImageKHR );
253
254       mEglImages.push_back( EglImagePair( mConsumeSurface, eglImageKHR) );
255     }
256   }
257 }
258
259 const char* NativeImageSourceQueueTizen::GetCustomFragmentPreFix()
260 {
261   return FRAGMENT_PREFIX;
262 }
263
264 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename()
265 {
266   return SAMPLER_TYPE;
267 }
268
269 int NativeImageSourceQueueTizen::GetEglImageTextureTarget()
270 {
271   return GL_TEXTURE_EXTERNAL_OES;
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