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