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 "egl_wrapper_display.h"
17
18 #include "egl_defs.h"
19 #if USE_IGRAPHICS_EXTENDS_HOOKS
20 #include "egl_wrapper_hook.h"
21 #endif
22 #include "egl_wrapper_context.h"
23 #include "egl_wrapper_surface.h"
24 #include "thread_private_data_ctl.h"
25 #include "wrapper_log.h"
26 #include "egl_blob_cache.h"
27 #include "external_window.h"
28 #include "surface.h"
29 #include "window.h"
30 #include <parameter.h>
31 #include <parameters.h>
32
33 namespace OHOS {
34 static constexpr const char *VENDOR_VALUE = "OpenHarmony";
35 static constexpr const char *VERSION_VALUE_1_4 = "1.4 OpenHarmony EGL";
36 static constexpr const char *VERSION_VALUE_1_5 = "1.5 OpenHarmony EGL";
37 static constexpr const char *CLIENT_API_VALUE = "OpenGL_ES";
38 static constexpr const char *EXTENSION_VALUE =
39 "EGL_KHR_mutable_render_buffer "
40 "EGL_KHR_config_attribs "
41 "EGL_KHR_image_base "
42 "EGL_KHR_gl_colorspace "
43 "EGL_KHR_get_all_proc_addresses "
44 "EGL_KHR_no_config_context "
45 "EGL_IMG_context_priority "
46 "EGL_EXT_pixel_format_float "
47 "EGL_ARM_pixmap_multisample_discard "
48 "EGL_EXT_protected_content "
49 "EGL_ARM_implicit_external_sync "
50 "EGL_KHR_gl_texture_2D_image "
51 "EGL_KHR_gl_renderbuffer_image "
52 "EGL_KHR_create_context "
53 "EGL_KHR_surfaceless_context "
54 "EGL_KHR_gl_texture_cubemap_image "
55 "EGL_EXT_create_context_robustness "
56 "EGL_EXT_image_gl_colorspace "
57 "EGL_EXT_platform_base "
58 "EGL_ANDROID_presentation_time "
59 "EGL_ANDROID_get_native_client_buffer "
60 "EGL_ANDROID_native_fence_sync "
61 "EGL_KHR_partial_update "
62 "EGL_KHR_image "
63 "EGL_KHR_fence_sync "
64 "EGL_KHR_wait_sync "
65 "EGL_EXT_protected_surface "
66 ;
67 static constexpr const char *WIDE_COLOR_AND_HDR_EXTENSIONS =
68 // wide color support
69 "EGL_EXT_gl_colorspace_display_p3_linear "
70 "EGL_EXT_gl_colorspace_display_p3 "
71 "EGL_EXT_gl_colorspace_display_p3_passthrough "
72 // hdr color space support
73 "EGL_EXT_gl_colorspace_bt2020_linear "
74 "EGL_EXT_gl_colorspace_bt2020_hlg "
75 "EGL_EXT_gl_colorspace_bt2020_pq "
76 ;
77
78 // Todo: remove after EGL api upgrade
79 #ifndef EGL_EXT_gl_colorspace_bt2020_hlg
80 #define EGL_EXT_gl_colorspace_bt2020_hlg 1
81 #define EGL_GL_COLORSPACE_BT2020_HLG_EXT 0x3540
82 #endif /* EGL_EXT_gl_colorspace_bt2020_hlg */
83
TranslateEglColorSpaceToNative(EGLint colorspace)84 static OH_NativeBuffer_ColorSpace TranslateEglColorSpaceToNative(EGLint colorspace)
85 {
86 switch (colorspace) {
87 case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
88 return OH_COLORSPACE_LINEAR_P3;
89 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
90 return OH_COLORSPACE_P3_FULL;
91 case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
92 return OH_COLORSPACE_DISPLAY_P3_SRGB;
93 case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
94 return OH_COLORSPACE_LINEAR_BT2020;
95 case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
96 return OH_COLORSPACE_BT2020_PQ_FULL;
97 case EGL_GL_COLORSPACE_BT2020_HLG_EXT:
98 return OH_COLORSPACE_BT2020_HLG_FULL;
99 default:
100 return OH_COLORSPACE_SRGB_FULL;
101 }
102 }
103
ExtractNonColorspaceInfoFromAttribs(const EGLint * attribList)104 static std::vector<EGLint> ExtractNonColorspaceInfoFromAttribs(const EGLint *attribList)
105 {
106 std::vector<EGLint> attribVec {};
107 for (const EGLint* attr = attribList; attr && attr[0] != EGL_NONE; attr += 2) {
108 if (attr[0] == EGL_GL_COLORSPACE_KHR) {
109 continue;
110 }
111 attribVec.push_back(attr[0]); // key
112 attribVec.push_back(attr[1]); // value
113 }
114 attribVec.push_back(EGL_NONE); // end
115 return attribVec;
116 }
117
118 static constexpr const char *SWAP_BUFFER_EXTENSIONS =
119 "EGL_KHR_swap_buffers_with_damage "
120 ;
121
122 EglWrapperDisplay EglWrapperDisplay::wrapperDisp_;
123
EglWrapperDisplay()124 EglWrapperDisplay::EglWrapperDisplay() noexcept : disp_(EGL_NO_DISPLAY), refCnt_(0)
125 {
126 WLOGD("");
127 }
128
~EglWrapperDisplay()129 EglWrapperDisplay::~EglWrapperDisplay()
130 {
131 WLOGD("");
132 }
133
UpdateQueryValue(EGLint * major,EGLint * minor)134 void EglWrapperDisplay::UpdateQueryValue(EGLint *major, EGLint *minor)
135 {
136 if (minor != nullptr && major != nullptr) {
137 // 1 is major version, 5 is minor version.
138 versionValue_ = (*major == 1 && *minor == 5) ? VERSION_VALUE_1_5 : VERSION_VALUE_1_4;
139 }
140 vendorValue_ = VENDOR_VALUE;
141 clientApiValue_ = CLIENT_API_VALUE;
142 extensionValue_ = EXTENSION_VALUE;
143 auto isPartialFlushSupport = system::GetParameter("debug.swap.buffer.with.damage", "1");
144 if (isPartialFlushSupport == "1") {
145 extensionValue_ = std::string(EXTENSION_VALUE) + std::string(SWAP_BUFFER_EXTENSIONS);
146 WLOGI("GetParameter debug.swap.buffer.with.damage 1");
147 } else {
148 WLOGI("GetParameter debug.swap.buffer.with.damage 0");
149 }
150 if (strstr(EXTENSION_VALUE, "EGL_KHR_gl_colorspace") != nullptr) {
151 hasColorSpaceSupport_ = true;
152 }
153 #ifdef USE_VIDEO_PROCESSING_ENGINE
154 hasWideColorAndHdrSupport_ = true;
155 #endif
156 if (hasColorSpaceSupport_ && hasWideColorAndHdrSupport_) {
157 extensionValue_ = extensionValue_ +
158 std::string(EXTENSION_VALUE) + std::string(WIDE_COLOR_AND_HDR_EXTENSIONS);
159 }
160 WLOGI("UpdateQueryValue extensions: %{public}s", extensionValue_.c_str());
161 }
162
Init(EGLint * major,EGLint * minor)163 EGLBoolean EglWrapperDisplay::Init(EGLint *major, EGLint *minor)
164 {
165 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
166 if (refCnt_ > 0) { // wait other thread init.
167 EglWrapperDispatchTablePtr table = &gWrapperHook;
168 if (major != nullptr) {
169 *major = table->major;
170 }
171 if (minor != nullptr) {
172 *minor = table->minor;
173 }
174 refCnt_++;
175 UpdateQueryValue(&table->major, &table->minor);
176 return EGL_TRUE;
177 }
178
179 ThreadPrivateDataCtl::SetGlHookTable(&gGlHookNoContext);
180 EglWrapperDispatchTablePtr table = &gWrapperHook;
181 table->major = -1;
182 table->minor = -1;
183 if (table->isLoad && table->egl.eglInitialize) {
184 if (table->egl.eglInitialize(disp_, &table->major, &table->minor)) {
185 WLOGD("initialized ver=%{public}d.%{public}d", table->major, table->minor);
186 if (major != nullptr) {
187 *major = table->major;
188 }
189 if (minor != nullptr) {
190 *minor = table->minor;
191 }
192 refCnt_++;
193 BlobCache::Get()->Init(this);
194 UpdateQueryValue(&table->major, &table->minor);
195 return EGL_TRUE;
196 } else {
197 WLOGE("eglInitialize Error.");
198 }
199 } else {
200 WLOGE("eglInitialize is invalid.");
201 }
202 return EGL_FALSE;
203 }
204
Terminate()205 EGLBoolean EglWrapperDisplay::Terminate()
206 {
207 WLOGD("");
208 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
209 if (refCnt_ == 0) {
210 WLOGI("display is not Init.");
211 return EGL_TRUE;
212 }
213
214 refCnt_--;
215 if (refCnt_ > 0) {
216 return EGL_TRUE;
217 }
218
219 EglWrapperDispatchTablePtr table = &gWrapperHook;
220 if (table->isLoad) {
221 if (table->egl.eglTerminate) {
222 BlobCache::Get()->Terminate();
223 ClearObjects();
224 return table->egl.eglTerminate(disp_);
225 }
226 }
227
228 WLOGE("eglTerminate is invalid.");
229 return EGL_FALSE;
230 }
231
InternalMakeCurrent(EglWrapperSurface * draw,EglWrapperSurface * read,EglWrapperContext * ctx,bool isAfterHook,EglWrapperContext * curCtx)232 EGLBoolean EglWrapperDisplay::InternalMakeCurrent(
233 EglWrapperSurface *draw, EglWrapperSurface *read, EglWrapperContext *ctx,
234 bool isAfterHook, EglWrapperContext *curCtx)
235 {
236 WLOGD("");
237 EGLContext actualCtx = EGL_NO_CONTEXT;
238 EGLSurface actualDraw = EGL_NO_SURFACE;
239 EGLSurface actualRead = EGL_NO_SURFACE;
240 if (draw != nullptr) {
241 actualDraw = draw->GetEglSurface();
242 }
243
244 if (read != nullptr) {
245 actualRead = read->GetEglSurface();
246 }
247
248 if (ctx != nullptr) {
249 actualCtx = ctx->GetEglContext();
250 }
251
252 EGLBoolean ret = EGL_FALSE;
253 EglWrapperDispatchTablePtr table = &gWrapperHook;
254 if (table->isLoad && table->egl.eglMakeCurrent) {
255 ret = table->egl.eglMakeCurrent(disp_, actualDraw, actualRead, actualCtx);
256 if (ret == EGL_TRUE) {
257 GlHookTable *hookTable = &gGlHookNoContext;
258 if (ctx != nullptr) {
259 hookTable = &gWrapperHook.gl;
260 ctx->SetCurrentSurface(draw, read);
261 }
262 #if USE_IGRAPHICS_EXTENDS_HOOKS
263 ChooseHookTable(isAfterHook, ctx, curCtx, &hookTable);
264 #endif
265 ThreadPrivateDataCtl::SetGlHookTable(hookTable);
266 ThreadPrivateDataCtl::SetContext(ctx);
267 } else {
268 WLOGE("eglMakeCurrent error.");
269 }
270 } else {
271 WLOGE("eglMakeCurrent is invalid.");
272 }
273 return ret;
274 }
275
276 #if USE_IGRAPHICS_EXTENDS_HOOKS
ChooseHookTable(bool isAfterHook,const EglWrapperContext * ctx,const EglWrapperContext * curCtx,GlHookTable ** ppHookTable)277 void EglWrapperDisplay::ChooseHookTable(bool isAfterHook,
278 const EglWrapperContext *ctx, const EglWrapperContext *curCtx,
279 GlHookTable **ppHookTable)
280 {
281 if (ppHookTable == nullptr) {
282 return;
283 }
284
285 if (isAfterHook) {
286 if (ctx == nullptr && curCtx != nullptr) {
287 *ppHookTable = &g_glHookCSDR;
288 }
289 } else {
290 EglWrapperHook& hookLayer(EglWrapperHook::GetInstance());
291 if (hookLayer.IsInit() && hookLayer.gtx.gtxGetSingleThreadStatus()) {
292 *ppHookTable = &g_glHookSingle;
293 }
294 }
295 }
296 #endif
297
MakeCurrent(EGLSurface draw,EGLSurface read,EGLContext ctx)298 EGLBoolean EglWrapperDisplay::MakeCurrent(EGLSurface draw, EGLSurface read, EGLContext ctx)
299 {
300 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
301
302 EglWrapperContext *ctxPtr = nullptr;
303 EglWrapperSurface *surDrawPtr = nullptr;
304 EglWrapperSurface *surReadPtr = nullptr;
305
306 if (ctx != EGL_NO_CONTEXT) {
307 ctxPtr = EglWrapperContext::GetWrapperContext(ctx);
308 if (!CheckObject(ctxPtr)) {
309 WLOGE("EGLContext is invalid.");
310 ThreadPrivateDataCtl::SetError(EGL_BAD_CONTEXT);
311 return EGL_FALSE;
312 }
313 } else {
314 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
315 WLOGE("EGLContext and EGLSurface is bad match.");
316 ThreadPrivateDataCtl::SetError(EGL_BAD_MATCH);
317 return EGL_FALSE;
318 }
319 if (ThreadPrivateDataCtl::GetContext() == EGL_NO_CONTEXT) {
320 WLOGI("There is just no current context. skip");
321 return EGL_TRUE;
322 }
323 }
324
325 if (draw != EGL_NO_SURFACE) {
326 surDrawPtr = EglWrapperSurface::GetWrapperSurface(draw);
327 if (!CheckObject(surDrawPtr)) {
328 WLOGE("EGLSurface is invalid.");
329 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
330 return EGL_FALSE;
331 }
332 }
333
334 if (read != EGL_NO_SURFACE) {
335 surReadPtr = EglWrapperSurface::GetWrapperSurface(read);
336 if (!CheckObject(surReadPtr)) {
337 WLOGE("EGLSurface is invalid.");
338 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
339 return EGL_FALSE;
340 }
341 }
342
343 return InternalMakeCurrent(surDrawPtr, surReadPtr, ctxPtr);
344 }
345
346 #if USE_IGRAPHICS_EXTENDS_HOOKS
MakeCurrentAfterHook(EGLSurface draw,EGLSurface read,EGLContext ctx)347 EGLBoolean EglWrapperDisplay::MakeCurrentAfterHook(EGLSurface draw, EGLSurface read, EGLContext ctx)
348 {
349 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
350
351 EglWrapperContext *ctxPtr = nullptr;
352 EglWrapperSurface *surDrawPtr = nullptr;
353 EglWrapperSurface *surReadPtr = nullptr;
354
355 EGLContext curC = ThreadPrivateDataCtl::GetContext();
356 EglWrapperContext *curCtx = EglWrapperContext::GetWrapperContext(curC);
357
358 if (ctx != EGL_NO_CONTEXT) {
359 ctxPtr = EglWrapperContext::GetWrapperContext(ctx);
360 if (!CheckObject(ctxPtr)) {
361 WLOGE("EGLContext is invalid.");
362 ThreadPrivateDataCtl::SetError(EGL_BAD_CONTEXT);
363 return EGL_FALSE;
364 }
365 } else {
366 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
367 WLOGE("EGLContext and EGLSurface is bad match.");
368 ThreadPrivateDataCtl::SetError(EGL_BAD_MATCH);
369 return EGL_FALSE;
370 }
371 if (ThreadPrivateDataCtl::GetContext() == EGL_NO_CONTEXT) {
372 WLOGI("There is just no current context. skip");
373 return EGL_TRUE;
374 }
375 }
376
377 if (draw != EGL_NO_SURFACE) {
378 surDrawPtr = EglWrapperSurface::GetWrapperSurface(draw);
379 if (!CheckObject(surDrawPtr)) {
380 WLOGE("EGLSurface is invalid.");
381 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
382 return EGL_FALSE;
383 }
384 }
385
386 if (read != EGL_NO_SURFACE) {
387 surReadPtr = EglWrapperSurface::GetWrapperSurface(read);
388 if (!CheckObject(surReadPtr)) {
389 WLOGE("EGLSurface is invalid.");
390 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
391 return EGL_FALSE;
392 }
393 }
394 return InternalMakeCurrent(surDrawPtr, surReadPtr, ctxPtr, true, curCtx);
395 }
396 #endif
397
GetWrapperDisplay(EGLDisplay display)398 EglWrapperDisplay *EglWrapperDisplay::GetWrapperDisplay(EGLDisplay display)
399 {
400 WLOGD("");
401 EglWrapperDisplay *disp = reinterpret_cast<EglWrapperDisplay *>(display);
402 if (disp == &wrapperDisp_) {
403 return disp;
404 }
405 WLOGE("invalid display pointer.");
406 return nullptr;
407 }
408
GetEglNativeDisplay(EGLenum platform,EGLNativeDisplayType disp,const EGLAttrib * attribList)409 EGLDisplay EglWrapperDisplay::GetEglNativeDisplay(EGLenum platform,
410 EGLNativeDisplayType disp, const EGLAttrib *attribList)
411 {
412 WLOGD("");
413 EglWrapperDispatchTablePtr table = &gWrapperHook;
414 if (table->isLoad) {
415 if (table->egl.eglGetPlatformDisplay) {
416 disp_ = table->egl.eglGetPlatformDisplay(platform, disp, attribList);
417 }
418
419 if (disp_ == EGL_NO_DISPLAY) {
420 if (attribList) {
421 WLOGW("attribList ignored.");
422 }
423
424 if (table->egl.eglGetDisplay) {
425 disp_ = table->egl.eglGetDisplay(disp);
426 } else {
427 WLOGE("eglGetDisplay is invalid.");
428 }
429 }
430 } else {
431 WLOGE("EglWrapperDispatchTable is not load.");
432 }
433
434 WLOGD("");
435
436 return (disp_ == EGL_NO_DISPLAY) ? disp_ : (EGLDisplay)&wrapperDisp_;
437 }
438
GetEglNativeDisplayExt(EGLenum platform,void * disp,const EGLint * attribList)439 EGLDisplay EglWrapperDisplay::GetEglNativeDisplayExt(EGLenum platform,
440 void *disp, const EGLint *attribList)
441 {
442 WLOGD("");
443 EglWrapperDispatchTablePtr table = &gWrapperHook;
444 if (table->isLoad && table->egl.eglGetPlatformDisplayEXT) {
445 disp_ = table->egl.eglGetPlatformDisplayEXT(platform, disp, attribList);
446 } else {
447 WLOGE("eglGetPlatformDisplayEXT is invalid.");
448 }
449
450 return (disp_ == EGL_NO_DISPLAY) ? disp_ : (EGLDisplay)&wrapperDisp_;
451 }
452
GetEglDisplay(EGLenum platform,EGLNativeDisplayType disp,const EGLAttrib * attribList)453 EGLDisplay EglWrapperDisplay::GetEglDisplay(EGLenum platform,
454 EGLNativeDisplayType disp, const EGLAttrib *attribList)
455 {
456 WLOGD("");
457 return wrapperDisp_.GetEglNativeDisplay(platform, disp, attribList);
458 }
459
GetEglDisplayExt(EGLenum platform,void * disp,const EGLint * attribList)460 EGLDisplay EglWrapperDisplay::GetEglDisplayExt(EGLenum platform,
461 void *disp, const EGLint *attribList)
462 {
463 return wrapperDisp_.GetEglNativeDisplayExt(platform, disp, attribList);
464 }
465
ValidateEglContext(EGLContext ctx)466 bool EglWrapperDisplay::ValidateEglContext(EGLContext ctx)
467 {
468 WLOGD("");
469 return false;
470 }
471
ValidateEglSurface(EGLSurface surf)472 bool EglWrapperDisplay::ValidateEglSurface(EGLSurface surf)
473 {
474 WLOGD("");
475 return false;
476 }
477
478 #if USE_IGRAPHICS_EXTENDS_HOOKS
ChooseGlesVersion(const EGLint * attribList)479 int EglWrapperDisplay::ChooseGlesVersion(const EGLint *attribList)
480 {
481 int version = EglWrapperDispatchTable::GLESV1_INDEX;
482 if (attribList) {
483 while (*attribList != EGL_NONE) {
484 GLint attr = *attribList++;
485 GLint value = *attribList++;
486 if (attr == EGL_CONTEXT_CLIENT_VERSION && (value == 2 || value == 3)) { // 2:version 3:version
487 version = EglWrapperDispatchTable::GLESV2_INDEX;
488 }
489 }
490 }
491 return version;
492 }
493 #endif
494
CreateEglContext(EGLConfig config,EGLContext shareList,const EGLint * attribList)495 EGLContext EglWrapperDisplay::CreateEglContext(EGLConfig config, EGLContext shareList, const EGLint *attribList)
496 {
497 WLOGD("");
498 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
499
500 EGLContext shareCtx = EGL_NO_CONTEXT;
501 if (shareList != EGL_NO_CONTEXT) {
502 EglWrapperContext *ctxPtr = EglWrapperContext::GetWrapperContext(shareList);
503 if (!CheckObject(ctxPtr)) {
504 WLOGE("EGLContext is invalid.");
505 ThreadPrivateDataCtl::SetError(EGL_BAD_CONTEXT);
506 return EGL_NO_CONTEXT;
507 }
508 shareCtx = ctxPtr->GetEglContext();
509 }
510
511 EglWrapperDispatchTablePtr table = &gWrapperHook;
512 if (table->isLoad && table->egl.eglCreateContext) {
513 EGLContext context = table->egl.eglCreateContext(disp_, config, shareCtx, attribList);
514 if (context != EGL_NO_CONTEXT) {
515 #if USE_IGRAPHICS_EXTENDS_HOOKS
516 return new EglWrapperContext(this, context, ChooseGlesVersion(attribList));
517 #else
518 return new EglWrapperContext(this, context);
519 #endif
520 } else {
521 WLOGE("egl.eglCreateContext error.");
522 }
523 } else {
524 WLOGE("eglCreateContext is invalid.");
525 }
526
527 return EGL_NO_CONTEXT;
528 }
529
DestroyEglContext(EGLContext context)530 EGLBoolean EglWrapperDisplay::DestroyEglContext(EGLContext context)
531 {
532 WLOGD("");
533 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
534
535 EglWrapperContext *ctxPtr = EglWrapperContext::GetWrapperContext(context);
536 if (!CheckObject(ctxPtr)) {
537 WLOGE("EGLContext is invalid.");
538 ThreadPrivateDataCtl::SetError(EGL_BAD_CONTEXT);
539 return EGL_FALSE;
540 }
541 EGLContext ctx = ctxPtr->GetEglContext();
542
543 EGLBoolean ret = EGL_FALSE;
544 EglWrapperDispatchTablePtr table = &gWrapperHook;
545 if (table->isLoad && table->egl.eglDestroyContext) {
546 ret = table->egl.eglDestroyContext(disp_, ctx);
547 if (ret == EGL_TRUE) {
548 ctxPtr->Destroy();
549 } else {
550 WLOGE("eglDestroyContext error.");
551 }
552 } else {
553 WLOGE("eglDestroyContext is invalid.");
554 }
555
556 return ret;
557 }
558
559 // Get the colorspace value that should be reported from queries.
560 // When the colorspace is unknown (no attribute passed), default to reporting LINEAR.
GetReportedColorSpace(EGLint colorSpace)561 static EGLint GetReportedColorSpace(EGLint colorSpace)
562 {
563 return colorSpace == EGL_UNKNOWN ? EGL_GL_COLORSPACE_LINEAR_KHR : colorSpace;
564 }
565
CreateEglSurface(EGLConfig config,NativeWindowType window,const EGLint * attribList)566 EGLSurface EglWrapperDisplay::CreateEglSurface(EGLConfig config,
567 NativeWindowType window, const EGLint *attribList)
568 {
569 WLOGD("");
570 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
571
572 if (!window) {
573 WLOGE("NativeWindowType window is invalid.");
574 ThreadPrivateDataCtl::SetError(EGL_BAD_NATIVE_WINDOW);
575 return EGL_NO_SURFACE;
576 }
577
578 // select correct colorspace and dataspace based on user's attribute list.
579 EGLint colorSpace = EGL_UNKNOWN;
580 EGLSurface surf = EGL_NO_SURFACE;
581 bool requestWideColor = false;
582 auto nativeWindow = static_cast<OHNativeWindow*>(window);
583 for (const EGLint* attr = attribList; attr && attr[0] != EGL_NONE; attr += 2) {
584 if (attr[0] == EGL_GL_COLORSPACE_KHR &&
585 (attr[1] == EGL_GL_COLORSPACE_LINEAR_KHR || attr[1] == EGL_GL_COLORSPACE_SRGB_KHR)) {
586 colorSpace = static_cast<EGLint>(attr[1]);
587 }
588 if (attr[0] == EGL_GL_COLORSPACE_KHR && attr[1] != EGL_GL_COLORSPACE_LINEAR_KHR) {
589 requestWideColor = true;
590 colorSpace = attr[1];
591 WLOGI("attrib colorspace: %{public}d", colorSpace);
592 }
593 }
594
595 EglWrapperDispatchTablePtr table = &gWrapperHook;
596 if (table->isLoad && table->egl.eglCreateWindowSurface) {
597 WLOGI("CreateEglSurface hasColorSpaceSupport_: %{public}d,"
598 "hasWideColorAndHdrSupport_ %{public}d , requestWideColor %{public}d",
599 hasColorSpaceSupport_, hasWideColorAndHdrSupport_, requestWideColor);
600 if (hasColorSpaceSupport_ && hasWideColorAndHdrSupport_ && requestWideColor) {
601 OH_NativeWindow_SetColorSpace(nativeWindow, TranslateEglColorSpaceToNative(colorSpace));
602 std::vector<EGLint> attribVec = ExtractNonColorspaceInfoFromAttribs(attribList);
603 surf = table->egl.eglCreateWindowSurface(disp_, config, window, attribVec.data());
604 } else {
605 surf = table->egl.eglCreateWindowSurface(disp_, config, window, attribList);
606 }
607 if (surf != EGL_NO_SURFACE) {
608 return new EglWrapperSurface(this, surf, window, GetReportedColorSpace(colorSpace));
609 } else {
610 WLOGE("egl.eglCreateWindowSurface error.");
611 }
612 } else {
613 WLOGE("eglCreateWindowSurface is invalid.");
614 }
615
616 return EGL_NO_SURFACE;
617 }
618
DestroyEglSurface(EGLSurface surf)619 EGLBoolean EglWrapperDisplay::DestroyEglSurface(EGLSurface surf)
620 {
621 WLOGD("");
622 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
623
624 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
625 if (!CheckObject(surfPtr)) {
626 WLOGE("EGLSurface is invalid.");
627 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
628 return EGL_FALSE;
629 }
630 EGLSurface sur = surfPtr->GetEglSurface();
631
632 EGLBoolean ret = EGL_FALSE;
633 EglWrapperDispatchTablePtr table = &gWrapperHook;
634 if (table->isLoad && table->egl.eglDestroySurface) {
635 ret = table->egl.eglDestroySurface(disp_, sur);
636 if (ret == EGL_TRUE) {
637 surfPtr->Destroy();
638 } else {
639 WLOGE("eglDestroySurface error.");
640 }
641 } else {
642 WLOGE("eglDestroySurface is invalid.");
643 }
644
645 return ret;
646 }
647
AddObject(EglWrapperObject * obj)648 void EglWrapperDisplay::AddObject(EglWrapperObject *obj)
649 {
650 std::lock_guard<std::mutex> lock(lockMutex_);
651 objects_.insert(obj);
652 }
653
RemoveObject(EglWrapperObject * obj)654 void EglWrapperDisplay::RemoveObject(EglWrapperObject *obj)
655 {
656 std::lock_guard<std::mutex> lock(lockMutex_);
657 objects_.erase(obj);
658 }
659
ClearObjects()660 void EglWrapperDisplay::ClearObjects()
661 {
662 std::lock_guard<std::mutex> lock(lockMutex_);
663 for (auto obj : objects_) {
664 obj->Release();
665 }
666 objects_.clear();
667 }
668
CheckObject(EglWrapperObject * obj)669 bool EglWrapperDisplay::CheckObject(EglWrapperObject *obj)
670 {
671 if (obj == nullptr) {
672 return false;
673 }
674 std::lock_guard<std::mutex> lock(lockMutex_);
675 if (objects_.find(obj) != objects_.end()) {
676 if (obj->GetDisplay() == this) {
677 return true;
678 }
679 }
680 return false;
681 }
682
CopyBuffers(EGLSurface surf,NativePixmapType target)683 EGLBoolean EglWrapperDisplay::CopyBuffers(EGLSurface surf, NativePixmapType target)
684 {
685 WLOGD("");
686 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
687
688 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
689 if (!CheckObject(surfPtr)) {
690 WLOGE("EGLSurface is invalid.");
691 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
692 return EGL_FALSE;
693 }
694
695 EGLBoolean ret = EGL_FALSE;
696 EglWrapperDispatchTablePtr table = &gWrapperHook;
697 if (table->isLoad && table->egl.eglCopyBuffers) {
698 ret = table->egl.eglCopyBuffers(disp_, surfPtr->GetEglSurface(), target);
699 } else {
700 WLOGE("eglCopyBuffers is invalid.");
701 }
702
703 return ret;
704 }
705
CreatePbufferSurface(EGLConfig config,const EGLint * attribList)706 EGLSurface EglWrapperDisplay::CreatePbufferSurface(EGLConfig config, const EGLint *attribList)
707 {
708 WLOGD("");
709 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
710
711 EglWrapperDispatchTablePtr table = &gWrapperHook;
712 if (table->isLoad && table->egl.eglCreatePbufferSurface) {
713 EGLSurface surf = table->egl.eglCreatePbufferSurface(disp_, config, attribList);
714 if (surf != EGL_NO_SURFACE) {
715 return new EglWrapperSurface(this, surf);
716 } else {
717 WLOGE("egl.eglCreatePbufferSurface error.");
718 }
719 } else {
720 WLOGE("eglCreatePbufferSurface is invalid.");
721 }
722
723 return EGL_NO_SURFACE;
724 }
725
CreatePixmapSurface(EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attribList)726 EGLSurface EglWrapperDisplay::CreatePixmapSurface(EGLConfig config,
727 EGLNativePixmapType pixmap, const EGLint* attribList)
728 {
729 WLOGD("");
730 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
731
732 EglWrapperDispatchTablePtr table = &gWrapperHook;
733 if (table->isLoad && table->egl.eglCreatePixmapSurface) {
734 EGLSurface surf = table->egl.eglCreatePixmapSurface(disp_, config, pixmap, attribList);
735 if (surf != EGL_NO_SURFACE) {
736 return new EglWrapperSurface(this, surf);
737 } else {
738 WLOGE("egl.eglCreatePixmapSurface error.");
739 }
740 } else {
741 WLOGE("eglCreatePixmapSurface is invalid.");
742 }
743
744 return EGL_NO_SURFACE;
745 }
746
QueryContext(EGLContext ctx,EGLint attribute,EGLint * value)747 EGLBoolean EglWrapperDisplay::QueryContext(EGLContext ctx, EGLint attribute, EGLint *value)
748 {
749 WLOGD("");
750 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
751
752 EglWrapperContext *ctxPtr = EglWrapperContext::GetWrapperContext(ctx);
753 if (!CheckObject(ctxPtr)) {
754 WLOGE("EGLContext is invalid.");
755 ThreadPrivateDataCtl::SetError(EGL_BAD_CONTEXT);
756 return EGL_FALSE;
757 }
758
759 EGLBoolean ret = EGL_FALSE;
760 EglWrapperDispatchTablePtr table = &gWrapperHook;
761 if (table->isLoad && table->egl.eglQueryContext) {
762 ret = table->egl.eglQueryContext(disp_,
763 ctxPtr->GetEglContext(), attribute, value);
764 } else {
765 WLOGE("eglQueryContext is invalid.");
766 }
767
768 return ret;
769 }
770
QuerySurface(EGLSurface surf,EGLint attribute,EGLint * value)771 EGLBoolean EglWrapperDisplay::QuerySurface(EGLSurface surf, EGLint attribute, EGLint *value)
772 {
773 WLOGD("");
774 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
775
776 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
777 if (!CheckObject(surfPtr)) {
778 WLOGE("EGLSurface is invalid.");
779 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
780 return EGL_FALSE;
781 }
782
783 if (surfPtr->GetColorSpaceAttribute(attribute, value)) {
784 return EGL_TRUE;
785 }
786
787 EGLBoolean ret = EGL_FALSE;
788 EglWrapperDispatchTablePtr table = &gWrapperHook;
789 if (table->isLoad && table->egl.eglQuerySurface) {
790 ret = table->egl.eglQuerySurface(disp_,
791 surfPtr->GetEglSurface(), attribute, value);
792 } else {
793 WLOGE("eglQuerySurface is invalid.");
794 }
795
796 return ret;
797 }
798
SwapBuffers(EGLSurface surf)799 EGLBoolean EglWrapperDisplay::SwapBuffers(EGLSurface surf)
800 {
801 WLOGD("");
802 EglWrapperSurface *surfPtr = nullptr;
803 {
804 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
805 surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
806 if (!CheckObject(surfPtr)) {
807 WLOGE("EGLSurface is invalid.");
808 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
809 return EGL_FALSE;
810 }
811 }
812
813 EGLBoolean ret = EGL_FALSE;
814 EglWrapperDispatchTablePtr table = &gWrapperHook;
815 if (table->isLoad && table->egl.eglSwapBuffers) {
816 ret = table->egl.eglSwapBuffers(disp_, surfPtr->GetEglSurface());
817 } else {
818 WLOGE("eglSwapBuffers is invalid.");
819 }
820
821 return ret;
822 }
823
BindTexImage(EGLSurface surf,EGLint buffer)824 EGLBoolean EglWrapperDisplay::BindTexImage(EGLSurface surf, EGLint buffer)
825 {
826 WLOGD("");
827 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
828
829 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
830 if (!CheckObject(surfPtr)) {
831 WLOGE("EGLSurface is invalid.");
832 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
833 return EGL_FALSE;
834 }
835
836 EGLBoolean ret = EGL_FALSE;
837 EglWrapperDispatchTablePtr table = &gWrapperHook;
838 if (table->isLoad && table->egl.eglBindTexImage) {
839 ret = table->egl.eglBindTexImage(disp_, surfPtr->GetEglSurface(), buffer);
840 } else {
841 WLOGE("eglBindTexImage is invalid.");
842 }
843
844 return ret;
845 }
846
ReleaseTexImage(EGLSurface surf,EGLint buffer)847 EGLBoolean EglWrapperDisplay::ReleaseTexImage(EGLSurface surf, EGLint buffer)
848 {
849 WLOGD("");
850 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
851
852 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
853 if (!CheckObject(surfPtr)) {
854 WLOGE("EGLSurface is invalid.");
855 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
856 return EGL_FALSE;
857 }
858
859 EGLBoolean ret = EGL_FALSE;
860 EglWrapperDispatchTablePtr table = &gWrapperHook;
861 if (table->isLoad && table->egl.eglReleaseTexImage) {
862 ret = table->egl.eglReleaseTexImage(disp_, surfPtr->GetEglSurface(), buffer);
863 } else {
864 WLOGE("eglReleaseTexImage is invalid.");
865 }
866
867 return ret;
868 }
869
SurfaceAttrib(EGLSurface surf,EGLint attribute,EGLint value)870 EGLBoolean EglWrapperDisplay::SurfaceAttrib(EGLSurface surf, EGLint attribute, EGLint value)
871 {
872 WLOGD("");
873 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
874
875 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
876 if (!CheckObject(surfPtr)) {
877 WLOGE("EGLSurface is invalid.");
878 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
879 return EGL_FALSE;
880 }
881
882 EGLBoolean ret = EGL_FALSE;
883 EglWrapperDispatchTablePtr table = &gWrapperHook;
884 if (table->isLoad && table->egl.eglSurfaceAttrib) {
885 ret = table->egl.eglSurfaceAttrib(disp_,
886 surfPtr->GetEglSurface(), attribute, value);
887 } else {
888 WLOGE("eglSurfaceAttrib is invalid.");
889 }
890
891 return ret;
892 }
893
CreatePbufferFromClientBuffer(EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attribList)894 EGLSurface EglWrapperDisplay::CreatePbufferFromClientBuffer(
895 EGLenum buftype, EGLClientBuffer buffer,
896 EGLConfig config, const EGLint *attribList)
897 {
898 WLOGD("");
899 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
900
901 EglWrapperDispatchTablePtr table = &gWrapperHook;
902 if (table->isLoad && table->egl.eglCreatePbufferFromClientBuffer) {
903 EGLSurface surf = table->egl.eglCreatePbufferFromClientBuffer(
904 disp_, buftype, buffer, config, attribList);
905 if (surf != EGL_NO_SURFACE) {
906 return new EglWrapperSurface(this, surf);
907 } else {
908 WLOGE("egl.eglCreatePbufferFromClientBuffer error.");
909 }
910 } else {
911 WLOGE("eglCreatePbufferFromClientBuffer is invalid.");
912 }
913
914 return EGL_NO_SURFACE;
915 }
916
CreateImage(EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attribList)917 EGLImage EglWrapperDisplay::CreateImage(EGLContext ctx, EGLenum target,
918 EGLClientBuffer buffer, const EGLAttrib *attribList)
919 {
920 WLOGD("");
921 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
922
923 EGLContext actualCtx = EGL_NO_CONTEXT;
924 if (ctx != EGL_NO_CONTEXT) {
925 EglWrapperContext *ctxPtr = EglWrapperContext::GetWrapperContext(ctx);
926 if (CheckObject(ctxPtr)) {
927 actualCtx = ctxPtr->GetEglContext();
928 }
929 }
930
931 EglWrapperDispatchTablePtr table = &gWrapperHook;
932 if (table->isLoad && table->egl.eglCreateImage) {
933 return table->egl.eglCreateImage(disp_, actualCtx, target, buffer, attribList);
934 } else {
935 WLOGE("eglCreateImage is invalid.");
936 }
937
938 return EGL_NO_IMAGE_KHR;
939 }
940
DestroyImage(EGLImage img)941 EGLBoolean EglWrapperDisplay::DestroyImage(EGLImage img)
942 {
943 WLOGD("");
944 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
945
946 EGLBoolean ret = EGL_FALSE;
947 EglWrapperDispatchTablePtr table = &gWrapperHook;
948 if (table->isLoad && table->egl.eglDestroyImage) {
949 ret = table->egl.eglDestroyImage(disp_, img);
950 } else {
951 WLOGE("eglDestroyImage is invalid.");
952 }
953
954 return ret;
955 }
956
CreatePlatformWindowSurface(EGLConfig config,void * nativeWindow,const EGLAttrib * attribList)957 EGLSurface EglWrapperDisplay::CreatePlatformWindowSurface(EGLConfig config,
958 void *nativeWindow, const EGLAttrib *attribList)
959 {
960 WLOGD("");
961 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
962
963 if (!nativeWindow) {
964 WLOGE("nativeWindow is invalid.");
965 ThreadPrivateDataCtl::SetError(EGL_BAD_NATIVE_WINDOW);
966 return EGL_NO_SURFACE;
967 }
968
969 EglWrapperDispatchTablePtr table = &gWrapperHook;
970 if (table->isLoad && table->egl.eglCreatePlatformWindowSurface) {
971 EGLSurface surf = table->egl.eglCreatePlatformWindowSurface(disp_,
972 config, nativeWindow, attribList);
973 if (surf != EGL_NO_SURFACE) {
974 return new EglWrapperSurface(this, surf);
975 } else {
976 WLOGE("egl.eglCreatePlatformWindowSurface error.");
977 }
978 } else {
979 WLOGE("eglCreatePlatformWindowSurface is invalid.");
980 }
981
982 return EGL_NO_SURFACE;
983 }
984
CreatePlatformPixmapSurface(EGLConfig config,void * nativePixmap,const EGLAttrib * attribList)985 EGLSurface EglWrapperDisplay::CreatePlatformPixmapSurface(EGLConfig config,
986 void *nativePixmap, const EGLAttrib *attribList)
987 {
988 WLOGD("");
989 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
990
991 if (!nativePixmap) {
992 WLOGE("nativePixmap is invalid.");
993 ThreadPrivateDataCtl::SetError(EGL_BAD_NATIVE_WINDOW);
994 return EGL_NO_SURFACE;
995 }
996
997 EglWrapperDispatchTablePtr table = &gWrapperHook;
998 if (table->isLoad && table->egl.eglCreatePlatformPixmapSurface) {
999 EGLSurface surf = table->egl.eglCreatePlatformPixmapSurface(disp_,
1000 config, nativePixmap, attribList);
1001 if (surf != EGL_NO_SURFACE) {
1002 return new EglWrapperSurface(this, surf);
1003 } else {
1004 WLOGE("egl.eglCreatePlatformPixmapSurface error.");
1005 }
1006 } else {
1007 WLOGE("eglCreatePlatformPixmapSurface is invalid.");
1008 }
1009
1010 return EGL_NO_SURFACE;
1011 }
1012
LockSurfaceKHR(EGLSurface surf,const EGLint * attribList)1013 EGLBoolean EglWrapperDisplay::LockSurfaceKHR(EGLSurface surf, const EGLint *attribList)
1014 {
1015 WLOGD("");
1016 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1017
1018 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
1019 if (!CheckObject(surfPtr)) {
1020 WLOGE("EGLSurface is invalid.");
1021 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1022 return EGL_FALSE;
1023 }
1024
1025 EGLBoolean ret = EGL_FALSE;
1026 EglWrapperDispatchTablePtr table = &gWrapperHook;
1027 if (table->isLoad && table->egl.eglLockSurfaceKHR) {
1028 ret = table->egl.eglLockSurfaceKHR(disp_,
1029 surfPtr->GetEglSurface(), attribList);
1030 } else {
1031 WLOGE("eglLockSurfaceKHR is invalid.");
1032 }
1033
1034 return ret;
1035 }
1036
UnlockSurfaceKHR(EGLSurface surf)1037 EGLBoolean EglWrapperDisplay::UnlockSurfaceKHR(EGLSurface surf)
1038 {
1039 WLOGD("");
1040 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1041
1042 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
1043 if (!CheckObject(surfPtr)) {
1044 WLOGE("EGLSurface is invalid.");
1045 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1046 return EGL_FALSE;
1047 }
1048
1049 EGLBoolean ret = EGL_FALSE;
1050 EglWrapperDispatchTablePtr table = &gWrapperHook;
1051 if (table->isLoad && table->egl.eglUnlockSurfaceKHR) {
1052 ret = table->egl.eglUnlockSurfaceKHR(disp_, surfPtr->GetEglSurface());
1053 } else {
1054 WLOGE("eglUnlockSurfaceKHR is invalid.");
1055 }
1056
1057 return ret;
1058 }
1059
CreateImageKHR(EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attribList)1060 EGLImageKHR EglWrapperDisplay::CreateImageKHR(EGLContext ctx, EGLenum target,
1061 EGLClientBuffer buffer, const EGLint *attribList)
1062 {
1063 WLOGD("");
1064 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1065
1066 EGLContext actualCtx = EGL_NO_CONTEXT;
1067 if (ctx != EGL_NO_CONTEXT) {
1068 EglWrapperContext *ctxPtr = EglWrapperContext::GetWrapperContext(ctx);
1069 if (CheckObject(ctxPtr)) {
1070 actualCtx = ctxPtr->GetEglContext();
1071 }
1072 }
1073
1074 EglWrapperDispatchTablePtr table = &gWrapperHook;
1075 if (table->isLoad && table->egl.eglCreateImageKHR) {
1076 return table->egl.eglCreateImageKHR(disp_, actualCtx, target, buffer, attribList);
1077 } else {
1078 WLOGE("eglCreateImageKHR is invalid.");
1079 }
1080
1081 return EGL_NO_IMAGE_KHR;
1082 }
1083
DestroyImageKHR(EGLImageKHR img)1084 EGLBoolean EglWrapperDisplay::DestroyImageKHR(EGLImageKHR img)
1085 {
1086 WLOGD("");
1087 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1088
1089 EGLBoolean ret = EGL_FALSE;
1090 EglWrapperDispatchTablePtr table = &gWrapperHook;
1091 if (table->isLoad && table->egl.eglDestroyImageKHR) {
1092 ret = table->egl.eglDestroyImageKHR(disp_, img);
1093 } else {
1094 WLOGE("eglDestroyImageKHR is invalid.");
1095 }
1096
1097 return ret;
1098 }
1099
CreateStreamProducerSurfaceKHR(EGLConfig config,EGLStreamKHR stream,const EGLint * attribList)1100 EGLSurface EglWrapperDisplay::CreateStreamProducerSurfaceKHR(EGLConfig config,
1101 EGLStreamKHR stream, const EGLint *attribList)
1102 {
1103 WLOGD("");
1104 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1105
1106 EglWrapperDispatchTablePtr table = &gWrapperHook;
1107 if (table->isLoad && table->egl.eglCreateStreamProducerSurfaceKHR) {
1108 EGLSurface surf = table->egl.eglCreateStreamProducerSurfaceKHR(
1109 disp_, config, stream, attribList);
1110 if (surf != EGL_NO_SURFACE) {
1111 return new EglWrapperSurface(this, surf);
1112 } else {
1113 WLOGE("egl.eglCreateStreamProducerSurfaceKHR error.");
1114 }
1115 } else {
1116 WLOGE("eglCreateStreamProducerSurfaceKHR is invalid.");
1117 }
1118
1119 return EGL_NO_SURFACE;
1120 }
1121
SwapBuffersWithDamageKHR(EGLSurface draw,EGLint * rects,EGLint nRects)1122 EGLBoolean EglWrapperDisplay::SwapBuffersWithDamageKHR(EGLSurface draw, EGLint *rects, EGLint nRects)
1123 {
1124 WLOGD("");
1125 EglWrapperSurface *surfacePtr = nullptr;
1126 {
1127 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1128 surfacePtr = EglWrapperSurface::GetWrapperSurface(draw);
1129 if (!CheckObject(surfacePtr)) {
1130 WLOGE("EGLSurface is invalid.");
1131 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1132 return EGL_FALSE;
1133 }
1134
1135 if (nRects < 0 || (nRects > 0 && rects == NULL)) {
1136 WLOGE("Parameter error.");
1137 ThreadPrivateDataCtl::SetError(EGL_BAD_PARAMETER);
1138 return EGL_FALSE;
1139 }
1140 }
1141 EGLBoolean ret = EGL_FALSE;
1142 EglWrapperDispatchTablePtr table = &gWrapperHook;
1143 if (table->isLoad && table->egl.eglSwapBuffersWithDamageKHR) {
1144 ret = table->egl.eglSwapBuffersWithDamageKHR(
1145 disp_, surfacePtr->GetEglSurface(), rects, nRects);
1146 } else {
1147 WLOGE("eglSwapBuffersWithDamageKHR is invalid.");
1148 }
1149
1150 return ret;
1151 }
1152
SetDamageRegionKHR(EGLSurface surf,EGLint * rects,EGLint nRects)1153 EGLBoolean EglWrapperDisplay::SetDamageRegionKHR(EGLSurface surf, EGLint *rects, EGLint nRects)
1154 {
1155 WLOGD("");
1156 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1157
1158 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surf);
1159 if (!CheckObject(surfPtr)) {
1160 WLOGE("EGLSurface is invalid.");
1161 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1162 return EGL_FALSE;
1163 }
1164
1165 if (nRects < 0 || (nRects > 0 && rects == nullptr)) {
1166 WLOGE("Parameter error.");
1167 ThreadPrivateDataCtl::SetError(EGL_BAD_PARAMETER);
1168 return EGL_FALSE;
1169 }
1170
1171 EGLBoolean ret = EGL_FALSE;
1172 EglWrapperDispatchTablePtr table = &gWrapperHook;
1173 if (table->isLoad && table->egl.eglSetDamageRegionKHR) {
1174 ret = table->egl.eglSetDamageRegionKHR(
1175 disp_, surfPtr->GetEglSurface(), rects, nRects);
1176 } else {
1177 WLOGE("eglSetDamageRegionKHR is invalid.");
1178 }
1179
1180 return ret;
1181 }
1182
GetCompositorTimingSupportedANDROID(EGLSurface surface,EGLint name)1183 EGLBoolean EglWrapperDisplay::GetCompositorTimingSupportedANDROID(EGLSurface surface, EGLint name)
1184 {
1185 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1186
1187 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surface);
1188 if (!CheckObject(surfPtr)) {
1189 WLOGE("EGLSurface is invalid.");
1190 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1191 return EGL_FALSE;
1192 }
1193
1194 if (surfPtr->GetNativeWindow() == nullptr) {
1195 WLOGE("GetCompositorTimingSupportedANDROID native window is nullptr.");
1196 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1197 return EGL_FALSE;
1198 }
1199
1200 switch (name) {
1201 case EGL_COMPOSITE_DEADLINE_ANDROID:
1202 case EGL_COMPOSITE_INTERVAL_ANDROID:
1203 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
1204 return EGL_TRUE;
1205 default:
1206 return EGL_FALSE;
1207 }
1208 }
1209
GetFrameTimestampSupportedANDROID(EGLSurface surface,EGLint timestamp)1210 EGLBoolean EglWrapperDisplay::GetFrameTimestampSupportedANDROID(EGLSurface surface, EGLint timestamp)
1211 {
1212 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1213
1214 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surface);
1215 if (!CheckObject(surfPtr)) {
1216 WLOGE("EGLSurface is invalid.");
1217 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1218 return EGL_FALSE;
1219 }
1220
1221 if (surfPtr->GetNativeWindow() == nullptr) {
1222 WLOGE("GetFrameTimestampSupportedANDROID native window is nullptr.");
1223 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1224 return EGL_FALSE;
1225 }
1226 switch (timestamp) {
1227 case EGL_COMPOSITE_DEADLINE_ANDROID:
1228 case EGL_COMPOSITE_INTERVAL_ANDROID:
1229 case EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID:
1230 case EGL_REQUESTED_PRESENT_TIME_ANDROID:
1231 case EGL_RENDERING_COMPLETE_TIME_ANDROID:
1232 case EGL_COMPOSITION_LATCH_TIME_ANDROID:
1233 case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
1234 case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
1235 case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
1236 case EGL_DEQUEUE_READY_TIME_ANDROID:
1237 case EGL_READS_DONE_TIME_ANDROID:
1238 return EGL_TRUE;
1239 default:
1240 return EGL_FALSE;
1241 }
1242 }
1243
PresentationTimeANDROID(EGLSurface surface,EGLnsecsANDROID time)1244 EGLBoolean EglWrapperDisplay::PresentationTimeANDROID(EGLSurface surface, EGLnsecsANDROID time)
1245 {
1246 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1247
1248 EglWrapperSurface *surfPtr = EglWrapperSurface::GetWrapperSurface(surface);
1249 if (!CheckObject(surfPtr)) {
1250 WLOGE("EGLSurface is invalid.");
1251 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1252 return EGL_FALSE;
1253 }
1254 if (surfPtr->GetNativeWindow() == nullptr) {
1255 WLOGE("PresentationTimeANDROID native window is nullptr.");
1256 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1257 return EGL_FALSE;
1258 }
1259
1260 if (NativeWindowHandleOpt(reinterpret_cast<OHNativeWindow*>(surfPtr->GetNativeWindow()),
1261 SET_UI_TIMESTAMP, time) != 0) {
1262 WLOGE("NativeWindowHandleOpt SET_UI_TIMESTAMP failed.");
1263 return EGL_FALSE;
1264 }
1265 return EGL_TRUE;
1266 }
1267
CreatePlatformWindowSurfaceEXT(EGLConfig config,void * nativeWindow,const EGLint * attribList)1268 EGLSurface EglWrapperDisplay::CreatePlatformWindowSurfaceEXT(EGLConfig config, void *nativeWindow,
1269 const EGLint *attribList)
1270 {
1271 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1272
1273 if (nativeWindow == nullptr) {
1274 WLOGE("CreatePlatformWindowSurfaceEXT nativeWindow is invalid.");
1275 ThreadPrivateDataCtl::SetError(EGL_BAD_NATIVE_WINDOW);
1276 return EGL_NO_SURFACE;
1277 }
1278
1279 EglWrapperDispatchTablePtr table = &gWrapperHook;
1280 if (table->isLoad && table->egl.eglCreatePlatformWindowSurfaceEXT) {
1281 EGLSurface surf = table->egl.eglCreatePlatformWindowSurfaceEXT(
1282 disp_, config, nativeWindow, attribList);
1283 if (surf != EGL_NO_SURFACE) {
1284 return new EglWrapperSurface(this, surf);
1285 } else {
1286 WLOGE("egl.eglCreatePlatformWindowSurfaceEXT error.");
1287 }
1288 } else {
1289 WLOGE("eglCreatePlatformWindowSurfaceEXT is invalid.");
1290 }
1291
1292 return EGL_NO_SURFACE;
1293 }
1294
CreatePlatformPixmapSurfaceEXT(EGLConfig config,void * nativePixmap,const EGLint * attribList)1295 EGLSurface EglWrapperDisplay::CreatePlatformPixmapSurfaceEXT(EGLConfig config, void *nativePixmap,
1296 const EGLint *attribList)
1297 {
1298 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1299
1300 if (nativePixmap == nullptr) {
1301 WLOGE("CreatePlatformPixmapSurfaceEXT nativePixmap is invalid.");
1302 ThreadPrivateDataCtl::SetError(EGL_BAD_NATIVE_WINDOW);
1303 return EGL_NO_SURFACE;
1304 }
1305
1306 EglWrapperDispatchTablePtr table = &gWrapperHook;
1307 if (table->isLoad && table->egl.eglCreatePlatformPixmapSurfaceEXT) {
1308 EGLSurface surf = table->egl.eglCreatePlatformPixmapSurfaceEXT(
1309 disp_, config, nativePixmap, attribList);
1310 if (surf != EGL_NO_SURFACE) {
1311 return new EglWrapperSurface(this, surf);
1312 } else {
1313 WLOGE("egl.eglCreatePlatformPixmapSurfaceEXT error.");
1314 }
1315 } else {
1316 WLOGE("eglCreatePlatformPixmapSurfaceEXT is invalid.");
1317 }
1318 return EGL_NO_SURFACE;
1319 }
1320
SwapBuffersWithDamageEXT(EGLSurface surface,const EGLint * rects,EGLint nRects)1321 EGLBoolean EglWrapperDisplay::SwapBuffersWithDamageEXT(EGLSurface surface, const EGLint *rects, EGLint nRects)
1322 {
1323 EglWrapperSurface *surfPtr = nullptr;
1324 {
1325 std::lock_guard<std::recursive_mutex> lock(refLockMutex_);
1326 surfPtr = EglWrapperSurface::GetWrapperSurface(surface);
1327 if (!CheckObject(surfPtr)) {
1328 WLOGE("EGLSurface is invalid.");
1329 ThreadPrivateDataCtl::SetError(EGL_BAD_SURFACE);
1330 return EGL_FALSE;
1331 }
1332
1333 if (nRects < 0 || (nRects > 0 && rects == nullptr)) {
1334 WLOGE("Parameter error.");
1335 ThreadPrivateDataCtl::SetError(EGL_BAD_PARAMETER);
1336 return EGL_FALSE;
1337 }
1338 }
1339
1340 EGLBoolean ret = EGL_FALSE;
1341 EglWrapperDispatchTablePtr table = &gWrapperHook;
1342 if (table->isLoad && table->egl.eglSwapBuffersWithDamageEXT) {
1343 ret = table->egl.eglSwapBuffersWithDamageEXT(
1344 disp_, surfPtr->GetEglSurface(), rects, nRects);
1345 } else {
1346 WLOGE("eglSwapBuffersWithDamageEXT is invalid.");
1347 }
1348 return ret;
1349 }
1350 } // namespace OHOS
1351