• 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 "base/System.h"
20 #include "base/SharedLibrary.h"
21 #include "host-common/logging.h"
22 #include "host-common/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 #endif
33 
34 #include <EGL/egl.h>
35 #include <EGL/eglext.h>
36 #include <EGL/eglext_angle.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;
320     EglOsEglDispatcher mDispatcher;
321     bool mHeadless = false;
322     std::string mClientExts;
323     std::string mVendor;
324 
325 #ifdef __linux__
326     ::Display* mGlxDisplay = nullptr;
327 #endif // __linux__
328 };
329 
EglOsEglDisplay(bool nullEgl)330 EglOsEglDisplay::EglOsEglDisplay(bool nullEgl) {
331     mVerbose = android::base::getEnvironmentVariable("ANDROID_EMUGL_VERBOSE") == "1";
332 
333     if (nullEgl) {
334         const EGLAttrib attr[] = {
335             EGL_PLATFORM_ANGLE_TYPE_ANGLE,
336             EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE,
337             EGL_NONE
338         };
339 
340         mDisplay = mDispatcher.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
341             (void*)EGL_DEFAULT_DISPLAY,
342             attr);
343 
344         if (mDisplay == EGL_NO_DISPLAY) {
345             fprintf(stderr, "%s: no display found that supports null backend\n", __func__);
346         }
347     } else if (android::base::getEnvironmentVariable("ANDROID_EMUGL_EXPERIMENTAL_FAST_PATH") == "1") {
348         const EGLAttrib attr[] = {
349             EGL_PLATFORM_ANGLE_TYPE_ANGLE,
350             EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
351             EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE,
352             EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE,
353             EGL_NONE
354         };
355 
356         mDisplay = mDispatcher.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
357             (void*)EGL_DEFAULT_DISPLAY,
358             attr);
359 
360         if (mDisplay == EGL_NO_DISPLAY) {
361             fprintf(stderr, "%s: no display found that supports the requested extensions\n", __func__);
362         }
363     }
364     else {
365         mDisplay = mDispatcher.eglGetDisplay(EGL_DEFAULT_DISPLAY);
366     }
367 
368     mDispatcher.eglInitialize(mDisplay, nullptr, nullptr);
369     mDispatcher.eglSwapInterval(mDisplay, 0);
370     auto clientExts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
371     auto vendor = mDispatcher.eglQueryString(mDisplay, EGL_VENDOR);
372 
373     if (mVerbose) {
374         fprintf(stderr, "%s: client exts: [%s]\n", __func__, clientExts);
375     }
376 
377     if (clientExts) {
378         mClientExts = clientExts;
379     }
380 
381     if (vendor) {
382         mVendor = vendor;
383     }
384 
385     mDispatcher.eglBindAPI(EGL_OPENGL_ES_API);
386     CHECK_EGL_ERR
387 
388     mHeadless = android::base::getEnvironmentVariable("ANDROID_EMU_HEADLESS") == "1";
389 
390 #ifdef ANDROID
391     mGlxDisplay = nullptr;
392 #elif defined(__linux__)
393     if (mHeadless) mGlxDisplay = nullptr;
394     else mGlxDisplay = getX11Api()->XOpenDisplay(0);
395 #endif // __linux__
396 
397     if (clientExts != nullptr && emugl::hasExtension(clientExts, "EGL_ANDROID_blob_cache")) {
398         mDispatcher.eglSetBlobCacheFuncsANDROID(mDisplay, SetBlob, GetBlob);
399     }
400 };
401 
~EglOsEglDisplay()402 EglOsEglDisplay::~EglOsEglDisplay() {
403 #ifdef ANDROID
404 #elif defined(__linux__)
405     if (mGlxDisplay) getX11Api()->XCloseDisplay(mGlxDisplay);
406 #endif // __linux__
407 }
408 
getMaxGlesVersion()409 EglOS::GlesVersion EglOsEglDisplay::getMaxGlesVersion() {
410     // TODO: Detect and return the highest version like in GLESVersionDetector.cpp
411     // GLES3.2 will also need some more autogen + enums if anyone is interested.
412     return EglOS::GlesVersion::ES31;
413 }
414 
getExtensionString()415 const char* EglOsEglDisplay::getExtensionString() {
416     return mClientExts.c_str();
417 }
418 
getVendorString()419 const char* EglOsEglDisplay::getVendorString() {
420     return mVendor.c_str();
421 }
422 
createImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)423 EGLImage EglOsEglDisplay::createImageKHR(
424         EGLDisplay dpy,
425         EGLContext ctx,
426         EGLenum target,
427         EGLClientBuffer buffer,
428         const EGLint *attrib_list) {
429     if (mDispatcher.eglCreateImageKHR) {
430         return mDispatcher.eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
431     } else {
432         return EGL_NO_IMAGE_KHR;
433     }
434 }
435 
destroyImageKHR(EGLDisplay dpy,EGLImage image)436 EGLBoolean EglOsEglDisplay::destroyImageKHR(
437         EGLDisplay dpy,
438         EGLImage image) {
439     if (mDispatcher.eglDestroyImage) {
440         return mDispatcher.eglDestroyImageKHR(dpy, image);
441     } else {
442         return EGL_FALSE;
443     }
444 }
445 
getNative()446 EGLDisplay EglOsEglDisplay::getNative() {
447     return mDisplay;
448 }
449 
queryConfigs(int renderableType,AddConfigCallback * addConfigFunc,void * addConfigOpaque)450 void EglOsEglDisplay::queryConfigs(int renderableType,
451                                    AddConfigCallback* addConfigFunc,
452                                    void* addConfigOpaque) {
453     D("%s\n", __FUNCTION__);
454     // ANGLE does not support GLES1 uses core profile engine.
455     // Querying underlying EGL with a conservative set of bits.
456     renderableType &= ~EGL_OPENGL_ES_BIT;
457 
458     const EGLint framebuffer_config_attributes[] = {
459         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
460         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
461         EGL_RED_SIZE, 1,
462         EGL_GREEN_SIZE, 1,
463         EGL_BLUE_SIZE, 1,
464         EGL_ALPHA_SIZE, 0,
465         EGL_NONE,
466     };
467 
468     EGLint numConfigs = 0;
469     mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, nullptr, 0, &numConfigs);
470     CHECK_EGL_ERR
471     std::unique_ptr<EGLConfig[]> configs(new EGLConfig[numConfigs]);
472     mDispatcher.eglChooseConfig(mDisplay, framebuffer_config_attributes, configs.get(), numConfigs,
473                                 &numConfigs);
474     CHECK_EGL_ERR
475 
476     if (mVerbose) {
477         fprintf(stderr, "%s: num configs: %d\n", __func__, numConfigs);
478     }
479 
480     for (int i = 0; i < numConfigs; i++) {
481         const EGLConfig cfg = configs.get()[i];
482         ConfigInfo configInfo;
483         // We do not have recordable_android
484         configInfo.recordable_android = 0;
485         EGLint _renderableType;
486         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RENDERABLE_TYPE,
487                                        &_renderableType);
488         // We do emulate GLES1
489         configInfo.renderable_type = _renderableType | EGL_OPENGL_ES_BIT;
490 
491         configInfo.frmt = new EglOsEglPixelFormat(cfg, _renderableType);
492         D("config %p renderable type 0x%x\n", cfg, _renderableType);
493 
494         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_RED_SIZE,
495                                        &configInfo.red_size);
496         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_GREEN_SIZE,
497                                        &configInfo.green_size);
498         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_BLUE_SIZE,
499                                        &configInfo.blue_size);
500         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_ALPHA_SIZE,
501                                        &configInfo.alpha_size);
502 
503         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_CONFIG_CAVEAT,
504                                        (EGLint*)&configInfo.caveat);
505         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_DEPTH_SIZE,
506                                        &configInfo.depth_size);
507         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_LEVEL,
508                                        &configInfo.frame_buffer_level);
509 
510         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_WIDTH,
511                                        &configInfo.max_pbuffer_width);
512         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_HEIGHT,
513                                        &configInfo.max_pbuffer_height);
514         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_MAX_PBUFFER_PIXELS,
515                                        &configInfo.max_pbuffer_size);
516 
517         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_RENDERABLE,
518                                        (EGLint*)&configInfo.native_renderable);
519         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_ID,
520                                        &configInfo.native_visual_id);
521         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_NATIVE_VISUAL_TYPE,
522                                        &configInfo.native_visual_type);
523 
524         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SAMPLES,
525                                        &configInfo.samples_per_pixel);
526         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_STENCIL_SIZE,
527                                        &configInfo.stencil_size);
528 
529         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_SURFACE_TYPE,
530                                        &configInfo.surface_type);
531         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_TYPE,
532                                        (EGLint*)&configInfo.transparent_type);
533         mDispatcher.eglGetConfigAttrib(mDisplay, cfg, EGL_TRANSPARENT_RED_VALUE,
534                                        &configInfo.trans_red_val);
535         mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
536                                        EGL_TRANSPARENT_GREEN_VALUE,
537                                        &configInfo.trans_green_val);
538         mDispatcher.eglGetConfigAttrib(mDisplay, cfg,
539                                        EGL_TRANSPARENT_BLUE_VALUE,
540                                        &configInfo.trans_blue_val);
541         CHECK_EGL_ERR
542 #ifdef __APPLE__
543         ((EglOsEglPixelFormat*)configInfo.frmt)->mRedSize = configInfo.red_size;
544         ((EglOsEglPixelFormat*)configInfo.frmt)->mGreenSize = configInfo.green_size;
545         ((EglOsEglPixelFormat*)configInfo.frmt)->mBlueSize = configInfo.blue_size;
546 #endif // __APPLE__
547         addConfigFunc(addConfigOpaque, &configInfo);
548     }
549     D("Host gets %d configs\n", numConfigs);
550 }
551 
552 std::shared_ptr<Context>
createContext(EGLint profileMask,const PixelFormat * pixelFormat,Context * sharedContext)553 EglOsEglDisplay::createContext(EGLint profileMask,
554                                const PixelFormat* pixelFormat,
555                                Context* sharedContext) {
556     (void)profileMask;
557 
558     D("%s\n", __FUNCTION__);
559     const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
560     D("with config %p\n", format->mConfigId);
561 
562     // Always GLES3
563     std::vector<EGLint> attributes = { EGL_CONTEXT_CLIENT_VERSION, 3 };
564     auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
565     auto vendor = mDispatcher.eglQueryString(mDisplay, EGL_VENDOR);
566 
567     // TODO (b/207426737): remove Imagination-specific workaround
568     bool disable_robustness = vendor && (strcmp(vendor, "Imagination Technologies") == 0);
569 
570     bool disableValidation = android::base::getEnvironmentVariable("ANDROID_EMUGL_EGL_VALIDATION") == "0";
571     if (exts != nullptr && emugl::hasExtension(exts, "EGL_KHR_create_context_no_error") && disableValidation) {
572         attributes.push_back(EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
573         attributes.push_back(EGL_TRUE);
574     }
575 
576     if (exts != nullptr && emugl::hasExtension(exts, "EGL_EXT_create_context_robustness") && !disable_robustness) {
577         attributes.push_back(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
578         attributes.push_back(EGL_LOSE_CONTEXT_ON_RESET_EXT);
579     }
580     attributes.push_back(EGL_NONE);
581 
582     // TODO: support GLES3.1
583     EglOsEglContext* nativeSharedCtx = (EglOsEglContext*)sharedContext;
584     EGLContext newNativeCtx = mDispatcher.eglCreateContext(
585             mDisplay, format->mConfigId,
586             nativeSharedCtx ? nativeSharedCtx->context() : nullptr,
587             attributes.data());
588     CHECK_EGL_ERR
589     std::shared_ptr<Context> res =
590         std::make_shared<EglOsEglContext>(
591             &mDispatcher, mDisplay, newNativeCtx);
592     D("%s done\n", __FUNCTION__);
593     return res;
594 }
595 
createPbufferSurface(const PixelFormat * pixelFormat,const PbufferInfo * info)596 Surface* EglOsEglDisplay::createPbufferSurface(const PixelFormat* pixelFormat,
597                                                const PbufferInfo* info) {
598     // D("%s\n", __FUNCTION__);
599     // const EglOsEglPixelFormat* format = (const EglOsEglPixelFormat*)pixelFormat;
600     // EGLint attrib[] = {EGL_WIDTH,
601     //                    info->width,
602     //                    EGL_HEIGHT,
603     //                    info->height,
604     //                    EGL_LARGEST_PBUFFER,
605     //                    info->largest,
606     //                    EGL_TEXTURE_FORMAT,
607     //                    info->format,
608     //                    EGL_TEXTURE_TARGET,
609     //                    info->target,
610     //                    EGL_MIPMAP_TEXTURE,
611     //                    info->hasMipmap,
612     //                    EGL_NONE};
613     // EGLSurface surface = mDispatcher.eglCreatePbufferSurface(
614     //         mDisplay, format->mConfigId, attrib);
615     // CHECK_EGL_ERR
616     // if (surface == EGL_NO_SURFACE) {
617     //     D("create pbuffer surface failed\n");
618     //     return nullptr;
619     // }
620     // return new EglOsEglSurface(EglOS::Surface::PBUFFER, surface);
621     return new EglOsEglSurface(EglOS::Surface::PBUFFER, 0);
622 }
623 
createWindowSurface(PixelFormat * pf,EGLNativeWindowType win)624 Surface* EglOsEglDisplay::createWindowSurface(PixelFormat* pf,
625                                               EGLNativeWindowType win) {
626     D("%s\n", __FUNCTION__);
627     std::vector<EGLint> surface_attribs;
628     auto exts = mDispatcher.eglQueryString(mDisplay, EGL_EXTENSIONS);
629     if (exts != nullptr && emugl::hasExtension(exts, "EGL_ANGLE_direct_composition")) {
630         surface_attribs.push_back(EGL_DIRECT_COMPOSITION_ANGLE);
631         surface_attribs.push_back(EGL_TRUE);
632     }
633     surface_attribs.push_back(EGL_NONE);
634     EGLSurface surface = mDispatcher.eglCreateWindowSurface(
635             mDisplay, ((EglOsEglPixelFormat*)pf)->mConfigId, win, surface_attribs.data());
636     CHECK_EGL_ERR
637     if (surface == EGL_NO_SURFACE) {
638         D("create window surface failed\n");
639         return nullptr;
640     }
641     return new EglOsEglSurface(EglOS::Surface::WINDOW, surface, win);
642 }
643 
releasePbuffer(Surface * pb)644 bool EglOsEglDisplay::releasePbuffer(Surface* pb) {
645     D("%s\n", __FUNCTION__);
646     if (!pb)
647         return false;
648     EglOsEglSurface* surface = (EglOsEglSurface*)pb;
649 
650     if (!surface->getHndl()) {
651         delete surface;
652         return true;
653     }
654 
655     bool ret = mDispatcher.eglDestroySurface(mDisplay, surface->getHndl());
656     CHECK_EGL_ERR
657     D("%s done\n", __FUNCTION__);
658     delete surface;
659     return ret;
660 }
661 
makeCurrent(Surface * read,Surface * draw,Context * context)662 bool EglOsEglDisplay::makeCurrent(Surface* read,
663                                   Surface* draw,
664                                   Context* context) {
665     D("%s\n", __FUNCTION__);
666     EglOsEglSurface* readSfc = (EglOsEglSurface*)read;
667     EglOsEglSurface* drawSfc = (EglOsEglSurface*)draw;
668     EglOsEglContext* ctx = (EglOsEglContext*)context;
669     if (ctx && !readSfc) {
670         D("warning: makeCurrent a context without surface\n");
671         return false;
672     }
673     D("%s %p\n", __FUNCTION__, ctx ? ctx->context() : nullptr);
674     bool ret = mDispatcher.eglMakeCurrent(
675             mDisplay, drawSfc ? drawSfc->getHndl() : EGL_NO_SURFACE,
676             readSfc ? readSfc->getHndl() : EGL_NO_SURFACE,
677             ctx ? ctx->context() : EGL_NO_CONTEXT);
678     if (readSfc) {
679         D("make current surface type %d %d\n", readSfc->type(),
680           drawSfc->type());
681     }
682     D("make current %d\n", ret);
683     CHECK_EGL_ERR
684     return ret;
685 }
686 
swapBuffers(Surface * surface)687 void EglOsEglDisplay::swapBuffers(Surface* surface) {
688     D("%s\n", __FUNCTION__);
689     EglOsEglSurface* sfc = (EglOsEglSurface*)surface;
690     mDispatcher.eglSwapBuffers(mDisplay, sfc->getHndl());
691 }
692 
releaseThread()693 EGLBoolean EglOsEglDisplay::releaseThread() {
694     D("%s\n", __FUNCTION__);
695     return mDispatcher.eglReleaseThread();
696 }
697 
isValidNativeWin(Surface * win)698 bool EglOsEglDisplay::isValidNativeWin(Surface* win) {
699     if (!win)
700         return false;
701     EglOsEglSurface* surface = (EglOsEglSurface*)win;
702     return surface->type() == EglOsEglSurface::WINDOW &&
703            isValidNativeWin(surface->getWin());
704 }
705 
isValidNativeWin(EGLNativeWindowType win)706 bool EglOsEglDisplay::isValidNativeWin(EGLNativeWindowType win) {
707 #ifdef _WIN32
708     return IsWindow(win);
709 #elif defined(ANDROID)
710     return true;
711 #elif defined(__linux__)
712     Window root;
713     int t;
714     unsigned int u;
715     return getX11Api()->XGetGeometry(mGlxDisplay, win, &root, &t, &t, &u, &u, &u, &u) != 0;
716 #else // __APPLE__
717     unsigned int width, height;
718     return nsGetWinDims(win, &width, &height);
719 #endif // __APPLE__
720 }
721 
checkWindowPixelFormatMatch(EGLNativeWindowType win,const PixelFormat * pixelFormat,unsigned int * width,unsigned int * height)722 bool EglOsEglDisplay::checkWindowPixelFormatMatch(EGLNativeWindowType win,
723                                  const PixelFormat* pixelFormat,
724                                  unsigned int* width,
725                                  unsigned int* height) {
726 #ifdef _WIN32
727     RECT r;
728     if (!GetClientRect(win, &r)) {
729         return false;
730     }
731     *width = r.right - r.left;
732     *height = r.bottom - r.top;
733     return true;
734 #elif defined(ANDROID)
735     *width = ANativeWindow_getWidth((ANativeWindow*)win);
736     *height = ANativeWindow_getHeight((ANativeWindow*)win);
737     return true;
738 #elif defined(__linux__)
739     //TODO: to check what does ATI & NVIDIA enforce on win pixelformat
740     unsigned int depth, border;
741     int x, y;
742     Window root;
743     return getX11Api()->XGetGeometry(
744             mGlxDisplay, win, &root, &x, &y, width, height, &border, &depth);
745 #else // __APPLE__
746     bool ret = nsGetWinDims(win, width, height);
747 
748     const EglOsEglPixelFormat* format = (EglOsEglPixelFormat*)pixelFormat;
749     int r = format->mRedSize;
750     int g = format->mGreenSize;
751     int b = format->mBlueSize;
752 
753     bool match = nsCheckColor(win, r + g + b);
754 
755     return ret && match;
756 #endif // __APPLE__
757 }
758 
sHostDisplay(bool nullEgl=false)759 static EglOsEglDisplay* sHostDisplay(bool nullEgl = false) {
760     static EglOsEglDisplay* d = new EglOsEglDisplay(nullEgl);
761     return d;
762 }
763 
764 class EglEngine : public EglOS::Engine {
765 public:
EglEngine(bool nullEgl)766     EglEngine(bool nullEgl) : EglOS::Engine(), mUseNullEgl(nullEgl) {}
767     ~EglEngine() = default;
768 
getDefaultDisplay()769     EglOS::Display* getDefaultDisplay() {
770         D("%s\n", __FUNCTION__);
771         return sHostDisplay(mUseNullEgl);
772     }
getGlLibrary()773     GlLibrary* getGlLibrary() {
774         D("%s\n", __FUNCTION__);
775         return &mGlLib;
776     }
eglGetProcAddress(const char * func)777     void* eglGetProcAddress(const char* func) {
778         return sHostDisplay()->eglGetProcAddress(func);
779     }
createWindowSurface(PixelFormat * pf,EGLNativeWindowType wnd)780     virtual EglOS::Surface* createWindowSurface(PixelFormat* pf,
781                                                 EGLNativeWindowType wnd) {
782         D("%s\n", __FUNCTION__);
783         return sHostDisplay()->createWindowSurface(pf, wnd);
784     }
785 
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attribs)786     EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib* attribs) override {
787         return sHostDisplay()->eglDebugMessageControlKHR(callback, attribs);
788     }
789 
790 private:
791     EglOsGlLibrary mGlLib;
792     bool mUseNullEgl;
793 };
794 
795 }  // namespace
796 
sHostEngine(bool nullEgl)797 static EglEngine* sHostEngine(bool nullEgl) {
798     static EglEngine* res = new EglEngine(nullEgl);
799     return res;
800 }
801 
802 namespace EglOS {
getEgl2EglHostInstance(bool nullEgl)803 Engine* getEgl2EglHostInstance(bool nullEgl) {
804     D("%s\n", __FUNCTION__);
805     return sHostEngine(nullEgl);
806 }
807 }  // namespace EglOS
808