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