• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // DisplayAndroid.cpp: Android implementation of egl::Display
8 
9 #include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
10 
11 #include <android/log.h>
12 #include <android/native_window.h>
13 
14 #include "common/debug.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/Surface.h"
18 #include "libANGLE/renderer/gl/ContextGL.h"
19 #include "libANGLE/renderer/gl/RendererGL.h"
20 #include "libANGLE/renderer/gl/egl/ContextEGL.h"
21 #include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
22 #include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
23 #include "libANGLE/renderer/gl/egl/RendererEGL.h"
24 #include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
25 #include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
26 #include "libANGLE/renderer/gl/renderergl_utils.h"
27 
28 namespace
29 {
GetEGLPath()30 const char *GetEGLPath()
31 {
32 #if defined(__LP64__)
33     return "/system/lib64/libEGL.so";
34 #else
35     return "/system/lib/libEGL.so";
36 #endif
37 }
38 }  // namespace
39 
40 namespace rx
41 {
42 
43 static constexpr bool kDefaultEGLVirtualizedContexts = true;
44 
DisplayAndroid(const egl::DisplayState & state)45 DisplayAndroid::DisplayAndroid(const egl::DisplayState &state)
46     : DisplayEGL(state),
47       mVirtualizedContexts(kDefaultEGLVirtualizedContexts),
48       mSupportsSurfaceless(false),
49       mDummyPbuffer(EGL_NO_SURFACE)
50 {}
51 
~DisplayAndroid()52 DisplayAndroid::~DisplayAndroid() {}
53 
initialize(egl::Display * display)54 egl::Error DisplayAndroid::initialize(egl::Display *display)
55 {
56     mDisplayAttributes = display->getAttributeMap();
57     mVirtualizedContexts =
58         ShouldUseVirtualizedContexts(mDisplayAttributes, kDefaultEGLVirtualizedContexts);
59 
60     FunctionsEGLDL *egl = new FunctionsEGLDL();
61     mEGL                = egl;
62     void *eglHandle =
63         reinterpret_cast<void *>(mDisplayAttributes.get(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE, 0));
64     ANGLE_TRY(egl->initialize(display->getNativeDisplayId(), GetEGLPath(), eglHandle));
65 
66     gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
67     ASSERT(eglVersion >= gl::Version(1, 4));
68 
69     static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR, "Extension define must match core");
70     EGLint esBit = (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
71                        ? EGL_OPENGL_ES3_BIT
72                        : EGL_OPENGL_ES2_BIT;
73 
74     // clang-format off
75     std::vector<EGLint> configAttribListBase =
76     {
77         EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
78         // Android doesn't support pixmaps
79         EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
80         EGL_CONFIG_CAVEAT, EGL_NONE,
81         EGL_CONFORMANT, esBit,
82         EGL_RENDERABLE_TYPE, esBit,
83     };
84     // clang-format on
85 
86     if (mEGL->hasExtension("EGL_EXT_pixel_format_float"))
87     {
88         // Don't request floating point configs
89         configAttribListBase.push_back(EGL_COLOR_COMPONENT_TYPE_EXT);
90         configAttribListBase.push_back(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
91     }
92 
93     std::vector<EGLint> configAttribListWithFormat = configAttribListBase;
94     // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
95     // must match for contexts to be compatible.
96     // Choose RGBA8888
97     configAttribListWithFormat.push_back(EGL_RED_SIZE);
98     configAttribListWithFormat.push_back(8);
99     configAttribListWithFormat.push_back(EGL_GREEN_SIZE);
100     configAttribListWithFormat.push_back(8);
101     configAttribListWithFormat.push_back(EGL_BLUE_SIZE);
102     configAttribListWithFormat.push_back(8);
103     configAttribListWithFormat.push_back(EGL_ALPHA_SIZE);
104     configAttribListWithFormat.push_back(8);
105     // Choose DEPTH24_STENCIL8
106     configAttribListWithFormat.push_back(EGL_DEPTH_SIZE);
107     configAttribListWithFormat.push_back(24);
108     configAttribListWithFormat.push_back(EGL_STENCIL_SIZE);
109     configAttribListWithFormat.push_back(8);
110     // Choose no multisampling
111     configAttribListWithFormat.push_back(EGL_SAMPLE_BUFFERS);
112     configAttribListWithFormat.push_back(0);
113 
114     // Complete the attrib lists
115     configAttribListBase.push_back(EGL_NONE);
116     configAttribListWithFormat.push_back(EGL_NONE);
117 
118     EGLint numConfig;
119     EGLConfig configWithFormat;
120 
121     EGLBoolean success =
122         mEGL->chooseConfig(configAttribListWithFormat.data(), &configWithFormat, 1, &numConfig);
123     if (success == EGL_FALSE)
124     {
125         return egl::EglNotInitialized()
126                << "eglChooseConfig failed with " << egl::Error(mEGL->getError());
127     }
128 
129     // A dummy pbuffer is only needed if surfaceless contexts are not supported.
130     mSupportsSurfaceless = mEGL->hasExtension("EGL_KHR_surfaceless_context");
131     if (!mSupportsSurfaceless)
132     {
133         int dummyPbufferAttribs[] = {
134             EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE,
135         };
136         mDummyPbuffer = mEGL->createPbufferSurface(configWithFormat, dummyPbufferAttribs);
137         if (mDummyPbuffer == EGL_NO_SURFACE)
138         {
139             return egl::EglNotInitialized()
140                    << "eglCreatePbufferSurface failed with " << egl::Error(mEGL->getError());
141         }
142     }
143 
144     // Create mDummyPbuffer with a normal config, but create a no_config mContext, if possible
145     if (mEGL->hasExtension("EGL_KHR_no_config_context"))
146     {
147         mConfigAttribList = configAttribListBase;
148         mConfig           = EGL_NO_CONFIG_KHR;
149     }
150     else
151     {
152         mConfigAttribList = configAttribListWithFormat;
153         mConfig           = configWithFormat;
154     }
155 
156     ANGLE_TRY(createRenderer(EGL_NO_CONTEXT, true, &mRenderer));
157 
158     const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
159     if (maxVersion < gl::Version(2, 0))
160     {
161         return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
162     }
163 
164     ANGLE_TRY(DisplayGL::initialize(display));
165 
166     std::string rendererDescription = mRenderer->getRendererDescription();
167     __android_log_print(ANDROID_LOG_INFO, "ANGLE", "%s", rendererDescription.c_str());
168     return egl::NoError();
169 }
170 
terminate()171 void DisplayAndroid::terminate()
172 {
173     DisplayGL::terminate();
174 
175     EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
176     if (success == EGL_FALSE)
177     {
178         ERR() << "eglMakeCurrent error " << egl::Error(mEGL->getError());
179     }
180 
181     if (mDummyPbuffer != EGL_NO_SURFACE)
182     {
183         success       = mEGL->destroySurface(mDummyPbuffer);
184         mDummyPbuffer = EGL_NO_SURFACE;
185         if (success == EGL_FALSE)
186         {
187             ERR() << "eglDestroySurface error " << egl::Error(mEGL->getError());
188         }
189     }
190 
191     mRenderer.reset();
192     mCurrentNativeContext.clear();
193 
194     egl::Error result = mEGL->terminate();
195     if (result.isError())
196     {
197         ERR() << "eglTerminate error " << result;
198     }
199 
200     SafeDelete(mEGL);
201 }
202 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)203 SurfaceImpl *DisplayAndroid::createWindowSurface(const egl::SurfaceState &state,
204                                                  EGLNativeWindowType window,
205                                                  const egl::AttributeMap &attribs)
206 {
207     EGLConfig config;
208     EGLint numConfig;
209     EGLBoolean success;
210 
211     const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
212     success                         = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
213     ASSERT(success && numConfig == 1);
214 
215     return new WindowSurfaceEGL(state, mEGL, config, window);
216 }
217 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)218 SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state,
219                                                   const egl::AttributeMap &attribs)
220 {
221     EGLConfig config;
222     EGLint numConfig;
223     EGLBoolean success;
224 
225     const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
226     success                         = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
227     ASSERT(success && numConfig == 1);
228 
229     return new PbufferSurfaceEGL(state, mEGL, config);
230 }
231 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)232 SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
233                                                            EGLenum buftype,
234                                                            EGLClientBuffer clientBuffer,
235                                                            const egl::AttributeMap &attribs)
236 {
237     UNIMPLEMENTED();
238     return nullptr;
239 }
240 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)241 SurfaceImpl *DisplayAndroid::createPixmapSurface(const egl::SurfaceState &state,
242                                                  NativePixmapType nativePixmap,
243                                                  const egl::AttributeMap &attribs)
244 {
245     UNIMPLEMENTED();
246     return nullptr;
247 }
248 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)249 ContextImpl *DisplayAndroid::createContext(const gl::State &state,
250                                            gl::ErrorSet *errorSet,
251                                            const egl::Config *configuration,
252                                            const gl::Context *shareContext,
253                                            const egl::AttributeMap &attribs)
254 {
255     std::shared_ptr<RendererEGL> renderer;
256     if (mVirtualizedContexts)
257     {
258         renderer = mRenderer;
259     }
260     else
261     {
262         EGLContext nativeShareContext = EGL_NO_CONTEXT;
263         if (shareContext)
264         {
265             ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
266             nativeShareContext          = shareContextEGL->getContext();
267         }
268 
269         // Create a new renderer for this context.  It only needs to share with the user's requested
270         // share context because there are no internal resources in DisplayAndroid that are shared
271         // at the GL level.
272         egl::Error error = createRenderer(nativeShareContext, false, &renderer);
273         if (error.isError())
274         {
275             ERR() << "Failed to create a shared renderer: " << error.getMessage();
276             return nullptr;
277         }
278     }
279 
280     return new ContextEGL(state, errorSet, renderer);
281 }
282 
283 template <typename T>
getConfigAttrib(EGLConfig config,EGLint attribute,T * value) const284 void DisplayAndroid::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
285 {
286     EGLint tmp;
287     EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
288     ASSERT(success == EGL_TRUE);
289     *value = tmp;
290 }
291 
292 template <typename T, typename U>
getConfigAttribIfExtension(EGLConfig config,EGLint attribute,T * value,const char * extension,const U & defaultValue) const293 void DisplayAndroid::getConfigAttribIfExtension(EGLConfig config,
294                                                 EGLint attribute,
295                                                 T *value,
296                                                 const char *extension,
297                                                 const U &defaultValue) const
298 {
299     if (mEGL->hasExtension(extension))
300     {
301         getConfigAttrib(config, attribute, value);
302     }
303     else
304     {
305         *value = static_cast<T>(defaultValue);
306     }
307 }
308 
generateConfigs()309 egl::ConfigSet DisplayAndroid::generateConfigs()
310 {
311     egl::ConfigSet configSet;
312     mConfigIds.clear();
313 
314     EGLint numConfigs;
315     EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
316     ASSERT(success == EGL_TRUE && numConfigs > 0);
317 
318     std::vector<EGLConfig> configs(numConfigs);
319     EGLint numConfigs2;
320     success =
321         mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
322     ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
323 
324     for (int i = 0; i < numConfigs; i++)
325     {
326         egl::Config config;
327 
328         getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
329         getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
330         getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
331         getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
332         getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
333         getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
334         getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
335         getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
336         getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
337         getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
338         getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
339         getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
340         getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
341         getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
342         getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
343         getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
344         getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
345         getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
346         getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
347         getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
348         getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
349         getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
350         getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
351         getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
352         getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
353         getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
354         getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
355         getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
356         getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
357         getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
358         getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
359         getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
360         getConfigAttribIfExtension(configs[i], EGL_COLOR_COMPONENT_TYPE_EXT,
361                                    &config.colorComponentType, "EGL_EXT_pixel_format_float",
362                                    EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
363 
364         if (config.colorBufferType == EGL_RGB_BUFFER)
365         {
366             ASSERT(config.colorComponentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
367             if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
368                 config.alphaSize == 8)
369             {
370                 config.renderTargetFormat = GL_RGBA8;
371             }
372             else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
373                      config.alphaSize == 0)
374             {
375                 config.renderTargetFormat = GL_RGB8;
376             }
377             else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 &&
378                      config.alphaSize == 0)
379             {
380                 config.renderTargetFormat = GL_RGB565;
381             }
382             else if (config.redSize == 5 && config.greenSize == 5 && config.blueSize == 5 &&
383                      config.alphaSize == 1)
384             {
385                 config.renderTargetFormat = GL_RGB5_A1;
386             }
387             else if (config.redSize == 4 && config.greenSize == 4 && config.blueSize == 4 &&
388                      config.alphaSize == 4)
389             {
390                 config.renderTargetFormat = GL_RGBA4;
391             }
392             else
393             {
394                 ERR() << "RGBA(" << config.redSize << "," << config.greenSize << ","
395                       << config.blueSize << "," << config.alphaSize << ") not handled";
396                 UNREACHABLE();
397             }
398         }
399         else
400         {
401             UNREACHABLE();
402         }
403 
404         if (config.depthSize == 0 && config.stencilSize == 0)
405         {
406             config.depthStencilFormat = GL_ZERO;
407         }
408         else if (config.depthSize == 16 && config.stencilSize == 0)
409         {
410             config.depthStencilFormat = GL_DEPTH_COMPONENT16;
411         }
412         else if (config.depthSize == 24 && config.stencilSize == 0)
413         {
414             config.depthStencilFormat = GL_DEPTH_COMPONENT24;
415         }
416         else if (config.depthSize == 24 && config.stencilSize == 8)
417         {
418             config.depthStencilFormat = GL_DEPTH24_STENCIL8;
419         }
420         else if (config.depthSize == 0 && config.stencilSize == 8)
421         {
422             config.depthStencilFormat = GL_STENCIL_INDEX8;
423         }
424         else
425         {
426             UNREACHABLE();
427         }
428 
429         config.matchNativePixmap  = EGL_NONE;
430         config.optimalOrientation = 0;
431 
432         int internalId         = configSet.add(config);
433         mConfigIds[internalId] = config.configID;
434     }
435 
436     return configSet;
437 }
438 
testDeviceLost()439 bool DisplayAndroid::testDeviceLost()
440 {
441     return false;
442 }
443 
restoreLostDevice(const egl::Display * display)444 egl::Error DisplayAndroid::restoreLostDevice(const egl::Display *display)
445 {
446     UNIMPLEMENTED();
447     return egl::NoError();
448 }
449 
isValidNativeWindow(EGLNativeWindowType window) const450 bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
451 {
452     return ANativeWindow_getFormat(window) >= 0;
453 }
454 
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const455 egl::Error DisplayAndroid::validateImageClientBuffer(const gl::Context *context,
456                                                      EGLenum target,
457                                                      EGLClientBuffer clientBuffer,
458                                                      const egl::AttributeMap &attribs) const
459 {
460     switch (target)
461     {
462         case EGL_NATIVE_BUFFER_ANDROID:
463             return egl::NoError();
464 
465         default:
466             return DisplayEGL::validateImageClientBuffer(context, target, clientBuffer, attribs);
467     }
468 }
469 
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)470 ExternalImageSiblingImpl *DisplayAndroid::createExternalImageSibling(
471     const gl::Context *context,
472     EGLenum target,
473     EGLClientBuffer buffer,
474     const egl::AttributeMap &attribs)
475 {
476     switch (target)
477     {
478         case EGL_NATIVE_BUFFER_ANDROID:
479             return new NativeBufferImageSiblingAndroid(buffer);
480 
481         default:
482             return DisplayEGL::createExternalImageSibling(context, target, buffer, attribs);
483     }
484 }
485 
createDevice()486 DeviceImpl *DisplayAndroid::createDevice()
487 {
488     UNIMPLEMENTED();
489     return nullptr;
490 }
491 
waitClient(const gl::Context * context)492 egl::Error DisplayAndroid::waitClient(const gl::Context *context)
493 {
494     UNIMPLEMENTED();
495     return egl::NoError();
496 }
497 
waitNative(const gl::Context * context,EGLint engine)498 egl::Error DisplayAndroid::waitNative(const gl::Context *context, EGLint engine)
499 {
500     UNIMPLEMENTED();
501     return egl::NoError();
502 }
503 
makeCurrent(egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)504 egl::Error DisplayAndroid::makeCurrent(egl::Surface *drawSurface,
505                                        egl::Surface *readSurface,
506                                        gl::Context *context)
507 {
508     CurrentNativeContext &currentContext = mCurrentNativeContext[std::this_thread::get_id()];
509 
510     EGLSurface newSurface = EGL_NO_SURFACE;
511     if (drawSurface)
512     {
513         SurfaceEGL *drawSurfaceEGL = GetImplAs<SurfaceEGL>(drawSurface);
514         newSurface                 = drawSurfaceEGL->getSurface();
515     }
516 
517     EGLContext newContext = EGL_NO_CONTEXT;
518     if (context)
519     {
520         ContextEGL *contextEGL = GetImplAs<ContextEGL>(context);
521         newContext             = contextEGL->getContext();
522     }
523 
524     // The context should never change when context virtualization is being used, even when a null
525     // context is being bound.
526     if (mVirtualizedContexts)
527     {
528         ASSERT(newContext == EGL_NO_CONTEXT || currentContext.context == EGL_NO_CONTEXT ||
529                newContext == currentContext.context);
530 
531         newContext = mRenderer->getContext();
532 
533         // If we know that we're only running on one thread (mVirtualizedContexts == true) and
534         // EGL_NO_SURFACE is going to be bound, we can optimize this case by not changing the
535         // surface binding and emulate the surfaceless extension in the frontend.
536         if (newSurface == EGL_NO_SURFACE)
537         {
538             newSurface = currentContext.surface;
539         }
540 
541         // It's possible that no surface has been created yet and the driver doesn't support
542         // surfaceless, bind the dummy pbuffer.
543         if (newSurface == EGL_NO_SURFACE && !mSupportsSurfaceless)
544         {
545             newSurface = mDummyPbuffer;
546             ASSERT(newSurface != EGL_NO_SURFACE);
547         }
548     }
549 
550     if (newSurface != currentContext.surface || newContext != currentContext.context)
551     {
552         if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
553         {
554             return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
555         }
556         currentContext.surface = newSurface;
557         currentContext.context = newContext;
558     }
559 
560     return DisplayGL::makeCurrent(drawSurface, readSurface, context);
561 }
562 
getMaxSupportedESVersion() const563 gl::Version DisplayAndroid::getMaxSupportedESVersion() const
564 {
565     return mRenderer->getMaxSupportedESVersion();
566 }
567 
destroyNativeContext(EGLContext context)568 void DisplayAndroid::destroyNativeContext(EGLContext context)
569 {
570     mEGL->destroyContext(context);
571 
572     // If this context is current, remove it from the tracking of current contexts to make sure we
573     // don't try to make it current again.
574     for (auto &currentContext : mCurrentNativeContext)
575     {
576         if (currentContext.second.context == context)
577         {
578             currentContext.second.surface = EGL_NO_SURFACE;
579             currentContext.second.context = EGL_NO_CONTEXT;
580         }
581     }
582 }
583 
generateExtensions(egl::DisplayExtensions * outExtensions) const584 void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) const
585 {
586     // Surfaceless can be support if the native driver supports it or we know that we are running on
587     // a single thread (mVirtualizedContexts == true)
588     outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts;
589 
590     DisplayEGL::generateExtensions(outExtensions);
591 }
592 
makeCurrentSurfaceless(gl::Context * context)593 egl::Error DisplayAndroid::makeCurrentSurfaceless(gl::Context *context)
594 {
595     // Nothing to do because EGL always uses the same context and the previous surface can be left
596     // current.
597     return egl::NoError();
598 }
599 
createRenderer(EGLContext shareContext,bool makeNewContextCurrent,std::shared_ptr<RendererEGL> * outRenderer)600 egl::Error DisplayAndroid::createRenderer(EGLContext shareContext,
601                                           bool makeNewContextCurrent,
602                                           std::shared_ptr<RendererEGL> *outRenderer)
603 {
604     EGLContext context = EGL_NO_CONTEXT;
605     native_egl::AttributeVector attribs;
606     ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
607 
608     if (mEGL->makeCurrent(mDummyPbuffer, context) == EGL_FALSE)
609     {
610         return egl::EglNotInitialized()
611                << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
612     }
613 
614     std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
615     functionsGL->initialize(mDisplayAttributes);
616 
617     outRenderer->reset(
618         new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
619 
620     CurrentNativeContext &currentContext = mCurrentNativeContext[std::this_thread::get_id()];
621     if (makeNewContextCurrent)
622     {
623         currentContext.surface = mDummyPbuffer;
624         currentContext.context = context;
625     }
626     else
627     {
628         // Reset the current context back to the previous state
629         if (mEGL->makeCurrent(currentContext.surface, currentContext.context) == EGL_FALSE)
630         {
631             return egl::EglNotInitialized()
632                    << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
633         }
634     }
635 
636     return egl::NoError();
637 }
638 
639 class WorkerContextAndroid final : public WorkerContext
640 {
641   public:
642     WorkerContextAndroid(EGLContext context, FunctionsEGL *functions, EGLSurface pbuffer);
643     ~WorkerContextAndroid() override;
644 
645     bool makeCurrent() override;
646     void unmakeCurrent() override;
647 
648   private:
649     EGLContext mContext;
650     FunctionsEGL *mFunctions;
651     EGLSurface mPbuffer;
652 };
653 
WorkerContextAndroid(EGLContext context,FunctionsEGL * functions,EGLSurface pbuffer)654 WorkerContextAndroid::WorkerContextAndroid(EGLContext context,
655                                            FunctionsEGL *functions,
656                                            EGLSurface pbuffer)
657     : mContext(context), mFunctions(functions), mPbuffer(pbuffer)
658 {}
659 
~WorkerContextAndroid()660 WorkerContextAndroid::~WorkerContextAndroid()
661 {
662     mFunctions->destroyContext(mContext);
663 }
664 
makeCurrent()665 bool WorkerContextAndroid::makeCurrent()
666 {
667     if (mFunctions->makeCurrent(mPbuffer, mContext) == EGL_FALSE)
668     {
669         ERR() << "Unable to make the EGL context current.";
670         return false;
671     }
672     return true;
673 }
674 
unmakeCurrent()675 void WorkerContextAndroid::unmakeCurrent()
676 {
677     mFunctions->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
678 }
679 
createWorkerContext(std::string * infoLog,EGLContext sharedContext,const native_egl::AttributeVector workerAttribs)680 WorkerContext *DisplayAndroid::createWorkerContext(std::string *infoLog,
681                                                    EGLContext sharedContext,
682                                                    const native_egl::AttributeVector workerAttribs)
683 {
684     EGLContext context = mEGL->createContext(mConfig, sharedContext, workerAttribs.data());
685     if (context == EGL_NO_CONTEXT)
686     {
687         *infoLog += "Unable to create the EGL context.";
688         return nullptr;
689     }
690     return new WorkerContextAndroid(context, mEGL, mDummyPbuffer);
691 }
692 
initializeFrontendFeatures(angle::FrontendFeatures * features) const693 void DisplayAndroid::initializeFrontendFeatures(angle::FrontendFeatures *features) const
694 {
695     mRenderer->initializeFrontendFeatures(features);
696 }
697 
populateFeatureList(angle::FeatureList * features)698 void DisplayAndroid::populateFeatureList(angle::FeatureList *features)
699 {
700     mRenderer->getFeatures().populateFeatureList(features);
701 }
702 
703 }  // namespace rx
704