Revert "[Tizen] Remove to call key consumed event in ATSPI bridge"
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-queue-impl-tizen.cpp
1 /*
2  * Copyright (c) 2022 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/devel-api/adaptor-framework/environment-variable.h>
28 #include <dali/internal/adaptor/common/adaptor-impl.h>
29 #include <dali/internal/graphics/common/egl-image-extensions.h>
30 #include <dali/internal/graphics/gles/egl-graphics.h>
31
32 namespace Dali
33 {
34 namespace Internal
35 {
36 namespace Adaptor
37 {
38 namespace
39 {
40 // clang-format off
41 int FORMATS_BLENDING_REQUIRED[] = {
42   TBM_FORMAT_ARGB4444, TBM_FORMAT_ABGR4444,
43   TBM_FORMAT_RGBA4444, TBM_FORMAT_BGRA4444,
44   TBM_FORMAT_RGBX5551, TBM_FORMAT_BGRX5551,
45   TBM_FORMAT_ARGB1555, TBM_FORMAT_ABGR1555,
46   TBM_FORMAT_RGBA5551, TBM_FORMAT_BGRA5551,
47   TBM_FORMAT_ARGB8888, TBM_FORMAT_ABGR8888,
48   TBM_FORMAT_RGBA8888, TBM_FORMAT_BGRA8888,
49   TBM_FORMAT_ARGB2101010, TBM_FORMAT_ABGR2101010,
50   TBM_FORMAT_RGBA1010102, TBM_FORMAT_BGRA1010102
51 };
52 // clang-format on
53
54 const char* SAMPLER_TYPE = "samplerExternalOES";
55
56 constexpr int32_t NUM_FORMATS_BLENDING_REQUIRED = 18;
57
58 constexpr int32_t DEFAULT_TBM_SURFACE_QUEUE_SIZE = 3u;
59 constexpr auto    TBM_SURFACE_QUEUE_SIZE         = "DALI_TBM_SURFACE_QUEUE_SIZE";
60
61 int32_t GetTbmSurfaceQueueSize()
62 {
63   static auto    queueSizeString = EnvironmentVariable::GetEnvironmentVariable(TBM_SURFACE_QUEUE_SIZE);
64   static int32_t queueSize       = queueSizeString ? std::atoi(queueSizeString) : DEFAULT_TBM_SURFACE_QUEUE_SIZE;
65   return queueSize;
66 }
67
68 } // namespace
69
70 NativeImageSourceQueueTizen* NativeImageSourceQueueTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
71 {
72   NativeImageSourceQueueTizen* image = new NativeImageSourceQueueTizen(width, height, colorFormat, nativeImageSourceQueue);
73   DALI_ASSERT_DEBUG(image && "NativeImageSourceQueueTizen allocation failed.");
74
75   if(image)
76   {
77     image->Initialize(colorFormat);
78   }
79
80   return image;
81 }
82
83 NativeImageSourceQueueTizen::NativeImageSourceQueueTizen(uint32_t width, uint32_t height, Dali::NativeImageSourceQueue::ColorFormat colorFormat, Any nativeImageSourceQueue)
84 : mMutex(),
85   mWidth(width),
86   mHeight(height),
87   mTbmQueue(NULL),
88   mConsumeSurface(NULL),
89   mEglImages(),
90   mBuffers(),
91   mEglGraphics(NULL),
92   mEglImageExtensions(NULL),
93   mOwnTbmQueue(false),
94   mBlendingRequired(false),
95   mIsResized(false)
96 {
97   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
98
99   GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
100   mEglGraphics                = static_cast<EglGraphics*>(graphics);
101
102   mTbmQueue = GetSurfaceFromAny(nativeImageSourceQueue);
103
104   if(mTbmQueue != NULL)
105   {
106     mBlendingRequired = CheckBlending(tbm_surface_queue_get_format(mTbmQueue));
107     mWidth            = tbm_surface_queue_get_width(mTbmQueue);
108     mHeight           = tbm_surface_queue_get_height(mTbmQueue);
109   }
110 }
111
112 NativeImageSourceQueueTizen::~NativeImageSourceQueueTizen()
113 {
114   if(mOwnTbmQueue)
115   {
116     if(mTbmQueue != NULL)
117     {
118       tbm_surface_queue_destroy(mTbmQueue);
119     }
120   }
121 }
122
123 void NativeImageSourceQueueTizen::Initialize(Dali::NativeImageSourceQueue::ColorFormat colorFormat)
124 {
125   if(mWidth == 0 || mHeight == 0)
126   {
127     return;
128   }
129
130   if(mTbmQueue == NULL)
131   {
132     int tbmFormat = TBM_FORMAT_ARGB8888;
133
134     switch(colorFormat)
135     {
136       case Dali::NativeImageSourceQueue::ColorFormat::RGBA8888: // TODO : Implement me after other codes fixed.
137       case Dali::NativeImageSourceQueue::ColorFormat::BGRA8888:
138       {
139         tbmFormat         = TBM_FORMAT_ARGB8888;
140         mBlendingRequired = true;
141         break;
142       }
143       case Dali::NativeImageSourceQueue::ColorFormat::RGBX8888: // TODO : Implement me after other codes fixed.
144       case Dali::NativeImageSourceQueue::ColorFormat::BGRX8888:
145       {
146         tbmFormat         = TBM_FORMAT_XRGB8888;
147         mBlendingRequired = false;
148         break;
149       }
150       case Dali::NativeImageSourceQueue::ColorFormat::RGB888: // TODO : Implement me after other codes fixed.
151       case Dali::NativeImageSourceQueue::ColorFormat::BGR888:
152       {
153         tbmFormat         = TBM_FORMAT_RGB888;
154         mBlendingRequired = false;
155         break;
156       }
157       default:
158       {
159         DALI_LOG_WARNING("Wrong color format.\n");
160         return;
161       }
162     }
163
164     mTbmQueue = tbm_surface_queue_create(GetTbmSurfaceQueueSize(), mWidth, mHeight, tbmFormat, 0);
165     if(!mTbmQueue)
166     {
167       DALI_LOG_ERROR("NativeImageSourceQueueTizen::Initialize: tbm_surface_queue_create is failed! [%p]\n", mTbmQueue);
168       return;
169     }
170
171     mOwnTbmQueue = true;
172   }
173 }
174
175 tbm_surface_queue_h NativeImageSourceQueueTizen::GetSurfaceFromAny(Any source) const
176 {
177   if(source.Empty())
178   {
179     return NULL;
180   }
181
182   if(source.GetType() == typeid(tbm_surface_queue_h))
183   {
184     return AnyCast<tbm_surface_queue_h>(source);
185   }
186   else
187   {
188     return NULL;
189   }
190 }
191
192 Any NativeImageSourceQueueTizen::GetNativeImageSourceQueue() const
193 {
194   return Any(mTbmQueue);
195 }
196
197 void NativeImageSourceQueueTizen::SetSize(uint32_t width, uint32_t height)
198 {
199   Dali::Mutex::ScopedLock lock(mMutex);
200
201   if(mWidth == width && mHeight == height)
202   {
203     return;
204   }
205
206   tbm_surface_queue_reset(mTbmQueue, width, height, tbm_surface_queue_get_format(mTbmQueue));
207
208   mWidth     = width;
209   mHeight    = height;
210   mIsResized = true;
211 }
212
213 void NativeImageSourceQueueTizen::IgnoreSourceImage()
214 {
215   Dali::Mutex::ScopedLock lock(mMutex);
216   tbm_surface_h           surface;
217
218   if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
219   {
220     if(tbm_surface_queue_acquire(mTbmQueue, &surface) != TBM_SURFACE_QUEUE_ERROR_NONE)
221     {
222       DALI_LOG_ERROR("NativeImageSourceQueueTizen::IgnoreSourceImage: Failed to aquire a tbm_surface\n");
223       return;
224     }
225
226     if(tbm_surface_internal_is_valid(surface))
227     {
228       tbm_surface_queue_release(mTbmQueue, surface);
229     }
230   }
231 }
232
233 bool NativeImageSourceQueueTizen::CanDequeueBuffer()
234 {
235   Dali::Mutex::ScopedLock lock(mMutex);
236   if(tbm_surface_queue_can_dequeue(mTbmQueue, 0))
237   {
238     return true;
239   }
240   return false;
241 }
242
243 uint8_t* NativeImageSourceQueueTizen::DequeueBuffer(uint32_t& width, uint32_t& height, uint32_t& stride)
244 {
245   Dali::Mutex::ScopedLock lock(mMutex);
246   if(mTbmQueue == NULL)
247   {
248     DALI_LOG_ERROR("TbmQueue is NULL");
249     return NULL;
250   }
251
252   tbm_surface_h tbmSurface;
253   if(tbm_surface_queue_dequeue(mTbmQueue, &tbmSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
254   {
255     DALI_LOG_ERROR("Failed to dequeue a tbm_surface [%p]\n", tbmSurface);
256     return NULL;
257   }
258
259   tbm_surface_info_s info;
260   int                ret = tbm_surface_map(tbmSurface, TBM_OPTION_WRITE, &info);
261   if(ret != TBM_SURFACE_ERROR_NONE)
262   {
263     DALI_LOG_ERROR("tbm_surface_map is failed! [%d] [%p]\n", ret, tbmSurface);
264     tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
265     return NULL;
266   }
267
268   unsigned char* buffer = info.planes[0].ptr;
269   if(!buffer)
270   {
271     DALI_LOG_ERROR("tbm buffer pointer is null! [%p]\n", tbmSurface);
272     tbm_surface_unmap(tbmSurface);
273     tbm_surface_queue_cancel_dequeue(mTbmQueue, tbmSurface);
274     return NULL;
275   }
276
277   tbm_surface_internal_ref(tbmSurface);
278
279   stride = info.planes[0].stride;
280   width  = mWidth;
281   height = mHeight;
282
283   // Push the buffer
284   mBuffers.push_back(BufferPair(tbmSurface, buffer));
285   return buffer;
286 }
287
288 bool NativeImageSourceQueueTizen::EnqueueBuffer(uint8_t* buffer)
289 {
290   Dali::Mutex::ScopedLock lock(mMutex);
291   auto                    bufferInstance = std::find_if(mBuffers.begin(),
292                                      mBuffers.end(),
293                                      [buffer](BufferPair pair) { return (pair.second == buffer); });
294   if(bufferInstance != mBuffers.end())
295   {
296     tbm_surface_internal_unref((*bufferInstance).first);
297     tbm_surface_unmap((*bufferInstance).first);
298     tbm_surface_queue_enqueue(mTbmQueue, (*bufferInstance).first);
299     mBuffers.erase(bufferInstance);
300     return true;
301   }
302   return false;
303 }
304
305 bool NativeImageSourceQueueTizen::CreateResource()
306 {
307   mEglImageExtensions = mEglGraphics->GetImageExtensions();
308   DALI_ASSERT_DEBUG(mEglImageExtensions);
309
310   return true;
311 }
312
313 void NativeImageSourceQueueTizen::DestroyResource()
314 {
315   Dali::Mutex::ScopedLock lock(mMutex);
316
317   ResetEglImageList(true);
318 }
319
320 uint32_t NativeImageSourceQueueTizen::TargetTexture()
321 {
322   return 0;
323 }
324
325 void NativeImageSourceQueueTizen::PrepareTexture()
326 {
327   Dali::Mutex::ScopedLock lock(mMutex);
328
329   tbm_surface_h oldSurface = mConsumeSurface;
330
331   if(tbm_surface_queue_can_acquire(mTbmQueue, 0))
332   {
333     if(tbm_surface_queue_acquire(mTbmQueue, &mConsumeSurface) != TBM_SURFACE_QUEUE_ERROR_NONE)
334     {
335       DALI_LOG_ERROR("Failed to aquire a tbm_surface\n");
336       return;
337     }
338
339     if(oldSurface)
340     {
341       if(tbm_surface_internal_is_valid(oldSurface))
342       {
343         tbm_surface_queue_release(mTbmQueue, oldSurface);
344       }
345     }
346
347     if(mIsResized)
348     {
349       ResetEglImageList(false);
350       mIsResized = false;
351     }
352
353     if(mConsumeSurface)
354     {
355       bool existing = false;
356       for(auto&& iter : mEglImages)
357       {
358         if(iter.first == mConsumeSurface)
359         {
360           // Find the surface in the existing list
361           existing = true;
362           mEglImageExtensions->TargetTextureKHR(iter.second);
363           break;
364         }
365       }
366
367       if(!existing)
368       {
369         // Push the surface
370         tbm_surface_internal_ref(mConsumeSurface);
371
372         void* eglImageKHR = mEglImageExtensions->CreateImageKHR(reinterpret_cast<EGLClientBuffer>(mConsumeSurface));
373         mEglImageExtensions->TargetTextureKHR(eglImageKHR);
374
375         mEglImages.push_back(EglImagePair(mConsumeSurface, eglImageKHR));
376       }
377     }
378   }
379 }
380
381 bool NativeImageSourceQueueTizen::ApplyNativeFragmentShader(std::string& shader)
382 {
383   return mEglGraphics->ApplyNativeFragmentShader(shader, SAMPLER_TYPE);
384 }
385
386 const char* NativeImageSourceQueueTizen::GetCustomSamplerTypename() const
387 {
388   return SAMPLER_TYPE;
389 }
390
391 int NativeImageSourceQueueTizen::GetTextureTarget() const
392 {
393   return GL_TEXTURE_EXTERNAL_OES;
394 }
395
396 Any NativeImageSourceQueueTizen::GetNativeImageHandle() const
397 {
398   return nullptr;
399 }
400
401 bool NativeImageSourceQueueTizen::SourceChanged() const
402 {
403   return false;
404 }
405
406 void NativeImageSourceQueueTizen::ResetEglImageList(bool releaseConsumeSurface)
407 {
408   // When Tbm surface queue is reset(resized), the surface acquired before reset() is still valid, not the others.
409   // We can still use the acquired surface so that we will release it as the oldSurface in PrepareTexture() when the next surface is ready.
410   if(releaseConsumeSurface && mConsumeSurface)
411   {
412     if(tbm_surface_internal_is_valid(mConsumeSurface))
413     {
414       tbm_surface_queue_release(mTbmQueue, mConsumeSurface);
415     }
416     mConsumeSurface = NULL;
417   }
418
419   for(auto&& iter : mEglImages)
420   {
421     mEglImageExtensions->DestroyImageKHR(iter.second);
422
423     tbm_surface_internal_unref(iter.first);
424   }
425   mEglImages.clear();
426 }
427
428 bool NativeImageSourceQueueTizen::CheckBlending(int format)
429 {
430   for(int32_t i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
431   {
432     if(format == FORMATS_BLENDING_REQUIRED[i])
433     {
434       return true;
435     }
436   }
437
438   return false;
439 }
440
441 } // namespace Adaptor
442
443 } // namespace Internal
444
445 } // namespace Dali