Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / tizen / egl-image-extensions-tizen.cpp
index f8d8463..cf79bdb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-
 // CLASS HEADER
 #include <dali/internal/graphics/common/egl-image-extensions.h>
 
 // EXTERNAL INCLUDES
-#if DALI_GLES_VERSION >= 30
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-
-#else
 #include <GLES2/gl2.h>
-#endif // DALI_GLES_VERSION >= 30
-
 #include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
 
 #include <EGL/eglext.h>
 
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+
 #include <dali/integration-api/debug.h>
 
 // INTERNAL INCLUDES
-#include <dali/internal/graphics/gles20/egl-implementation.h>
+#include <dali/internal/graphics/gles/egl-implementation.h>
 
 // TBM surface support
 #ifndef EGL_NATIVE_SURFACE_TIZEN
 namespace
 {
 // function pointers assigned in InitializeEglImageKHR
-PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHRProc = 0;
-PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHRProc = 0;
+PFNEGLCREATEIMAGEKHRPROC            eglCreateImageKHRProc            = 0;
+PFNEGLDESTROYIMAGEKHRPROC           eglDestroyImageKHRProc           = 0;
 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESProc = 0;
-} // unnamed namespace
 
+const std::string EGL_TIZEN_IMAGE_NATIVE_SURFACE = "EGL_TIZEN_image_native_surface";
+const std::string EGL_EXT_IMAGE_DMA_BUF_IMPORT   = "EGL_EXT_image_dma_buf_import";
+
+} // unnamed namespace
 
 namespace Dali
 {
-
 namespace Internal
 {
-
 namespace Adaptor
 {
+struct EglImageExtensions::Impl
+{
+  bool mIsTizenImageNativeSurfaceSupported{false};
+  bool mIsExtImageDmaBufImportSupported{false};
+};
 
 EglImageExtensions::EglImageExtensions(EglImplementation* eglImpl)
-: mEglImplementation(eglImpl),
+: mImpl(new Impl()),
+  mEglImplementation(eglImpl),
   mImageKHRInitialized(false),
   mImageKHRInitializeFailed(false)
 {
-  DALI_ASSERT_ALWAYS( eglImpl && "EGL Implementation not instantiated" );
+  DALI_ASSERT_ALWAYS(eglImpl && "EGL Implementation not instantiated");
 }
 
 EglImageExtensions::~EglImageExtensions()
 {
+  delete mImpl;
 }
 
 void* EglImageExtensions::CreateImageKHR(EGLClientBuffer clientBuffer)
 {
-  if (mImageKHRInitialized == false)
+  if(mImageKHRInitialized == false)
   {
     InitializeEglImageKHR();
   }
 
-  if (mImageKHRInitialized == false)
+  if(mImageKHRInitialized == false)
   {
     return NULL;
   }
 
+  EGLImageKHR eglImage = EGL_NO_IMAGE_KHR;
+
   // Use the EGL image extension
-  const EGLint attribs[] =
+  if(mImpl->mIsTizenImageNativeSurfaceSupported)
   {
-    EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
-    EGL_NONE
-  };
-
-  EGLImageKHR eglImage  = eglCreateImageKHRProc( mEglImplementation->GetDisplay(),
-                                             EGL_NO_CONTEXT,
-                                             EGL_NATIVE_SURFACE_TIZEN,
-                                             clientBuffer,
-                                             attribs );
-
-  DALI_ASSERT_DEBUG( EGL_NO_IMAGE_KHR != eglImage && "X11Image::GlExtensionCreate eglCreateImageKHR failed!\n");
-  if( EGL_NO_IMAGE_KHR == eglImage )
+    // If EGL_TIZEN_image_native_surface is supported
+    const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+
+    eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
+                                     EGL_NO_CONTEXT,
+                                     EGL_NATIVE_SURFACE_TIZEN,
+                                     clientBuffer,
+                                     attribs);
+  }
+  else if(mImpl->mIsExtImageDmaBufImportSupported)
   {
-    switch( eglGetError() )
+    // Else then use EGL_EXT_image_dma_buf_import
+    tbm_surface_info_s info;
+    tbm_surface_h      tbmSurface = reinterpret_cast<tbm_surface_h>(clientBuffer);
+
+    if(tbm_surface_get_info(tbmSurface, &info) != TBM_SURFACE_ERROR_NONE)
     {
-      case EGL_SUCCESS :
+      return NULL;
+    }
+
+    // We support only 1 plane
+    tbm_bo tbmBo = tbm_surface_internal_get_bo(tbmSurface, tbm_surface_internal_get_plane_bo_idx(tbmSurface, 0));
+
+    // clang-format off
+    const EGLint attribs[] = {EGL_WIDTH, static_cast<EGLint>(info.width),
+                              EGL_HEIGHT, static_cast<EGLint>(info.height),
+                              EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(info.format),
+                              EGL_DMA_BUF_PLANE0_FD_EXT, static_cast<EGLint>(reinterpret_cast<size_t>(tbm_bo_get_handle(tbmBo, TBM_DEVICE_3D).ptr)),
+                              EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(info.planes[0].offset),
+                              EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(info.planes[0].stride),
+                              EGL_NONE};
+    // clang-format on
+
+    eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
+                                     EGL_NO_CONTEXT,
+                                     EGL_LINUX_DMA_BUF_EXT,
+                                     nullptr,
+                                     attribs);
+  }
+  else
+  {
+    DALI_LOG_ERROR("Not supported\n");
+    return EGL_NO_IMAGE_KHR;
+  }
+
+  if(EGL_NO_IMAGE_KHR == eglImage)
+  {
+    switch(eglGetError())
+    {
+      case EGL_SUCCESS:
       {
         break;
       }
       case EGL_BAD_DISPLAY:
       {
-        DALI_LOG_ERROR( "EGL_BAD_DISPLAY: Invalid EGLDisplay object\n" );
+        DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
         break;
       }
       case EGL_BAD_CONTEXT:
       {
-        DALI_LOG_ERROR( "EGL_BAD_CONTEXT: Invalid EGLContext object\n" );
+        DALI_LOG_ERROR("EGL_BAD_CONTEXT: Invalid EGLContext object\n");
         break;
       }
       case EGL_BAD_PARAMETER:
       {
-        DALI_LOG_ERROR( "EGL_BAD_PARAMETER: Invalid target parameter or attribute in attrib_list\n" );
+        DALI_LOG_ERROR("EGL_BAD_PARAMETER: Invalid target parameter or attribute in attrib_list\n");
         break;
       }
       case EGL_BAD_MATCH:
       {
-        DALI_LOG_ERROR( "EGL_BAD_MATCH: attrib_list does not match target\n" );
+        DALI_LOG_ERROR("EGL_BAD_MATCH: attrib_list does not match target\n");
         break;
       }
       case EGL_BAD_ACCESS:
       {
-        DALI_LOG_ERROR( "EGL_BAD_ACCESS: Previously bound off-screen, or EGLImage sibling error\n" );
+        DALI_LOG_ERROR("EGL_BAD_ACCESS: Previously bound off-screen, or EGLImage sibling error\n");
         break;
       }
       case EGL_BAD_ALLOC:
       {
-        DALI_LOG_ERROR( "EGL_BAD_ALLOC: Insufficient memory is available\n" );
+        DALI_LOG_ERROR("EGL_BAD_ALLOC: Insufficient memory is available\n");
         break;
       }
       default:
@@ -142,20 +183,21 @@ void* EglImageExtensions::CreateImageKHR(EGLClientBuffer clientBuffer)
       }
     }
   }
+  DALI_ASSERT_DEBUG(EGL_NO_IMAGE_KHR != eglImage && "EglImageExtensions::CreateImageKHR: eglCreateImageKHR failed!\n");
 
   return eglImage;
 }
 
 void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
 {
-  DALI_ASSERT_DEBUG( mImageKHRInitialized );
+  DALI_ASSERT_DEBUG(mImageKHRInitialized);
 
-  if( ! mImageKHRInitialized )
+  if(!mImageKHRInitialized)
   {
     return;
   }
 
-  if( eglImageKHR == NULL )
+  if(eglImageKHR == NULL)
   {
     return;
   }
@@ -164,23 +206,23 @@ void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
 
   EGLBoolean result = eglDestroyImageKHRProc(mEglImplementation->GetDisplay(), eglImage);
 
-  if( EGL_FALSE == result )
+  if(EGL_FALSE == result)
   {
-    switch( eglGetError() )
+    switch(eglGetError())
     {
       case EGL_BAD_DISPLAY:
       {
-        DALI_LOG_ERROR( "EGL_BAD_DISPLAY: Invalid EGLDisplay object\n" );
+        DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
         break;
       }
       case EGL_BAD_PARAMETER:
       {
-        DALI_LOG_ERROR( "EGL_BAD_PARAMETER: eglImage is not a valid EGLImageKHR object created with respect to EGLDisplay\n" );
+        DALI_LOG_ERROR("EGL_BAD_PARAMETER: eglImage is not a valid EGLImageKHR object created with respect to EGLDisplay\n");
         break;
       }
       case EGL_BAD_ACCESS:
       {
-        DALI_LOG_ERROR( "EGL_BAD_ACCESS: EGLImage sibling error\n" );
+        DALI_LOG_ERROR("EGL_BAD_ACCESS: EGLImage sibling error\n");
         break;
       }
       default:
@@ -193,9 +235,9 @@ void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
 
 void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
 {
-  DALI_ASSERT_DEBUG( mImageKHRInitialized );
+  DALI_ASSERT_DEBUG(mImageKHRInitialized);
 
-  if( eglImageKHR != NULL )
+  if(eglImageKHR != NULL)
   {
     EGLImageKHR eglImage = static_cast<EGLImageKHR>(eglImageKHR);
 
@@ -203,13 +245,13 @@ void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
     GLint glError = glGetError();
 #endif
 
-    glEGLImageTargetTexture2DOESProc(GL_TEXTURE_EXTERNAL_OES, reinterpret_cast< GLeglImageOES >( eglImage ) );
+    glEGLImageTargetTexture2DOESProc(GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<GLeglImageOES>(eglImage));
 
 #ifdef EGL_ERROR_CHECKING
     glError = glGetError();
-    if( GL_NO_ERROR != glError )
+    if(GL_NO_ERROR != glError)
     {
-      DALI_LOG_ERROR(" glEGLImageTargetTexture2DOES returned error %0x04x\n", glError );
+      DALI_LOG_ERROR(" glEGLImageTargetTexture2DOES returned error %0x04x\n", glError);
     }
 #endif
   }
@@ -218,14 +260,14 @@ void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
 void EglImageExtensions::InitializeEglImageKHR()
 {
   // avoid trying to reload extended KHR functions, if it fails the first time
-  if( ! mImageKHRInitializeFailed )
+  if(!mImageKHRInitializeFailed)
   {
-    eglCreateImageKHRProc  = reinterpret_cast< PFNEGLCREATEIMAGEKHRPROC >( eglGetProcAddress("eglCreateImageKHR") );
-    eglDestroyImageKHRProc = reinterpret_cast< PFNEGLDESTROYIMAGEKHRPROC >( eglGetProcAddress("eglDestroyImageKHR") );
-    glEGLImageTargetTexture2DOESProc = reinterpret_cast< PFNGLEGLIMAGETARGETTEXTURE2DOESPROC >( eglGetProcAddress("glEGLImageTargetTexture2DOES") );
+    eglCreateImageKHRProc            = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+    eglDestroyImageKHRProc           = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+    glEGLImageTargetTexture2DOESProc = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
   }
 
-  if (eglCreateImageKHRProc && eglDestroyImageKHRProc && glEGLImageTargetTexture2DOESProc)
+  if(eglCreateImageKHRProc && eglDestroyImageKHRProc && glEGLImageTargetTexture2DOESProc)
   {
     mImageKHRInitialized = true;
   }
@@ -233,6 +275,20 @@ void EglImageExtensions::InitializeEglImageKHR()
   {
     mImageKHRInitializeFailed = true;
   }
+
+  std::string extensionStr = eglQueryString(mEglImplementation->GetDisplay(), EGL_EXTENSIONS);
+
+  auto found = extensionStr.find(EGL_TIZEN_IMAGE_NATIVE_SURFACE);
+  if(found != std::string::npos)
+  {
+    mImpl->mIsTizenImageNativeSurfaceSupported = true;
+  }
+
+  found = extensionStr.find(EGL_EXT_IMAGE_DMA_BUF_IMPORT);
+  if(found != std::string::npos)
+  {
+    mImpl->mIsExtImageDmaBufImportSupported = true;
+  }
 }
 
 } // namespace Adaptor