1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "gl_egl_state.h"
16 #include <cstdint>
17
18 #include "display_common.h"
19 #include "display_bytrace.h"
20 namespace OHOS {
21 namespace HDI {
22 namespace DISPLAY {
CheckEglExtension(const char * extensions,const char * extension)23 static bool CheckEglExtension(const char *extensions, const char *extension)
24 {
25 size_t extlen = strlen(extension);
26 const char *end = extensions + strlen(extensions);
27 constexpr char CHARACTER_WHITESPACE = ' ';
28 constexpr const char *CHARACTER_STRING_WHITESPACE = " ";
29 while (extensions < end) {
30 size_t n = 0;
31
32 /* Skip whitespaces, if any */
33 if (*extensions == CHARACTER_WHITESPACE) {
34 extensions++;
35 continue;
36 }
37
38 n = strcspn(extensions, CHARACTER_STRING_WHITESPACE);
39 /* Compare strings */
40 if (n == extlen && strncmp(extension, extensions, n) == 0) {
41 return true; /* Found */
42 }
43 extensions += n;
44 }
45 /* Not found */
46 return false;
47 }
48
GetPlatformEglDisplay(EGLenum platform,void * native_display,const EGLint * attrib_list)49 static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void *native_display, const EGLint *attrib_list)
50 {
51 using GetPlatformDisplayExt = PFNEGLGETPLATFORMDISPLAYEXTPROC;
52 constexpr const char *EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland";
53 constexpr const char *EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland";
54 constexpr const char *EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT";
55 static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL;
56
57 if (!eglGetPlatformDisplayExt) {
58 const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
59 if (extensions && (CheckEglExtension(extensions, EGL_EXT_PLATFORM_WAYLAND) ||
60 CheckEglExtension(extensions, EGL_KHR_PLATFORM_WAYLAND))) {
61 eglGetPlatformDisplayExt = (GetPlatformDisplayExt)eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT);
62 }
63 }
64
65 if (eglGetPlatformDisplayExt) {
66 return eglGetPlatformDisplayExt(platform, native_display, attrib_list);
67 }
68
69 return eglGetDisplay((EGLNativeDisplayType)native_display);
70 }
71
Init(const EGLint surfaceType)72 bool GlEglState::Init(const EGLint surfaceType)
73 {
74 uint32_t ret;
75 DISPLAY_LOGD();
76 eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, nullptr);
77 DISPLAY_CHK_RETURN((eglDisplay_ == EGL_NO_DISPLAY), false,
78 DISPLAY_LOGE("can not get eglDisplay glerror : %{puiblic}d", eglGetError()));
79
80 EGLint major = 0, minor = 0;
81 ret = eglInitialize(eglDisplay_, &major, &minor);
82 DISPLAY_CHK_RETURN((ret == EGL_FALSE), false,
83 DISPLAY_LOGE("egl initialize failed glerror : %{public}d", eglGetError()));
84
85 ret = eglBindAPI(EGL_OPENGL_ES_API);
86 DISPLAY_CHK_RETURN((ret == EGL_FALSE), false,
87 DISPLAY_LOGE("egl bind OpenGL ES API failed glerror : %{public}d", eglGetError()));
88
89 EGLint outNum;
90 EGLint configAttr[] = {EGL_SURFACE_TYPE, surfaceType, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
91 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE};
92 ret = eglChooseConfig(eglDisplay_, configAttr, &eglConfig_, 1, &outNum);
93 DISPLAY_CHK_RETURN(((ret == EGL_FALSE) || (outNum < 1)), false,
94 DISPLAY_LOGE("Failed to choose egl config glerror %{public}d", eglGetError()));
95
96 constexpr EGLint EGL_CONTEXT_CLIENT_VERSION_NUM = 2;
97 static const EGLint contextAttr[] = {
98 EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM,
99 EGL_NONE
100 };
101 eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, contextAttr);
102 DISPLAY_CHK_RETURN((ret == EGL_FALSE), false,
103 DISPLAY_LOGE("Failed to create egl context glerror : %{public}d", eglGetError()));
104 return true;
105 }
106
Init(uint32_t width,uint32_t height)107 bool GlEglState::Init(uint32_t width, uint32_t height)
108 {
109 if (!Init(EGL_PBUFFER_BIT)) {
110 DISPLAY_LOGE("Init failed");
111 }
112 EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
113 eglSurface_ = eglCreatePbufferSurface(eglDisplay_, eglConfig_, attribs);
114 if (eglSurface_ == EGL_NO_SURFACE) {
115 DISPLAY_LOGE("Failed to create eglsurface %{public}x", eglGetError());
116 }
117 return true;
118 }
119
Init(NativeWindowType window)120 bool GlEglState::Init(NativeWindowType window)
121 {
122 if (window == nullptr) {
123 return false;
124 }
125 if (!Init(EGL_WINDOW_BIT)) {
126 DISPLAY_LOGE("Init failed");
127 return false;
128 }
129 nativeWindow_ = window;
130 CreateEglSurface(nativeWindow_);
131 return true;
132 }
133
MakeCurrent()134 void GlEglState::MakeCurrent()
135 {
136 DISPLAY_LOGD();
137 if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) {
138 DISPLAY_LOGE("can not make cuurent glerror %{public}d", eglGetError());
139 }
140 }
141
SwapBuffer()142 void GlEglState::SwapBuffer()
143 {
144 DisplayBytrace trace = DisplayBytrace("SwapBuffer");
145 DISPLAY_LOGD();
146 if (!eglSwapBuffers(eglDisplay_, eglSurface_)) {
147 DISPLAY_LOGE("Failed to SwapBuffers on surface %{public}p glerror %{public}d", eglSurface_, eglGetError());
148 }
149 }
150
CreateEglSurface(EGLNativeWindowType nativeWindow)151 void GlEglState::CreateEglSurface(EGLNativeWindowType nativeWindow)
152 {
153 uint32_t ret = eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
154 if (!ret) {
155 DISPLAY_LOGW("Failed to make current glerror %{public}x", eglGetError());
156 }
157 eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, nativeWindow, nullptr);
158 if (eglSurface_ == EGL_NO_SURFACE) {
159 DISPLAY_LOGE("Failed to create eglsurface %{public}x", eglGetError());
160 }
161 }
162 }
163 }
164 }