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