7f72939119d53037e30a7f3829c3db87cad9b080
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-queue-impl-tizen.cpp
1 /*
2  * Copyright (c) 2021 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/adaptor/common/adaptor-impl.h>
28 #include <dali/internal/graphics/common/egl-image-extensions.h>
29 #include <dali/internal/graphics/gles/egl-graphics.h>
30
31 namespace Dali
32 {
33 namespace Internal
34 {
35 namespace Adaptor
36 {
37 namespace
38 {
39 #define TBM_SURFACE_QUEUE_SIZE 3
40
41 const char* SAMPLER_TYPE = "samplerExternalOES";
42
43 // clang-format off
44 int FORMATS_BLENDING_REQUIRED[] = {
45   TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
46   TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
47   TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
48   TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
49   TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
50   TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
51   TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
52   TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
53   TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
54 };
55 // clang-format on
56
57 const int NUM_FORMATS_BLENDING_REQUIRED = 18;
58
59 } // namespace
60
61 NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue)
62 {
63   NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, depth, nativeImageSourceQueue);
64   DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
65
66   if(image)
67   {
68     image->Initialize(depth);
69   }
70
71   return image;
72 }
73
74 NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorDepth depth, Any nativeImageSourceQueue)
75 : mCustomFragmentPrefix(),
76   mMutex(),
77   mWidth(width),
78   mHeight(height),
79   mTbmQueue(NULL),
80   mConsumeSurface(NULL),
81   mEglImages(),
82   mEglGraphics(NULL),
83   mEglImageExtensions(NULL),
84   mOwnTbmQueue(false),
85   mBlendingRequired(false)
86 {
87   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
88
89   GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
90   mEglGraphics                = static_cast<EglGraphics*>(graphics);
91
92   mCustomFragmentPrefix = mEglGraphics->GetEglImageExtensionString();
93
94   mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
95
96   if(mTbmQueue != NULL)
97   {
98     mBlendingRequired = CheckBlending(tbm_surface_queue_get_format(mTbmQueue));
99     mWidth            = tbm_surface_queue_get_width(mTbmQueue);
100     mHeight           = tbm_surface_queue_get_height(mTbmQueue);
101   }
102 }
103
104 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
105 {
106   if(mOwnTbmQueue)
107   {
108     if(mTbmQueue != NULL)
109     {
110       tbm_surface_queue_destroy(mTbmQueue);
111     }
112   }
113 }
114
115 void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorDepth depth)
116 {
117   if(mWidth == 0 || mHeight == 0)
118   {
119     return;
120   }
121
122   if(mTbmQueue == NULL)
123   {
124     int format = TBM_FORMAT_ARGB8888;
125
126     switch(depth)
127     {
128       case Dali::NativeImageSourceQueue::COLOR_DEPTH_DEFAULT:
129       case Dali::NativeImageSourceQueue::COLOR_DEPTH_32:
130       {
131         format            = TBM_FORMAT_ARGB8888;
132         mBlendingRequired = true;
133         break;
134       }
135       case Dali::NativeImageSourceQueue::COLOR_DEPTH_24:
136       {
137         format            = TBM_FORMAT_RGB888;
138         mBlendingRequired = false;
139         break;
140       }
141       default:
142       {
143         DALI_LOG_WARNING("Wrong color depth.\n");
144         return;
145       }
146     }
147
148     mTbmQueue = tbm_surface_queue_create(TBM_SURFACE_QUEUE_SIZE, mWidth, mHeight, format, 0);
149     if(!mTbmQueue)
150     {
151       DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
152       return;
153     }
154
155     mOwnTbmQueue = true;
156   }
157 }
158
159 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny(Any source) const
160 {
161   if(source.Empty())
162   {
163     return NULL;
164   }
165
166   if(source.GetType() == typeid(tbm_surface_queue_h))
167   {
168     return AnyCast<tbm_surface_queue_h>(source);
169   }
170   else
171   {
172     return NULL;
173   }
174 }
175
176 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
177 {
178   return Any(mTbmQueue);
179 }
180
181 void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
182 {
183   Dali::Mutex::ScopedLock lock(mMutex);
184
185   tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
186
187   mWidth  = width;
188   mHeight = height;
189
190   ResetEglImageList();
191 }
192
193 void NativeImageSourceQueueTizen::IgnoreSourceImage()
194 {
195   Dali::Mutex::ScopedLock lock(mMutex);
196   tbm_surface_h           surface;
197
198   if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
199   {
200     if(tbm_surface_queue_acquire(mTbmQueue, &surface) != TBM_SURFACE_QUEUE_ERROR_NONE)
201     {
202       DALI_LOG_ERROR("NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n");
203       return;
204     }
205
206     if(tbm_surface_internal_is_valid(surface))
207     {
208       tbm_surface_queue_release(mTbmQueue, surface);
209     }
210   }
211 }
212
213 bool NativeImageSourceQueueTizen::CreateResource()
214 {
215   mEglImageExtensions = mEglGraphics->GetImageExtensions();
216   DALI_ASSERT_DEBUG(mEglImageExtensions);
217
218   return true;
219 }
220
221 void NativeImageSourceQueueTizen::DestroyResource()
222 {
223   Dali::Mutex::ScopedLock lock(mMutex);
224
225   ResetEglImageList();
226 }
227
228 uint32_t NativeImageSourceQueueTizen::TargetTexture()
229 {
230   return 0;
231 }
232
233 void NativeImageSourceQueueTizen::PrepareTexture()
234 {
235   Dali::Mutex::ScopedLock lock(mMutex);
236
237   tbm_surface_h oldSurface = mConsumeSurface;
238
239   if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
240   {
241     if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
242     {
243       DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
244       return;
245     }
246
247     if(oldSurface)
248     {
249       if(tbm_surface_internal_is_valid(oldSurface))
250       {
251         tbm_surface_queue_release(mTbmQueue, oldSurface);
252       }
253     }
254
255     if(mConsumeSurface)
256     {
257       bool existing = false;
258       for(auto&& iter : mEglImages)
259       {
260         if(iter.first == mConsumeSurface)
261         {
262           // Find the surface in the existing list
263           existing = true;
264           mEglImageExtensions->TargetTextureKHR(iter.second);
265           break;
266         }
267       }
268
269       if(!existing)
270       {
271         // Push the surface
272         tbm_surface_internal_ref(mConsumeSurface);
273
274         void* eglImageKHR = mEglImageExtensions->CreateImageKHR(reinterpret_cast<EGLClientBuffer>(mConsumeSurface));
275         mEglImageExtensions->TargetTextureKHR(eglImageKHR);
276
277         mEglImages.push_back(EglImagePair(mConsumeSurface, eglImageKHR));
278       }
279     }
280   }
281 }
282
283 const char* NativeImageSourceQueueTizen::GetCustomFragmentPrefix() const
284 {
285   return mCustomFragmentPrefix;
286 }
287
288 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
289 {
290   return SAMPLER_TYPE;
291 }
292
293 int NativeImageSourceQueueTizen::GetTextureTarget() const
294 {
295   return GL_TEXTURE_EXTERNAL_OES;
296 }
297
298 Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
299 {
300   return nullptr;
301 }
302
303 bool NativeImageSourceQueueTizen::SourceChanged() const
304 {
305   return false;
306 }
307
308 void NativeImageSourceQueueTizen::ResetEglImageList()
309 {
310   if(mConsumeSurface)
311   {
312     if(tbm_surface_internal_is_valid(mConsumeSurface))
313     {
314       tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
315     }
316     mConsumeSurface = NULL;
317   }
318
319   for(auto&& iter : mEglImages)
320   {
321     mEglImageExtensions->DestroyImageKHR(iter.second);
322
323     tbm_surface_internal_unref(iter.first);
324   }
325   mEglImages.clear();
326 }
327
328 bool NativeImageSourceQueueTizen::CheckBlending(int format)
329 {
330   for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
331   {
332     if(format == FORMATS_BLENDING_REQUIRED[i])
333     {
334       return true;
335     }
336   }
337
338   return false;
339 }
340
341 } // namespace Adaptor
342
343 } // namespace Internal
344
345 } // namespace Dali