1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "EglOsApi.h"
18
19 #include "aemu/base/system/System.h"
20 #include "aemu/base/SharedLibrary.h"
21 #include "host-common/logging.h"
22 #include "host-common/opengl/misc.h"
23 #include "GLcommon/GLLibrary.h"
24 #include "ShaderCache.h"
25
26 #ifdef ANDROID
27 #include <android/native_window.h>
28 #endif
29
30 #ifdef __linux__
31 #include "X11Support.h"
32 #include "X11ErrorHandler.h"
33 #endif
34
35 #ifdef __QNX__
36 #include "screen/screen.h"
37 #endif
38
39 #include <EGL/egl.h>
40 #include <EGL/eglext.h>
41 #include <GLES2/gl2.h>
42 #include <cstring>
43 #include <memory>
44 #include <vector>
45
46 #define DEBUG 0
47 #if DEBUG
48 #define D(...) fprintf(stderr, __VA_ARGS__);
49 #define CHECK_EGL_ERR \
50 { \
51 EGLint err = mDispatcher.eglGetError(); \
52 if (err != EGL_SUCCESS) \
53 D("%s: %s %d get egl error %d\n", __FUNCTION__, __FILE__, \
54 __LINE__, err); \
55 }
56 #else
57 #define D(...) ((void)0);
58 #define CHECK_EGL_ERR ((void)0);
59 #endif
60
61 #if defined(__WIN32) || defined(_MSC_VER)
62
63 static const char* kEGLLibName = "libEGL.dll";
64 static const char* kGLES2LibName = "libGLESv2.dll";
65
66 #elif defined(__linux__)
67
68
69 static const char* kEGLLibName = "libEGL.so";
70 static const char* kGLES2LibName = "libGLESv2.so";
71
72 static const char* kEGLLibNameAlt = "libEGL.so.1";
73 static const char* kGLES2LibNameAlt = "libGLESv2.so.2";
74
75 #elif defined(__QNX__)
76
77 static const char* kEGLLibName = "libEGL.so";
78 static const char* kGLES2LibName = "libGLESv2.so";
79
80 #else // __APPLE__
81
82 #include "MacNative.h"
83
84 static const char* kEGLLibName = "libEGL.dylib";
85 static const char* kGLES2LibName = "libGLESv2.dylib";
86
87 #endif // __APPLE__
88
89 // List of EGL functions of interest to probe with GetProcAddress()
90 #define LIST_EGL_FUNCTIONS(X) \
91 X(void*, eglGetProcAddress, \
92 (const char* procname)) \
93 X(const char*, eglQueryString, \
94 (EGLDisplay dpy, EGLint id)) \
95 X(EGLDisplay, eglGetPlatformDisplay, \
96 (EGLenum platform, void *native_display, const EGLAttrib *attrib_list)) \
97 X(EGLDisplay, eglGetPlatformDisplayEXT, \
98 (EGLenum platform, void *native_display, const EGLint *attrib_list)) \
99 X(EGLBoolean, eglBindAPI, \
100 (EGLenum api)) \
101 X(EGLBoolean, eglChooseConfig, \
102 (EGLDisplay display, EGLint const* attrib_list, EGLConfig* configs, \
103 EGLint config_size, EGLint* num_config)) \
104 X(EGLContext, eglCreateContext, \
105 (EGLDisplay display, EGLConfig config, EGLContext share_context, \
106 EGLint const* attrib_list)) \
107 X(EGLSurface, eglCreatePbufferSurface, \
108 (EGLDisplay display, EGLConfig config, EGLint const* attrib_list)) \
109 X(EGLBoolean, eglDestroyContext, (EGLDisplay display, EGLContext context)) \
110 X(EGLBoolean, eglDestroySurface, (EGLDisplay display, EGLSurface surface)) \
111 X(EGLBoolean, eglGetConfigAttrib, \
112 (EGLDisplay display, EGLConfig config, EGLint attribute, \
113 EGLint * value)) \
114 X(EGLDisplay, eglGetDisplay, (NativeDisplayType native_display)) \
115 X(EGLint, eglGetError, (void)) \
116 X(EGLBoolean, eglInitialize, \
117 (EGLDisplay display, EGLint * major, EGLint * minor)) \
118 X(EGLBoolean, eglMakeCurrent, \
119 (EGLDisplay display, EGLSurface draw, EGLSurface read, \
120 EGLContext context)) \
121 X(EGLBoolean, eglSwapBuffers, (EGLDisplay display, EGLSurface surface)) \
122 X(EGLSurface, eglCreateWindowSurface, \
123 (EGLDisplay display, EGLConfig config, \
124 EGLNativeWindowType native_window, EGLint const* attrib_list)) \
125 X(EGLBoolean, eglSwapInterval, \
126 (EGLDisplay display, EGLint interval)) \
127 X(void, eglSetBlobCacheFuncsANDROID, (EGLDisplay display, \
128 EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)) \
129 X(EGLImage, eglCreateImageKHR, (EGLDisplay dpy, \
130 EGLContext ctx, EGLenum target, EGLClientBuffer buffer, \
131 const EGLint *attrib_list)) \
132 X(EGLBoolean, eglDestroyImageKHR, (EGLDisplay dpy, EGLImage image)) \
133 X(EGLImage, eglCreateImage, (EGLDisplay dpy, \
134 EGLContext ctx, EGLenum target, EGLClientBuffer buffer, \
135 const EGLAttrib *attrib_list)) \
136 X(EGLBoolean, eglDestroyImage, (EGLDisplay dpy, EGLImage image)) \
137 X(EGLBoolean, eglReleaseThread, (void)) \
138 X(EGLint, eglDebugMessageControlKHR, \
139 (EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list)) \
140
141 namespace {
142 using namespace EglOS;
143
144 class EglOsEglDispatcher {
145 public:
146 #define DECLARE_EGL_POINTER(return_type, function_name, signature) \
147 return_type(EGLAPIENTRY* function_name) signature = nullptr;
148 LIST_EGL_FUNCTIONS(DECLARE_EGL_POINTER);
149
EglOsEglDispatcher()150 EglOsEglDispatcher() {
151 D("loading %s\n", kEGLLibName);
152 char error[256];
153 mLib = android::base::SharedLibrary::open(kEGLLibName, error, sizeof(error));
154 if (!mLib) {
155 #ifdef __linux__
156 ERR("%s: Could not open EGL library %s [%s]. Trying again with [%s]", __FUNCTION__,
157 kEGLLibName, error, kEGLLibNameAlt);
158 mLib = android::base::SharedLibrary::open(kEGLLibNameAlt, error, sizeof(error));
159 if (!mLib) {
160 ERR("%s: Could not open EGL library %s [%s]", __FUNCTION__,
161 kEGLLibNameAlt, error);
162 }
163 #else
164 ERR("%s: Could not open EGL library %s [%s]", __FUNCTION__,
165 kEGLLibName, error);
166 #endif
167 }
168
169 #define LOAD_EGL_POINTER(return_type, function_name, signature) \
170 this->function_name = \
171 reinterpret_cast<return_type(GL_APIENTRY*) signature>( \
172 mLib->findSymbol(#function_name)); \
173 if (!this->function_name) { \
174 this->function_name = \
175 reinterpret_cast<return_type(GL_APIENTRY*) signature>( \
176 this->eglGetProcAddress(#function_name)); \
177 } \
178 if (!this->function_name) { \
179 D("%s: Could not find %s in underlying EGL library\n", \
180 __FUNCTION__, \
181 #function_name); \
182 }
183
184 LIST_EGL_FUNCTIONS(LOAD_EGL_POINTER);
185 }
186 ~EglOsEglDispatcher() = default;
187
188 private:
189 android::base::SharedLibrary* mLib = nullptr;
190 };
191
192 class EglOsGlLibrary : public GlLibrary {
193 public:
EglOsGlLibrary()194 EglOsGlLibrary() {
195 char error[256];
196 mLib = android::base::SharedLibrary::open(kGLES2LibName, error, sizeof(error));
197 if (!mLib) {
198 #ifdef __linux__
199 ERR("%s: Could not open GL library %s [%s]. Trying again with [%s]", __FUNCTION__,
200 kGLES2LibName, error, kGLES2LibNameAlt);
201 mLib = android::base::SharedLibrary::open(kGLES2LibNameAlt, error, sizeof(error));
202 if (!mLib) {
203 ERR("%s: Could not open GL library %s [%s]", __FUNCTION__,
204 kGLES2LibNameAlt, error);
205 }
206 #else
207 ERR("%s: Could not open GL library %s [%s]", __FUNCTION__,
208 kGLES2LibName, error);
209 #endif
210 }
211 }
findSymbol(const char * name)212 GlFunctionPointer findSymbol(const char* name) {
213 if (!mLib) {
214 return NULL;
215 }
216 return reinterpret_cast<GlFunctionPointer>(mLib->findSymbol(name));
217 }
218 ~EglOsGlLibrary() = default;
219
220 private:
221 android::base::SharedLibrary* mLib = nullptr;
222 };
223
224 class EglOsEglPixelFormat : public EglOS::PixelFormat {
225 public:
EglOsEglPixelFormat(EGLConfig configId,EGLint clientCtxVer)226 EglOsEglPixelFormat(EGLConfig configId, EGLint clientCtxVer)
227 : mConfigId(configId), mClientCtxVer(clientCtxVer) {}
clone()228 PixelFormat* clone() {
229 return new EglOsEglPixelFormat(mConfigId, mClientCtxVer);
230 }
231 EGLConfig mConfigId;
232 EGLint mClientCtxVer;
233 #ifdef __APPLE__
234 int mRedSize = 0;
235 int mGreenSize = 0;
236 int mBlueSize = 0;
237 #endif // __APPLE__
238 };
239
240 class EglOsEglContext : public EglOS::Context {
241 public:
EglOsEglContext(EglOsEglDispatcher * dispatcher,EGLDisplay display,EGLContext context)242 EglOsEglContext(EglOsEglDispatcher* dispatcher,
243 EGLDisplay display,
244 EGLContext context) :
245 mDispatcher(dispatcher),
246 mDisplay(display),
247 mNativeCtx(context) { }
248
~EglOsEglContext()249 virtual ~EglOsEglContext() {
250 D("%s %p\n", __FUNCTION__, mNativeCtx);
251 if (!mDispatcher->eglDestroyContext(mDisplay, mNativeCtx)) {
252 // TODO: print a better error message
253 }
254 }
255
context() const256 EGLContext context() const {
257 return mNativeCtx;
258 }
259
getNative()260 virtual void* getNative() { return (void*)mNativeCtx; }
261 private:
262 EglOsEglDispatcher* mDispatcher = nullptr;
263 EGLDisplay mDisplay;
264 EGLContext mNativeCtx;
265 };
266
267 class EglOsEglSurface : public EglOS::Surface {
268 public:
EglOsEglSurface(SurfaceType type,EGLSurface eglSurface,EGLNativeWindowType win=0)269 EglOsEglSurface(SurfaceType type,
270 EGLSurface eglSurface,
271 EGLNativeWindowType win = 0)
272 : EglOS::Surface(type), mHndl(eglSurface), mWin(win) {}
getHndl()273 EGLSurface getHndl() { return mHndl; }
getWin()274 EGLNativeWindowType getWin() { return mWin; }
275
276 private:
277 EGLSurface mHndl;
278 EGLNativeWindowType mWin;
279 };
280
281 class EglOsEglDisplay : public EglOS::Display {
282 public:
283 EglOsEglDisplay(bool nullEgl);
284 ~EglOsEglDisplay();
285 virtual EglOS::GlesVersion getMaxGlesVersion();
286 virtual const char* getExtensionString();
287 virtual const char* getVendorString();
288 virtual EGLImage createImageKHR(
289 EGLDisplay dpy,
290 EGLContext ctx,
291 EGLenum target,
292 EGLClientBuffer buffer,
293 const EGLint *attrib_list);
294 virtual EGLBoolean destroyImageKHR(
295 EGLDisplay dpy,
296 EGLImage image);
297 virtual EGLDisplay getNative();
298 void queryConfigs(int renderableType,
299 AddConfigCallback* addConfigFunc,
300 void* addConfigOpaque);
301 virtual std::shared_ptr<Context>
302 createContext(EGLint profileMask,
303 const PixelFormat* pixelFormat,
304 Context* sharedContext) override;
305 Surface* createPbufferSurface(const PixelFormat* pixelFormat,
306 const PbufferInfo* info);
307 Surface* createWindowSurface(PixelFormat* pf, EGLNativeWindowType win);
308 bool releasePbuffer(Surface* pb);
309 bool makeCurrent(Surface* read, Surface* draw, Context* context);
310 EGLBoolean releaseThread();
311 void swapBuffers(Surface* srfc);
312 bool isValidNativeWin(Surface* win);
313 bool isValidNativeWin(EGLNativeWindowType win);
314 bool checkWindowPixelFormatMatch(EGLNativeWindowType win,
315 const PixelFormat* pixelFormat,
316 unsigned int* width,
317 unsigned int* height);
eglGetProcAddress(const char * func)318 void* eglGetProcAddress(const char* func) {
319 return mDispatcher.eglGetProcAddress(func);
320 }
321
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attribs)322 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib* attribs) {
323 return mDispatcher.eglDebugMessageControlKHR(callback, attribs);
324 }
325
326 private:
327 bool mVerbose = false;
328 EGLDisplay mDisplay = EGL_NO_DISPLAY;
329 EglOsEglDispatcher mDispatcher;
330 bool mHeadless = false;
331 std::string mClientExts;
332 std::string mVendor;
333 GlesVersion mGlesVersion;
334
335 #ifdef __linux__
336 ::Display* mGlxDisplay = nullptr;
337 #endif // __linux__
338 };
339
EglOsEglDisplay(bool nullEgl)340 EglOsEglDisplay::EglOsEglDisplay(bool nullEgl) {
341 mVerbose = android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1";
342
343 if (nullEgl) {
344 #ifdef EGL_ANGLE_platform_angle
345 const EGLAttrib attr[] = {
346 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
347 EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE,
348 EGL_NONE
349 };
350
351 mDisplay = mDispatcher.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
352 (void*)EGL_DEFAULT_DISPLAY,
353 attr);
354
355 if (mDisplay == EGL_NO_DISPLAY) {
356 fprintf(stderr, "%s: no display found that supports null backend\n", __func__);
357 }
358 #else
359 fprintf(stderr, "EGL Null display not compiled, falling back to default display\n");
360 #endif
361 } else if (android::base::getEnvironmentVariable("ANDROID_EMUGL_EXPERIMENTAL_FAST_PATH") == "1") {
362 #ifdef EGL_ANGLE_platform_angle
363 const EGLAttrib attr[] = {
364 EGL_PLATFORM_ANGLE_TYPE_ANGLE,
365 EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
366 EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
367 EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
368 EGL_NONE
369 };
370
371 mDisplay = mDispatcher.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
372 (void*)EGL_DEFAULT_DISPLAY,
373 attr);
374
375 if (mDisplay == EGL_NO_DISPLAY) {
376 fprintf(stderr, "%s: no display found that supports the requested extensions\n", __func__);
377 }
378 #endif
379 }
380
381 if (mDisplay == EGL_NO_DISPLAY)
382 mDisplay = mDispatcher.eglGetDisplay(EGL_DEFAULT_DISPLAY);
383
384 mDispatcher.eglInitialize(mDisplay, nullptr, nullptr);
385 mDispatcher.eglSwapInterval(mDisplay, 0);
386 auto clientExts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
387 auto vendor = mDispatcher.eglQueryString(mDisplay, EGL_VENDOR);
388
389 if (mVerbose) {
390 fprintf(stderr, "%s: client exts: [%s]\n", __func__, clientExts);
391 }
392
393 if (clientExts) {
394 mClientExts = clientExts;
395 }
396
397 if (vendor) {
398 mVendor = vendor;
399 }
400
401 mDispatcher.eglBindAPI(EGL_OPENGL_ES_API);
402 CHECK_EGL_ERR
403
404 mHeadless = android::base::getEnvironmentVariable("ANDROID_EMU_HEADLESS") == "1";
405
406 #ifdef ANDROID
407 mGlxDisplay = nullptr;
408 #elif defined(__linux__)
409 if (mHeadless) mGlxDisplay = nullptr;
410 else mGlxDisplay = getX11Api()->XOpenDisplay(0);
411 #endif // __linux__
412
413 if (clientExts != nullptr && emugl::hasExtension(clientExts, "EGL_ANDROID_blob_cache")) {
414 mDispatcher.eglSetBlobCacheFuncsANDROID(mDisplay, SetBlob, GetBlob);
415 }
416
417 mGlesVersion = GlesVersion::ES2;
418
419 static const EGLint gles3ConfigAttribs[] =
420 { EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
421 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT, EGL_NONE };
422
423 static const EGLint pbufAttribs[] =
424 { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
425
426 static const EGLint gles31Attribs[] =
427 { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
428 EGL_CONTEXT_MINOR_VERSION_KHR, 1, EGL_NONE };
429
430 static const EGLint gles30Attribs[] =
431 { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
432 EGL_CONTEXT_MINOR_VERSION_KHR, 0, EGL_NONE };
433
434 EGLConfig config;
435
436 int numConfigs;
437 if (mDispatcher.eglChooseConfig(
438 mDisplay, gles3ConfigAttribs, &config, 1, &numConfigs) &&
439 numConfigs != 0) {
440 EGLSurface surface = mDispatcher.eglCreatePbufferSurface(mDisplay,
441 config, pbufAttribs);
442 if (surface != EGL_NO_SURFACE) {
443 EGLContext ctx = mDispatcher.eglCreateContext(mDisplay,
444 config, EGL_NO_CONTEXT, gles31Attribs);
445
446 if (ctx != EGL_NO_CONTEXT) {
447 mGlesVersion = GlesVersion::ES31;
448 } else {
449 ctx = mDispatcher.eglCreateContext(mDisplay, config,
450 EGL_NO_CONTEXT, gles30Attribs);
451 if (ctx != EGL_NO_CONTEXT) {
452 mGlesVersion = GlesVersion::ES30;
453 }
454 }
455 mDispatcher.eglDestroySurface(mDisplay, surface);
456 if (ctx != EGL_NO_CONTEXT) {
457 mDispatcher.eglDestroyContext(mDisplay, ctx);
458 }
459 }
460 }
461 };
462
~EglOsEglDisplay()463 EglOsEglDisplay::~EglOsEglDisplay() {
464 #ifdef ANDROID
465 #elif defined(__linux__)
466 if (mGlxDisplay) getX11Api()->XCloseDisplay(mGlxDisplay);
467 #endif // __linux__
468 }
469
getMaxGlesVersion()470 EglOS::GlesVersion EglOsEglDisplay::getMaxGlesVersion() {
471 // Maximum GLES3.1
472 // GLES3.2 will also need some more autogen + enums if anyone is interested.
473 return mGlesVersion;
474 }
475
getExtensionString()476 const char* EglOsEglDisplay::getExtensionString() {
477 return mClientExts.c_str();
478 }
479
getVendorString()480 const char* EglOsEglDisplay::getVendorString() {
481 return mVendor.c_str();
482 }
483
createImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)484 EGLImage EglOsEglDisplay::createImageKHR(
485 EGLDisplay dpy,
486 EGLContext ctx,
487 EGLenum target,
488 EGLClientBuffer buffer,
489 const EGLint *attrib_list) {
490 if (mDispatcher.eglCreateImageKHR) {
491 return mDispatcher.eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
492 } else {
493 return EGL_NO_IMAGE_KHR;
494 }
495 }
496
destroyImageKHR(EGLDisplay dpy,EGLImage image)497 EGLBoolean EglOsEglDisplay::destroyImageKHR(
498 EGLDisplay dpy,
499 EGLImage image) {
500 if (mDispatcher.eglDestroyImage) {
501 return mDispatcher.eglDestroyImageKHR(dpy, image);
502 } else {
503 return EGL_FALSE;
504 }
505 }
506
getNative()507 EGLDisplay EglOsEglDisplay::getNative() {
508 return mDisplay;
509 }
510
queryConfigs(int renderableType,AddConfigCallback * addConfigFunc,void * addConfigOpaque)511 void EglOsEglDisplay::queryConfigs(int renderableType,
512 AddConfigCallback* addConfigFunc,
513 void* addConfigOpaque) {
514 D("%s\n", __FUNCTION__);
515
516 const EGLint framebuffer_config_attributes[] = {
517 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
518 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
519 EGL_RED_SIZE, 1,
520 EGL_GREEN_SIZE, 1,
521 EGL_BLUE_SIZE, 1,
522 EGL_ALPHA_SIZE, 0,
523 EGL_NONE,
524 };
525
526 EGLint numConfigs = 0;
527 mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, nullptr, 0, &numConfigs);
528 CHECK_EGL_ERR
529 std::unique_ptr<EGLConfig[]> configs(new EGLConfig[numConfigs]);
530 mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, configs.get(), numConfigs,
531 &numConfigs);
532 CHECK_EGL_ERR
533
534 if (mVerbose) {
535 fprintf(stderr, "%s: num configs: %d\n", __func__, numConfigs);
536 }
537
538 for (int i = 0; i < numConfigs; i++) {
539 const EGLConfig cfg = configs.get()[i];
540 ConfigInfo configInfo;
541 // We do not have recordable_android
542 configInfo.recordable_android = 0;
543 EGLint _renderableType;
544 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RENDERABLE_TYPE,
545 &_renderableType);
546 // We do emulate GLES1
547 configInfo.renderable_type = _renderableType | EGL_OPENGL_ES_BIT;
548
549 configInfo.frmt = new EglOsEglPixelFormat(cfg, _renderableType);
550 D("config %p renderable type 0x%x\n", cfg, _renderableType);
551
552 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RED_SIZE,
553 &configInfo.red_size);
554 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_GREEN_SIZE,
555 &configInfo.green_size);
556 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_BLUE_SIZE,
557 &configInfo.blue_size);
558 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_ALPHA_SIZE,
559 &configInfo.alpha_size);
560 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_ALPHA_MASK_SIZE,
561 &configInfo.alpha_mask_size);
562
563 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_CONFIG_CAVEAT,
564 (EGLint*)&configInfo.caveat);
565 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_DEPTH_SIZE,
566 &configInfo.depth_size);
567 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_LEVEL,
568 &configInfo.frame_buffer_level);
569
570 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_WIDTH,
571 &configInfo.max_pbuffer_width);
572 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_HEIGHT,
573 &configInfo.max_pbuffer_height);
574 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_PIXELS,
575 &configInfo.max_pbuffer_size);
576
577 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_RENDERABLE,
578 (EGLint*)&configInfo.native_renderable);
579 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_ID,
580 &configInfo.native_visual_id);
581 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_TYPE,
582 &configInfo.native_visual_type);
583
584 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SAMPLES,
585 &configInfo.samples_per_pixel);
586 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_STENCIL_SIZE,
587 &configInfo.stencil_size);
588
589 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SURFACE_TYPE,
590 &configInfo.surface_type);
591 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_TYPE,
592 (EGLint*)&configInfo.transparent_type);
593 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_RED_VALUE,
594 &configInfo.trans_red_val);
595 mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
596 EGL_TRANSPARENT_GREEN_VALUE,
597 &configInfo.trans_green_val);
598 mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
599 EGL_TRANSPARENT_BLUE_VALUE,
600 &configInfo.trans_blue_val);
601 CHECK_EGL_ERR
602 #ifdef __APPLE__
603 ((EglOsEglPixelFormat*)configInfo.frmt)->mRedSize = configInfo.red_size;
604 ((EglOsEglPixelFormat*)configInfo.frmt)->mGreenSize = configInfo.green_size;
605 ((EglOsEglPixelFormat*)configInfo.frmt)->mBlueSize = configInfo.blue_size;
606 #endif // __APPLE__
607 addConfigFunc(addConfigOpaque, &configInfo);
608 }
609 D("Host gets %d configs\n", numConfigs);
610 }
611
612 std::shared_ptr<Context>
createContext(EGLint profileMask,const PixelFormat * pixelFormat,Context * sharedContext)613 EglOsEglDisplay::createContext(EGLint profileMask,
614 const PixelFormat* pixelFormat,
615 Context* sharedContext) {
616 (void)profileMask;
617
618 D("%s\n", __FUNCTION__);
619 const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
620 D("with config %p\n", format->mConfigId);
621
622 // Always GLES3
623 std::vector<EGLint> attributes = { EGL_CONTEXT_CLIENT_VERSION, 3 };
624 auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
625 auto vendor = mDispatcher.eglQueryString(mDisplay, EGL_VENDOR);
626
627 // TODO (b/207426737): remove Imagination-specific workaround
628 bool disable_robustness = vendor && (strcmp(vendor, "Imagination Technologies") == 0);
629
630 bool disableValidation = android::base::getEnvironmentVariable("ANDROID_EMUGL_EGL_VALIDATION") == "0";
631 if (exts != nullptr && emugl::hasExtension(exts, "EGL_KHR_create_context_no_error") && disableValidation) {
632 attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
633 attributes.push_back(EGL_TRUE);
634 }
635
636 if (exts != nullptr && emugl::hasExtension(exts, "EGL_EXT_create_context_robustness") && !disable_robustness) {
637 attributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
638 attributes.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
639 }
640 attributes.push_back(EGL_NONE);
641
642 // TODO: support GLES3.1
643 EglOsEglContext* nativeSharedCtx = (EglOsEglContext*)sharedContext;
644 EGLContext newNativeCtx = mDispatcher.eglCreateContext(
645 mDisplay, format->mConfigId,
646 nativeSharedCtx ? nativeSharedCtx->context() : nullptr,
647 attributes.data());
648 CHECK_EGL_ERR
649 std::shared_ptr<Context> res =
650 std::make_shared<EglOsEglContext>(
651 &mDispatcher, mDisplay, newNativeCtx);
652 D("%s done\n", __FUNCTION__);
653 return res;
654 }
655
createPbufferSurface(const PixelFormat * pixelFormat,const PbufferInfo * info)656 Surface* EglOsEglDisplay::createPbufferSurface(const PixelFormat* pixelFormat,
657 const PbufferInfo* info) {
658 // D("%s\n", __FUNCTION__);
659 // const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
660 // EGLint attrib[] = {EGL_WIDTH,
661 // info->width,
662 // EGL_HEIGHT,
663 // info->height,
664 // EGL_LARGEST_PBUFFER,
665 // info->largest,
666 // EGL_TEXTURE_FORMAT,
667 // info->format,
668 // EGL_TEXTURE_TARGET,
669 // info->target,
670 // EGL_MIPMAP_TEXTURE,
671 // info->hasMipmap,
672 // EGL_NONE};
673 // EGLSurface surface = mDispatcher.eglCreatePbufferSurface(
674 // mDisplay, format->mConfigId, attrib);
675 // CHECK_EGL_ERR
676 // if (surface == EGL_NO_SURFACE) {
677 // D("create pbuffer surface failed\n");
678 // return nullptr;
679 // }
680 // return new EglOsEglSurface(EglOS::Surface::PBUFFER, surface);
681 return new EglOsEglSurface(EglOS::Surface::PBUFFER, 0);
682 }
683
createWindowSurface(PixelFormat * pf,EGLNativeWindowType win)684 Surface* EglOsEglDisplay::createWindowSurface(PixelFormat* pf,
685 EGLNativeWindowType win) {
686 D("%s\n", __FUNCTION__);
687 std::vector<EGLint> surface_attribs;
688 auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
689 if (exts != nullptr && emugl::hasExtension(exts, "EGL_ANGLE_direct_composition")) {
690 #ifdef EGL_ANGLE_direct_composition
691 surface_attribs.push_back(EGL_DIRECT_COMPOSITION_ANGLE);
692 surface_attribs.push_back(EGL_TRUE);
693 #endif
694 }
695 surface_attribs.push_back(EGL_NONE);
696 #ifdef __APPLE__
697 win = nsGetLayer(win);
698 #endif
699 EGLSurface surface = mDispatcher.eglCreateWindowSurface(
700 mDisplay, ((EglOsEglPixelFormat*)pf)->mConfigId, win, surface_attribs.data()
701 );
702 CHECK_EGL_ERR
703 if (surface == EGL_NO_SURFACE) {
704 D("create window surface failed\n");
705 return nullptr;
706 }
707 return new EglOsEglSurface(EglOS::Surface::WINDOW, surface, win);
708 }
709
releasePbuffer(Surface * pb)710 bool EglOsEglDisplay::releasePbuffer(Surface* pb) {
711 D("%s\n", __FUNCTION__);
712 if (!pb)
713 return false;
714 EglOsEglSurface* surface = (EglOsEglSurface*)pb;
715
716 if (!surface->getHndl()) {
717 delete surface;
718 return true;
719 }
720
721 bool ret = mDispatcher.eglDestroySurface(mDisplay, surface->getHndl());
722 CHECK_EGL_ERR
723 D("%s done\n", __FUNCTION__);
724 delete surface;
725 return ret;
726 }
727
makeCurrent(Surface * read,Surface * draw,Context * context)728 bool EglOsEglDisplay::makeCurrent(Surface* read,
729 Surface* draw,
730 Context* context) {
731 D("%s\n", __FUNCTION__);
732 EglOsEglSurface* readSfc = (EglOsEglSurface*)read;
733 EglOsEglSurface* drawSfc = (EglOsEglSurface*)draw;
734 EglOsEglContext* ctx = (EglOsEglContext*)context;
735 if (ctx && !readSfc) {
736 D("warning: makeCurrent a context without surface\n");
737 return false;
738 }
739 D("%s %p\n", __FUNCTION__, ctx ? ctx->context() : nullptr);
740 bool ret = mDispatcher.eglMakeCurrent(
741 mDisplay, drawSfc ? drawSfc->getHndl() : EGL_NO_SURFACE,
742 readSfc ? readSfc->getHndl() : EGL_NO_SURFACE,
743 ctx ? ctx->context() : EGL_NO_CONTEXT);
744 if (readSfc) {
745 D("make current surface type %d %d\n", readSfc->type(),
746 drawSfc->type());
747 }
748 D("make current %d\n", ret);
749 CHECK_EGL_ERR
750 return ret;
751 }
752
swapBuffers(Surface * surface)753 void EglOsEglDisplay::swapBuffers(Surface* surface) {
754 D("%s\n", __FUNCTION__);
755 EglOsEglSurface* sfc = (EglOsEglSurface*)surface;
756 mDispatcher.eglSwapBuffers(mDisplay, sfc->getHndl());
757 }
758
releaseThread()759 EGLBoolean EglOsEglDisplay::releaseThread() {
760 D("%s\n", __FUNCTION__);
761 return mDispatcher.eglReleaseThread();
762 }
763
isValidNativeWin(Surface * win)764 bool EglOsEglDisplay::isValidNativeWin(Surface* win) {
765 if (!win) {
766 return false;
767 }
768 EglOsEglSurface* surface = (EglOsEglSurface*)win;
769 return surface->type() == EglOsEglSurface::WINDOW &&
770 isValidNativeWin(surface->getWin());
771 }
772
isValidNativeWin(EGLNativeWindowType win)773 bool EglOsEglDisplay::isValidNativeWin(EGLNativeWindowType win) {
774 #ifdef _WIN32
775 return IsWindow(win);
776 #elif defined(ANDROID)
777 return true;
778 #elif defined(__linux__)
779 Window root;
780 int t;
781 unsigned int u;
782 X11ErrorHandler handler(mGlxDisplay);
783 return getX11Api()->XGetGeometry(mGlxDisplay, win, &root, &t, &t, &u, &u, &u, &u) != 0;
784 #elif defined(__QNX__)
785 int size[2];
786 return screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, size) != -1;
787 #else // __APPLE__
788 unsigned int width, height;
789 return nsGetWinDims(win, &width, &height);
790 #endif // __APPLE__
791 }
792
checkWindowPixelFormatMatch(EGLNativeWindowType win,const PixelFormat * pixelFormat,unsigned int * width,unsigned int * height)793 bool EglOsEglDisplay::checkWindowPixelFormatMatch(EGLNativeWindowType win,
794 const PixelFormat* pixelFormat,
795 unsigned int* width,
796 unsigned int* height) {
797 #ifdef _WIN32
798 RECT r;
799 if (!GetClientRect(win, &r)) {
800 return false;
801 }
802 *width = r.right - r.left;
803 *height = r.bottom - r.top;
804 return true;
805 #elif defined(ANDROID)
806 *width = ANativeWindow_getWidth((ANativeWindow*)win);
807 *height = ANativeWindow_getHeight((ANativeWindow*)win);
808 return true;
809 #elif defined(__linux__)
810 //TODO: to check what does ATI & NVIDIA enforce on win pixelformat
811 unsigned int depth, border;
812 int x, y;
813 Window root;
814 X11ErrorHandler handler(mGlxDisplay);
815 return getX11Api()->XGetGeometry(
816 mGlxDisplay, win, &root, &x, &y, width, height, &border, &depth);
817 #elif defined(__QNX__)
818 int size[2];
819 if (screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, size) == -1) {
820 return false;
821 }
822 *width = size[0];
823 *height = size[1];
824 return true;
825 #else // __APPLE__
826 bool ret = nsGetWinDims(win, width, height);
827
828 const EglOsEglPixelFormat* format = (EglOsEglPixelFormat*)pixelFormat;
829 int r = format->mRedSize;
830 int g = format->mGreenSize;
831 int b = format->mBlueSize;
832
833 bool match = nsCheckColor(win, r + g + b);
834
835 return ret && match;
836 #endif // __APPLE__
837 }
838
sHostDisplay(bool nullEgl=false)839 static EglOsEglDisplay* sHostDisplay(bool nullEgl = false) {
840 static EglOsEglDisplay* d = new EglOsEglDisplay(nullEgl);
841 return d;
842 }
843
844 class EglEngine : public EglOS::Engine {
845 public:
EglEngine(bool nullEgl)846 EglEngine(bool nullEgl)
847 :
848 EglOS::Engine(),
849 #ifdef __QNX__ // Ensure libEGL is loaded prior to libGLES
850 mDisplay(sHostDisplay(nullEgl)),
851 #endif
852 mUseNullEgl(nullEgl) {
853 }
854
855 ~EglEngine() = default;
856
getDefaultDisplay()857 EglOS::Display* getDefaultDisplay() {
858 D("%s\n", __FUNCTION__);
859 return sHostDisplay(mUseNullEgl);
860 }
getGlLibrary()861 GlLibrary* getGlLibrary() {
862 D("%s\n", __FUNCTION__);
863 return &mGlLib;
864 }
eglGetProcAddress(const char * func)865 void* eglGetProcAddress(const char* func) { return sHostDisplay()->eglGetProcAddress(func); }
createWindowSurface(PixelFormat * pf,EGLNativeWindowType wnd)866 virtual EglOS::Surface* createWindowSurface(PixelFormat* pf, EGLNativeWindowType wnd) {
867 D("%s\n", __FUNCTION__);
868 return sHostDisplay()->createWindowSurface(pf, wnd);
869 }
870
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attribs)871 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib* attribs) override {
872 return sHostDisplay()->eglDebugMessageControlKHR(callback, attribs);
873 }
874
875 private:
876 #ifdef __QNX__
877 EglOsEglDisplay* mDisplay;
878 #endif
879 EglOsGlLibrary mGlLib;
880 bool mUseNullEgl;
881 };
882
883 } // namespace
884
sHostEngine(bool nullEgl)885 static EglEngine* sHostEngine(bool nullEgl) {
886 static EglEngine* res = new EglEngine(nullEgl);
887 return res;
888 }
889
890 namespace EglOS {
getEgl2EglHostInstance(bool nullEgl)891 Engine* getEgl2EglHostInstance(bool nullEgl) {
892 D("%s\n", __FUNCTION__);
893 return sHostEngine(nullEgl);
894 }
895 } // namespace EglOS
896