• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }