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 
465     emulationGl->mTextureDraw = std::make_unique<TextureDraw>();
466     if (!emulationGl->mTextureDraw) {
467         ERR("Failed to initialize TextureDraw.");
468         return nullptr;
469     }
470 
471     emulationGl->mCompositorGl = std::make_unique<CompositorGl>(emulationGl->mTextureDraw.get());
472 
473     emulationGl->mDisplayGl = std::make_unique<DisplayGl>(emulationGl->mTextureDraw.get());
474 
475     {
476         auto surface1 = DisplaySurfaceGl::createPbufferSurface(emulationGl->mEglDisplay,
477                                                                emulationGl->mEglConfig,
478                                                                emulationGl->mEglContext,
479                                                                getGlesMaxContextAttribs(),
480                                                                /*width=*/1,
481                                                                /*height=*/1);
482         if (!surface1) {
483             ERR("Failed to create pbuffer surface for ReadbackWorkerGl.");
484             return nullptr;
485         }
486 
487         auto surface2 = DisplaySurfaceGl::createPbufferSurface(emulationGl->mEglDisplay,
488                                                                emulationGl->mEglConfig,
489                                                                emulationGl->mEglContext,
490                                                                getGlesMaxContextAttribs(),
491                                                                /*width=*/1,
492                                                                /*height=*/1);
493         if (!surface2) {
494             ERR("Failed to create pbuffer surface for ReadbackWorkerGl.");
495             return nullptr;
496         }
497 
498         emulationGl->mReadbackWorkerGl = std::make_unique<ReadbackWorkerGl>(std::move(surface1),
499                                                                             std::move(surface2));
500     }
501 
502     return emulationGl;
503 }
504 
~EmulationGl()505 EmulationGl::~EmulationGl() {
506     if (mPbufferSurface) {
507         // TODO(b/267349580): remove after Mac issue fixed.
508         mTextureDraw.release();
509         // const auto* displaySurfaceGl =
510         //    reinterpret_cast<const DisplaySurfaceGl*>(mPbufferSurface->getImpl());
511         // RecursiveScopedContextBind contextBind(displaySurfaceGl->getContextHelper());
512         // if (contextBind.isOk()) {
513         //     mTextureDraw.reset();
514         // } else {
515         //     ERR("Failed to bind context for destroying TextureDraw.");
516         // }
517     }
518 
519     if (mEglDisplay != EGL_NO_DISPLAY) {
520         s_egl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
521         if (mEglContext != EGL_NO_CONTEXT) {
522             s_egl.eglDestroyContext(mEglDisplay, mEglContext);
523             mEglContext = EGL_NO_CONTEXT;
524         }
525         mEglDisplay = EGL_NO_DISPLAY;
526     }
527 }
528 
createFakeWindowSurface()529 std::unique_ptr<gfxstream::DisplaySurface> EmulationGl::createFakeWindowSurface() {
530     return std::make_unique<gfxstream::DisplaySurface>(
531         mWidth, mHeight,
532         DisplaySurfaceGl::createPbufferSurface(
533             mEglDisplay, mEglConfig, mEglContext, getGlesMaxContextAttribs(), mWidth, mHeight));
534 }
535 
getGlesMaxContextAttribs()536 /*static*/ const GLint* EmulationGl::getGlesMaxContextAttribs() {
537     int glesMaj, glesMin;
538     emugl::getGlesVersion(&glesMaj, &glesMin);
539     if (shouldEnableCoreProfile()) {
540         if (glesMaj == 2) {
541             return kGles2ContextAttribsCoreGL;
542         } else {
543             return kGles3ContextAttribsCoreGL;
544         }
545     }
546     if (glesMaj == 2) {
547         return kGles2ContextAttribsESOrGLCompat;
548     } else {
549         return kGles3ContextAttribsESOrGLCompat;
550     }
551 }
552 
getEglDispatch()553 const EGLDispatch* EmulationGl::getEglDispatch() {
554     return &s_egl;
555 }
556 
getGles2Dispatch()557 const GLESv2Dispatch* EmulationGl::getGles2Dispatch() {
558     return &s_gles2;
559 }
560 
getGlesMaxDispatchVersion() const561 GLESDispatchMaxVersion EmulationGl::getGlesMaxDispatchVersion() const {
562     return mGlesDispatchMaxVersion;
563 }
564 
hasEglExtension(const std::string & ext) const565 bool EmulationGl::hasEglExtension(const std::string& ext) const {
566     return mEglExtensions.find(ext) != mEglExtensions.end();
567 }
568 
getEglVersion(EGLint * major,EGLint * minor) const569 void EmulationGl::getEglVersion(EGLint* major, EGLint* minor) const {
570     if (major) {
571         *major = mEglVersionMajor;
572     }
573     if (minor) {
574         *minor = mEglVersionMinor;
575     }
576 }
577 
getGlesVersion(GLint * major,GLint * minor) const578 void EmulationGl::getGlesVersion(GLint* major, GLint* minor) const {
579     if (major) {
580         *major = mGlesVersionMajor;
581     }
582     if (minor) {
583         *minor = mGlesVersionMinor;
584     }
585 }
586 
isMesa() const587 bool EmulationGl::isMesa() const { return mGlesVersion.find("Mesa") != std::string::npos; }
588 
isFastBlitSupported() const589 bool EmulationGl::isFastBlitSupported() const {
590     return mFastBlitSupported;
591 }
592 
disableFastBlitForTesting()593 void EmulationGl::disableFastBlitForTesting() {
594     mFastBlitSupported = false;
595 }
596 
isAsyncReadbackSupported() const597 bool EmulationGl::isAsyncReadbackSupported() const {
598     return mGlesVersionMajor > 2;
599 }
600 
createWindowSurface(uint32_t width,uint32_t height,EGLNativeWindowType window)601 std::unique_ptr<DisplaySurface> EmulationGl::createWindowSurface(
602         uint32_t width,
603         uint32_t height,
604         EGLNativeWindowType window) {
605     auto surfaceGl = DisplaySurfaceGl::createWindowSurface(mEglDisplay,
606                                                            mEglConfig,
607                                                            mEglContext,
608                                                            getGlesMaxContextAttribs(),
609                                                            window);
610     if (!surfaceGl) {
611         ERR("Failed to create DisplaySurfaceGl.");
612         return nullptr;
613     }
614 
615     return std::make_unique<DisplaySurface>(width,
616                                             height,
617                                             std::move(surfaceGl));
618 }
619 
getColorBufferContextHelper()620 ContextHelper* EmulationGl::getColorBufferContextHelper() {
621     if (!mPbufferSurface) {
622         return nullptr;
623     }
624 
625     const auto* surfaceGl = static_cast<const DisplaySurfaceGl*>(mPbufferSurface->getImpl());
626     return surfaceGl->getContextHelper();
627 }
628 
createBuffer(uint64_t size,HandleType handle)629 std::unique_ptr<BufferGl> EmulationGl::createBuffer(uint64_t size, HandleType handle) {
630     return BufferGl::create(size, handle, getColorBufferContextHelper());
631 }
632 
loadBuffer(android::base::Stream * stream)633 std::unique_ptr<BufferGl> EmulationGl::loadBuffer(android::base::Stream* stream) {
634     return BufferGl::onLoad(stream, getColorBufferContextHelper());
635 }
636 
isFormatSupported(GLenum format)637 bool EmulationGl::isFormatSupported(GLenum format) {
638     const std::vector<GLenum> kUnhandledFormats = {
639         GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH24_STENCIL8,
640         GL_DEPTH_COMPONENT32F, GL_DEPTH32F_STENCIL8
641     };
642 
643     if (std::find(kUnhandledFormats.begin(), kUnhandledFormats.end(), format) !=
644             kUnhandledFormats.end()) {
645         return false;
646     }
647     // TODO(b/356603558): add proper GL querying, for now preserve existing assumption
648     return true;
649 }
650 
createColorBuffer(uint32_t width,uint32_t height,GLenum internalFormat,FrameworkFormat frameworkFormat,HandleType handle)651 std::unique_ptr<ColorBufferGl> EmulationGl::createColorBuffer(uint32_t width, uint32_t height,
652                                                               GLenum internalFormat,
653                                                               FrameworkFormat frameworkFormat,
654                                                               HandleType handle) {
655     return ColorBufferGl::create(mEglDisplay, width, height, internalFormat, frameworkFormat,
656                                  handle, getColorBufferContextHelper(), mTextureDraw.get(),
657                                  isFastBlitSupported(), mFeatures);
658 }
659 
loadColorBuffer(android::base::Stream * stream)660 std::unique_ptr<ColorBufferGl> EmulationGl::loadColorBuffer(android::base::Stream* stream) {
661     return ColorBufferGl::onLoad(stream, mEglDisplay, getColorBufferContextHelper(),
662                                  mTextureDraw.get(), isFastBlitSupported(), mFeatures);
663 }
664 
createEmulatedEglContext(uint32_t emulatedEglConfigIndex,const EmulatedEglContext * sharedContext,GLESApi api,HandleType handle)665 std::unique_ptr<EmulatedEglContext> EmulationGl::createEmulatedEglContext(
666         uint32_t emulatedEglConfigIndex,
667         const EmulatedEglContext* sharedContext,
668         GLESApi api,
669         HandleType handle) {
670     if (!mEmulatedEglConfigs) {
671         ERR("EmulatedEglConfigs unavailable.");
672         return nullptr;
673     }
674 
675     const EmulatedEglConfig* emulatedEglConfig = mEmulatedEglConfigs->get(emulatedEglConfigIndex);
676     if (!emulatedEglConfig) {
677         ERR("Failed to find emulated EGL config %d", emulatedEglConfigIndex);
678         return nullptr;
679     }
680 
681     EGLConfig config = emulatedEglConfig->getHostEglConfig();
682     EGLContext share = sharedContext ? sharedContext->getEGLContext() : EGL_NO_CONTEXT;
683 
684     return EmulatedEglContext::create(mEglDisplay, config, share, handle, api);
685 }
686 
loadEmulatedEglContext(android::base::Stream * stream)687 std::unique_ptr<EmulatedEglContext> EmulationGl::loadEmulatedEglContext(
688         android::base::Stream* stream) {
689     return EmulatedEglContext::onLoad(stream, mEglDisplay);
690 }
691 
createEmulatedEglFenceSync(EGLenum type,int destroyWhenSignaled)692 std::unique_ptr<EmulatedEglFenceSync> EmulationGl::createEmulatedEglFenceSync(
693         EGLenum type,
694         int destroyWhenSignaled) {
695     const bool hasNativeFence = type == EGL_SYNC_NATIVE_FENCE_ANDROID;
696     return EmulatedEglFenceSync::create(mEglDisplay,
697                                         hasNativeFence,
698                                         destroyWhenSignaled);
699 
700 }
701 
createEmulatedEglImage(EmulatedEglContext * context,EGLenum target,EGLClientBuffer buffer)702 std::unique_ptr<EmulatedEglImage> EmulationGl::createEmulatedEglImage(
703         EmulatedEglContext* context,
704         EGLenum target,
705         EGLClientBuffer buffer) {
706     EGLContext eglContext = context ? context->getEGLContext() : EGL_NO_CONTEXT;
707     return EmulatedEglImage::create(mEglDisplay, eglContext, target, buffer);
708 }
709 
createEmulatedEglWindowSurface(uint32_t emulatedConfigIndex,uint32_t width,uint32_t height,HandleType handle)710 std::unique_ptr<EmulatedEglWindowSurface> EmulationGl::createEmulatedEglWindowSurface(
711         uint32_t emulatedConfigIndex,
712         uint32_t width,
713         uint32_t height,
714         HandleType handle) {
715     if (!mEmulatedEglConfigs) {
716         ERR("EmulatedEglConfigs unavailable.");
717         return nullptr;
718     }
719 
720     const EmulatedEglConfig* emulatedEglConfig = mEmulatedEglConfigs->get(emulatedConfigIndex);
721     if (!emulatedEglConfig) {
722         ERR("Failed to find emulated EGL config %d", emulatedConfigIndex);
723         return nullptr;
724     }
725 
726     EGLConfig config = emulatedEglConfig->getHostEglConfig();
727 
728     return EmulatedEglWindowSurface::create(mEglDisplay, config, width, height, handle);
729 }
730 
loadEmulatedEglWindowSurface(android::base::Stream * stream,const ColorBufferMap & colorBuffers,const EmulatedEglContextMap & contexts)731 std::unique_ptr<EmulatedEglWindowSurface> EmulationGl::loadEmulatedEglWindowSurface(
732         android::base::Stream* stream,
733         const ColorBufferMap& colorBuffers,
734         const EmulatedEglContextMap& contexts) {
735     return EmulatedEglWindowSurface::onLoad(stream, mEglDisplay, colorBuffers, contexts);
736 }
737 
738 }  // namespace gl
739 }  // namespace gfxstream
740