Merge "Fix svace issue for image-operator" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / tizen / egl-image-extensions-tizen.cpp
1 /*
2  * Copyright (c) 2023 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/graphics/common/egl-image-extensions.h>
20
21 // EXTERNAL INCLUDES
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
24 #include <GLES3/gl3.h>
25
26 #include <EGL/eglext.h>
27
28 #include <tbm_bufmgr.h>
29 #include <tbm_surface.h>
30 #include <tbm_surface_internal.h>
31
32 #include <dali/integration-api/debug.h>
33
34 // INTERNAL INCLUDES
35 #include <dali/internal/graphics/gles/egl-implementation.h>
36
37 // TBM surface support
38 #ifndef EGL_NATIVE_SURFACE_TIZEN
39 #define EGL_NATIVE_SURFACE_TIZEN 0x32A1
40 #endif
41
42 namespace
43 {
44 // function pointers assigned in InitializeEglImageKHR
45 PFNEGLCREATEIMAGEKHRPROC            eglCreateImageKHRProc            = 0;
46 PFNEGLDESTROYIMAGEKHRPROC           eglDestroyImageKHRProc           = 0;
47 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOESProc = 0;
48
49 const char* EGL_TIZEN_IMAGE_NATIVE_SURFACE = "EGL_TIZEN_image_native_surface";
50 const char* EGL_EXT_IMAGE_DMA_BUF_IMPORT   = "EGL_EXT_image_dma_buf_import";
51
52 } // unnamed namespace
53
54 namespace Dali
55 {
56 namespace Internal
57 {
58 namespace Adaptor
59 {
60 struct EglImageExtensions::Impl
61 {
62   bool mIsTizenImageNativeSurfaceSupported{false};
63   bool mIsExtImageDmaBufImportSupported{false};
64 };
65
66 EglImageExtensions::EglImageExtensions(EglImplementation* eglImpl)
67 : mImpl(new Impl()),
68   mEglImplementation(eglImpl),
69   mImageKHRInitialized(false),
70   mImageKHRInitializeFailed(false)
71 {
72   DALI_ASSERT_ALWAYS(eglImpl && "EGL Implementation not instantiated");
73 }
74
75 EglImageExtensions::~EglImageExtensions()
76 {
77   delete mImpl;
78 }
79
80 void* EglImageExtensions::CreateImageKHR(EGLClientBuffer clientBuffer)
81 {
82   if(mImageKHRInitialized == false)
83   {
84     InitializeEglImageKHR();
85   }
86
87   if(mImageKHRInitialized == false)
88   {
89     return NULL;
90   }
91
92   EGLImageKHR eglImage = EGL_NO_IMAGE_KHR;
93
94   // Use the EGL image extension
95   if(mImpl->mIsTizenImageNativeSurfaceSupported)
96   {
97     // If EGL_TIZEN_image_native_surface is supported
98     const EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
99
100     eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
101                                      EGL_NO_CONTEXT,
102                                      EGL_NATIVE_SURFACE_TIZEN,
103                                      clientBuffer,
104                                      attribs);
105   }
106   else if(mImpl->mIsExtImageDmaBufImportSupported)
107   {
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);
111
112     if(tbm_surface_get_info(tbmSurface, &info) != TBM_SURFACE_ERROR_NONE)
113     {
114       return NULL;
115     }
116
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));
119
120     // clang-format off
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),
127                               EGL_NONE};
128     // clang-format on
129
130     eglImage = eglCreateImageKHRProc(mEglImplementation->GetDisplay(),
131                                      EGL_NO_CONTEXT,
132                                      EGL_LINUX_DMA_BUF_EXT,
133                                      nullptr,
134                                      attribs);
135   }
136   else
137   {
138     DALI_LOG_ERROR("Not supported\n");
139     return EGL_NO_IMAGE_KHR;
140   }
141
142   if(EGL_NO_IMAGE_KHR == eglImage)
143   {
144     switch(eglGetError())
145     {
146       case EGL_SUCCESS:
147       {
148         break;
149       }
150       case EGL_BAD_DISPLAY:
151       {
152         DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
153         break;
154       }
155       case EGL_BAD_CONTEXT:
156       {
157         DALI_LOG_ERROR("EGL_BAD_CONTEXT: Invalid EGLContext object\n");
158         break;
159       }
160       case EGL_BAD_PARAMETER:
161       {
162         DALI_LOG_ERROR("EGL_BAD_PARAMETER: Invalid target parameter or attribute in attrib_list\n");
163         break;
164       }
165       case EGL_BAD_MATCH:
166       {
167         DALI_LOG_ERROR("EGL_BAD_MATCH: attrib_list does not match target\n");
168         break;
169       }
170       case EGL_BAD_ACCESS:
171       {
172         DALI_LOG_ERROR("EGL_BAD_ACCESS: Previously bound off-screen, or EGLImage sibling error\n");
173         break;
174       }
175       case EGL_BAD_ALLOC:
176       {
177         DALI_LOG_ERROR("EGL_BAD_ALLOC: Insufficient memory is available\n");
178         break;
179       }
180       default:
181       {
182         break;
183       }
184     }
185   }
186   DALI_ASSERT_DEBUG(EGL_NO_IMAGE_KHR != eglImage && "EglImageExtensions::CreateImageKHR: eglCreateImageKHR failed!\n");
187
188   return eglImage;
189 }
190
191 void EglImageExtensions::DestroyImageKHR(void* eglImageKHR)
192 {
193   DALI_ASSERT_DEBUG(mImageKHRInitialized);
194
195   if(!mImageKHRInitialized)
196   {
197     return;
198   }
199
200   if(eglImageKHR == NULL)
201   {
202     return;
203   }
204
205   EGLImageKHR eglImage = static_cast<EGLImageKHR>(eglImageKHR);
206
207   EGLBoolean result = eglDestroyImageKHRProc(mEglImplementation->GetDisplay(), eglImage);
208
209   if(EGL_FALSE == result)
210   {
211     switch(eglGetError())
212     {
213       case EGL_BAD_DISPLAY:
214       {
215         DALI_LOG_ERROR("EGL_BAD_DISPLAY: Invalid EGLDisplay object\n");
216         break;
217       }
218       case EGL_BAD_PARAMETER:
219       {
220         DALI_LOG_ERROR("EGL_BAD_PARAMETER: eglImage is not a valid EGLImageKHR object created with respect to EGLDisplay\n");
221         break;
222       }
223       case EGL_BAD_ACCESS:
224       {
225         DALI_LOG_ERROR("EGL_BAD_ACCESS: EGLImage sibling error\n");
226         break;
227       }
228       default:
229       {
230         break;
231       }
232     }
233   }
234 }
235
236 void EglImageExtensions::TargetTextureKHR(void* eglImageKHR)
237 {
238   DALI_ASSERT_DEBUG(mImageKHRInitialized);
239
240   if(eglImageKHR != NULL)
241   {
242     EGLImageKHR eglImage = static_cast<EGLImageKHR>(eglImageKHR);
243
244 #ifdef EGL_ERROR_CHECKING
245     GLint glError = glGetError();
246 #endif
247
248     glEGLImageTargetTexture2DOESProc(GL_TEXTURE_EXTERNAL_OES, reinterpret_cast<GLeglImageOES>(eglImage));
249
250 #ifdef EGL_ERROR_CHECKING
251     glError = glGetError();
252     if(GL_NO_ERROR != glError)
253     {
254       DALI_LOG_ERROR(" glEGLImageTargetTexture2DOES returned error %0x04x\n", glError);
255     }
256 #endif
257   }
258 }
259
260 void EglImageExtensions::InitializeEglImageKHR()
261 {
262   // avoid trying to reload extended KHR functions, if it fails the first time
263   if(!mImageKHRInitializeFailed)
264   {
265     eglCreateImageKHRProc            = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
266     eglDestroyImageKHRProc           = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
267     glEGLImageTargetTexture2DOESProc = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
268   }
269
270   if(eglCreateImageKHRProc && eglDestroyImageKHRProc && glEGLImageTargetTexture2DOESProc)
271   {
272     mImageKHRInitialized = true;
273   }
274   else
275   {
276     mImageKHRInitializeFailed = true;
277   }
278
279   std::string extensionStr = eglQueryString(mEglImplementation->GetDisplay(), EGL_EXTENSIONS);
280
281   auto found = extensionStr.find(EGL_TIZEN_IMAGE_NATIVE_SURFACE);
282   if(found != std::string::npos)
283   {
284     mImpl->mIsTizenImageNativeSurfaceSupported = true;
285   }
286
287   found = extensionStr.find(EGL_EXT_IMAGE_DMA_BUF_IMPORT);
288   if(found != std::string::npos)
289   {
290     mImpl->mIsExtImageDmaBufImportSupported = true;
291   }
292 }
293
294 } // namespace Adaptor
295
296 } // namespace Internal
297
298 } // namespace Dali