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