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