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 "common/system_utils.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/Surface.h"
16 #include "libANGLE/renderer/gl/ContextGL.h"
17 #include "libANGLE/renderer/gl/RendererGL.h"
18 #include "libANGLE/renderer/gl/egl/ContextEGL.h"
19 #include "libANGLE/renderer/gl/egl/DeviceEGL.h"
20 #include "libANGLE/renderer/gl/egl/DmaBufImageSiblingEGL.h"
21 #include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
22 #include "libANGLE/renderer/gl/egl/ImageEGL.h"
23 #include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
24 #include "libANGLE/renderer/gl/egl/RendererEGL.h"
25 #include "libANGLE/renderer/gl/egl/SyncEGL.h"
26 #include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
27 #include "libANGLE/renderer/gl/renderergl_utils.h"
28
29 namespace
30 {
31
GetRobustnessVideoMemoryPurge(const egl::AttributeMap & attribs)32 rx::RobustnessVideoMemoryPurgeStatus GetRobustnessVideoMemoryPurge(const egl::AttributeMap &attribs)
33 {
34 return static_cast<rx::RobustnessVideoMemoryPurgeStatus>(
35 attribs.get(EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV, GL_FALSE));
36 }
37
RenderableTypesFromPlatformAttrib(const rx::FunctionsEGL * egl,const EGLAttrib platformAttrib)38 std::vector<EGLint> RenderableTypesFromPlatformAttrib(const rx::FunctionsEGL *egl,
39 const EGLAttrib platformAttrib)
40 {
41 std::vector<EGLint> renderableTypes;
42 switch (platformAttrib)
43 {
44 case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
45 renderableTypes.push_back(EGL_OPENGL_BIT);
46 break;
47
48 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
49 {
50 static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR,
51 "Extension define must match core");
52
53 gl::Version eglVersion(egl->majorVersion, egl->minorVersion);
54 if (eglVersion >= gl::Version(1, 5) || egl->hasExtension("EGL_KHR_create_context"))
55 {
56 renderableTypes.push_back(EGL_OPENGL_ES3_BIT);
57 }
58 renderableTypes.push_back(EGL_OPENGL_ES2_BIT);
59 }
60 break;
61
62 default:
63 break;
64 }
65 return renderableTypes;
66 }
67
68 class WorkerContextEGL final : public rx::WorkerContext
69 {
70 public:
71 WorkerContextEGL(EGLContext context, rx::FunctionsEGL *functions, EGLSurface pbuffer);
72 ~WorkerContextEGL() override;
73
74 bool makeCurrent() override;
75 void unmakeCurrent() override;
76
77 private:
78 EGLContext mContext;
79 rx::FunctionsEGL *mFunctions;
80 EGLSurface mPbuffer;
81 };
82
WorkerContextEGL(EGLContext context,rx::FunctionsEGL * functions,EGLSurface pbuffer)83 WorkerContextEGL::WorkerContextEGL(EGLContext context,
84 rx::FunctionsEGL *functions,
85 EGLSurface pbuffer)
86 : mContext(context), mFunctions(functions), mPbuffer(pbuffer)
87 {}
88
~WorkerContextEGL()89 WorkerContextEGL::~WorkerContextEGL()
90 {
91 mFunctions->destroyContext(mContext);
92 }
93
makeCurrent()94 bool WorkerContextEGL::makeCurrent()
95 {
96 if (mFunctions->makeCurrent(mPbuffer, mContext) == EGL_FALSE)
97 {
98 ERR() << "Unable to make the EGL context current.";
99 return false;
100 }
101 return true;
102 }
103
unmakeCurrent()104 void WorkerContextEGL::unmakeCurrent()
105 {
106 mFunctions->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
107 }
108
109 } // namespace
110
111 namespace rx
112 {
113
DisplayEGL(const egl::DisplayState & state)114 DisplayEGL::DisplayEGL(const egl::DisplayState &state) : DisplayGL(state) {}
115
~DisplayEGL()116 DisplayEGL::~DisplayEGL() {}
117
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)118 ImageImpl *DisplayEGL::createImage(const egl::ImageState &state,
119 const gl::Context *context,
120 EGLenum target,
121 const egl::AttributeMap &attribs)
122 {
123 return new ImageEGL(state, context, target, attribs, mEGL);
124 }
125
createSync(const egl::AttributeMap & attribs)126 EGLSyncImpl *DisplayEGL::createSync(const egl::AttributeMap &attribs)
127 {
128 return new SyncEGL(attribs, mEGL);
129 }
130
getEGLPath() const131 const char *DisplayEGL::getEGLPath() const
132 {
133 #if defined(ANGLE_PLATFORM_ANDROID)
134 # if defined(__LP64__)
135 return "/system/lib64/libEGL.so";
136 # else
137 return "/system/lib/libEGL.so";
138 # endif
139 #else
140 return "libEGL.so.1";
141 #endif
142 }
143
initializeContext(EGLContext shareContext,const egl::AttributeMap & eglAttributes,EGLContext * outContext,native_egl::AttributeVector * outAttribs) const144 egl::Error DisplayEGL::initializeContext(EGLContext shareContext,
145 const egl::AttributeMap &eglAttributes,
146 EGLContext *outContext,
147 native_egl::AttributeVector *outAttribs) const
148 {
149 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
150
151 EGLint requestedMajor =
152 eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
153 EGLint requestedMinor =
154 eglAttributes.getAsInt(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
155 bool initializeRequested = requestedMajor != EGL_DONT_CARE && requestedMinor != EGL_DONT_CARE;
156
157 static_assert(EGL_CONTEXT_MAJOR_VERSION == EGL_CONTEXT_MAJOR_VERSION_KHR,
158 "Major Version define should match");
159 static_assert(EGL_CONTEXT_MINOR_VERSION == EGL_CONTEXT_MINOR_VERSION_KHR,
160 "Minor Version define should match");
161
162 std::vector<egl::AttributeMap> contextAttribLists;
163 if (eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_create_context"))
164 {
165 if (initializeRequested)
166 {
167 egl::AttributeMap requestedVersionAttribs;
168 requestedVersionAttribs.insert(EGL_CONTEXT_MAJOR_VERSION, requestedMajor);
169 requestedVersionAttribs.insert(EGL_CONTEXT_MINOR_VERSION, requestedMinor);
170
171 contextAttribLists.push_back(std::move(requestedVersionAttribs));
172 }
173 else
174 {
175 // clang-format off
176 const gl::Version esVersionsFrom2_0[] = {
177 gl::Version(3, 2),
178 gl::Version(3, 1),
179 gl::Version(3, 0),
180 gl::Version(2, 0),
181 };
182 // clang-format on
183
184 for (const auto &version : esVersionsFrom2_0)
185 {
186 egl::AttributeMap versionAttribs;
187 versionAttribs.insert(EGL_CONTEXT_MAJOR_VERSION,
188 static_cast<EGLint>(version.major));
189 versionAttribs.insert(EGL_CONTEXT_MINOR_VERSION,
190 static_cast<EGLint>(version.minor));
191
192 contextAttribLists.push_back(std::move(versionAttribs));
193 }
194 }
195 }
196 else
197 {
198 if (initializeRequested && (requestedMajor != 2 || requestedMinor != 0))
199 {
200 return egl::EglBadAttribute() << "Unsupported requested context version";
201 }
202
203 egl::AttributeMap fallbackAttribs;
204 fallbackAttribs.insert(EGL_CONTEXT_CLIENT_VERSION, 2);
205
206 contextAttribLists.push_back(std::move(fallbackAttribs));
207 }
208
209 for (const egl::AttributeMap &attribs : contextAttribLists)
210 {
211 // If robustness is supported, try to create a context with robustness enabled. If it fails,
212 // fall back to creating a context without the robustness parameters. We've seen devices
213 // that expose the robustness extensions but fail to create robust contexts.
214 if (mHasEXTCreateContextRobustness)
215 {
216 egl::AttributeMap attribsWithRobustness(attribs);
217
218 attribsWithRobustness.insert(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY,
219 EGL_LOSE_CONTEXT_ON_RESET);
220 if (mHasNVRobustnessVideoMemoryPurge)
221 {
222 attribsWithRobustness.insert(EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV, GL_TRUE);
223 }
224
225 native_egl::AttributeVector attribVector = attribsWithRobustness.toIntVector();
226 EGLContext context = mEGL->createContext(mConfig, shareContext, attribVector.data());
227 if (context != EGL_NO_CONTEXT)
228 {
229 *outContext = context;
230 *outAttribs = std::move(attribVector);
231 return egl::NoError();
232 }
233
234 INFO() << "EGL_EXT_create_context_robustness available but robust context creation "
235 "failed.";
236 }
237
238 native_egl::AttributeVector attribVector = attribs.toIntVector();
239 EGLContext context = mEGL->createContext(mConfig, shareContext, attribVector.data());
240 if (context != EGL_NO_CONTEXT)
241 {
242 *outContext = context;
243 *outAttribs = std::move(attribVector);
244 return egl::NoError();
245 }
246 }
247
248 return egl::Error(mEGL->getError(), "eglCreateContext failed");
249 }
250
initialize(egl::Display * display)251 egl::Error DisplayEGL::initialize(egl::Display *display)
252 {
253 mDisplayAttributes = display->getAttributeMap();
254 mEGL = new FunctionsEGLDL();
255
256 void *eglHandle =
257 reinterpret_cast<void *>(mDisplayAttributes.get(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE, 0));
258 EGLAttrib platformType =
259 mDisplayAttributes.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
260 ANGLE_TRY(
261 mEGL->initialize(platformType, display->getNativeDisplayId(), getEGLPath(), eglHandle));
262
263 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
264 if (eglVersion < gl::Version(1, 4))
265 {
266 return egl::EglNotInitialized() << "EGL >= 1.4 is required";
267 }
268
269 // https://anglebug.com/7664
270 // TODO: turn this into a feature so we can communicate that this is disabled on purpose.
271 mSupportsDmaBufImportModifiers = mEGL->hasExtension("EGL_EXT_image_dma_buf_import_modifiers");
272
273 bool isKevin = mEGL->vendorString.find("ARM") != std::string::npos &&
274 mEGL->versionString.find("r26p0-01rel0") != std::string::npos;
275 mNoOpDmaBufImportModifiers = isKevin || !mEGL->hasDmaBufImportModifierFunctions();
276
277 mHasEXTCreateContextRobustness = mEGL->hasExtension("EGL_EXT_create_context_robustness");
278 mHasNVRobustnessVideoMemoryPurge = mEGL->hasExtension("EGL_NV_robustness_video_memory_purge");
279 mSupportsNoConfigContexts = mEGL->hasExtension("EGL_KHR_no_config_context") ||
280 mEGL->hasExtension("EGL_KHR_no_config_context");
281 mSupportsSurfaceless = mEGL->hasExtension("EGL_KHR_surfaceless_context");
282
283 if (!mSupportsNoConfigContexts)
284 {
285 const EGLAttrib platformAttrib = mDisplayAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, 0);
286 std::vector<EGLint> renderableTypes =
287 RenderableTypesFromPlatformAttrib(mEGL, platformAttrib);
288 if (renderableTypes.empty())
289 {
290 return egl::EglNotInitialized() << "No available renderable types.";
291 }
292
293 const EGLint surfaceTypes[] = {EGL_WINDOW_BIT | EGL_PBUFFER_BIT, EGL_DONT_CARE};
294
295 egl::AttributeMap configAttribs;
296 // Choose RGBA8888
297 configAttribs.insert(EGL_RED_SIZE, 8);
298 configAttribs.insert(EGL_GREEN_SIZE, 8);
299 configAttribs.insert(EGL_BLUE_SIZE, 8);
300 configAttribs.insert(EGL_ALPHA_SIZE, 8);
301
302 // Choose D24S8
303 // EGL1.5 spec Section 2.2 says that depth, multisample and stencil buffer depths
304 // must match for contexts to be compatible.
305 configAttribs.insert(EGL_DEPTH_SIZE, 24);
306 configAttribs.insert(EGL_STENCIL_SIZE, 8);
307
308 for (EGLint surfaceType : surfaceTypes)
309 {
310 configAttribs.insert(EGL_SURFACE_TYPE, surfaceType);
311
312 for (EGLint renderableType : renderableTypes)
313 {
314 configAttribs.insert(EGL_RENDERABLE_TYPE, renderableType);
315
316 std::vector<EGLint> attribVector = configAttribs.toIntVector();
317
318 EGLint numConfig = 0;
319 if (mEGL->chooseConfig(attribVector.data(), &mConfig, 1, &numConfig) == EGL_TRUE)
320 {
321 break;
322 }
323 }
324 }
325
326 if (mConfig == EGL_NO_CONFIG_KHR)
327 {
328 return egl::EglNotInitialized()
329 << "eglChooseConfig failed with " << egl::Error(mEGL->getError());
330 }
331
332 mConfigAttribList = configAttribs.toIntVector();
333 }
334
335 // A mock pbuffer is only needed if surfaceless contexts are not supported.
336 mSupportsSurfaceless = mEGL->hasExtension("EGL_KHR_surfaceless_context");
337 if (!mSupportsSurfaceless)
338 {
339 // clang-format off
340 constexpr const EGLint pbufferConfigAttribs[] =
341 {
342 // We want RGBA8 and DEPTH24_STENCIL8
343 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
344 EGL_RED_SIZE, 8,
345 EGL_GREEN_SIZE, 8,
346 EGL_BLUE_SIZE, 8,
347 EGL_ALPHA_SIZE, 8,
348 EGL_DEPTH_SIZE, 24,
349 EGL_STENCIL_SIZE, 8,
350 EGL_NONE,
351 };
352
353 constexpr const int mockPbufferAttribs[] = {
354 EGL_WIDTH, 1,
355 EGL_HEIGHT, 1,
356 EGL_NONE,
357 };
358 // clang-format on
359
360 EGLint numConfig;
361 EGLConfig pbufferConfig;
362 if (!mEGL->chooseConfig(pbufferConfigAttribs, &pbufferConfig, 1, &numConfig) ||
363 numConfig < 1)
364 {
365 return egl::EglNotInitialized() << "Failed to find a config for the mock pbuffer.";
366 }
367
368 mMockPbuffer = mEGL->createPbufferSurface(pbufferConfig, mockPbufferAttribs);
369 if (mMockPbuffer == EGL_NO_SURFACE)
370 {
371 return egl::EglNotInitialized()
372 << "eglCreatePbufferSurface failed with " << egl::Error(mEGL->getError());
373 }
374 }
375
376 ANGLE_TRY(createRenderer(EGL_NO_CONTEXT, true, false, &mRenderer));
377
378 const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
379 if (maxVersion < gl::Version(2, 0))
380 {
381 return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
382 }
383
384 ANGLE_TRY(DisplayGL::initialize(display));
385
386 INFO() << "ANGLE DisplayEGL initialized: " << getRendererDescription();
387
388 return egl::NoError();
389 }
390
terminate()391 void DisplayEGL::terminate()
392 {
393 DisplayGL::terminate();
394
395 EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
396 if (success == EGL_FALSE)
397 {
398 ERR() << "eglMakeCurrent error " << egl::Error(mEGL->getError());
399 }
400
401 if (mMockPbuffer != EGL_NO_SURFACE)
402 {
403 success = mEGL->destroySurface(mMockPbuffer);
404 mMockPbuffer = EGL_NO_SURFACE;
405 if (success == EGL_FALSE)
406 {
407 ERR() << "eglDestroySurface error " << egl::Error(mEGL->getError());
408 }
409 }
410
411 mRenderer.reset();
412 mVirtualizationGroups.clear();
413
414 mCurrentNativeContexts.clear();
415
416 egl::Error result = mEGL->terminate();
417 if (result.isError())
418 {
419 ERR() << "eglTerminate error " << result;
420 }
421
422 SafeDelete(mEGL);
423 }
424
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)425 SurfaceImpl *DisplayEGL::createWindowSurface(const egl::SurfaceState &state,
426 EGLNativeWindowType window,
427 const egl::AttributeMap &attribs)
428 {
429 EGLConfig config;
430 EGLint numConfig;
431 EGLBoolean success;
432
433 const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
434 success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
435 ASSERT(success && numConfig == 1);
436
437 return new WindowSurfaceEGL(state, mEGL, config, window);
438 }
439
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)440 SurfaceImpl *DisplayEGL::createPbufferSurface(const egl::SurfaceState &state,
441 const egl::AttributeMap &attribs)
442 {
443 EGLConfig config;
444 EGLint numConfig;
445 EGLBoolean success;
446
447 const EGLint configAttribList[] = {EGL_CONFIG_ID, mConfigIds[state.config->configID], EGL_NONE};
448 success = mEGL->chooseConfig(configAttribList, &config, 1, &numConfig);
449 ASSERT(success && numConfig == 1);
450
451 return new PbufferSurfaceEGL(state, mEGL, config);
452 }
453
454 class ExternalSurfaceEGL : public SurfaceEGL
455 {
456 public:
ExternalSurfaceEGL(const egl::SurfaceState & state,const FunctionsEGL * egl,EGLConfig config,EGLint width,EGLint height)457 ExternalSurfaceEGL(const egl::SurfaceState &state,
458 const FunctionsEGL *egl,
459 EGLConfig config,
460 EGLint width,
461 EGLint height)
462 : SurfaceEGL(state, egl, config), mWidth(width), mHeight(height)
463 {}
464 ~ExternalSurfaceEGL() override = default;
465
initialize(const egl::Display * display)466 egl::Error initialize(const egl::Display *display) override { return egl::NoError(); }
getSwapBehavior() const467 EGLint getSwapBehavior() const override { return EGL_BUFFER_DESTROYED; }
getWidth() const468 EGLint getWidth() const override { return mWidth; }
getHeight() const469 EGLint getHeight() const override { return mHeight; }
isExternal() const470 bool isExternal() const override { return true; }
471
472 private:
473 const EGLint mWidth;
474 const EGLint mHeight;
475 };
476
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)477 SurfaceImpl *DisplayEGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
478 EGLenum buftype,
479 EGLClientBuffer clientBuffer,
480 const egl::AttributeMap &attribs)
481 {
482 switch (buftype)
483 {
484 case EGL_EXTERNAL_SURFACE_ANGLE:
485 return new ExternalSurfaceEGL(state, mEGL, EGL_NO_CONFIG_KHR,
486 attribs.getAsInt(EGL_WIDTH, 0),
487 attribs.getAsInt(EGL_HEIGHT, 0));
488
489 default:
490 return DisplayGL::createPbufferFromClientBuffer(state, buftype, clientBuffer, attribs);
491 }
492 }
493
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)494 SurfaceImpl *DisplayEGL::createPixmapSurface(const egl::SurfaceState &state,
495 NativePixmapType nativePixmap,
496 const egl::AttributeMap &attribs)
497 {
498 UNIMPLEMENTED();
499 return nullptr;
500 }
501
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)502 ContextImpl *DisplayEGL::createContext(const gl::State &state,
503 gl::ErrorSet *errorSet,
504 const egl::Config *configuration,
505 const gl::Context *shareContext,
506 const egl::AttributeMap &attribs)
507 {
508 bool usingExternalContext = attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE;
509 EGLAttrib virtualizationGroup =
510 attribs.get(EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE, EGL_DONT_CARE);
511 bool globalTextureShareGroup =
512 attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
513
514 std::shared_ptr<RendererEGL> renderer = mRenderer;
515 if (usingExternalContext)
516 {
517 ASSERT(!shareContext);
518 egl::Error error = createRenderer(EGL_NO_CONTEXT, false, true, &renderer);
519 if (error.isError())
520 {
521 ERR() << "Failed to create a shared renderer: " << error.getMessage();
522 return nullptr;
523 }
524 }
525 else if (virtualizationGroup != EGL_DONT_CARE)
526 {
527 renderer = mVirtualizationGroups[virtualizationGroup].lock();
528 if (!renderer)
529 {
530 // If the user requested a dispaly-level texture share group, all contexts must be in
531 // the same share group. Otherwise honor the user's share group request.
532 EGLContext nativeShareContext = EGL_NO_CONTEXT;
533 if (globalTextureShareGroup)
534 {
535 nativeShareContext = mRenderer->getContext();
536 }
537 else if (shareContext)
538 {
539 ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
540 nativeShareContext = shareContextEGL->getContext();
541 }
542
543 // Create a new renderer for this context.
544 egl::Error error = createRenderer(nativeShareContext, false, false, &renderer);
545 if (error.isError())
546 {
547 ERR() << "Failed to create a shared renderer: " << error.getMessage();
548 return nullptr;
549 }
550
551 mVirtualizationGroups[virtualizationGroup] = renderer;
552 }
553 }
554 ASSERT(renderer);
555
556 RobustnessVideoMemoryPurgeStatus robustnessVideoMemoryPurgeStatus =
557 GetRobustnessVideoMemoryPurge(attribs);
558 return new ContextEGL(state, errorSet, renderer, robustnessVideoMemoryPurgeStatus);
559 }
560
561 template <typename T>
getConfigAttrib(EGLConfig config,EGLint attribute,T * value) const562 void DisplayEGL::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
563 {
564 EGLint tmp;
565 EGLBoolean success = mEGL->getConfigAttrib(config, attribute, &tmp);
566 ASSERT(success == EGL_TRUE);
567 *value = tmp;
568 }
569
570 template <typename T, typename U>
getConfigAttribIfExtension(EGLConfig config,EGLint attribute,T * value,const char * extension,const U & defaultValue) const571 void DisplayEGL::getConfigAttribIfExtension(EGLConfig config,
572 EGLint attribute,
573 T *value,
574 const char *extension,
575 const U &defaultValue) const
576 {
577 if (mEGL->hasExtension(extension))
578 {
579 getConfigAttrib(config, attribute, value);
580 }
581 else
582 {
583 *value = static_cast<T>(defaultValue);
584 }
585 }
586
generateConfigs()587 egl::ConfigSet DisplayEGL::generateConfigs()
588 {
589 egl::ConfigSet configSet;
590 mConfigIds.clear();
591
592 std::vector<EGLConfig> configs;
593 if (mSupportsNoConfigContexts)
594 {
595 // Gather all configs
596 EGLint numConfigs;
597 EGLBoolean success = mEGL->getConfigs(nullptr, 0, &numConfigs);
598 ASSERT(success == EGL_TRUE && numConfigs > 0);
599
600 configs.resize(numConfigs);
601 EGLint numConfigs2;
602 success = mEGL->getConfigs(configs.data(), numConfigs, &numConfigs2);
603 ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
604 }
605 else
606 {
607 // Choose configs that match the attribute list of the config used for the context
608 EGLint numConfigs;
609 EGLBoolean success = mEGL->chooseConfig(mConfigAttribList.data(), nullptr, 0, &numConfigs);
610 ASSERT(success == EGL_TRUE && numConfigs > 0);
611
612 configs.resize(numConfigs);
613 EGLint numConfigs2;
614 success =
615 mEGL->chooseConfig(mConfigAttribList.data(), configs.data(), numConfigs, &numConfigs2);
616 ASSERT(success == EGL_TRUE && numConfigs2 == numConfigs);
617 }
618
619 for (size_t i = 0; i < configs.size(); i++)
620 {
621 egl::Config config;
622
623 getConfigAttrib(configs[i], EGL_BUFFER_SIZE, &config.bufferSize);
624 getConfigAttrib(configs[i], EGL_RED_SIZE, &config.redSize);
625 getConfigAttrib(configs[i], EGL_GREEN_SIZE, &config.greenSize);
626 getConfigAttrib(configs[i], EGL_BLUE_SIZE, &config.blueSize);
627 getConfigAttrib(configs[i], EGL_LUMINANCE_SIZE, &config.luminanceSize);
628 getConfigAttrib(configs[i], EGL_ALPHA_SIZE, &config.alphaSize);
629 getConfigAttrib(configs[i], EGL_ALPHA_MASK_SIZE, &config.alphaMaskSize);
630 getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGB, &config.bindToTextureRGB);
631 getConfigAttrib(configs[i], EGL_BIND_TO_TEXTURE_RGBA, &config.bindToTextureRGBA);
632 getConfigAttrib(configs[i], EGL_COLOR_BUFFER_TYPE, &config.colorBufferType);
633 getConfigAttrib(configs[i], EGL_CONFIG_CAVEAT, &config.configCaveat);
634 getConfigAttrib(configs[i], EGL_CONFIG_ID, &config.configID);
635 getConfigAttrib(configs[i], EGL_CONFORMANT, &config.conformant);
636 getConfigAttrib(configs[i], EGL_DEPTH_SIZE, &config.depthSize);
637 getConfigAttrib(configs[i], EGL_LEVEL, &config.level);
638 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_WIDTH, &config.maxPBufferWidth);
639 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_HEIGHT, &config.maxPBufferHeight);
640 getConfigAttrib(configs[i], EGL_MAX_PBUFFER_PIXELS, &config.maxPBufferPixels);
641 getConfigAttrib(configs[i], EGL_MAX_SWAP_INTERVAL, &config.maxSwapInterval);
642 getConfigAttrib(configs[i], EGL_MIN_SWAP_INTERVAL, &config.minSwapInterval);
643 getConfigAttrib(configs[i], EGL_NATIVE_RENDERABLE, &config.nativeRenderable);
644 getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_ID, &config.nativeVisualID);
645 getConfigAttrib(configs[i], EGL_NATIVE_VISUAL_TYPE, &config.nativeVisualType);
646 getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE, &config.renderableType);
647 getConfigAttrib(configs[i], EGL_SAMPLE_BUFFERS, &config.sampleBuffers);
648 getConfigAttrib(configs[i], EGL_SAMPLES, &config.samples);
649 getConfigAttrib(configs[i], EGL_STENCIL_SIZE, &config.stencilSize);
650 getConfigAttrib(configs[i], EGL_SURFACE_TYPE, &config.surfaceType);
651 getConfigAttrib(configs[i], EGL_TRANSPARENT_TYPE, &config.transparentType);
652 getConfigAttrib(configs[i], EGL_TRANSPARENT_RED_VALUE, &config.transparentRedValue);
653 getConfigAttrib(configs[i], EGL_TRANSPARENT_GREEN_VALUE, &config.transparentGreenValue);
654 getConfigAttrib(configs[i], EGL_TRANSPARENT_BLUE_VALUE, &config.transparentBlueValue);
655 getConfigAttribIfExtension(configs[i], EGL_COLOR_COMPONENT_TYPE_EXT,
656 &config.colorComponentType, "EGL_EXT_pixel_format_float",
657 EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
658
659 config.surfaceType = fixSurfaceType(config.surfaceType);
660
661 if (config.colorBufferType == EGL_RGB_BUFFER)
662 {
663 config.renderTargetFormat = gl::GetConfigColorBufferFormat(&config);
664 if (config.renderTargetFormat == GL_NONE)
665 {
666 ERR() << "RGBA(" << config.redSize << "," << config.greenSize << ","
667 << config.blueSize << "," << config.alphaSize << ") not handled";
668 continue;
669 }
670 }
671 else
672 {
673 continue;
674 }
675 config.depthStencilFormat = gl::GetConfigDepthStencilBufferFormat(&config);
676
677 config.matchNativePixmap = EGL_NONE;
678 config.optimalOrientation = 0;
679
680 int internalId = configSet.add(config);
681 mConfigIds[internalId] = config.configID;
682 }
683
684 return configSet;
685 }
686
testDeviceLost()687 bool DisplayEGL::testDeviceLost()
688 {
689 return false;
690 }
691
restoreLostDevice(const egl::Display * display)692 egl::Error DisplayEGL::restoreLostDevice(const egl::Display *display)
693 {
694 UNIMPLEMENTED();
695 return egl::NoError();
696 }
697
isValidNativeWindow(EGLNativeWindowType window) const698 bool DisplayEGL::isValidNativeWindow(EGLNativeWindowType window) const
699 {
700 return true;
701 }
702
validateClientBuffer(const egl::Config * configuration,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const703 egl::Error DisplayEGL::validateClientBuffer(const egl::Config *configuration,
704 EGLenum buftype,
705 EGLClientBuffer clientBuffer,
706 const egl::AttributeMap &attribs) const
707 {
708 switch (buftype)
709 {
710 case EGL_EXTERNAL_SURFACE_ANGLE:
711 ASSERT(clientBuffer == nullptr);
712 return egl::NoError();
713
714 default:
715 return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
716 }
717 }
718
waitClient(const gl::Context * context)719 egl::Error DisplayEGL::waitClient(const gl::Context *context)
720 {
721 UNIMPLEMENTED();
722 return egl::NoError();
723 }
724
waitNative(const gl::Context * context,EGLint engine)725 egl::Error DisplayEGL::waitNative(const gl::Context *context, EGLint engine)
726 {
727 UNIMPLEMENTED();
728 return egl::NoError();
729 }
730
makeCurrent(egl::Display * display,egl::Surface * drawSurface,egl::Surface * readSurface,gl::Context * context)731 egl::Error DisplayEGL::makeCurrent(egl::Display *display,
732 egl::Surface *drawSurface,
733 egl::Surface *readSurface,
734 gl::Context *context)
735 {
736 CurrentNativeContext ¤tContext =
737 mCurrentNativeContexts[angle::GetCurrentThreadUniqueId()];
738
739 EGLSurface newSurface = EGL_NO_SURFACE;
740 if (drawSurface)
741 {
742 SurfaceEGL *drawSurfaceEGL = GetImplAs<SurfaceEGL>(drawSurface);
743 newSurface = drawSurfaceEGL->getSurface();
744 }
745
746 EGLContext newContext = EGL_NO_CONTEXT;
747 if (context)
748 {
749 ContextEGL *contextEGL = GetImplAs<ContextEGL>(context);
750 newContext = contextEGL->getContext();
751 }
752
753 if (currentContext.isExternalContext || (context && context->isExternal()))
754 {
755 ASSERT(currentContext.surface == EGL_NO_SURFACE);
756 if (!currentContext.isExternalContext)
757 {
758 // Switch to an ANGLE external context.
759 ASSERT(context);
760 ASSERT(currentContext.context == EGL_NO_CONTEXT);
761 currentContext.context = newContext;
762 currentContext.isExternalContext = true;
763
764 // We only support using external surface with external context.
765 ASSERT(GetImplAs<SurfaceEGL>(drawSurface)->isExternal());
766 ASSERT(GetImplAs<SurfaceEGL>(drawSurface)->getSurface() == EGL_NO_SURFACE);
767 }
768 else if (context)
769 {
770 // Switch surface but not context.
771 ASSERT(currentContext.context == newContext);
772 ASSERT(newSurface == EGL_NO_SURFACE);
773 ASSERT(newContext != EGL_NO_CONTEXT);
774 // We only support using external surface with external context.
775 ASSERT(GetImplAs<SurfaceEGL>(drawSurface)->isExternal());
776 ASSERT(GetImplAs<SurfaceEGL>(drawSurface)->getSurface() == EGL_NO_SURFACE);
777 }
778 else
779 {
780 // Release the ANGLE external context.
781 ASSERT(newSurface == EGL_NO_SURFACE);
782 ASSERT(newContext == EGL_NO_CONTEXT);
783 ASSERT(currentContext.context != EGL_NO_CONTEXT);
784 currentContext.context = EGL_NO_CONTEXT;
785 currentContext.isExternalContext = false;
786 }
787
788 // Do not need to call eglMakeCurrent(), since we don't support switching EGLSurface for
789 // external context.
790 return DisplayGL::makeCurrent(display, drawSurface, readSurface, context);
791 }
792
793 if (newSurface != currentContext.surface || newContext != currentContext.context)
794 {
795 if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
796 {
797 return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
798 }
799 currentContext.surface = newSurface;
800 currentContext.context = newContext;
801 }
802
803 return DisplayGL::makeCurrent(display, drawSurface, readSurface, context);
804 }
805
getMaxSupportedESVersion() const806 gl::Version DisplayEGL::getMaxSupportedESVersion() const
807 {
808 return mRenderer->getMaxSupportedESVersion();
809 }
810
destroyNativeContext(EGLContext context)811 void DisplayEGL::destroyNativeContext(EGLContext context)
812 {
813 // If this context is current, remove it from the tracking of current contexts to make sure we
814 // don't try to make it current again.
815 for (auto ¤tContext : mCurrentNativeContexts)
816 {
817 if (currentContext.second.context == context)
818 {
819 currentContext.second.surface = EGL_NO_SURFACE;
820 currentContext.second.context = EGL_NO_CONTEXT;
821 }
822 }
823
824 mEGL->destroyContext(context);
825 }
826
generateExtensions(egl::DisplayExtensions * outExtensions) const827 void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
828 {
829 gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
830
831 outExtensions->createContextRobustness =
832 mEGL->hasExtension("EGL_EXT_create_context_robustness");
833
834 outExtensions->postSubBuffer = false; // Since SurfaceEGL::postSubBuffer is not implemented
835 outExtensions->presentationTime = mEGL->hasExtension("EGL_ANDROID_presentation_time");
836
837 // Contexts are virtualized so textures and semaphores can be shared globally
838 outExtensions->displayTextureShareGroup = true;
839 outExtensions->displaySemaphoreShareGroup = true;
840
841 // We will fallback to regular swap if swapBuffersWithDamage isn't
842 // supported, so indicate support here to keep validation happy.
843 outExtensions->swapBuffersWithDamage = true;
844
845 outExtensions->image = mEGL->hasExtension("EGL_KHR_image");
846 outExtensions->imageBase = mEGL->hasExtension("EGL_KHR_image_base");
847 // Pixmaps are not supported in ANGLE's EGL implementation.
848 // outExtensions->imagePixmap = mEGL->hasExtension("EGL_KHR_image_pixmap");
849 outExtensions->glTexture2DImage = mEGL->hasExtension("EGL_KHR_gl_texture_2D_image");
850 outExtensions->glTextureCubemapImage = mEGL->hasExtension("EGL_KHR_gl_texture_cubemap_image");
851 outExtensions->glTexture3DImage = mEGL->hasExtension("EGL_KHR_gl_texture_3D_image");
852 outExtensions->glRenderbufferImage = mEGL->hasExtension("EGL_KHR_gl_renderbuffer_image");
853 outExtensions->pixelFormatFloat = mEGL->hasExtension("EGL_EXT_pixel_format_float");
854
855 outExtensions->glColorspace = mEGL->hasExtension("EGL_KHR_gl_colorspace");
856 if (outExtensions->glColorspace)
857 {
858 outExtensions->glColorspaceDisplayP3Linear =
859 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3_linear");
860 outExtensions->glColorspaceDisplayP3 =
861 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3");
862 outExtensions->glColorspaceScrgb = mEGL->hasExtension("EGL_EXT_gl_colorspace_scrgb");
863 outExtensions->glColorspaceScrgbLinear =
864 mEGL->hasExtension("EGL_EXT_gl_colorspace_scrgb_linear");
865 outExtensions->glColorspaceDisplayP3Passthrough =
866 mEGL->hasExtension("EGL_EXT_gl_colorspace_display_p3_passthrough");
867 outExtensions->imageGlColorspace = mEGL->hasExtension("EGL_EXT_image_gl_colorspace");
868 }
869
870 outExtensions->imageNativeBuffer = mEGL->hasExtension("EGL_ANDROID_image_native_buffer");
871
872 outExtensions->getFrameTimestamps = mEGL->hasExtension("EGL_ANDROID_get_frame_timestamps");
873
874 outExtensions->fenceSync =
875 eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_fence_sync");
876 outExtensions->waitSync =
877 eglVersion >= gl::Version(1, 5) || mEGL->hasExtension("EGL_KHR_wait_sync");
878
879 outExtensions->getNativeClientBufferANDROID =
880 mEGL->hasExtension("EGL_ANDROID_get_native_client_buffer");
881
882 outExtensions->createNativeClientBufferANDROID =
883 mEGL->hasExtension("EGL_ANDROID_create_native_client_buffer");
884
885 outExtensions->nativeFenceSyncANDROID = mEGL->hasExtension("EGL_ANDROID_native_fence_sync");
886
887 outExtensions->noConfigContext = mSupportsNoConfigContexts;
888
889 outExtensions->surfacelessContext = mEGL->hasExtension("EGL_KHR_surfaceless_context");
890
891 outExtensions->framebufferTargetANDROID = mEGL->hasExtension("EGL_ANDROID_framebuffer_target");
892
893 outExtensions->imageDmaBufImportEXT = mEGL->hasExtension("EGL_EXT_image_dma_buf_import");
894
895 outExtensions->imageDmaBufImportModifiersEXT = mSupportsDmaBufImportModifiers;
896
897 outExtensions->robustnessVideoMemoryPurgeNV = mHasNVRobustnessVideoMemoryPurge;
898
899 outExtensions->bufferAgeEXT = mEGL->hasExtension("EGL_EXT_buffer_age");
900
901 // Surfaceless can be support if the native driver supports it or we know that we are running on
902 // a single thread (mVirtualizedContexts == true)
903 outExtensions->surfacelessContext = mSupportsSurfaceless;
904
905 outExtensions->externalContextAndSurface = true;
906
907 outExtensions->contextVirtualizationANGLE = true;
908
909 DisplayGL::generateExtensions(outExtensions);
910 }
911
generateCaps(egl::Caps * outCaps) const912 void DisplayEGL::generateCaps(egl::Caps *outCaps) const
913 {
914 outCaps->textureNPOT = true; // Since we request GLES >= 2
915 }
916
setBlobCacheFuncs(EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)917 void DisplayEGL::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
918 {
919 if (mEGL->hasExtension("EGL_ANDROID_blob_cache"))
920 {
921 mEGL->setBlobCacheFuncsANDROID(set, get);
922 }
923 }
924
makeCurrentSurfaceless(gl::Context * context)925 egl::Error DisplayEGL::makeCurrentSurfaceless(gl::Context *context)
926 {
927 // Nothing to do because EGL always uses the same context and the previous surface can be left
928 // current.
929 return egl::NoError();
930 }
931
createRenderer(EGLContext shareContext,bool makeNewContextCurrent,bool isExternalContext,std::shared_ptr<RendererEGL> * outRenderer)932 egl::Error DisplayEGL::createRenderer(EGLContext shareContext,
933 bool makeNewContextCurrent,
934 bool isExternalContext,
935 std::shared_ptr<RendererEGL> *outRenderer)
936 {
937 EGLContext context = EGL_NO_CONTEXT;
938 native_egl::AttributeVector attribs;
939
940 // If isExternalContext is true, the external context is current, so we don't need to make the
941 // mMockPbuffer current.
942 if (isExternalContext)
943 {
944 ASSERT(shareContext == EGL_NO_CONTEXT);
945 ASSERT(!makeNewContextCurrent);
946 // TODO(penghuang): Should we consider creating a share context to avoid querying and
947 // restoring GL context state? http://anglebug.com/5509
948 context = mEGL->getCurrentContext();
949 ASSERT(context != EGL_NO_CONTEXT);
950 // TODO(penghuang): get the version from the current context. http://anglebug.com/5509
951 attribs = {EGL_CONTEXT_MAJOR_VERSION, 2, EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE};
952 }
953 else
954 {
955 ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
956 if (mEGL->makeCurrent(mMockPbuffer, context) == EGL_FALSE)
957 {
958 return egl::EglNotInitialized()
959 << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
960 }
961 }
962
963 std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
964 functionsGL->initialize(mDisplayAttributes);
965
966 outRenderer->reset(new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context,
967 attribs, isExternalContext));
968
969 CurrentNativeContext ¤tContext =
970 mCurrentNativeContexts[angle::GetCurrentThreadUniqueId()];
971 if (makeNewContextCurrent)
972 {
973 currentContext.surface = mMockPbuffer;
974 currentContext.context = context;
975 }
976 else if (!isExternalContext)
977 {
978 // Reset the current context back to the previous state
979 if (mEGL->makeCurrent(currentContext.surface, currentContext.context) == EGL_FALSE)
980 {
981 return egl::EglNotInitialized()
982 << "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
983 }
984 }
985
986 return egl::NoError();
987 }
988
createWorkerContext(std::string * infoLog,EGLContext sharedContext,const native_egl::AttributeVector workerAttribs)989 WorkerContext *DisplayEGL::createWorkerContext(std::string *infoLog,
990 EGLContext sharedContext,
991 const native_egl::AttributeVector workerAttribs)
992 {
993 EGLContext context = mEGL->createContext(mConfig, sharedContext, workerAttribs.data());
994 if (context == EGL_NO_CONTEXT)
995 {
996 *infoLog += "Unable to create the EGL context.";
997 return nullptr;
998 }
999 return new WorkerContextEGL(context, mEGL, EGL_NO_SURFACE);
1000 }
1001
initializeFrontendFeatures(angle::FrontendFeatures * features) const1002 void DisplayEGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
1003 {
1004 mRenderer->initializeFrontendFeatures(features);
1005 }
1006
populateFeatureList(angle::FeatureList * features)1007 void DisplayEGL::populateFeatureList(angle::FeatureList *features)
1008 {
1009 mRenderer->getFeatures().populateFeatureList(features);
1010 }
1011
getRenderer() const1012 RendererGL *DisplayEGL::getRenderer() const
1013 {
1014 return mRenderer.get();
1015 }
1016
validateImageClientBuffer(const gl::Context * context,EGLenum target,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs) const1017 egl::Error DisplayEGL::validateImageClientBuffer(const gl::Context *context,
1018 EGLenum target,
1019 EGLClientBuffer clientBuffer,
1020 const egl::AttributeMap &attribs) const
1021 {
1022 switch (target)
1023 {
1024 case EGL_LINUX_DMA_BUF_EXT:
1025 return egl::NoError();
1026
1027 default:
1028 return DisplayGL::validateImageClientBuffer(context, target, clientBuffer, attribs);
1029 }
1030 }
1031
createExternalImageSibling(const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const egl::AttributeMap & attribs)1032 ExternalImageSiblingImpl *DisplayEGL::createExternalImageSibling(const gl::Context *context,
1033 EGLenum target,
1034 EGLClientBuffer buffer,
1035 const egl::AttributeMap &attribs)
1036 {
1037 switch (target)
1038 {
1039 case EGL_LINUX_DMA_BUF_EXT:
1040 ASSERT(context == nullptr);
1041 ASSERT(buffer == nullptr);
1042 return new DmaBufImageSiblingEGL(attribs);
1043
1044 default:
1045 return DisplayGL::createExternalImageSibling(context, target, buffer, attribs);
1046 }
1047 }
1048
fixSurfaceType(EGLint surfaceType) const1049 EGLint DisplayEGL::fixSurfaceType(EGLint surfaceType) const
1050 {
1051 // Pixmaps are not supported on EGL, make sure the config doesn't expose them.
1052 return surfaceType & ~EGL_PIXMAP_BIT;
1053 }
1054
getFunctionsEGL() const1055 const FunctionsEGL *DisplayEGL::getFunctionsEGL() const
1056 {
1057 return mEGL;
1058 }
1059
createDevice()1060 DeviceImpl *DisplayEGL::createDevice()
1061 {
1062 return new DeviceEGL(this);
1063 }
1064
supportsDmaBufFormat(EGLint format) const1065 bool DisplayEGL::supportsDmaBufFormat(EGLint format) const
1066 {
1067 return std::find(std::begin(mDrmFormats), std::end(mDrmFormats), format) !=
1068 std::end(mDrmFormats);
1069 }
1070
queryDmaBufFormats(EGLint maxFormats,EGLint * formats,EGLint * numFormats)1071 egl::Error DisplayEGL::queryDmaBufFormats(EGLint maxFormats, EGLint *formats, EGLint *numFormats)
1072
1073 {
1074 if (!mDrmFormatsInitialized)
1075 {
1076 if (!mNoOpDmaBufImportModifiers)
1077 {
1078 EGLint numFormatsInit = 0;
1079 if (mEGL->queryDmaBufFormatsEXT(0, nullptr, &numFormatsInit) && numFormatsInit > 0)
1080 {
1081 mDrmFormats.resize(numFormatsInit);
1082 if (!mEGL->queryDmaBufFormatsEXT(numFormatsInit, mDrmFormats.data(),
1083 &numFormatsInit))
1084 {
1085 mDrmFormats.resize(0);
1086 }
1087 }
1088 }
1089 mDrmFormatsInitialized = true;
1090 }
1091
1092 EGLint formatsSize = static_cast<EGLint>(mDrmFormats.size());
1093 *numFormats = formatsSize;
1094 if (maxFormats > 0)
1095 {
1096 // Do not copy data beyond the limits of the vector
1097 maxFormats = std::min(maxFormats, formatsSize);
1098 std::memcpy(formats, mDrmFormats.data(), maxFormats * sizeof(EGLint));
1099 }
1100
1101 return egl::NoError();
1102 }
1103
queryDmaBufModifiers(EGLint drmFormat,EGLint maxModifiers,EGLuint64KHR * modifiers,EGLBoolean * externalOnly,EGLint * numModifiers)1104 egl::Error DisplayEGL::queryDmaBufModifiers(EGLint drmFormat,
1105 EGLint maxModifiers,
1106 EGLuint64KHR *modifiers,
1107 EGLBoolean *externalOnly,
1108 EGLint *numModifiers)
1109
1110 {
1111 *numModifiers = 0;
1112 if (!mNoOpDmaBufImportModifiers)
1113 {
1114 if (!mEGL->queryDmaBufModifiersEXT(drmFormat, maxModifiers, modifiers, externalOnly,
1115 numModifiers))
1116 {
1117 return egl::Error(mEGL->getError(), "eglQueryDmaBufModifiersEXT failed");
1118 }
1119 }
1120
1121 return egl::NoError();
1122 }
1123
1124 } // namespace rx
1125