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