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 // DisplayEGL.cpp: Common across EGL parts of platform specific egl::Display implementations
8
9 #include "libANGLE/renderer/gl/egl/DisplayEGL.h"
10
11 #include "common/debug.h"
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/Surface.h"
15 #include "libANGLE/renderer/gl/ContextGL.h"
16 #include "libANGLE/renderer/gl/RendererGL.h"
17 #include "libANGLE/renderer/gl/egl/ContextEGL.h"
18 #include "libANGLE/renderer/gl/egl/DmaBufImageSiblingEGL.h"
19 #include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
20 #include "libANGLE/renderer/gl/egl/ImageEGL.h"
21 #include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
22 #include "libANGLE/renderer/gl/egl/RendererEGL.h"
23 #include "libANGLE/renderer/gl/egl/SyncEGL.h"
24 #include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
25 #include "libANGLE/renderer/gl/renderergl_utils.h"
26
27 namespace
28 {
29
ESBitFromPlatformAttrib(const rx::FunctionsEGL * egl,const EGLAttrib platformAttrib)30 EGLint ESBitFromPlatformAttrib(const rx::FunctionsEGL *egl, const EGLAttrib platformAttrib)
31 {
32 EGLint esBit = EGL_NONE;
33 switch (platformAttrib)
34 {
35 case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
36 {
37 esBit = EGL_OPENGL_BIT;
38 break;
39 }
40
41 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
42 {
43 static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR,
44 "Extension define must match core");
45
46 gl::Version eglVersion(egl->majorVersion, egl->minorVersion);
47 esBit = (eglVersion >= gl::Version(1, 5) || egl->hasExtension("EGL_KHR_create_context"))
48 ? EGL_OPENGL_ES3_BIT
49 : EGL_OPENGL_ES2_BIT;
50 break;
51 }
52
53 default:
54 break;
55 }
56 return esBit;
57 }
58
59 class WorkerContextEGL final : public rx::WorkerContext
60 {
61 public:
62 WorkerContextEGL(EGLContext context, rx::FunctionsEGL *functions, EGLSurface pbuffer);
63 ~WorkerContextEGL() override;
64
65 bool makeCurrent() override;
66 void unmakeCurrent() override;
67
68 private:
69 EGLContext mContext;
70 rx::FunctionsEGL *mFunctions;
71 EGLSurface mPbuffer;
72 };
73
WorkerContextEGL(EGLContext context,rx::FunctionsEGL * functions,EGLSurface pbuffer)74 WorkerContextEGL::WorkerContextEGL(EGLContext context,
75 rx::FunctionsEGL *functions,
76 EGLSurface pbuffer)
77 : mContext(context), mFunctions(functions), mPbuffer(pbuffer)
78 {}
79
~WorkerContextEGL()80 WorkerContextEGL::~WorkerContextEGL()
81 {
82 mFunctions->destroyContext(mContext);
83 }
84
makeCurrent()85 bool WorkerContextEGL::makeCurrent()
86 {
87 if (mFunctions->makeCurrent(mPbuffer, mContext) == EGL_FALSE)
88 {
89 ERR() << "Unable to make the EGL context current.";
90 return false;
91 }
92 return true;
93 }
94
unmakeCurrent()95 void WorkerContextEGL::unmakeCurrent()
96 {
97 mFunctions->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
98 }
99
100 } // namespace
101
102 namespace rx
103 {
104
DisplayEGL(const egl::DisplayState & state)105 DisplayEGL::DisplayEGL(const egl::DisplayState &state)
106 : DisplayGL(state), mRenderer(nullptr), mEGL(nullptr), mConfig(EGL_NO_CONFIG_KHR)
107 {}
108
~DisplayEGL()109 DisplayEGL::~DisplayEGL() {}
110
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)111 ImageImpl *DisplayEGL::createImage(const egl::ImageState &state,
112 const gl::Context *context,
113 EGLenum target,
114 const egl::AttributeMap &attribs)
115 {
116 return new ImageEGL(state, context, target, attribs, mEGL);
117 }
118
createSync(const egl::AttributeMap & attribs)119 EGLSyncImpl *DisplayEGL::createSync(const egl::AttributeMap &attribs)
120 {
121 return new SyncEGL(attribs, mEGL);
122 }
123
getVendorString() const124 std::string DisplayEGL::getVendorString() const
125 {
126 const char *vendor = mEGL->queryString(EGL_VENDOR);
127 ASSERT(vendor);
128 return vendor;
129 }
130
initializeContext(EGLContext shareContext,const egl::AttributeMap & eglAttributes,EGLContext * outContext,native_egl::AttributeVector * outAttribs) const131 egl::Error DisplayEGL::initializeContext(EGLContext shareContext,
132 const egl::AttributeMap &eglAttributes,
133 EGLContext *outContext,
134 native_egl::AttributeVector *outAttribs) const
135 {
136 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
137
138 EGLint requestedMajor =
139 eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
140 EGLint requestedMinor =
141 eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
142 bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE;
143
144 static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR,
145 "Major Version define should match");
146 static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR,
147 "Minor Version define should match");
148
149 std::vector<native_egl::AttributeVector> contextAttribLists;
150 if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
151 {
152 if (initializeRequested)
153 {
154 contextAttribLists.push_back({EGL_CONTEXT_MAJOR_VERSION, requestedMajor,
155 EGL_CONTEXT_MINOR_VERSION, requestedMinor, EGL_NONE});
156 }
157 else
158 {
159 // clang-format off
160 const gl::Version esVersionsFrom2_0[] = {
161 gl::Version(3, 2),
162 gl::Version(3, 1),
163 gl::Version(3, 0),
164 gl::Version(2, 0),
165 };
166 // clang-format on
167
168 for (const auto &version : esVersionsFrom2_0)
169 {
170 contextAttribLists.push_back(
171 {EGL_CONTEXT_MAJOR_VERSION, static_cast<EGLint>(version.major),
172 EGL_CONTEXT_MINOR_VERSION, static_cast<EGLint>(version.minor), EGL_NONE});
173 }
174 }
175 }
176 else
177 {
178 if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0))
179 {
180 return egl::EglBadAttribute() << "Unsupported requested context version";
181 }
182 contextAttribLists.push_back({EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE});
183 }
184
185 EGLContext context = EGL_NO_CONTEXT;
186 for (const auto &attribList : contextAttribLists)
187 {
188 context = mEGL->createContext(mConfig, shareContext, attribList.data());
189 if (context != EGL_NO_CONTEXT)
190 {
191 *outContext = context;
192 *outAttribs = attribList;
193 return egl::NoError();
194 }
195 }
196
197 return egl::Error(mEGL->getError(), "eglCreateContext failed");
198 }
199
initialize(egl::Display * display)200 egl::Error DisplayEGL::initialize(egl::Display *display)
201 {
202 mDisplayAttributes = display->getAttributeMap();
203 mEGL = new FunctionsEGLDL();
204
205 void *eglHandle =
206 reinterpret_cast<void *>(mDisplayAttributes.get(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE, 0));
207 ANGLE_TRY(mEGL->initialize(display->getNativeDisplayId(), "libEGL.so.1", eglHandle));
208
209 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
210 if (eglVersion < gl::Version(1, 4))
211 {
212 return egl::EglNotInitialized() << "EGL >= 1.4 is required";
213 }
214
215 // Only support modern EGL implementation to keep default implementation
216 // simple.
217 const char *necessaryExtensions[] = {
218 "EGL_KHR_no_config_context",
219 "EGL_KHR_surfaceless_context",
220 };
221
222 for (const char *ext : necessaryExtensions)
223 {
224 if (!mEGL->hasExtension(ext))
225 {
226 return egl::EglNotInitialized() << "need " << ext;
227 }
228 }
229
230 const EGLAttrib platformAttrib = mDisplayAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, 0);
231 EGLint esBit = ESBitFromPlatformAttrib(mEGL, platformAttrib);
232 if (esBit == EGL_NONE)
233 {
234 return egl::EglNotInitialized() << "No matching ES Bit";
235 }
236
237 std::vector<EGLint> configAttribListBase = {
238 EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
239 EGL_CONFIG_CAVEAT, EGL_NONE, EGL_CONFORMANT, esBit,
240 EGL_RENDERABLE_TYPE, esBit, EGL_NONE};
241
242 mConfigAttribList = configAttribListBase;
243
244 EGLContext context = EGL_NO_CONTEXT;
245 native_egl::AttributeVector attribs;
246 ANGLE_TRY(initializeContext(EGL_NO_CONTEXT, mDisplayAttributes, &context, &attribs));
247
248 if (!mEGL->makeCurrent(EGL_NO_SURFACE, context))
249 {
250 return egl::EglNotInitialized() << "Could not make context current.";
251 }
252
253 std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
254 functionsGL->initialize(mDisplayAttributes);
255
256 mRenderer.reset(
257 new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
258 const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
259 if (maxVersion < gl::Version(2, 0))
260 {
261 return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
262 }
263
264 ANGLE_TRY(DisplayGL::initialize(display));
265
266 return egl::NoError();
267 }
268
terminate()269 void DisplayEGL::terminate()
270 {
271 DisplayGL::terminate();
272
273 EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
274 if (success == EGL_FALSE)
275 {
276 ERR() << "eglMakeCurrent error " << egl::Error(mEGL->getError());
277 }
278
279 mRenderer.reset();
280
281 egl::Error result = mEGL->terminate();
282 if (result.isError())
283 {
284 ERR() << "eglTerminate error " << result;
285 }
286
287 SafeDelete(mEGL);
288 }
289
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)290 SurfaceImpl *DisplayEGL::createWindowSurface(const egl::SurfaceState &state,
291 EGLNativeWindowType window,
292 const egl::AttributeMap &attribs)
293 {
294 EGLConfig config;
295 EGLint numConfig;
296 EGLBoolean success;
297
298 const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
299 success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
300 ASSERT(success && numConfig == 1);
301
302 return new WindowSurfaceEGL(state, mEGL, config, window);
303 }
304
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)305 SurfaceImpl *DisplayEGL::createPbufferSurface(const egl::SurfaceState &state,
306 const egl::AttributeMap &attribs)
307 {
308 EGLConfig config;
309 EGLint numConfig;
310 EGLBoolean success;
311
312 const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
313 success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
314 ASSERT(success && numConfig == 1);
315
316 return new PbufferSurfaceEGL(state, mEGL, config);
317 }
318
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)319 SurfaceImpl *DisplayEGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
320 EGLenum buftype,
321 EGLClientBuffer clientBuffer,
322 const egl::AttributeMap &attribs)
323 {
324 UNIMPLEMENTED();
325 return nullptr;
326 }
327
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)328 SurfaceImpl *DisplayEGL::createPixmapSurface(const egl::SurfaceState &state,
329 NativePixmapType nativePixmap,
330 const egl::AttributeMap &attribs)
331 {
332 UNIMPLEMENTED();
333 return nullptr;
334 }
335
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)336 ContextImpl *DisplayEGL::createContext(const gl::State &state,
337 gl::ErrorSet *errorSet,
338 const egl::Config *configuration,
339 const gl::Context *shareContext,
340 const egl::AttributeMap &attribs)
341 {
342 std::shared_ptr<RendererEGL> renderer;
343 EGLContext nativeShareContext = EGL_NO_CONTEXT;
344 if (shareContext)
345 {
346 ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
347 nativeShareContext = shareContextEGL->getContext();
348 }
349
350 egl::Error error = createRenderer(nativeShareContext, &renderer);
351 if (error.isError())
352 {
353 ERR() << "Failed to create a shared renderer: " << error.getMessage();
354 return nullptr;
355 }
356
357 return new ContextEGL(state, errorSet, renderer);
358 }
359
360 template <typename T>
getConfigAttrib(EGLConfig config,EGLint attribute,T * value) const361 void DisplayEGL::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
362 {
363 EGLint tmp;
364 EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
365 ASSERT(success == EGL_TRUE);
366 *value = tmp;
367 }
368
369 template <typename T, typename U>
getConfigAttribIfExtension(EGLConfig config,EGLint attribute,T * value,const char * extension,const U & defaultValue) const370 void DisplayEGL::getConfigAttribIfExtension(EGLConfig config,
371 EGLint attribute,
372 T *value,
373 const char *extension,
374 const U &defaultValue) const
375 {
376 if (mEGL->hasExtension(extension))
377 {
378 getConfigAttrib(config, attribute, value);
379 }
380 else
381 {
382 *value = static_cast<T>(defaultValue);
383 }
384 }
385
generateConfigs()386 egl::ConfigSet DisplayEGL::generateConfigs()
387 {
388 egl::ConfigSet configSet;
389 mConfigIds.clear();
390
391 EGLint numConfigs;
392 EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
393 ASSERT(success == EGL_TRUE && numConfigs > 0);
394
395 std::vector<EGLConfig> configs(numConfigs);
396 EGLint numConfigs2;
397 success =
398 mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
399 ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
400
401 for (int i = 0; i < numConfigs; i++)
402 {
403 egl::Config config;
404
405 getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
406 getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
407 getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
408 getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
409 getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
410 getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
411 getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
412 getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
413 getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
414 getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
415 getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
416 getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
417 getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
418 getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
419 getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
420 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
421 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
422 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
423 getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
424 getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
425 getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
426 getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
427 getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
428 getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
429 getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
430 getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
431 getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
432 getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
433 getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
434 getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
435 getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
436 getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
437 getConfigAttribIfExtension(configs[i], EGL_COLOR_COMPONENT_TYPE_EXT,
438 &config.colorComponentType, "EGL_EXT_pixel_format_float",
439 EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
440
441 if (config.colorBufferType == EGL_RGB_BUFFER)
442 {
443 ASSERT(config.colorComponentType == EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
444 if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
445 config.alphaSize == 8)
446 {
447 config.renderTargetFormat = GL_RGBA8;
448 }
449 else if (config.redSize == 8 && config.greenSize == 8 && config.blueSize == 8 &&
450 config.alphaSize == 0)
451 {
452 config.renderTargetFormat = GL_RGB8;
453 }
454 else if (config.redSize == 5 && config.greenSize == 6 && config.blueSize == 5 &&
455 config.alphaSize == 0)
456 {
457 config.renderTargetFormat = GL_RGB565;
458 }
459 else if (config.redSize == 5 && config.greenSize == 5 && config.blueSize == 5 &&
460 config.alphaSize == 1)
461 {
462 config.renderTargetFormat = GL_RGB5_A1;
463 }
464 else if (config.redSize == 4 && config.greenSize == 4 && config.blueSize == 4 &&
465 config.alphaSize == 4)
466 {
467 config.renderTargetFormat = GL_RGBA4;
468 }
469 else
470 {
471 ERR() << "RGBA(" << config.redSize << "," << config.greenSize << ","
472 << config.blueSize << "," << config.alphaSize << ") not handled";
473 UNREACHABLE();
474 }
475 }
476 else
477 {
478 UNREACHABLE();
479 }
480
481 if (config.depthSize == 0 && config.stencilSize == 0)
482 {
483 config.depthStencilFormat = GL_ZERO;
484 }
485 else if (config.depthSize == 16 && config.stencilSize == 0)
486 {
487 config.depthStencilFormat = GL_DEPTH_COMPONENT16;
488 }
489 else if (config.depthSize == 24 && config.stencilSize == 0)
490 {
491 config.depthStencilFormat = GL_DEPTH_COMPONENT24;
492 }
493 else if (config.depthSize == 24 && config.stencilSize == 8)
494 {
495 config.depthStencilFormat = GL_DEPTH24_STENCIL8;
496 }
497 else if (config.depthSize == 0 && config.stencilSize == 8)
498 {
499 config.depthStencilFormat = GL_STENCIL_INDEX8;
500 }
501 else
502 {
503 UNREACHABLE();
504 }
505
506 config.matchNativePixmap = EGL_NONE;
507 config.optimalOrientation = 0;
508
509 int internalId = configSet.add(config);
510 mConfigIds[internalId] = config.configID;
511 }
512
513 return configSet;
514 }
515
testDeviceLost()516 bool DisplayEGL::testDeviceLost()
517 {
518 return false;
519 }
520
restoreLostDevice(const egl::Display * display)521 egl::Error DisplayEGL::restoreLostDevice(const egl::Display *display)
522 {
523 UNIMPLEMENTED();
524 return egl::NoError();
525 }
526
isValidNativeWindow(EGLNativeWindowType window) const527 bool DisplayEGL::isValidNativeWindow(EGLNativeWindowType window) const
528 {
529 return true;
530 }
531
createDevice()532 DeviceImpl *DisplayEGL::createDevice()
533 {
534 UNIMPLEMENTED();
535 return nullptr;
536 }
537
waitClient(const gl::Context * context)538 egl::Error DisplayEGL::waitClient(const gl::Context *context)
539 {
540 UNIMPLEMENTED();
541 return egl::NoError();
542 }
543
waitNative(const gl::Context * context,EGLint engine)544 egl::Error DisplayEGL::waitNative(const gl::Context *context, EGLint engine)
545 {
546 UNIMPLEMENTED();
547 return egl::NoError();
548 }
549
makeCurrent(egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)550 egl::Error DisplayEGL::makeCurrent(egl::Surface *drawSurface,
551 egl::Surface *readSurface,
552 gl::Context *context)
553 {
554 EGLSurface newSurface = EGL_NO_SURFACE;
555 if (drawSurface)
556 {
557 SurfaceEGL *drawSurfaceEGL = GetImplAs<SurfaceEGL>(drawSurface);
558 newSurface = drawSurfaceEGL->getSurface();
559 }
560
561 EGLContext newContext = EGL_NO_CONTEXT;
562 if (context)
563 {
564 ContextEGL *contextEGL = GetImplAs<ContextEGL>(context);
565 newContext = contextEGL->getContext();
566 }
567
568 if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
569 {
570 return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
571 }
572
573 return DisplayGL::makeCurrent(drawSurface, readSurface, context);
574 }
575
getMaxSupportedESVersion() const576 gl::Version DisplayEGL::getMaxSupportedESVersion() const
577 {
578 return mRenderer->getMaxSupportedESVersion();
579 }
580
destroyNativeContext(EGLContext context)581 void DisplayEGL::destroyNativeContext(EGLContext context)
582 {
583 mEGL->destroyContext(context);
584 }
585
generateExtensions(egl::DisplayExtensions * outExtensions) const586 void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
587 {
588 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
589
590 outExtensions->createContextRobustness =
591 mEGL->hasExtension("EGL_EXT_create_context_robustness");
592
593 outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented
594 outExtensions->presentationTime = mEGL->hasExtension("EGL_ANDROID_presentation_time");
595
596 // Contexts are virtualized so textures can be shared globally
597 outExtensions->displayTextureShareGroup = true;
598
599 // We will fallback to regular swap if swapBuffersWithDamage isn't
600 // supported, so indicate support here to keep validation happy.
601 outExtensions->swapBuffersWithDamage = true;
602
603 outExtensions->image = mEGL->hasExtension("EGL_KHR_image");
604 outExtensions->imageBase = mEGL->hasExtension("EGL_KHR_image_base");
605 // Pixmaps are not supported in ANGLE's EGL implementation.
606 // outExtensions->imagePixmap = mEGL->hasExtension("EGL_KHR_image_pixmap");
607 outExtensions->glTexture2DImage = mEGL->hasExtension("EGL_KHR_gl_texture_2D_image");
608 outExtensions->glTextureCubemapImage = mEGL->hasExtension("EGL_KHR_gl_texture_cubemap_image");
609 outExtensions->glTexture3DImage = mEGL->hasExtension("EGL_KHR_gl_texture_3D_image");
610 outExtensions->glRenderbufferImage = mEGL->hasExtension("EGL_KHR_gl_renderbuffer_image");
611 outExtensions->pixelFormatFloat = mEGL->hasExtension("EGL_EXT_pixel_format_float");
612
613 outExtensions->glColorspace = mEGL->hasExtension("EGL_KHR_gl_colorspace");
614 if (outExtensions->glColorspace)
615 {
616 outExtensions->glColorspaceDisplayP3Linear =
617 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3_linear");
618 outExtensions->glColorspaceDisplayP3 =
619 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3");
620 outExtensions->glColorspaceScrgb = mEGL->hasExtension("EGL_EXT_gl_colorspace_scrgb");
621 outExtensions->glColorspaceScrgbLinear =
622 mEGL->hasExtension("EGL_EXT_gl_colorspace_scrgb_linear");
623 outExtensions->glColorspaceDisplayP3Passthrough =
624 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3_passthrough");
625 outExtensions->imageGlColorspace = mEGL->hasExtension("EGL_EXT_image_gl_colorspace");
626 }
627
628 outExtensions->imageNativeBuffer = mEGL->hasExtension("EGL_ANDROID_image_native_buffer");
629
630 outExtensions->getFrameTimestamps = mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps");
631
632 outExtensions->fenceSync =
633 eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_fence_sync");
634 outExtensions->waitSync =
635 eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_wait_sync");
636
637 outExtensions->getNativeClientBufferANDROID =
638 mEGL->hasExtension("EGL_ANDROID_get_native_client_buffer");
639
640 outExtensions->nativeFenceSyncANDROID = mEGL->hasExtension("EGL_ANDROID_native_fence_sync");
641
642 outExtensions->noConfigContext = mEGL->hasExtension("EGL_KHR_no_config_context");
643
644 outExtensions->surfacelessContext = mEGL->hasExtension("EGL_KHR_surfaceless_context");
645
646 outExtensions->framebufferTargetANDROID = mEGL->hasExtension("EGL_ANDROID_framebuffer_target");
647
648 outExtensions->imageDmaBufImportEXT = mEGL->hasExtension("EGL_EXT_image_dma_buf_import");
649
650 outExtensions->imageDmaBufImportModifiersEXT =
651 mEGL->hasExtension("EGL_EXT_image_dma_buf_import_modifiers");
652
653 DisplayGL::generateExtensions(outExtensions);
654 }
655
generateCaps(egl::Caps * outCaps) const656 void DisplayEGL::generateCaps(egl::Caps *outCaps) const
657 {
658 outCaps->textureNPOT = true; // Since we request GLES >= 2
659 }
660
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)661 void DisplayEGL::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
662 {
663 if (mEGL->hasExtension("EGL_ANDROID_blob_cache"))
664 {
665 mEGL->setBlobCacheFuncsANDROID(set, get);
666 }
667 }
668
makeCurrentSurfaceless(gl::Context * context)669 egl::Error DisplayEGL::makeCurrentSurfaceless(gl::Context *context)
670 {
671 // Nothing to do because EGL always uses the same context and the previous surface can be left
672 // current.
673 return egl::NoError();
674 }
675
createRenderer(EGLContext shareContext,std::shared_ptr<RendererEGL> * outRenderer)676 egl::Error DisplayEGL::createRenderer(EGLContext shareContext,
677 std::shared_ptr<RendererEGL> *outRenderer)
678 {
679 EGLContext context = EGL_NO_CONTEXT;
680 native_egl::AttributeVector attribs;
681 ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
682
683 if (mEGL->makeCurrent(EGL_NO_SURFACE, context) == EGL_FALSE)
684 {
685 return egl::EglNotInitialized()
686 << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
687 }
688
689 std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
690 functionsGL->initialize(mDisplayAttributes);
691
692 outRenderer->reset(
693 new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
694
695 return egl::NoError();
696 }
697
createWorkerContext(std::string * infoLog,EGLContext sharedContext,const native_egl::AttributeVector workerAttribs)698 WorkerContext *DisplayEGL::createWorkerContext(std::string *infoLog,
699 EGLContext sharedContext,
700 const native_egl::AttributeVector workerAttribs)
701 {
702 EGLContext context = mEGL->createContext(mConfig, sharedContext, workerAttribs.data());
703 if (context == EGL_NO_CONTEXT)
704 {
705 *infoLog += "Unable to create the EGL context.";
706 return nullptr;
707 }
708 return new WorkerContextEGL(context, mEGL, EGL_NO_SURFACE);
709 }
710
initializeFrontendFeatures(angle::FrontendFeatures * features) const711 void DisplayEGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
712 {
713 mRenderer->initializeFrontendFeatures(features);
714 }
715
populateFeatureList(angle::FeatureList * features)716 void DisplayEGL::populateFeatureList(angle::FeatureList *features)
717 {
718 mRenderer->getFeatures().populateFeatureList(features);
719 }
720
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const721 egl::Error DisplayEGL::validateImageClientBuffer(const gl::Context *context,
722 EGLenum target,
723 EGLClientBuffer clientBuffer,
724 const egl::AttributeMap &attribs) const
725 {
726 switch (target)
727 {
728 case EGL_LINUX_DMA_BUF_EXT:
729 return egl::NoError();
730
731 default:
732 return DisplayGL::validateImageClientBuffer(context, target, clientBuffer, attribs);
733 }
734 }
735
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)736 ExternalImageSiblingImpl *DisplayEGL::createExternalImageSibling(const gl::Context *context,
737 EGLenum target,
738 EGLClientBuffer buffer,
739 const egl::AttributeMap &attribs)
740 {
741 switch (target)
742 {
743 case EGL_LINUX_DMA_BUF_EXT:
744 ASSERT(context == nullptr);
745 ASSERT(buffer == nullptr);
746 return new DmaBufImageSiblingEGL(attribs);
747
748 default:
749 return DisplayGL::createExternalImageSibling(context, target, buffer, attribs);
750 }
751 }
752
753 } // namespace rx
754