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