2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/graphics/common/egl-image-extensions.h>
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
24 #include <GLES3/gl3.h>
26 #include <EGL/eglext.h>
28 #include <tbm_bufmgr.h>
29 #include <tbm_surface.h>
30 #include <tbm_surface_internal.h>
32 #include <dali/integration-api/debug.h>
35 #include <dali/internal/graphics/gles/egl-implementation.h>
37 // TBM surface support
38 #ifndef EGL_NATIVE_SURFACE_TIZEN
39 #define EGL_NATIVE_SURFACE_TIZEN 0x32A1
44 // function pointers assigned in InitializeEglImageKHR
45 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHRProc = 0;
46 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHRProc = 0;
47 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESProc = 0;
49 const std::string EGL_TIZEN_IMAGE_NATIVE_SURFACE = "EGL_TIZEN_image_native_surface";
50 const std::string EGL_EXT_IMAGE_DMA_BUF_IMPORT = "EGL_EXT_image_dma_buf_import";
52 } // unnamed namespace
60 struct EglImageExtensions::Impl
62 bool mIsTizenImageNativeSurfaceSupported{false};
63 bool mIsExtImageDmaBufImportSupported{false};
66 EglImageExtensions::EglImageExtensions(EglImplementation* eglImpl)
68 mEglImplementation(eglImpl),
69 mImageKHRInitialized(false),
70 mImageKHRInitializeFailed(false)
72 DALI_ASSERT_ALWAYS(eglImpl && "EGL Implementation not instantiated");
75 EglImageExtensions::~EglImageExtensions()
80 void* EglImageExtensions::CreateImageKHR(EGLClientBuffer clientBuffer)
82 if(mImageKHRInitialized == false)
84 InitializeEglImageKHR();
87 if(mImageKHRInitialized == false)
92 EGLImageKHR eglImage = EGL_NO_IMAGE_KHR;
94 // Use the EGL image extension
95 if(mImpl->mIsTizenImageNativeSurfaceSupported)
97 // If EGL_TIZEN_image_native_surface is supported
98 const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
100 eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
102 EGL_NATIVE_SURFACE_TIZEN,
106 else if(mImpl->mIsExtImageDmaBufImportSupported)
108 // Else then use EGL_EXT_image_dma_buf_import
109 tbm_surface_info_s info;
110 tbm_surface_h tbmSurface = reinterpret_cast<tbm_surface_h>(clientBuffer);
112 if(tbm_surface_get_info(tbmSurface, &info) != TBM_SURFACE_ERROR_NONE)
117 // We support only 1 plane
118 tbm_bo tbmBo = tbm_surface_internal_get_bo(tbmSurface, tbm_surface_internal_get_plane_bo_idx(tbmSurface, 0));
121 const EGLint attribs[] = {EGL_WIDTH, static_cast<EGLint>(info.width),
122 EGL_HEIGHT, static_cast<EGLint>(info.height),
123 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(info.format),
124 EGL_DMA_BUF_PLANE0_FD_EXT, static_cast<EGLint>(reinterpret_cast<size_t>(tbm_bo_get_handle(tbmBo, TBM_DEVICE_3D).ptr)),
125 EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(info.planes[0].offset),
126 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(info.planes[0].stride),
130 eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
132 EGL_LINUX_DMA_BUF_EXT,
138 DALI_LOG_ERROR("Not supported\n");
139 return EGL_NO_IMAGE_KHR;
142 if(EGL_NO_IMAGE_KHR == eglImage)
144 switch(eglGetError())
150 case EGL_BAD_DISPLAY:
152 DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
155 case EGL_BAD_CONTEXT:
157 DALI_LOG_ERROR("EGL_BAD_CONTEXT: Invalid EGLContext object\n");
160 case EGL_BAD_PARAMETER:
162 DALI_LOG_ERROR("EGL_BAD_PARAMETER: Invalid target parameter or attribute in attrib_list\n");
167 DALI_LOG_ERROR("EGL_BAD_MATCH: attrib_list does not match target\n");
172 DALI_LOG_ERROR("EGL_BAD_ACCESS: Previously bound off-screen, or EGLImage sibling error\n");
177 DALI_LOG_ERROR("EGL_BAD_ALLOC: Insufficient memory is available\n");
186 DALI_ASSERT_DEBUG(EGL_NO_IMAGE_KHR != eglImage && "EglImageExtensions::CreateImageKHR: eglCreateImageKHR failed!\n");
191 void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
193 DALI_ASSERT_DEBUG(mImageKHRInitialized);
195 if(!mImageKHRInitialized)
200 if(eglImageKHR == NULL)
205 EGLImageKHR eglImage = static_cast<EGLImageKHR>(eglImageKHR);
207 EGLBoolean result = eglDestroyImageKHRProc(mEglImplementation->GetDisplay(), eglImage);
209 if(EGL_FALSE == result)
211 switch(eglGetError())
213 case EGL_BAD_DISPLAY:
215 DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
218 case EGL_BAD_PARAMETER:
220 DALI_LOG_ERROR("EGL_BAD_PARAMETER: eglImage is not a valid EGLImageKHR object created with respect to EGLDisplay\n");
225 DALI_LOG_ERROR("EGL_BAD_ACCESS: EGLImage sibling error\n");
236 void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
238 DALI_ASSERT_DEBUG(mImageKHRInitialized);
240 if(eglImageKHR != NULL)
242 EGLImageKHR eglImage = static_cast<EGLImageKHR>(eglImageKHR);
244 #ifdef EGL_ERROR_CHECKING
245 GLint glError = glGetError();
248 glEGLImageTargetTexture2DOESProc(GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<GLeglImageOES>(eglImage));
250 #ifdef EGL_ERROR_CHECKING
251 glError = glGetError();
252 if(GL_NO_ERROR != glError)
254 DALI_LOG_ERROR(" glEGLImageTargetTexture2DOES returned error %0x04x\n", glError);
260 void EglImageExtensions::InitializeEglImageKHR()
262 // avoid trying to reload extended KHR functions, if it fails the first time
263 if(!mImageKHRInitializeFailed)
265 eglCreateImageKHRProc = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
266 eglDestroyImageKHRProc = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
267 glEGLImageTargetTexture2DOESProc = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
270 if(eglCreateImageKHRProc && eglDestroyImageKHRProc && glEGLImageTargetTexture2DOESProc)
272 mImageKHRInitialized = true;
276 mImageKHRInitializeFailed = true;
279 std::string extensionStr = eglQueryString(mEglImplementation->GetDisplay(), EGL_EXTENSIONS);
281 auto found = extensionStr.find(EGL_TIZEN_IMAGE_NATIVE_SURFACE);
282 if(found != std::string::npos)
284 mImpl->mIsTizenImageNativeSurfaceSupported = true;
287 found = extensionStr.find(EGL_EXT_IMAGE_DMA_BUF_IMPORT);
288 if(found != std::string::npos)
290 mImpl->mIsExtImageDmaBufImportSupported = true;
294 } // namespace Adaptor
296 } // namespace Internal