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