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