• 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 "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