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 ¤tContext = 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 ¤tContext : 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 ¤tContext = 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