[Tizen] Revert "Make to use right egl image extension name in the glsl 3.x"
[platform/core/uifw/dali-adaptor.git] / dali / internal / imaging / tizen / native-image-source-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-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 #include <cstring>
26
27 // INTERNAL INCLUDES
28 #include <dali/integration-api/adaptor-framework/render-surface-interface.h>
29 #include <dali/internal/adaptor/common/adaptor-impl.h>
30 #include <dali/internal/graphics/common/egl-image-extensions.h>
31 #include <dali/internal/graphics/gles/egl-graphics.h>
32
33 namespace Dali
34 {
35 namespace Internal
36 {
37 namespace Adaptor
38 {
39 namespace
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 tbm_format 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 using Dali::Integration::PixelBuffer;
63
64 NativeImageSourceTizen* NativeImageSourceTizen::New(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
65 {
66   NativeImageSourceTizen* image = new NativeImageSourceTizen(width, height, depth, nativeImageSource);
67   DALI_ASSERT_DEBUG(image && "NativeImageSource allocation failed.");
68
69   if(image)
70   {
71     image->Initialize();
72   }
73
74   return image;
75 }
76
77 NativeImageSourceTizen::NativeImageSourceTizen(uint32_t width, uint32_t height, Dali::NativeImageSource::ColorDepth depth, Any nativeImageSource)
78 : mWidth(width),
79   mHeight(height),
80   mOwnTbmSurface(false),
81   mTbmSurface(NULL),
82   mTbmFormat(0),
83   mBlendingRequired(false),
84   mColorDepth(depth),
85   mEglImageKHR(NULL),
86   mEglGraphics(NULL),
87   mEglImageExtensions(NULL),
88   mSetSource(false),
89   mMutex(),
90   mIsBufferAcquired(false)
91 {
92   DALI_ASSERT_ALWAYS(Adaptor::IsAvailable());
93
94   GraphicsInterface* graphics = &(Adaptor::GetImplementation(Adaptor::Get()).GetGraphicsInterface());
95   mEglGraphics                = static_cast<EglGraphics*>(graphics);
96
97   mTbmSurface = GetSurfaceFromAny(nativeImageSource);
98
99   if(mTbmSurface != NULL)
100   {
101     tbm_surface_internal_ref(mTbmSurface);
102     mBlendingRequired = CheckBlending(tbm_surface_get_format(mTbmSurface));
103     mWidth            = tbm_surface_get_width(mTbmSurface);
104     mHeight           = tbm_surface_get_height(mTbmSurface);
105   }
106 }
107
108 void NativeImageSourceTizen::Initialize()
109 {
110   if(mTbmSurface != NULL || mWidth == 0 || mHeight == 0)
111   {
112     return;
113   }
114
115   tbm_format format = TBM_FORMAT_RGB888;
116   int        depth  = 0;
117
118   switch(mColorDepth)
119   {
120     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
121     {
122       format = TBM_FORMAT_ARGB8888;
123       depth  = 32;
124       break;
125     }
126     case Dali::NativeImageSource::COLOR_DEPTH_8:
127     {
128       format = TBM_FORMAT_C8;
129       depth  = 8;
130       break;
131     }
132     case Dali::NativeImageSource::COLOR_DEPTH_16:
133     {
134       format = TBM_FORMAT_RGB565;
135       depth  = 16;
136       break;
137     }
138     case Dali::NativeImageSource::COLOR_DEPTH_24:
139     {
140       format = TBM_FORMAT_RGB888;
141       depth  = 24;
142       break;
143     }
144     case Dali::NativeImageSource::COLOR_DEPTH_32:
145     {
146       format = TBM_FORMAT_ARGB8888;
147       depth  = 32;
148       break;
149     }
150     default:
151     {
152       DALI_LOG_WARNING("Wrong color depth.\n");
153       return;
154     }
155   }
156
157   // set whether blending is required according to pixel format based on the depth
158   /* default pixel format is RGB888
159      If depth = 8, Pixel::A8;
160      If depth = 16, Pixel::RGB565;
161      If depth = 32, Pixel::RGBA8888 */
162   mBlendingRequired = (depth == 32 || depth == 8);
163
164   mTbmSurface    = tbm_surface_create(mWidth, mHeight, format);
165   mOwnTbmSurface = true;
166 }
167
168 tbm_surface_h NativeImageSourceTizen::GetSurfaceFromAny(Any source) const
169 {
170   if(source.Empty())
171   {
172     return NULL;
173   }
174
175   if(source.GetType() == typeid(tbm_surface_h))
176   {
177     return AnyCast<tbm_surface_h>(source);
178   }
179   else
180   {
181     return NULL;
182   }
183 }
184
185 void NativeImageSourceTizen::DestroySurface()
186 {
187   if(mTbmSurface)
188   {
189     if(mIsBufferAcquired)
190     {
191       ReleaseBuffer();
192     }
193     if(mOwnTbmSurface)
194     {
195       if(tbm_surface_destroy(mTbmSurface) != TBM_SURFACE_ERROR_NONE)
196       {
197         DALI_LOG_ERROR("Failed to destroy tbm_surface\n");
198       }
199     }
200     else
201     {
202       tbm_surface_internal_unref(mTbmSurface);
203     }
204   }
205 }
206
207 NativeImageSourceTizen::~NativeImageSourceTizen()
208 {
209   DestroySurface();
210 }
211
212 Any NativeImageSourceTizen::GetNativeImageSource() const
213 {
214   return Any(mTbmSurface);
215 }
216
217 bool NativeImageSourceTizen::GetPixels(std::vector<unsigned char>& pixbuf, unsigned& width, unsigned& height, Pixel::Format& pixelFormat) const
218 {
219   Dali::Mutex::ScopedLock lock(mMutex);
220   if(mTbmSurface != NULL)
221   {
222     tbm_surface_info_s surface_info;
223
224     if(tbm_surface_map(mTbmSurface, TBM_SURF_OPTION_READ, &surface_info) != TBM_SURFACE_ERROR_NONE)
225     {
226       DALI_LOG_ERROR("Fail to map tbm_surface\n");
227
228       width  = 0;
229       height = 0;
230
231       return false;
232     }
233
234     tbm_format     format = surface_info.format;
235     uint32_t       stride = surface_info.planes[0].stride;
236     unsigned char* ptr    = surface_info.planes[0].ptr;
237
238     width  = mWidth;
239     height = mHeight;
240     size_t lineSize;
241     size_t offset;
242     size_t cOffset;
243
244     switch(format)
245     {
246       case TBM_FORMAT_RGB888:
247       {
248         lineSize    = width * 3;
249         pixelFormat = Pixel::RGB888;
250         pixbuf.resize(lineSize * height);
251         unsigned char* bufptr = &pixbuf[0];
252
253         for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
254         {
255           for(unsigned int c = 0; c < width; ++c)
256           {
257             cOffset                 = c * 3;
258             offset                  = cOffset + r * stride;
259             *(bufptr + cOffset)     = ptr[offset + 2];
260             *(bufptr + cOffset + 1) = ptr[offset + 1];
261             *(bufptr + cOffset + 2) = ptr[offset];
262           }
263         }
264         break;
265       }
266       case TBM_FORMAT_RGBA8888:
267       {
268         lineSize    = width * 4;
269         pixelFormat = Pixel::RGBA8888;
270         pixbuf.resize(lineSize * height);
271         unsigned char* bufptr = &pixbuf[0];
272
273         for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
274         {
275           for(unsigned int c = 0; c < width; ++c)
276           {
277             cOffset                 = c * 4;
278             offset                  = cOffset + r * stride;
279             *(bufptr + cOffset)     = ptr[offset + 3];
280             *(bufptr + cOffset + 1) = ptr[offset + 2];
281             *(bufptr + cOffset + 2) = ptr[offset + 1];
282             *(bufptr + cOffset + 3) = ptr[offset];
283           }
284         }
285         break;
286       }
287       case TBM_FORMAT_ARGB8888:
288       {
289         lineSize    = width * 4;
290         pixelFormat = Pixel::RGBA8888;
291         pixbuf.resize(lineSize * height);
292         unsigned char* bufptr = &pixbuf[0];
293
294         for(unsigned int r = 0; r < height; ++r, bufptr += lineSize)
295         {
296           for(unsigned int c = 0; c < width; ++c)
297           {
298             cOffset                 = c * 4;
299             offset                  = cOffset + r * stride;
300             *(bufptr + cOffset)     = ptr[offset + 2];
301             *(bufptr + cOffset + 1) = ptr[offset + 1];
302             *(bufptr + cOffset + 2) = ptr[offset];
303             *(bufptr + cOffset + 3) = ptr[offset + 3];
304           }
305         }
306         break;
307       }
308       default:
309       {
310         DALI_ASSERT_ALWAYS(0 && "Tbm surface has unsupported pixel format.\n");
311
312         return false;
313       }
314     }
315
316     if(tbm_surface_unmap(mTbmSurface) != TBM_SURFACE_ERROR_NONE)
317     {
318       DALI_LOG_ERROR("Fail to unmap tbm_surface\n");
319     }
320
321     return true;
322   }
323
324   DALI_LOG_WARNING("TBM surface does not exist.\n");
325
326   width  = 0;
327   height = 0;
328
329   return false;
330 }
331
332 void NativeImageSourceTizen::SetSource(Any source)
333 {
334   Dali::Mutex::ScopedLock lock(mMutex);
335
336   DestroySurface();
337
338   mOwnTbmSurface = false;
339   mTbmSurface    = GetSurfaceFromAny(source);
340
341   if(mTbmSurface != NULL)
342   {
343     mSetSource = true;
344     tbm_surface_internal_ref(mTbmSurface);
345     mBlendingRequired = CheckBlending(tbm_surface_get_format(mTbmSurface));
346     mWidth            = tbm_surface_get_width(mTbmSurface);
347     mHeight           = tbm_surface_get_height(mTbmSurface);
348   }
349 }
350
351 bool NativeImageSourceTizen::IsColorDepthSupported(Dali::NativeImageSource::ColorDepth colorDepth)
352 {
353   uint32_t*  formats;
354   uint32_t   formatNum;
355   tbm_format format = TBM_FORMAT_RGB888;
356
357   switch(colorDepth)
358   {
359     case Dali::NativeImageSource::COLOR_DEPTH_DEFAULT:
360     {
361       format = TBM_FORMAT_ARGB8888;
362       break;
363     }
364     case Dali::NativeImageSource::COLOR_DEPTH_8:
365     {
366       format = TBM_FORMAT_C8;
367       break;
368     }
369     case Dali::NativeImageSource::COLOR_DEPTH_16:
370     {
371       format = TBM_FORMAT_RGB565;
372       break;
373     }
374     case Dali::NativeImageSource::COLOR_DEPTH_24:
375     {
376       format = TBM_FORMAT_RGB888;
377       break;
378     }
379     case Dali::NativeImageSource::COLOR_DEPTH_32:
380     {
381       format = TBM_FORMAT_ARGB8888;
382       break;
383     }
384   }
385
386   if(tbm_surface_query_formats(&formats, &formatNum))
387   {
388     for(unsigned int i = 0; i < formatNum; i++)
389     {
390       if(formats[i] == format)
391       {
392         free(formats);
393         return true;
394       }
395     }
396   }
397
398   free(formats);
399   return false;
400 }
401
402 bool NativeImageSourceTizen::CreateResource()
403 {
404   // If an EGL image exists, use it as it is without creating it.
405   if(mEglImageKHR != NULL)
406   {
407     return true;
408   }
409
410   // casting from an unsigned int to a void *, which should then be cast back
411   // to an unsigned int in the driver.
412   EGLClientBuffer eglBuffer = reinterpret_cast<EGLClientBuffer>(mTbmSurface);
413   if(!eglBuffer || !tbm_surface_internal_is_valid(mTbmSurface))
414   {
415     return false;
416   }
417
418   mEglImageExtensions = mEglGraphics->GetImageExtensions();
419   DALI_ASSERT_DEBUG(mEglImageExtensions);
420
421   mEglImageKHR = mEglImageExtensions->CreateImageKHR(eglBuffer);
422
423   return mEglImageKHR != NULL;
424 }
425
426 void NativeImageSourceTizen::DestroyResource()
427 {
428   Dali::Mutex::ScopedLock lock(mMutex);
429   if(mEglImageKHR)
430   {
431     mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
432
433     mEglImageKHR = NULL;
434   }
435 }
436
437 uint32_t NativeImageSourceTizen::TargetTexture()
438 {
439   mEglImageExtensions->TargetTextureKHR(mEglImageKHR);
440
441   return 0;
442 }
443
444 void NativeImageSourceTizen::PrepareTexture()
445 {
446   Dali::Mutex::ScopedLock lock(mMutex);
447   if(mSetSource)
448   {
449     // Destroy previous eglImage because use for new one.
450     // if mEglImageKHR is not to be NULL here, it will not be updated with a new eglImage.
451     mEglImageExtensions->DestroyImageKHR(mEglImageKHR);
452     mEglImageKHR = NULL;
453
454     if(CreateResource())
455     {
456       TargetTexture();
457     }
458
459     mSetSource = false;
460   }
461 }
462
463 const char* NativeImageSourceTizen::GetCustomFragmentPrefix() const
464 {
465   return FRAGMENT_PREFIX;
466 }
467
468 const char* NativeImageSourceTizen::GetCustomSamplerTypename() const
469 {
470   return SAMPLER_TYPE;
471 }
472
473 int NativeImageSourceTizen::GetTextureTarget() const
474 {
475   return GL_TEXTURE_EXTERNAL_OES;
476 }
477
478 Any NativeImageSourceTizen::GetNativeImageHandle() const
479 {
480   return GetNativeImageSource();
481 }
482
483 bool NativeImageSourceTizen::SourceChanged() const
484 {
485   return false;
486 }
487
488 bool NativeImageSourceTizen::CheckBlending(tbm_format format)
489 {
490   if(mTbmFormat != format)
491   {
492     for(int i = 0; i < NUM_FORMATS_BLENDING_REQUIRED; ++i)
493     {
494       if(format == FORMATS_BLENDING_REQUIRED[i])
495       {
496         mBlendingRequired = true;
497         break;
498       }
499     }
500     mTbmFormat = format;
501   }
502
503   return mBlendingRequired;
504 }
505
506 uint8_t* NativeImageSourceTizen::AcquireBuffer(uint16_t& width, uint16_t& height, uint16_t& stride)
507 {
508   Dali::Mutex::ScopedLock lock(mMutex);
509   if(mTbmSurface != NULL)
510   {
511     tbm_surface_info_s info;
512
513     if(tbm_surface_map(mTbmSurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &info) != TBM_SURFACE_ERROR_NONE)
514     {
515       DALI_LOG_ERROR("Fail to map tbm_surface\n");
516
517       width  = 0;
518       height = 0;
519
520       return NULL;
521     }
522     tbm_surface_internal_ref(mTbmSurface);
523     mIsBufferAcquired = true;
524
525     stride = info.planes[0].stride;
526     width  = mWidth;
527     height = mHeight;
528
529     return info.planes[0].ptr;
530   }
531   return NULL;
532 }
533
534 bool NativeImageSourceTizen::ReleaseBuffer()
535 {
536   Dali::Mutex::ScopedLock lock(mMutex);
537   bool                    ret = false;
538   if(mTbmSurface != NULL)
539   {
540     ret = (tbm_surface_unmap(mTbmSurface) == TBM_SURFACE_ERROR_NONE);
541     if(!ret)
542     {
543       DALI_LOG_ERROR("Fail to unmap tbm_surface\n");
544     }
545     tbm_surface_internal_unref(mTbmSurface);
546     mIsBufferAcquired = false;
547   }
548   return ret;
549 }
550
551 } // namespace Adaptor
552
553 } // namespace Internal
554
555 } // namespace Dali