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
16 #include "native_image.h"
17
18 #include <cstddef>
19 #include <iostream>
20 #include <ostream>
21 #include <thread>
22 #include <unistd.h>
23 #include <EGL/egl.h>
24 #include <EGL/eglext.h>
25 #include "graphic_common_c.h"
26 #include "surface_type.h"
27 #include "window.h"
28 #include "GLES/gl.h"
29
30 namespace {
31 using GetPlatformDisplayExt = PFNEGLGETPLATFORMDISPLAYEXTPROC;
32 constexpr const char* EGL_EXT_PLATFORM_WAYLAND = "EGL_EXT_platform_wayland";
33 constexpr const char* EGL_KHR_PLATFORM_WAYLAND = "EGL_KHR_platform_wayland";
34 constexpr int32_t EGL_CONTEXT_CLIENT_VERSION_NUM = 2;
35 constexpr char CHARACTER_WHITESPACE = ' ';
36 constexpr const char* CHARACTER_STRING_WHITESPACE = " ";
37 constexpr const char* EGL_GET_PLATFORM_DISPLAY_EXT = "eglGetPlatformDisplayEXT";
38 EGLDisplay g_eglDisplay = EGL_NO_DISPLAY;
39 EGLContext g_eglContext = EGL_NO_CONTEXT;
40 EGLConfig g_config;
41
CheckEglExtension(const char * extensions,const char * extension)42 static bool CheckEglExtension(const char* extensions, const char* extension)
43 {
44 size_t extlen = strlen(extension);
45 const char* end = extensions + strlen(extensions);
46
47 while (extensions < end) {
48 size_t n = 0;
49 /* Skip whitespaces, if any */
50 if (*extensions == CHARACTER_WHITESPACE) {
51 extensions++;
52 continue;
53 }
54 n = strcspn(extensions, CHARACTER_STRING_WHITESPACE);
55 /* Compare strings */
56 if (n == extlen && strncmp(extension, extensions, n) == 0) {
57 return true; /* Found */
58 }
59 extensions += n;
60 }
61 /* Not found */
62 return false;
63 }
64
GetPlatformEglDisplay(EGLenum platform,void * nativeDisplay,const EGLint * attribList)65 static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void* nativeDisplay, const EGLint* attribList)
66 {
67 static GetPlatformDisplayExt eglGetPlatformDisplayExt = NULL;
68
69 if (!eglGetPlatformDisplayExt) {
70 const char* extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
71 if (extensions &&
72 (CheckEglExtension(extensions, EGL_EXT_PLATFORM_WAYLAND) ||
73 CheckEglExtension(extensions, EGL_KHR_PLATFORM_WAYLAND))) {
74 eglGetPlatformDisplayExt =
75 static_cast<GetPlatformDisplayExt>(eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT));
76 }
77 }
78
79 if (eglGetPlatformDisplayExt) {
80 return eglGetPlatformDisplayExt(platform, nativeDisplay, attribList);
81 }
82
83 return eglGetDisplay(static_cast<EGLNativeDisplayType>(nativeDisplay));
84 }
85
AddBuffer(OHNativeWindow * nativeWindow)86 void AddBuffer(OHNativeWindow* nativeWindow)
87 {
88 int code = SET_USAGE;
89 int32_t usage = OHOS::BUFFER_USAGE_CPU_READ | OHOS::BUFFER_USAGE_CPU_WRITE | OHOS::BUFFER_USAGE_MEM_DMA;
90 int32_t ret = NativeWindowHandleOpt(nativeWindow, code, usage);
91 if (ret != GSERROR_OK) {
92 std::cout << "NativeWindowHandleOpt SET_USAGE faile" << std::endl;
93 }
94 code = SET_BUFFER_GEOMETRY;
95 int32_t width = 0x100;
96 int32_t height = 0x100;
97 ret = NativeWindowHandleOpt(nativeWindow, code, width, height);
98 if (ret != GSERROR_OK) {
99 std::cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY failed" << std::endl;
100 }
101 code = SET_STRIDE;
102 int32_t stride = 0x8;
103 ret = NativeWindowHandleOpt(nativeWindow, code, stride);
104 if (ret != GSERROR_OK) {
105 std::cout << "NativeWindowHandleOpt SET_STRIDE failed" << std::endl;
106 }
107 code = SET_FORMAT;
108 int32_t format = GRAPHIC_PIXEL_FMT_RGBA_8888;
109 ret = NativeWindowHandleOpt(nativeWindow, code, format);
110 if (ret != GSERROR_OK) {
111 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
112 }
113
114 NativeWindowBuffer* nativeWindowBuffer = nullptr;
115 int fenceFd = -1;
116 ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &nativeWindowBuffer, &fenceFd);
117 if (ret != GSERROR_OK) {
118 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
119 }
120
121 struct Region *region = new Region();
122 struct Region::Rect *rect = new Region::Rect();
123 rect->x = 0x100;
124 rect->y = 0x100;
125 rect->w = 0x100;
126 rect->h = 0x100;
127 region->rects = rect;
128 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, nativeWindowBuffer, fenceFd, *region);
129 if (ret != GSERROR_OK) {
130 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
131 }
132 delete region;
133 }
134
GetData(OH_NativeImage * image,OHNativeWindow * nativeWindow)135 int32_t GetData(OH_NativeImage* image, OHNativeWindow* nativeWindow)
136 {
137 AddBuffer(nativeWindow);
138 int32_t ret = OH_NativeImage_UpdateSurfaceImage(image);
139 if (ret != SURFACE_ERROR_OK) {
140 std::cout << "OH_NativeImage_UpdateSurfaceImage failed" << std::endl;
141 return -1;
142 }
143
144 int64_t timeStamp = OH_NativeImage_GetTimestamp(image);
145 if (timeStamp == SURFACE_ERROR_ERROR) {
146 std::cout << "OH_NativeImage_GetTimestamp failed" << std::endl;
147 return -1;
148 }
149
150 float matrix[16];
151 ret = OH_NativeImage_GetTransformMatrix(image, matrix);
152 if (ret != SURFACE_ERROR_OK) {
153 std::cout << "OH_NativeImage_GetTransformMatrix failed" << std::endl;
154 return -1;
155 }
156 return SURFACE_ERROR_OK;
157 }
158
InitEglContext()159 void InitEglContext()
160 {
161 if (g_eglContext != EGL_NO_DISPLAY) {
162 return;
163 }
164
165 std::cout << "Creating EGLContext!!!" << std::endl;
166 g_eglDisplay = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL);
167 if (g_eglDisplay == EGL_NO_DISPLAY) {
168 std::cout << "Failed to create EGLDisplay gl errno : " << eglGetError() << std::endl;
169 return;
170 }
171
172 EGLint major, minor;
173 if (eglInitialize(g_eglDisplay, &major, &minor) == EGL_FALSE) {
174 std::cout << "Failed to initialize EGLDisplay" << std::endl;
175 return;
176 }
177
178 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
179 std::cout << "Failed to bind OpenGL ES API" << std::endl;
180 return;
181 }
182
183 unsigned int ret;
184 EGLint count;
185 EGLint configAttribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
186 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
187
188 ret = eglChooseConfig(g_eglDisplay, configAttribs, &g_config, 1, &count);
189 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
190 std::cout << "Failed to eglChooseConfig" << std::endl;
191 return;
192 }
193
194 static const EGLint CONTEXT_ATTRIBS[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE };
195
196 g_eglContext = eglCreateContext(g_eglDisplay, g_config, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
197 if (g_eglContext == EGL_NO_CONTEXT) {
198 std::cout << "Failed to create egl context %{public}x, error:" << eglGetError() << std::endl;
199 return;
200 }
201
202 eglMakeCurrent(g_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, g_eglContext);
203
204 std::cout << "Create EGL context successfully, version" << major << "." << minor << std::endl;
205 }
206
Deinit()207 void Deinit()
208 {
209 if (g_eglDisplay == EGL_NO_DISPLAY) {
210 return;
211 }
212 eglDestroyContext(g_eglDisplay, g_eglContext);
213 eglMakeCurrent(g_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
214 eglTerminate(g_eglDisplay);
215 eglReleaseThread();
216
217 g_eglDisplay = EGL_NO_DISPLAY;
218 g_eglContext = EGL_NO_CONTEXT;
219 }
220
221 }
222
main(int32_t argc,const char * argv[])223 int32_t main(int32_t argc, const char *argv[])
224 {
225 std::cout << "sample start" << std::endl;
226 InitEglContext();
227 GLuint textureId;
228 glGenTextures(1, &textureId);
229
230 OH_NativeImage* image = OH_NativeImage_Create(textureId, GL_TEXTURE_2D);
231
232 OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(image);
233 if (nativeWindow == nullptr) {
234 std::cout << "OH_NativeImage_AcquireNativeWindow failed" << std::endl;
235 return -1;
236 }
237
238 int32_t ret = GetData(image, nativeWindow);
239 if (ret != SURFACE_ERROR_OK) {
240 return -1;
241 }
242
243 GLuint textureId2;
244 glGenTextures(1, &textureId2);
245 ret = OH_NativeImage_AttachContext(image, textureId2);
246 if (ret != SURFACE_ERROR_OK) {
247 std::cout << "OH_NativeImage_AttachContext textureId2 failed" << std::endl;
248 return -1;
249 }
250
251 ret = GetData(image, nativeWindow);
252 if (ret != SURFACE_ERROR_OK) {
253 return -1;
254 }
255
256 ret = OH_NativeImage_DetachContext(image);
257 if (ret != SURFACE_ERROR_OK) {
258 std::cout << "OH_NativeImage_DetachContext failed" << std::endl;
259 return -1;
260 }
261
262 ret = OH_NativeImage_AttachContext(image, textureId2);
263 if (ret != SURFACE_ERROR_OK) {
264 std::cout << "OH_NativeImage_AttachContext after OH_NativeImage_DetachContext failed" << std::endl;
265 return -1;
266 }
267
268 ret = GetData(image, nativeWindow);
269 if (ret != SURFACE_ERROR_OK) {
270 return -1;
271 }
272
273 OH_NativeImage_Destroy(&image);
274 if (image != nullptr) {
275 std::cout << "OH_NativeImage_Destroy failed" << std::endl;
276 return -1;
277 }
278
279 Deinit();
280 std::cout << "sample end successfully" << std::endl;
281 return 0;
282 }