Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 123fd97

Browse files
Julien IsorceCommit Bot
authored andcommitted
Provide default implementation of rx::DisplayEGL
Will allow to use EGL instead of GLX on X11. Meant to be used on modern EGL so it requires the extensions EGL_KHR_no_config_context and EGL_KHR_surfaceless_context. This keeps the default implementation simple (no pBuffer fallback) Also provide simple WorkerContextEGL. Bug: angleproject:4328 Change-Id: I92a1ded9e09e65de8bb83710274e0a73ecdff0a4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2061168 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 parent 4b7bac7 commit 123fd97

File tree

4 files changed

+282
-7
lines changed

4 files changed

+282
-7
lines changed

src/libANGLE/renderer/gl/egl/DisplayEGL.cpp

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,95 @@
88

99
#include "libANGLE/renderer/gl/egl/DisplayEGL.h"
1010

11+
#include "common/debug.h"
12+
#include "libANGLE/Context.h"
13+
#include "libANGLE/Display.h"
1114
#include "libANGLE/Surface.h"
15+
#include "libANGLE/renderer/gl/ContextGL.h"
16+
#include "libANGLE/renderer/gl/RendererGL.h"
17+
#include "libANGLE/renderer/gl/egl/ContextEGL.h"
18+
#include "libANGLE/renderer/gl/egl/FunctionsEGLDL.h"
1219
#include "libANGLE/renderer/gl/egl/ImageEGL.h"
1320
#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
1421
#include "libANGLE/renderer/gl/egl/RendererEGL.h"
1522
#include "libANGLE/renderer/gl/egl/SyncEGL.h"
1623
#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
24+
#include "libANGLE/renderer/gl/renderergl_utils.h"
25+
26+
namespace
27+
{
28+
29+
EGLint ESBitFromPlatformAttrib(const rx::FunctionsEGL *egl, const EGLAttrib platformAttrib)
30+
{
31+
EGLint esBit = EGL_NONE;
32+
switch (platformAttrib)
33+
{
34+
case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
35+
{
36+
esBit = EGL_OPENGL_BIT;
37+
break;
38+
}
39+
40+
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
41+
{
42+
static_assert(EGL_OPENGL_ES3_BIT == EGL_OPENGL_ES3_BIT_KHR,
43+
"Extension define must match core");
44+
45+
gl::Version eglVersion(egl->majorVersion, egl->minorVersion);
46+
esBit = (eglVersion >= gl::Version(1, 5) || egl->hasExtension("EGL_KHR_create_context"))
47+
? EGL_OPENGL_ES3_BIT
48+
: EGL_OPENGL_ES2_BIT;
49+
break;
50+
}
51+
52+
default:
53+
break;
54+
}
55+
return esBit;
56+
}
57+
58+
class WorkerContextEGL final : public rx::WorkerContext
59+
{
60+
public:
61+
WorkerContextEGL(EGLContext context, rx::FunctionsEGL *functions, EGLSurface pbuffer);
62+
~WorkerContextEGL() override;
63+
64+
bool makeCurrent() override;
65+
void unmakeCurrent() override;
66+
67+
private:
68+
EGLContext mContext;
69+
rx::FunctionsEGL *mFunctions;
70+
EGLSurface mPbuffer;
71+
};
72+
73+
WorkerContextEGL::WorkerContextEGL(EGLContext context,
74+
rx::FunctionsEGL *functions,
75+
EGLSurface pbuffer)
76+
: mContext(context), mFunctions(functions), mPbuffer(pbuffer)
77+
{}
78+
79+
WorkerContextEGL::~WorkerContextEGL()
80+
{
81+
mFunctions->destroyContext(mContext);
82+
}
83+
84+
bool WorkerContextEGL::makeCurrent()
85+
{
86+
if (mFunctions->makeCurrent(mPbuffer, mContext) == EGL_FALSE)
87+
{
88+
ERR() << "Unable to make the EGL context current.";
89+
return false;
90+
}
91+
return true;
92+
}
93+
94+
void WorkerContextEGL::unmakeCurrent()
95+
{
96+
mFunctions->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
97+
}
98+
99+
} // namespace
17100

18101
namespace rx
19102
{
@@ -113,6 +196,96 @@ egl::Error DisplayEGL::initializeContext(EGLContext shareContext,
113196
return egl::Error(mEGL->getError(), "eglCreateContext failed");
114197
}
115198

199+
egl::Error DisplayEGL::initialize(egl::Display *display)
200+
{
201+
mDisplayAttributes = display->getAttributeMap();
202+
mEGL = new FunctionsEGLDL();
203+
204+
void *eglHandle =
205+
reinterpret_cast<void *>(mDisplayAttributes.get(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE, 0));
206+
ANGLE_TRY(mEGL->initialize(display->getNativeDisplayId(), "libEGL.so.1", eglHandle));
207+
208+
gl::Version eglVersion(mEGL->majorVersion, mEGL->minorVersion);
209+
if (eglVersion < gl::Version(1, 4))
210+
{
211+
return egl::EglNotInitialized() << "EGL >= 1.4 is required";
212+
}
213+
214+
// Only support modern EGL implementation to keep default implementation
215+
// simple.
216+
const char *necessaryExtensions[] = {
217+
"EGL_KHR_no_config_context",
218+
"EGL_KHR_surfaceless_context",
219+
};
220+
221+
for (const char *ext : necessaryExtensions)
222+
{
223+
if (!mEGL->hasExtension(ext))
224+
{
225+
return egl::EglNotInitialized() << "need " << ext;
226+
}
227+
}
228+
229+
const EGLAttrib platformAttrib = mDisplayAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, 0);
230+
EGLint esBit = ESBitFromPlatformAttrib(mEGL, platformAttrib);
231+
if (esBit == EGL_NONE)
232+
{
233+
return egl::EglNotInitialized() << "No matching ES Bit";
234+
}
235+
236+
std::vector<EGLint> configAttribListBase = {
237+
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
238+
EGL_CONFIG_CAVEAT, EGL_NONE, EGL_CONFORMANT, esBit,
239+
EGL_RENDERABLE_TYPE, esBit, EGL_NONE};
240+
241+
mConfigAttribList = configAttribListBase;
242+
243+
EGLContext context = EGL_NO_CONTEXT;
244+
native_egl::AttributeVector attribs;
245+
ANGLE_TRY(initializeContext(EGL_NO_CONTEXT, mDisplayAttributes, &context, &attribs));
246+
247+
if (!mEGL->makeCurrent(EGL_NO_SURFACE, context))
248+
{
249+
return egl::EglNotInitialized() << "Could not make context current.";
250+
}
251+
252+
std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
253+
functionsGL->initialize(mDisplayAttributes);
254+
255+
mRenderer.reset(
256+
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
257+
const gl::Version &maxVersion = mRenderer->getMaxSupportedESVersion();
258+
if (maxVersion < gl::Version(2, 0))
259+
{
260+
return egl::EglNotInitialized() << "OpenGL ES 2.0 is not supportable.";
261+
}
262+
263+
ANGLE_TRY(DisplayGL::initialize(display));
264+
265+
return egl::NoError();
266+
}
267+
268+
void DisplayEGL::terminate()
269+
{
270+
DisplayGL::terminate();
271+
272+
EGLBoolean success = mEGL->makeCurrent(EGL_NO_SURFACE, EGL_NO_CONTEXT);
273+
if (success == EGL_FALSE)
274+
{
275+
ERR() << "eglMakeCurrent error " << egl::Error(mEGL->getError());
276+
}
277+
278+
mRenderer.reset();
279+
280+
egl::Error result = mEGL->terminate();
281+
if (result.isError())
282+
{
283+
ERR() << "eglTerminate error " << result;
284+
}
285+
286+
SafeDelete(mEGL);
287+
}
288+
116289
SurfaceImpl *DisplayEGL::createWindowSurface(const egl::SurfaceState &state,
117290
EGLNativeWindowType window,
118291
const egl::AttributeMap &attribs)
@@ -159,6 +332,30 @@ SurfaceImpl *DisplayEGL::createPixmapSurface(const egl::SurfaceState &state,
159332
return nullptr;
160333
}
161334

335+
ContextImpl *DisplayEGL::createContext(const gl::State &state,
336+
gl::ErrorSet *errorSet,
337+
const egl::Config *configuration,
338+
const gl::Context *shareContext,
339+
const egl::AttributeMap &attribs)
340+
{
341+
std::shared_ptr<RendererEGL> renderer;
342+
EGLContext nativeShareContext = EGL_NO_CONTEXT;
343+
if (shareContext)
344+
{
345+
ContextEGL *shareContextEGL = GetImplAs<ContextEGL>(shareContext);
346+
nativeShareContext = shareContextEGL->getContext();
347+
}
348+
349+
egl::Error error = createRenderer(nativeShareContext, &renderer);
350+
if (error.isError())
351+
{
352+
ERR() << "Failed to create a shared renderer: " << error.getMessage();
353+
return nullptr;
354+
}
355+
356+
return new ContextEGL(state, errorSet, renderer);
357+
}
358+
162359
template <typename T>
163360
void DisplayEGL::getConfigAttrib(EGLConfig config, EGLint attribute, T *value) const
164361
{
@@ -349,6 +546,32 @@ egl::Error DisplayEGL::waitNative(const gl::Context *context, EGLint engine)
349546
return egl::NoError();
350547
}
351548

549+
egl::Error DisplayEGL::makeCurrent(egl::Surface *drawSurface,
550+
egl::Surface *readSurface,
551+
gl::Context *context)
552+
{
553+
EGLSurface newSurface = EGL_NO_SURFACE;
554+
if (drawSurface)
555+
{
556+
SurfaceEGL *drawSurfaceEGL = GetImplAs<SurfaceEGL>(drawSurface);
557+
newSurface = drawSurfaceEGL->getSurface();
558+
}
559+
560+
EGLContext newContext = EGL_NO_CONTEXT;
561+
if (context)
562+
{
563+
ContextEGL *contextEGL = GetImplAs<ContextEGL>(context);
564+
newContext = contextEGL->getContext();
565+
}
566+
567+
if (mEGL->makeCurrent(newSurface, newContext) == EGL_FALSE)
568+
{
569+
return egl::Error(mEGL->getError(), "eglMakeCurrent failed");
570+
}
571+
572+
return DisplayGL::makeCurrent(drawSurface, readSurface, context);
573+
}
574+
352575
gl::Version DisplayEGL::getMaxSupportedESVersion() const
353576
{
354577
return mRenderer->getMaxSupportedESVersion();
@@ -416,6 +639,8 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
416639

417640
outExtensions->noConfigContext = mEGL->hasExtension("EGL_KHR_no_config_context");
418641

642+
outExtensions->surfacelessContext = mEGL->hasExtension("EGL_KHR_surfaceless_context");
643+
419644
outExtensions->framebufferTargetANDROID = mEGL->hasExtension("EGL_ANDROID_framebuffer_target");
420645

421646
DisplayGL::generateExtensions(outExtensions);
@@ -441,6 +666,41 @@ egl::Error DisplayEGL::makeCurrentSurfaceless(gl::Context *context)
441666
return egl::NoError();
442667
}
443668

669+
egl::Error DisplayEGL::createRenderer(EGLContext shareContext,
670+
std::shared_ptr<RendererEGL> *outRenderer)
671+
{
672+
EGLContext context = EGL_NO_CONTEXT;
673+
native_egl::AttributeVector attribs;
674+
ANGLE_TRY(initializeContext(shareContext, mDisplayAttributes, &context, &attribs));
675+
676+
if (mEGL->makeCurrent(EGL_NO_SURFACE, context) == EGL_FALSE)
677+
{
678+
return egl::EglNotInitialized()
679+
<< "eglMakeCurrent failed with " << egl::Error(mEGL->getError());
680+
}
681+
682+
std::unique_ptr<FunctionsGL> functionsGL(mEGL->makeFunctionsGL());
683+
functionsGL->initialize(mDisplayAttributes);
684+
685+
outRenderer->reset(
686+
new RendererEGL(std::move(functionsGL), mDisplayAttributes, this, context, attribs));
687+
688+
return egl::NoError();
689+
}
690+
691+
WorkerContext *DisplayEGL::createWorkerContext(std::string *infoLog,
692+
EGLContext sharedContext,
693+
const native_egl::AttributeVector workerAttribs)
694+
{
695+
EGLContext context = mEGL->createContext(mConfig, sharedContext, workerAttribs.data());
696+
if (context == EGL_NO_CONTEXT)
697+
{
698+
*infoLog += "Unable to create the EGL context.";
699+
return nullptr;
700+
}
701+
return new WorkerContextEGL(context, mEGL, EGL_NO_SURFACE);
702+
}
703+
444704
void DisplayEGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
445705
{
446706
mRenderer->initializeFrontendFeatures(features);

src/libANGLE/renderer/gl/egl/DisplayEGL.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
#include <vector>
1515

1616
#include "libANGLE/renderer/gl/DisplayGL.h"
17-
#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
1817
#include "libANGLE/renderer/gl/egl/egl_utils.h"
1918

2019
namespace rx
2120
{
2221

22+
class FunctionsEGLDL;
2323
class RendererEGL;
2424
class WorkerContext;
2525

@@ -44,7 +44,10 @@ class DisplayEGL : public DisplayGL
4444

4545
virtual WorkerContext *createWorkerContext(std::string *infoLog,
4646
EGLContext sharedContext,
47-
const native_egl::AttributeVector workerAttribs) = 0;
47+
const native_egl::AttributeVector workerAttribs);
48+
49+
egl::Error initialize(egl::Display *display) override;
50+
void terminate() override;
4851

4952
SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
5053
EGLNativeWindowType window,
@@ -59,6 +62,12 @@ class DisplayEGL : public DisplayGL
5962
NativePixmapType nativePixmap,
6063
const egl::AttributeMap &attribs) override;
6164

65+
ContextImpl *createContext(const gl::State &state,
66+
gl::ErrorSet *errorSet,
67+
const egl::Config *configuration,
68+
const gl::Context *shareContext,
69+
const egl::AttributeMap &attribs) override;
70+
6271
egl::ConfigSet generateConfigs() override;
6372

6473
bool testDeviceLost() override;
@@ -71,6 +80,10 @@ class DisplayEGL : public DisplayGL
7180
egl::Error waitClient(const gl::Context *context) override;
7281
egl::Error waitNative(const gl::Context *context, EGLint engine) override;
7382

83+
egl::Error makeCurrent(egl::Surface *drawSurface,
84+
egl::Surface *readSurface,
85+
gl::Context *context) override;
86+
7487
gl::Version getMaxSupportedESVersion() const override;
7588

7689
void initializeFrontendFeatures(angle::FrontendFeatures *features) const override;
@@ -85,6 +98,8 @@ class DisplayEGL : public DisplayGL
8598

8699
void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
87100

101+
egl::Error createRenderer(EGLContext shareContext, std::shared_ptr<RendererEGL> *outRenderer);
102+
88103
egl::Error makeCurrentSurfaceless(gl::Context *context) override;
89104

90105
template <typename T>
@@ -98,7 +113,7 @@ class DisplayEGL : public DisplayGL
98113
const U &defaultValue) const;
99114

100115
std::shared_ptr<RendererEGL> mRenderer;
101-
FunctionsEGL *mEGL;
116+
FunctionsEGLDL *mEGL;
102117
EGLConfig mConfig;
103118
egl::AttributeMap mDisplayAttributes;
104119
std::vector<EGLint> mConfigAttribList;

src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -346,11 +346,11 @@ void DisplayAndroid::destroyNativeContext(EGLContext context)
346346

347347
void DisplayAndroid::generateExtensions(egl::DisplayExtensions *outExtensions) const
348348
{
349+
DisplayEGL::generateExtensions(outExtensions);
350+
349351
// Surfaceless can be support if the native driver supports it or we know that we are running on
350352
// a single thread (mVirtualizedContexts == true)
351353
outExtensions->surfacelessContext = mSupportsSurfaceless || mVirtualizedContexts;
352-
353-
DisplayEGL::generateExtensions(outExtensions);
354354
}
355355

356356
egl::Error DisplayAndroid::createRenderer(EGLContext shareContext,

0 commit comments

Comments
 (0)