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