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 eglDisplay_ = EGL_NO_DISPLAY;
39 EGLContext eglContext_ = EGL_NO_CONTEXT;
40 EGLConfig 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 * native_display,const EGLint * attrib_list)65 static EGLDisplay GetPlatformEglDisplay(EGLenum platform, void* native_display, const EGLint* attrib_list)
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 = (GetPlatformDisplayExt)eglGetProcAddress(EGL_GET_PLATFORM_DISPLAY_EXT);
75 }
76 }
77
78 if (eglGetPlatformDisplayExt) {
79 return eglGetPlatformDisplayExt(platform, native_display, attrib_list);
80 }
81
82 return eglGetDisplay((EGLNativeDisplayType)native_display);
83 }
84
AddBuffer(OHNativeWindow * nativeWindow)85 void AddBuffer(OHNativeWindow* nativeWindow)
86 {
87 int code = SET_USAGE;
88 int32_t usage = OHOS::BUFFER_USAGE_CPU_READ | OHOS::BUFFER_USAGE_CPU_WRITE | OHOS::BUFFER_USAGE_MEM_DMA;
89 int32_t ret = NativeWindowHandleOpt(nativeWindow, code, usage);
90 if (ret != GSERROR_OK) {
91 std::cout << "NativeWindowHandleOpt SET_USAGE faile" << std::endl;
92 }
93 code = SET_BUFFER_GEOMETRY;
94 int32_t width = 0x100;
95 int32_t height = 0x100;
96 ret = NativeWindowHandleOpt(nativeWindow, code, width, height);
97 if (ret != GSERROR_OK) {
98 std::cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY failed" << std::endl;
99 }
100 code = SET_STRIDE;
101 int32_t stride = 0x8;
102 ret = NativeWindowHandleOpt(nativeWindow, code, stride);
103 if (ret != GSERROR_OK) {
104 std::cout << "NativeWindowHandleOpt SET_STRIDE failed" << std::endl;
105 }
106 code = SET_FORMAT;
107 int32_t format = GRAPHIC_PIXEL_FMT_RGBA_8888;
108 ret = NativeWindowHandleOpt(nativeWindow, code, format);
109 if (ret != GSERROR_OK) {
110 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
111 }
112
113 NativeWindowBuffer* nativeWindowBuffer = nullptr;
114 int fenceFd = -1;
115 ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &nativeWindowBuffer, &fenceFd);
116 if (ret != GSERROR_OK) {
117 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
118 }
119
120 struct Region *region = new Region();
121 struct Region::Rect *rect = new Region::Rect();
122 rect->x = 0x100;
123 rect->y = 0x100;
124 rect->w = 0x100;
125 rect->h = 0x100;
126 region->rects = rect;
127 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, nativeWindowBuffer, fenceFd, *region);
128 if (ret != GSERROR_OK) {
129 std::cout << "NativeWindowHandleOpt SET_FORMAT failed" << std::endl;
130 }
131 delete region;
132 }
133
GetData(OH_NativeImage * image,OHNativeWindow * nativeWindow)134 int32_t GetData(OH_NativeImage* image, OHNativeWindow* nativeWindow)
135 {
136 AddBuffer(nativeWindow);
137 int32_t ret = OH_NativeImage_UpdateSurfaceImage(image);
138 if (ret != SURFACE_ERROR_OK) {
139 std::cout << "OH_NativeImage_UpdateSurfaceImage failed" << std::endl;
140 return -1;
141 }
142
143 int64_t timeStamp = OH_NativeImage_GetTimestamp(image);
144 if (timeStamp == SURFACE_ERROR_ERROR) {
145 std::cout << "OH_NativeImage_GetTimestamp failed" << std::endl;
146 return -1;
147 }
148
149 float matrix[16];
150 ret = OH_NativeImage_GetTransformMatrix(image, matrix);
151 if (ret != SURFACE_ERROR_OK) {
152 std::cout << "OH_NativeImage_GetTransformMatrix failed" << std::endl;
153 return -1;
154 }
155 return SURFACE_ERROR_OK;
156 }
157
InitEglContext()158 void InitEglContext()
159 {
160 if (eglContext_ != EGL_NO_DISPLAY) {
161 return;
162 }
163
164 std::cout << "Creating EGLContext!!!" << std::endl;
165 eglDisplay_ = GetPlatformEglDisplay(EGL_PLATFORM_OHOS_KHR, EGL_DEFAULT_DISPLAY, NULL);
166 if (eglDisplay_ == EGL_NO_DISPLAY) {
167 std::cout << "Failed to create EGLDisplay gl errno : " << eglGetError() << std::endl;
168 return;
169 }
170
171 EGLint major, minor;
172 if (eglInitialize(eglDisplay_, &major, &minor) == EGL_FALSE) {
173 std::cout << "Failed to initialize EGLDisplay" << std::endl;
174 return;
175 }
176
177 if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
178 std::cout << "Failed to bind OpenGL ES API" << std::endl;
179 return;
180 }
181
182 unsigned int ret;
183 EGLint count;
184 EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
185 EGL_ALPHA_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, EGL_NONE };
186
187 ret = eglChooseConfig(eglDisplay_, config_attribs, &config_, 1, &count);
188 if (!(ret && static_cast<unsigned int>(count) >= 1)) {
189 std::cout << "Failed to eglChooseConfig" << std::endl;
190 return;
191 }
192
193 static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, EGL_CONTEXT_CLIENT_VERSION_NUM, EGL_NONE };
194
195 eglContext_ = eglCreateContext(eglDisplay_, config_, EGL_NO_CONTEXT, context_attribs);
196 if (eglContext_ == EGL_NO_CONTEXT) {
197 std::cout << "Failed to create egl context %{public}x, error:" << eglGetError() << std::endl;
198 return;
199 }
200
201 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext_);
202
203 std::cout << "Create EGL context successfully, version" << major << "." << minor << std::endl;
204 }
205
Deinit()206 void Deinit()
207 {
208 if (eglDisplay_ == EGL_NO_DISPLAY) {
209 return;
210 }
211 eglDestroyContext(eglDisplay_, eglContext_);
212 eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
213 eglTerminate(eglDisplay_);
214 eglReleaseThread();
215
216 eglDisplay_ = EGL_NO_DISPLAY;
217 eglContext_ = EGL_NO_CONTEXT;
218 }
219
220 }
221
main(int32_t argc,const char * argv[])222 int32_t main(int32_t argc, const char *argv[])
223 {
224 std::cout << "sample start" << std::endl;
225 InitEglContext();
226 GLuint textureId;
227 glGenTextures(1, &textureId);
228
229 OH_NativeImage* image = OH_NativeImage_Create(textureId, GL_TEXTURE_2D);
230
231 OHNativeWindow* nativeWindow = OH_NativeImage_AcquireNativeWindow(image);
232 if (nativeWindow == nullptr) {
233 std::cout << "OH_NativeImage_AcquireNativeWindow failed" << std::endl;
234 return -1;
235 }
236
237 int32_t ret = GetData(image, nativeWindow);
238 if (ret != SURFACE_ERROR_OK) {
239 return -1;
240 }
241
242 GLuint textureId2;
243 glGenTextures(1, &textureId2);
244 ret = OH_NativeImage_AttachContext(image, textureId2);
245 if (ret != SURFACE_ERROR_OK) {
246 std::cout << "OH_NativeImage_AttachContext textureId2 failed" << std::endl;
247 return -1;
248 }
249
250 ret = GetData(image, nativeWindow);
251 if (ret != SURFACE_ERROR_OK) {
252 return -1;
253 }
254
255 ret = OH_NativeImage_DetachContext(image);
256 if (ret != SURFACE_ERROR_OK) {
257 std::cout << "OH_NativeImage_DetachContext failed" << std::endl;
258 return -1;
259 }
260
261 ret = OH_NativeImage_AttachContext(image, textureId2);
262 if (ret != SURFACE_ERROR_OK) {
263 std::cout << "OH_NativeImage_AttachContext after OH_NativeImage_DetachContext failed" << std::endl;
264 return -1;
265 }
266
267 ret = GetData(image, nativeWindow);
268 if (ret != SURFACE_ERROR_OK) {
269 return -1;
270 }
271
272 OH_NativeImage_Destroy(&image);
273 if (image != nullptr) {
274 std::cout << "OH_NativeImage_Destroy failed" << std::endl;
275 return -1;
276 }
277
278 Deinit();
279 std::cout << "sample end successfully" << std::endl;
280 return 0;
281 }