1 // Copyright (C) 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "EmulationGl.h"
16
17 #include <algorithm>
18 #include <cstring>
19 #include <optional>
20 #include <vector>
21
22 #include "DisplaySurfaceGl.h"
23 #include "GLESVersionDetector.h"
24 #include "OpenGLESDispatch/DispatchTables.h"
25 #include "OpenGLESDispatch/EGLDispatch.h"
26 #include "OpenGLESDispatch/GLESv2Dispatch.h"
27 #include "OpenGLESDispatch/OpenGLDispatchLoader.h"
28 #include "RenderThreadInfoGl.h"
29 #include "aemu/base/misc/StringUtils.h"
30 #include "host-common/GfxstreamFatalError.h"
31 #include "host-common/feature_control.h"
32 #include "host-common/logging.h"
33 #include "host-common/opengl/misc.h"
34
35 namespace gfxstream {
36 namespace gl {
37 namespace {
38
EglDebugCallback(EGLenum error,const char * command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char * message)39 static void EGLAPIENTRY EglDebugCallback(EGLenum error,
40 const char *command,
41 EGLint messageType,
42 EGLLabelKHR threadLabel,
43 EGLLabelKHR objectLabel,
44 const char *message) {
45 GL_LOG("command:%s message:%s", command, message);
46 }
47
GlDebugCallback(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)48 static void GL_APIENTRY GlDebugCallback(GLenum source,
49 GLenum type,
50 GLuint id,
51 GLenum severity,
52 GLsizei length,
53 const GLchar *message,
54 const void *userParam) {
55 GL_LOG("message:%s", message);
56 }
57
58 static const GLint kGles2ContextAttribsESOrGLCompat[] = {
59 EGL_CONTEXT_CLIENT_VERSION, 2, //
60 EGL_NONE, //
61 };
62
63 static const GLint kGles2ContextAttribsCoreGL[] = {
64 EGL_CONTEXT_CLIENT_VERSION, 2, //
65 EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, //
66 EGL_NONE, //
67 };
68
69 static const GLint kGles3ContextAttribsESOrGLCompat[] = {
70 EGL_CONTEXT_CLIENT_VERSION, 3, //
71 EGL_NONE, //
72 };
73
74 static const GLint kGles3ContextAttribsCoreGL[] = {
75 EGL_CONTEXT_CLIENT_VERSION, 3, //
76 EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, //
77 EGL_NONE, //
78 };
79
validateGles2Context(EGLDisplay display)80 static bool validateGles2Context(EGLDisplay display) {
81 const GLint configAttribs[] = {
82 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
83 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
84 EGL_NONE,
85 };
86
87 EGLint numConfigs = 0;
88 EGLConfig config;
89 if (!s_egl.eglChooseConfig(display, configAttribs, &config, 1, &numConfigs)) {
90 ERR("Failed to find GLES 2.x config.");
91 return false;
92 }
93 if (numConfigs != 1) {
94 ERR("Failed to find exactly 1 GLES 2.x config: found %d.", numConfigs);
95 return false;
96 }
97
98 const EGLint surfaceAttribs[] = {
99 EGL_WIDTH, 1,
100 EGL_HEIGHT, 1,
101 EGL_NONE,
102 };
103
104 EGLSurface surface = s_egl.eglCreatePbufferSurface(display, config, surfaceAttribs);
105 if (surface == EGL_NO_SURFACE) {
106 ERR("Failed to create GLES 2.x pbuffer surface.");
107 return false;
108 }
109
110 const GLint* contextAttribs = EmulationGl::getGlesMaxContextAttribs();
111 EGLContext context = s_egl.eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
112 if (context == EGL_NO_CONTEXT) {
113 ERR("Failed to create GLES 2.x context.");
114 s_egl.eglDestroySurface(display, surface);
115 return false;
116 }
117
118 if (!s_egl.eglMakeCurrent(display, surface, surface, context)) {
119 ERR("Failed to make GLES 2.x context current.");
120 s_egl.eglDestroySurface(display, surface);
121 s_egl.eglDestroyContext(display, context);
122 return false;
123 }
124
125 const char* extensions = (const char*)s_gles2.glGetString(GL_EXTENSIONS);
126 if (extensions == nullptr) {
127 ERR("Failed to query GLES 2.x context extensions.");
128 s_egl.eglDestroySurface(display, surface);
129 s_egl.eglDestroyContext(display, context);
130 return false;
131 }
132
133 // It is rare but some drivers actually fail this...
134 if (!s_egl.eglMakeCurrent(display, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE)) {
135 ERR("Failed to unbind GLES 2.x context.");
136 s_egl.eglDestroySurface(display, surface);
137 s_egl.eglDestroyContext(display, context);
138 return false;
139 }
140
141 s_egl.eglDestroyContext(display, context);
142 s_egl.eglDestroySurface(display, surface);
143 return true;
144 }
145
getEmulationEglConfig(EGLDisplay display,bool allowWindowSurface)146 static std::optional<EGLConfig> getEmulationEglConfig(EGLDisplay display, bool allowWindowSurface) {
147 GLint surfaceType = EGL_PBUFFER_BIT;
148
149 if (allowWindowSurface) {
150 surfaceType |= EGL_WINDOW_BIT;
151 }
152
153 // On Linux, we need RGB888 exactly, or eglMakeCurrent will fail,
154 // as glXMakeContextCurrent needs to match the format of the
155 // native pixmap.
156 constexpr const EGLint kWantedRedSize = 8;
157 constexpr const EGLint kWantedGreenSize = 8;
158 constexpr const EGLint kWantedBlueSize = 8;
159
160 const GLint configAttribs[] = {
161 EGL_RED_SIZE, kWantedRedSize, //
162 EGL_GREEN_SIZE, kWantedGreenSize, //
163 EGL_BLUE_SIZE, kWantedBlueSize, //
164 EGL_SURFACE_TYPE, surfaceType, //
165 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //
166 EGL_NONE, //
167 };
168
169 EGLint numConfigs = 0;
170 s_egl.eglGetConfigs(display, nullptr, 0, &numConfigs);
171
172 std::vector<EGLConfig> configs(numConfigs);
173
174 EGLint numMatchedConfigs = 0;
175 s_egl.eglChooseConfig(display, configAttribs, configs.data(), numConfigs, &numMatchedConfigs);
176
177 configs.resize(numMatchedConfigs);
178
179 for (EGLConfig config : configs) {
180 EGLint foundRedSize = 0;
181 s_egl.eglGetConfigAttrib(display, config, EGL_RED_SIZE, &foundRedSize);
182 if (foundRedSize != kWantedRedSize) {
183 continue;
184 }
185
186 EGLint foundGreenSize = 0;
187 s_egl.eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &foundGreenSize);
188 if (foundGreenSize != kWantedGreenSize) {
189 continue;
190 }
191
192 EGLint foundBlueSize = 0;
193 s_egl.eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &foundBlueSize);
194 if (foundBlueSize != kWantedBlueSize) {
195 continue;
196 }
197
198 return config;
199 }
200
201 return std::nullopt;
202 }
203
204 } // namespace
205
create(uint32_t width,uint32_t height,gfxstream::host::FeatureSet features,bool allowWindowSurface,bool egl2egl)206 std::unique_ptr<EmulationGl> EmulationGl::create(uint32_t width, uint32_t height,
207 gfxstream::host::FeatureSet features,
208 bool allowWindowSurface, bool egl2egl) {
209 // Loads the glestranslator function pointers.
210 if (!LazyLoadedEGLDispatch::get()) {
211 ERR("Failed to load EGL dispatch.");
212 return nullptr;
213 }
214 if (!LazyLoadedGLESv1Dispatch::get()) {
215 ERR("Failed to load GLESv1 dispatch.");
216 return nullptr;
217 }
218 if (!LazyLoadedGLESv2Dispatch::get()) {
219 ERR("Failed to load GLESv2 dispatch.");
220 return nullptr;
221 }
222
223 if (s_egl.eglUseOsEglApi) {
224 s_egl.eglUseOsEglApi(egl2egl, EGL_FALSE);
225 }
226
227
228 std::unique_ptr<EmulationGl> emulationGl(new EmulationGl());
229
230 emulationGl->mFeatures = features;
231 emulationGl->mWidth = width;
232 emulationGl->mHeight = height;
233
234 emulationGl->mEglDisplay = s_egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
235 if (emulationGl->mEglDisplay == EGL_NO_DISPLAY) {
236 ERR("Failed to get EGL display.");
237 return nullptr;
238 }
239
240 GL_LOG("call eglInitialize");
241 if (!s_egl.eglInitialize(emulationGl->mEglDisplay,
242 &emulationGl->mEglVersionMajor,
243 &emulationGl->mEglVersionMinor)) {
244 ERR("Failed to eglInitialize.");
245 return nullptr;
246 }
247
248 if (s_egl.eglSetNativeTextureDecompressionEnabledANDROID) {
249 s_egl.eglSetNativeTextureDecompressionEnabledANDROID(
250 emulationGl->mEglDisplay,
251 emulationGl->mFeatures.NativeTextureDecompression.enabled);
252 }
253
254 if (s_egl.eglSetProgramBinaryLinkStatusEnabledANDROID) {
255 s_egl.eglSetProgramBinaryLinkStatusEnabledANDROID(
256 emulationGl->mEglDisplay,
257 emulationGl->mFeatures.GlProgramBinaryLinkStatus.enabled);
258 }
259
260 s_egl.eglBindAPI(EGL_OPENGL_ES_API);
261
262 #ifdef ENABLE_GL_LOG
263 if (s_egl.eglDebugMessageControlKHR) {
264 const EGLAttrib controls[] = {
265 EGL_DEBUG_MSG_CRITICAL_KHR,
266 EGL_TRUE,
267 EGL_DEBUG_MSG_ERROR_KHR,
268 EGL_TRUE,
269 EGL_DEBUG_MSG_WARN_KHR,
270 EGL_TRUE,
271 EGL_DEBUG_MSG_INFO_KHR,
272 EGL_FALSE,
273 EGL_NONE,
274 EGL_NONE,
275 };
276
277 if (s_egl.eglDebugMessageControlKHR(&EglDebugCallback, controls) == EGL_SUCCESS) {
278 GL_LOG("Successfully set eglDebugMessageControlKHR");
279 } else {
280 GL_LOG("Failed to eglDebugMessageControlKHR");
281 }
282 } else {
283 GL_LOG("eglDebugMessageControlKHR not available");
284 }
285 #endif
286
287 emulationGl->mEglVendor = s_egl.eglQueryString(emulationGl->mEglDisplay, EGL_VENDOR);
288
289 const std::string eglExtensions = s_egl.eglQueryString(emulationGl->mEglDisplay, EGL_EXTENSIONS);
290 android::base::split<std::string>(eglExtensions, " ",
291 [&](const std::string& found) {
292 emulationGl->mEglExtensions.insert(found);
293 });
294
295 if (!emulationGl->hasEglExtension("EGL_KHR_gl_texture_2D_image")) {
296 ERR("Failed to find required EGL_KHR_gl_texture_2D_image extension.");
297 return nullptr;
298 }
299
300 emulationGl->mGlesDispatchMaxVersion
301 = calcMaxVersionFromDispatch(emulationGl->mFeatures, emulationGl->mEglDisplay);
302 if (s_egl.eglSetMaxGLESVersion) {
303 // eglSetMaxGLESVersion must be called before any context binding
304 // because it changes how we initialize the dispatcher table.
305 s_egl.eglSetMaxGLESVersion(emulationGl->mGlesDispatchMaxVersion);
306 }
307
308 int glesVersionMajor;
309 int glesVersionMinor;
310 emugl::getGlesVersion(&glesVersionMajor, &glesVersionMinor);
311 emulationGl->mGlesVersionMajor = glesVersionMajor;
312 emulationGl->mGlesVersionMinor = glesVersionMinor;
313
314 if (!validateGles2Context(emulationGl->mEglDisplay)) {
315 ERR("Failed to validate creating GLES 2.x context.");
316 return nullptr;
317 }
318
319 // TODO (b/207426737): Remove the Imagination-specific workaround.
320 const bool disableFastBlit =
321 emulationGl->mEglVendor.find("Imagination Technologies") != std::string::npos;
322
323 emulationGl->mFastBlitSupported =
324 (emulationGl->mGlesDispatchMaxVersion > GLES_DISPATCH_MAX_VERSION_2) &&
325 !disableFastBlit &&
326 (emugl::getRenderer() == SELECTED_RENDERER_HOST ||
327 emugl::getRenderer() == SELECTED_RENDERER_SWIFTSHADER_INDIRECT ||
328 emugl::getRenderer() == SELECTED_RENDERER_ANGLE_INDIRECT);
329
330 auto eglConfigOpt = getEmulationEglConfig(emulationGl->mEglDisplay, allowWindowSurface);
331 if (!eglConfigOpt) {
332 ERR("Failed to find config for emulation GL.");
333 return nullptr;
334 }
335 emulationGl->mEglConfig = *eglConfigOpt;
336
337 const GLint* maxContextAttribs = getGlesMaxContextAttribs();
338
339 emulationGl->mEglContext = s_egl.eglCreateContext(emulationGl->mEglDisplay,
340 emulationGl->mEglConfig,
341 EGL_NO_CONTEXT,
342 maxContextAttribs);
343 if (emulationGl->mEglContext == EGL_NO_CONTEXT) {
344 ERR("Failed to create context, error 0x%x.", s_egl.eglGetError());
345 return nullptr;
346 }
347
348 // Create another context which shares with the default context to be
349 // used when we bind the pbuffer. This prevents switching the drawable
350 // binding back and forth on the framebuffer context.
351 // The main purpose of it is to solve a "blanking" behaviour we see on
352 // on Mac platform when switching binded drawable for a context however
353 // it is more efficient on other platforms as well.
354 auto pbufferSurfaceGl = DisplaySurfaceGl::createPbufferSurface(emulationGl->mEglDisplay,
355 emulationGl->mEglConfig,
356 emulationGl->mEglContext,
357 maxContextAttribs,
358 /*width=*/1,
359 /*height=*/1);
360 if (!pbufferSurfaceGl) {
361 ERR("Failed to create pbuffer display surface.");
362 return nullptr;
363 }
364 auto* pbufferSurfaceGlPtr = pbufferSurfaceGl.get();
365
366 emulationGl->mPbufferSurface = std::make_unique<gfxstream::DisplaySurface>(
367 /*width=*/1,
368 /*height=*/1,
369 std::move(pbufferSurfaceGl));
370
371 emulationGl->mEmulatedEglConfigs =
372 std::make_unique<EmulatedEglConfigList>(emulationGl->mEglDisplay,
373 emulationGl->mGlesDispatchMaxVersion,
374 emulationGl->mFeatures);
375 if (emulationGl->mEmulatedEglConfigs->empty()) {
376 ERR("Failed to initialize emulated configs.");
377 return nullptr;
378 }
379
380 const bool hasEsOrEs2Context =
381 std::any_of(emulationGl->mEmulatedEglConfigs->begin(),
382 emulationGl->mEmulatedEglConfigs->end(),
383 [](const EmulatedEglConfig& config) {
384 const GLint renderableType = config.getRenderableType();
385 return renderableType & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
386 });
387 if (!hasEsOrEs2Context) {
388 ERR("Failed to find any usable guest EGL configs.");
389 return nullptr;
390 }
391
392 RecursiveScopedContextBind contextBind(pbufferSurfaceGlPtr->getContextHelper());
393 if (!contextBind.isOk()) {
394 ERR("Failed to make pbuffer context and surface current");
395 return nullptr;
396 }
397
398 #ifdef ENABLE_GL_LOG
399 bool debugSetup = false;
400 if (s_gles2.glDebugMessageCallback) {
401 s_gles2.glEnable(GL_DEBUG_OUTPUT);
402 s_gles2.glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
403 s_gles2.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
404 GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE);
405 s_gles2.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
406 GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE);
407 s_gles2.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
408 GL_DEBUG_SEVERITY_LOW, 0, nullptr, GL_TRUE);
409 s_gles2.glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE,
410 GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr,
411 GL_TRUE);
412 s_gles2.glDebugMessageCallback(&GlDebugCallback, nullptr);
413 debugSetup = s_gles2.glGetError() == GL_NO_ERROR;
414 if (!debugSetup) {
415 ERR("Failed to set up glDebugMessageCallback");
416 } else {
417 GL_LOG("Successfully set up glDebugMessageCallback");
418 }
419 }
420 if (s_gles2.glDebugMessageCallbackKHR && !debugSetup) {
421 s_gles2.glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE,
422 GL_DEBUG_SEVERITY_HIGH_KHR, 0, nullptr,
423 GL_TRUE);
424 s_gles2.glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE,
425 GL_DEBUG_SEVERITY_MEDIUM_KHR, 0, nullptr,
426 GL_TRUE);
427 s_gles2.glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE,
428 GL_DEBUG_SEVERITY_LOW_KHR, 0, nullptr,
429 GL_TRUE);
430 s_gles2.glDebugMessageControlKHR(GL_DONT_CARE, GL_DONT_CARE,
431 GL_DEBUG_SEVERITY_NOTIFICATION_KHR, 0, nullptr,
432 GL_TRUE);
433 s_gles2.glDebugMessageCallbackKHR(&GlDebugCallback, nullptr);
434 debugSetup = s_gles2.glGetError() == GL_NO_ERROR;
435 if (!debugSetup) {
436 ERR("Failed to set up glDebugMessageCallbackKHR");
437 } else {
438 GL_LOG("Successfully set up glDebugMessageCallbackKHR");
439 }
440 }
441 if (!debugSetup) {
442 GL_LOG("glDebugMessageCallback and glDebugMessageCallbackKHR not available");
443 }
444 #endif
445
446 emulationGl->mGlesVendor = (const char*)s_gles2.glGetString(GL_VENDOR);
447 emulationGl->mGlesRenderer = (const char*)s_gles2.glGetString(GL_RENDERER);
448 emulationGl->mGlesVersion = (const char*)s_gles2.glGetString(GL_VERSION);
449 emulationGl->mGlesExtensions = (const char*)s_gles2.glGetString(GL_EXTENSIONS);
450
451 s_gles2.glGetError();
452 GLint numDeviceUuids = 0;
453 s_gles2.glGetIntegerv(GL_NUM_DEVICE_UUIDS_EXT, &numDeviceUuids);
454 if (numDeviceUuids == 1) {
455 GlesUuid uuid{};
456 s_gles2.glGetUnsignedBytei_vEXT(GL_DEVICE_UUID_EXT, 0, uuid.data());
457 emulationGl->mGlesDeviceUuid = uuid;
458 }
459
460 emulationGl->mGlesVulkanInteropSupported = false;
461 if (s_egl.eglQueryVulkanInteropSupportANDROID) {
462 emulationGl->mGlesVulkanInteropSupported = s_egl.eglQueryVulkanInteropSupportANDROID();
463 }
464 if (emulationGl->mGlesVulkanInteropSupported) {
465 // Intel: b/271028352 workaround
466 const std::vector<const char*> disallowList = {"Intel", "AMD Radeon Pro WX 3200"};
467 const std::string& glesRenderer = emulationGl->getGlesRenderer();
468 for (const auto& disallowed : disallowList) {
469 if (strstr(glesRenderer.c_str(), disallowed)) {
470 emulationGl->mGlesVulkanInteropSupported = false;
471 break;
472 }
473 }
474 }
475
476 emulationGl->mTextureDraw = std::make_unique<TextureDraw>();
477 if (!emulationGl->mTextureDraw) {
478 ERR("Failed to initialize TextureDraw.");
479 return nullptr;
480 }
481
482 emulationGl->mCompositorGl = std::make_unique<CompositorGl>(emulationGl->mTextureDraw.get());
483
484 emulationGl->mDisplayGl = std::make_unique<DisplayGl>(emulationGl->mTextureDraw.get());
485
486 {
487 auto surface1 = DisplaySurfaceGl::createPbufferSurface(emulationGl->mEglDisplay,
488 emulationGl->mEglConfig,
489 emulationGl->mEglContext,
490 getGlesMaxContextAttribs(),
491 /*width=*/1,
492 /*height=*/1);
493 if (!surface1) {
494 ERR("Failed to create pbuffer surface for ReadbackWorkerGl.");
495 return nullptr;
496 }
497
498 auto surface2 = DisplaySurfaceGl::createPbufferSurface(emulationGl->mEglDisplay,
499 emulationGl->mEglConfig,
500 emulationGl->mEglContext,
501 getGlesMaxContextAttribs(),
502 /*width=*/1,
503 /*height=*/1);
504 if (!surface2) {
505 ERR("Failed to create pbuffer surface for ReadbackWorkerGl.");
506 return nullptr;
507 }
508
509 emulationGl->mReadbackWorkerGl = std::make_unique<ReadbackWorkerGl>(std::move(surface1),
510 std::move(surface2));
511 }
512
513 return emulationGl;
514 }
515
~EmulationGl()516 EmulationGl::~EmulationGl() {
517 if (mPbufferSurface) {
518 const auto* displaySurfaceGl =
519 reinterpret_cast<const DisplaySurfaceGl*>(mPbufferSurface->getImpl());
520
521 RecursiveScopedContextBind contextBind(displaySurfaceGl->getContextHelper());
522 if (contextBind.isOk()) {
523 mTextureDraw.reset();
524 } else {
525 ERR("Failed to bind context for destroying TextureDraw.");
526 }
527 }
528
529 if (mEglDisplay != EGL_NO_DISPLAY) {
530 s_egl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
531 if (mEglContext != EGL_NO_CONTEXT) {
532 s_egl.eglDestroyContext(mEglDisplay, mEglContext);
533 mEglContext = EGL_NO_CONTEXT;
534 }
535 mEglDisplay = EGL_NO_DISPLAY;
536 }
537 }
538
createFakeWindowSurface()539 std::unique_ptr<gfxstream::DisplaySurface> EmulationGl::createFakeWindowSurface() {
540 return std::make_unique<gfxstream::DisplaySurface>(
541 mWidth, mHeight,
542 DisplaySurfaceGl::createPbufferSurface(
543 mEglDisplay, mEglConfig, mEglContext, getGlesMaxContextAttribs(), mWidth, mHeight));
544 }
545
getGlesMaxContextAttribs()546 /*static*/ const GLint* EmulationGl::getGlesMaxContextAttribs() {
547 int glesMaj, glesMin;
548 emugl::getGlesVersion(&glesMaj, &glesMin);
549 if (shouldEnableCoreProfile()) {
550 if (glesMaj == 2) {
551 return kGles2ContextAttribsCoreGL;
552 } else {
553 return kGles3ContextAttribsCoreGL;
554 }
555 }
556 if (glesMaj == 2) {
557 return kGles2ContextAttribsESOrGLCompat;
558 } else {
559 return kGles3ContextAttribsESOrGLCompat;
560 }
561 }
562
getEglDispatch()563 const EGLDispatch* EmulationGl::getEglDispatch() {
564 return &s_egl;
565 }
566
getGles2Dispatch()567 const GLESv2Dispatch* EmulationGl::getGles2Dispatch() {
568 return &s_gles2;
569 }
570
getGlesMaxDispatchVersion() const571 GLESDispatchMaxVersion EmulationGl::getGlesMaxDispatchVersion() const {
572 return mGlesDispatchMaxVersion;
573 }
574
hasEglExtension(const std::string & ext) const575 bool EmulationGl::hasEglExtension(const std::string& ext) const {
576 return mEglExtensions.find(ext) != mEglExtensions.end();
577 }
578
getEglVersion(EGLint * major,EGLint * minor) const579 void EmulationGl::getEglVersion(EGLint* major, EGLint* minor) const {
580 if (major) {
581 *major = mEglVersionMajor;
582 }
583 if (minor) {
584 *minor = mEglVersionMinor;
585 }
586 }
587
getGlesVersion(GLint * major,GLint * minor) const588 void EmulationGl::getGlesVersion(GLint* major, GLint* minor) const {
589 if (major) {
590 *major = mGlesVersionMajor;
591 }
592 if (minor) {
593 *minor = mGlesVersionMinor;
594 }
595 }
596
isMesa() const597 bool EmulationGl::isMesa() const { return mGlesVersion.find("Mesa") != std::string::npos; }
598
isFastBlitSupported() const599 bool EmulationGl::isFastBlitSupported() const {
600 return mFastBlitSupported;
601 }
602
disableFastBlitForTesting()603 void EmulationGl::disableFastBlitForTesting() {
604 mFastBlitSupported = false;
605 }
606
isAsyncReadbackSupported() const607 bool EmulationGl::isAsyncReadbackSupported() const {
608 return mGlesVersionMajor > 2;
609 }
610
createWindowSurface(uint32_t width,uint32_t height,EGLNativeWindowType window)611 std::unique_ptr<DisplaySurface> EmulationGl::createWindowSurface(
612 uint32_t width,
613 uint32_t height,
614 EGLNativeWindowType window) {
615 auto surfaceGl = DisplaySurfaceGl::createWindowSurface(mEglDisplay,
616 mEglConfig,
617 mEglContext,
618 getGlesMaxContextAttribs(),
619 window);
620 if (!surfaceGl) {
621 ERR("Failed to create DisplaySurfaceGl.");
622 return nullptr;
623 }
624
625 return std::make_unique<DisplaySurface>(width,
626 height,
627 std::move(surfaceGl));
628 }
629
getColorBufferContextHelper()630 ContextHelper* EmulationGl::getColorBufferContextHelper() {
631 if (!mPbufferSurface) {
632 return nullptr;
633 }
634
635 const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(mPbufferSurface->getImpl());
636 return surfaceGl->getContextHelper();
637 }
638
createBuffer(uint64_t size,HandleType handle)639 std::unique_ptr<BufferGl> EmulationGl::createBuffer(uint64_t size, HandleType handle) {
640 return BufferGl::create(size, handle, getColorBufferContextHelper());
641 }
642
loadBuffer(android::base::Stream * stream)643 std::unique_ptr<BufferGl> EmulationGl::loadBuffer(android::base::Stream* stream) {
644 return BufferGl::onLoad(stream, getColorBufferContextHelper());
645 }
646
isFormatSupported(GLenum format)647 bool EmulationGl::isFormatSupported(GLenum format) {
648 const std::vector<GLenum> kUnhandledFormats = {
649 GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8,
650 GL_DEPTH_COMPONENT32F, GL_DEPTH32F_STENCIL8
651 };
652
653 if (std::find(kUnhandledFormats.begin(), kUnhandledFormats.end(), format) !=
654 kUnhandledFormats.end()) {
655 return false;
656 }
657 // TODO(b/356603558): add proper GL querying, for now preserve existing assumption
658 return true;
659 }
660
createColorBuffer(uint32_t width,uint32_t height,GLenum internalFormat,FrameworkFormat frameworkFormat,HandleType handle)661 std::unique_ptr<ColorBufferGl> EmulationGl::createColorBuffer(uint32_t width, uint32_t height,
662 GLenum internalFormat,
663 FrameworkFormat frameworkFormat,
664 HandleType handle) {
665 return ColorBufferGl::create(mEglDisplay, width, height, internalFormat, frameworkFormat,
666 handle, getColorBufferContextHelper(), mTextureDraw.get(),
667 isFastBlitSupported(), mFeatures);
668 }
669
loadColorBuffer(android::base::Stream * stream)670 std::unique_ptr<ColorBufferGl> EmulationGl::loadColorBuffer(android::base::Stream* stream) {
671 return ColorBufferGl::onLoad(stream, mEglDisplay, getColorBufferContextHelper(),
672 mTextureDraw.get(), isFastBlitSupported(), mFeatures);
673 }
674
createEmulatedEglContext(uint32_t emulatedEglConfigIndex,const EmulatedEglContext * sharedContext,GLESApi api,HandleType handle)675 std::unique_ptr<EmulatedEglContext> EmulationGl::createEmulatedEglContext(
676 uint32_t emulatedEglConfigIndex,
677 const EmulatedEglContext* sharedContext,
678 GLESApi api,
679 HandleType handle) {
680 if (!mEmulatedEglConfigs) {
681 ERR("EmulatedEglConfigs unavailable.");
682 return nullptr;
683 }
684
685 const EmulatedEglConfig* emulatedEglConfig = mEmulatedEglConfigs->get(emulatedEglConfigIndex);
686 if (!emulatedEglConfig) {
687 ERR("Failed to find emulated EGL config %d", emulatedEglConfigIndex);
688 return nullptr;
689 }
690
691 EGLConfig config = emulatedEglConfig->getHostEglConfig();
692 EGLContext share = sharedContext ? sharedContext->getEGLContext() : EGL_NO_CONTEXT;
693
694 return EmulatedEglContext::create(mEglDisplay, config, share, handle, api);
695 }
696
loadEmulatedEglContext(android::base::Stream * stream)697 std::unique_ptr<EmulatedEglContext> EmulationGl::loadEmulatedEglContext(
698 android::base::Stream* stream) {
699 return EmulatedEglContext::onLoad(stream, mEglDisplay);
700 }
701
createEmulatedEglFenceSync(EGLenum type,int destroyWhenSignaled)702 std::unique_ptr<EmulatedEglFenceSync> EmulationGl::createEmulatedEglFenceSync(
703 EGLenum type,
704 int destroyWhenSignaled) {
705 const bool hasNativeFence = type == EGL_SYNC_NATIVE_FENCE_ANDROID;
706 return EmulatedEglFenceSync::create(mEglDisplay,
707 hasNativeFence,
708 destroyWhenSignaled);
709
710 }
711
createEmulatedEglImage(EmulatedEglContext * context,EGLenum target,EGLClientBuffer buffer)712 std::unique_ptr<EmulatedEglImage> EmulationGl::createEmulatedEglImage(
713 EmulatedEglContext* context,
714 EGLenum target,
715 EGLClientBuffer buffer) {
716 EGLContext eglContext = context ? context->getEGLContext() : EGL_NO_CONTEXT;
717 return EmulatedEglImage::create(mEglDisplay, eglContext, target, buffer);
718 }
719
createEmulatedEglWindowSurface(uint32_t emulatedConfigIndex,uint32_t width,uint32_t height,HandleType handle)720 std::unique_ptr<EmulatedEglWindowSurface> EmulationGl::createEmulatedEglWindowSurface(
721 uint32_t emulatedConfigIndex,
722 uint32_t width,
723 uint32_t height,
724 HandleType handle) {
725 if (!mEmulatedEglConfigs) {
726 ERR("EmulatedEglConfigs unavailable.");
727 return nullptr;
728 }
729
730 const EmulatedEglConfig* emulatedEglConfig = mEmulatedEglConfigs->get(emulatedConfigIndex);
731 if (!emulatedEglConfig) {
732 ERR("Failed to find emulated EGL config %d", emulatedConfigIndex);
733 return nullptr;
734 }
735
736 EGLConfig config = emulatedEglConfig->getHostEglConfig();
737
738 return EmulatedEglWindowSurface::create(mEglDisplay, config, width, height, handle);
739 }
740
loadEmulatedEglWindowSurface(android::base::Stream * stream,const ColorBufferMap & colorBuffers,const EmulatedEglContextMap & contexts)741 std::unique_ptr<EmulatedEglWindowSurface> EmulationGl::loadEmulatedEglWindowSurface(
742 android::base::Stream* stream,
743 const ColorBufferMap& colorBuffers,
744 const EmulatedEglContextMap& contexts) {
745 return EmulatedEglWindowSurface::onLoad(stream, mEglDisplay, colorBuffers, contexts);
746 }
747
748 } // namespace gl
749 } // namespace gfxstream
750