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