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 // ANGLE does not support GLES1 uses core profile engine.
516 // Querying underlying EGL with a conservative set of bits.
517 renderableType &= ~EGL_OPENGL_ES_BIT;
518
519 const EGLint framebuffer_config_attributes[] = {
520 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
521 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
522 EGL_RED_SIZE, 1,
523 EGL_GREEN_SIZE, 1,
524 EGL_BLUE_SIZE, 1,
525 EGL_ALPHA_SIZE, 0,
526 EGL_NONE,
527 };
528
529 EGLint numConfigs = 0;
530 mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, nullptr, 0, &numConfigs);
531 CHECK_EGL_ERR
532 std::unique_ptr<EGLConfig[]> configs(new EGLConfig[numConfigs]);
533 mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, configs.get(), numConfigs,
534 &numConfigs);
535 CHECK_EGL_ERR
536
537 if (mVerbose) {
538 fprintf(stderr, "%s: num configs: %d\n", __func__, numConfigs);
539 }
540
541 for (int i = 0; i < numConfigs; i++) {
542 const EGLConfig cfg = configs.get()[i];
543 ConfigInfo configInfo;
544 // We do not have recordable_android
545 configInfo.recordable_android = 0;
546 EGLint _renderableType;
547 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RENDERABLE_TYPE,
548 &_renderableType);
549 // We do emulate GLES1
550 configInfo.renderable_type = _renderableType | EGL_OPENGL_ES_BIT;
551
552 configInfo.frmt = new EglOsEglPixelFormat(cfg, _renderableType);
553 D("config %p renderable type 0x%x\n", cfg, _renderableType);
554
555 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RED_SIZE,
556 &configInfo.red_size);
557 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_GREEN_SIZE,
558 &configInfo.green_size);
559 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_BLUE_SIZE,
560 &configInfo.blue_size);
561 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_ALPHA_SIZE,
562 &configInfo.alpha_size);
563
564 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_CONFIG_CAVEAT,
565 (EGLint*)&configInfo.caveat);
566 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_DEPTH_SIZE,
567 &configInfo.depth_size);
568 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_LEVEL,
569 &configInfo.frame_buffer_level);
570
571 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_WIDTH,
572 &configInfo.max_pbuffer_width);
573 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_HEIGHT,
574 &configInfo.max_pbuffer_height);
575 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_PIXELS,
576 &configInfo.max_pbuffer_size);
577
578 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_RENDERABLE,
579 (EGLint*)&configInfo.native_renderable);
580 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_ID,
581 &configInfo.native_visual_id);
582 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_TYPE,
583 &configInfo.native_visual_type);
584
585 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SAMPLES,
586 &configInfo.samples_per_pixel);
587 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_STENCIL_SIZE,
588 &configInfo.stencil_size);
589
590 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SURFACE_TYPE,
591 &configInfo.surface_type);
592 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_TYPE,
593 (EGLint*)&configInfo.transparent_type);
594 mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_RED_VALUE,
595 &configInfo.trans_red_val);
596 mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
597 EGL_TRANSPARENT_GREEN_VALUE,
598 &configInfo.trans_green_val);
599 mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
600 EGL_TRANSPARENT_BLUE_VALUE,
601 &configInfo.trans_blue_val);
602 CHECK_EGL_ERR
603 #ifdef __APPLE__
604 ((EglOsEglPixelFormat*)configInfo.frmt)->mRedSize = configInfo.red_size;
605 ((EglOsEglPixelFormat*)configInfo.frmt)->mGreenSize = configInfo.green_size;
606 ((EglOsEglPixelFormat*)configInfo.frmt)->mBlueSize = configInfo.blue_size;
607 #endif // __APPLE__
608 addConfigFunc(addConfigOpaque, &configInfo);
609 }
610 D("Host gets %d configs\n", numConfigs);
611 }
612
613 std::shared_ptr<Context>
createContext(EGLint profileMask,const PixelFormat * pixelFormat,Context * sharedContext)614 EglOsEglDisplay::createContext(EGLint profileMask,
615 const PixelFormat* pixelFormat,
616 Context* sharedContext) {
617 (void)profileMask;
618
619 D("%s\n", __FUNCTION__);
620 const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
621 D("with config %p\n", format->mConfigId);
622
623 // Always GLES3
624 std::vector<EGLint> attributes = { EGL_CONTEXT_CLIENT_VERSION, 3 };
625 auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
626 auto vendor = mDispatcher.eglQueryString(mDisplay, EGL_VENDOR);
627
628 // TODO (b/207426737): remove Imagination-specific workaround
629 bool disable_robustness = vendor && (strcmp(vendor, "Imagination Technologies") == 0);
630
631 bool disableValidation = android::base::getEnvironmentVariable("ANDROID_EMUGL_EGL_VALIDATION") == "0";
632 if (exts != nullptr && emugl::hasExtension(exts, "EGL_KHR_create_context_no_error") && disableValidation) {
633 attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
634 attributes.push_back(EGL_TRUE);
635 }
636
637 if (exts != nullptr && emugl::hasExtension(exts, "EGL_EXT_create_context_robustness") && !disable_robustness) {
638 attributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
639 attributes.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
640 }
641 attributes.push_back(EGL_NONE);
642
643 // TODO: support GLES3.1
644 EglOsEglContext* nativeSharedCtx = (EglOsEglContext*)sharedContext;
645 EGLContext newNativeCtx = mDispatcher.eglCreateContext(
646 mDisplay, format->mConfigId,
647 nativeSharedCtx ? nativeSharedCtx->context() : nullptr,
648 attributes.data());
649 CHECK_EGL_ERR
650 std::shared_ptr<Context> res =
651 std::make_shared<EglOsEglContext>(
652 &mDispatcher, mDisplay, newNativeCtx);
653 D("%s done\n", __FUNCTION__);
654 return res;
655 }
656
createPbufferSurface(const PixelFormat * pixelFormat,const PbufferInfo * info)657 Surface* EglOsEglDisplay::createPbufferSurface(const PixelFormat* pixelFormat,
658 const PbufferInfo* info) {
659 // D("%s\n", __FUNCTION__);
660 // const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
661 // EGLint attrib[] = {EGL_WIDTH,
662 // info->width,
663 // EGL_HEIGHT,
664 // info->height,
665 // EGL_LARGEST_PBUFFER,
666 // info->largest,
667 // EGL_TEXTURE_FORMAT,
668 // info->format,
669 // EGL_TEXTURE_TARGET,
670 // info->target,
671 // EGL_MIPMAP_TEXTURE,
672 // info->hasMipmap,
673 // EGL_NONE};
674 // EGLSurface surface = mDispatcher.eglCreatePbufferSurface(
675 // mDisplay, format->mConfigId, attrib);
676 // CHECK_EGL_ERR
677 // if (surface == EGL_NO_SURFACE) {
678 // D("create pbuffer surface failed\n");
679 // return nullptr;
680 // }
681 // return new EglOsEglSurface(EglOS::Surface::PBUFFER, surface);
682 return new EglOsEglSurface(EglOS::Surface::PBUFFER, 0);
683 }
684
createWindowSurface(PixelFormat * pf,EGLNativeWindowType win)685 Surface* EglOsEglDisplay::createWindowSurface(PixelFormat* pf,
686 EGLNativeWindowType win) {
687 D("%s\n", __FUNCTION__);
688 std::vector<EGLint> surface_attribs;
689 auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
690 if (exts != nullptr && emugl::hasExtension(exts, "EGL_ANGLE_direct_composition")) {
691 #ifdef EGL_ANGLE_direct_composition
692 surface_attribs.push_back(EGL_DIRECT_COMPOSITION_ANGLE);
693 surface_attribs.push_back(EGL_TRUE);
694 #endif
695 }
696 surface_attribs.push_back(EGL_NONE);
697 #ifdef __APPLE__
698 win = nsGetLayer(win);
699 #endif
700 EGLSurface surface = mDispatcher.eglCreateWindowSurface(
701 mDisplay, ((EglOsEglPixelFormat*)pf)->mConfigId, win, surface_attribs.data()
702 );
703 CHECK_EGL_ERR
704 if (surface == EGL_NO_SURFACE) {
705 D("create window surface failed\n");
706 return nullptr;
707 }
708 return new EglOsEglSurface(EglOS::Surface::WINDOW, surface, win);
709 }
710
releasePbuffer(Surface * pb)711 bool EglOsEglDisplay::releasePbuffer(Surface* pb) {
712 D("%s\n", __FUNCTION__);
713 if (!pb)
714 return false;
715 EglOsEglSurface* surface = (EglOsEglSurface*)pb;
716
717 if (!surface->getHndl()) {
718 delete surface;
719 return true;
720 }
721
722 bool ret = mDispatcher.eglDestroySurface(mDisplay, surface->getHndl());
723 CHECK_EGL_ERR
724 D("%s done\n", __FUNCTION__);
725 delete surface;
726 return ret;
727 }
728
makeCurrent(Surface * read,Surface * draw,Context * context)729 bool EglOsEglDisplay::makeCurrent(Surface* read,
730 Surface* draw,
731 Context* context) {
732 D("%s\n", __FUNCTION__);
733 EglOsEglSurface* readSfc = (EglOsEglSurface*)read;
734 EglOsEglSurface* drawSfc = (EglOsEglSurface*)draw;
735 EglOsEglContext* ctx = (EglOsEglContext*)context;
736 if (ctx && !readSfc) {
737 D("warning: makeCurrent a context without surface\n");
738 return false;
739 }
740 D("%s %p\n", __FUNCTION__, ctx ? ctx->context() : nullptr);
741 bool ret = mDispatcher.eglMakeCurrent(
742 mDisplay, drawSfc ? drawSfc->getHndl() : EGL_NO_SURFACE,
743 readSfc ? readSfc->getHndl() : EGL_NO_SURFACE,
744 ctx ? ctx->context() : EGL_NO_CONTEXT);
745 if (readSfc) {
746 D("make current surface type %d %d\n", readSfc->type(),
747 drawSfc->type());
748 }
749 D("make current %d\n", ret);
750 CHECK_EGL_ERR
751 return ret;
752 }
753
swapBuffers(Surface * surface)754 void EglOsEglDisplay::swapBuffers(Surface* surface) {
755 D("%s\n", __FUNCTION__);
756 EglOsEglSurface* sfc = (EglOsEglSurface*)surface;
757 mDispatcher.eglSwapBuffers(mDisplay, sfc->getHndl());
758 }
759
releaseThread()760 EGLBoolean EglOsEglDisplay::releaseThread() {
761 D("%s\n", __FUNCTION__);
762 return mDispatcher.eglReleaseThread();
763 }
764
isValidNativeWin(Surface * win)765 bool EglOsEglDisplay::isValidNativeWin(Surface* win) {
766 if (!win) {
767 return false;
768 }
769 EglOsEglSurface* surface = (EglOsEglSurface*)win;
770 return surface->type() == EglOsEglSurface::WINDOW &&
771 isValidNativeWin(surface->getWin());
772 }
773
isValidNativeWin(EGLNativeWindowType win)774 bool EglOsEglDisplay::isValidNativeWin(EGLNativeWindowType win) {
775 #ifdef _WIN32
776 return IsWindow(win);
777 #elif defined(ANDROID)
778 return true;
779 #elif defined(__linux__)
780 Window root;
781 int t;
782 unsigned int u;
783 X11ErrorHandler handler(mGlxDisplay);
784 return getX11Api()->XGetGeometry(mGlxDisplay, win, &root, &t, &t, &u, &u, &u, &u) != 0;
785 #elif defined(__QNX__)
786 int size[2];
787 return screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, size) != -1;
788 #else // __APPLE__
789 unsigned int width, height;
790 return nsGetWinDims(win, &width, &height);
791 #endif // __APPLE__
792 }
793
checkWindowPixelFormatMatch(EGLNativeWindowType win,const PixelFormat * pixelFormat,unsigned int * width,unsigned int * height)794 bool EglOsEglDisplay::checkWindowPixelFormatMatch(EGLNativeWindowType win,
795 const PixelFormat* pixelFormat,
796 unsigned int* width,
797 unsigned int* height) {
798 #ifdef _WIN32
799 RECT r;
800 if (!GetClientRect(win, &r)) {
801 return false;
802 }
803 *width = r.right - r.left;
804 *height = r.bottom - r.top;
805 return true;
806 #elif defined(ANDROID)
807 *width = ANativeWindow_getWidth((ANativeWindow*)win);
808 *height = ANativeWindow_getHeight((ANativeWindow*)win);
809 return true;
810 #elif defined(__linux__)
811 //TODO: to check what does ATI & NVIDIA enforce on win pixelformat
812 unsigned int depth, border;
813 int x, y;
814 Window root;
815 X11ErrorHandler handler(mGlxDisplay);
816 return getX11Api()->XGetGeometry(
817 mGlxDisplay, win, &root, &x, &y, width, height, &border, &depth);
818 #elif defined(__QNX__)
819 int size[2];
820 if (screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, size) == -1) {
821 return false;
822 }
823 *width = size[0];
824 *height = size[1];
825 return true;
826 #else // __APPLE__
827 bool ret = nsGetWinDims(win, width, height);
828
829 const EglOsEglPixelFormat* format = (EglOsEglPixelFormat*)pixelFormat;
830 int r = format->mRedSize;
831 int g = format->mGreenSize;
832 int b = format->mBlueSize;
833
834 bool match = nsCheckColor(win, r + g + b);
835
836 return ret && match;
837 #endif // __APPLE__
838 }
839
sHostDisplay(bool nullEgl=false)840 static EglOsEglDisplay* sHostDisplay(bool nullEgl = false) {
841 static EglOsEglDisplay* d = new EglOsEglDisplay(nullEgl);
842 return d;
843 }
844
845 class EglEngine : public EglOS::Engine {
846 public:
EglEngine(bool nullEgl)847 EglEngine(bool nullEgl)
848 :
849 #ifdef __QNX__ // Ensure libEGL is loaded prior to libGLES
850 mDisplay(sHostDisplay(nullEgl)),
851 #endif
852 EglOS::Engine(),
853 mUseNullEgl(nullEgl) {
854 }
855
856 ~EglEngine() = default;
857
getDefaultDisplay()858 EglOS::Display* getDefaultDisplay() {
859 D("%s\n", __FUNCTION__);
860 return sHostDisplay(mUseNullEgl);
861 }
getGlLibrary()862 GlLibrary* getGlLibrary() {
863 D("%s\n", __FUNCTION__);
864 return &mGlLib;
865 }
eglGetProcAddress(const char * func)866 void* eglGetProcAddress(const char* func) { return sHostDisplay()->eglGetProcAddress(func); }
createWindowSurface(PixelFormat * pf,EGLNativeWindowType wnd)867 virtual EglOS::Surface* createWindowSurface(PixelFormat* pf, EGLNativeWindowType wnd) {
868 D("%s\n", __FUNCTION__);
869 return sHostDisplay()->createWindowSurface(pf, wnd);
870 }
871
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attribs)872 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib* attribs) override {
873 return sHostDisplay()->eglDebugMessageControlKHR(callback, attribs);
874 }
875
876 private:
877 #ifdef __QNX__
878 EglOsEglDisplay* mDisplay;
879 #endif
880 EglOsGlLibrary mGlLib;
881 bool mUseNullEgl;
882 };
883
884 } // namespace
885
sHostEngine(bool nullEgl)886 static EglEngine* sHostEngine(bool nullEgl) {
887 static EglEngine* res = new EglEngine(nullEgl);
888 return res;
889 }
890
891 namespace EglOS {
getEgl2EglHostInstance(bool nullEgl)892 Engine* getEgl2EglHostInstance(bool nullEgl) {
893 D("%s\n", __FUNCTION__);
894 return sHostEngine(nullEgl);
895 }
896 } // namespace EglOS
897