Commit 4c06817a by Corentin Wallez Committed by Commit Bot

Add support for targetting GLES with DisplayGLX.

BUG=angleproject:1145 Change-Id: I3072c31f2f743943b2ed9a3b1a020529112d5f71 Reviewed-on: https://chromium-review.googlesource.com/324091Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 2e5dd41c
...@@ -180,6 +180,8 @@ rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap) ...@@ -180,6 +180,8 @@ rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
#if defined(ANGLE_PLATFORM_WINDOWS) #if defined(ANGLE_PLATFORM_WINDOWS)
impl = new rx::DisplayWGL(); impl = new rx::DisplayWGL();
#elif defined(ANGLE_USE_X11)
impl = new rx::DisplayGLX();
#else #else
// No GLES support on this platform, fail display creation. // No GLES support on this platform, fail display creation.
impl = nullptr; impl = nullptr;
......
...@@ -65,6 +65,8 @@ DisplayGLX::DisplayGLX() ...@@ -65,6 +65,8 @@ DisplayGLX::DisplayGLX()
mIsMesa(false), mIsMesa(false),
mHasMultisample(false), mHasMultisample(false),
mHasARBCreateContext(false), mHasARBCreateContext(false),
mHasARBCreateContextProfile(false),
mHasEXTCreateContextES2Profile(false),
mSwapControl(SwapControl::Absent), mSwapControl(SwapControl::Absent),
mMinSwapInterval(0), mMinSwapInterval(0),
mMaxSwapInterval(0), mMaxSwapInterval(0),
...@@ -104,6 +106,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -104,6 +106,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample"); mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context"); mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
mHasARBCreateContextProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
mHasEXTCreateContextES2Profile = mGLX.hasExtension("GLX_EXT_create_context_es2_profile");
// Choose the swap_control extension to use, if any. // Choose the swap_control extension to use, if any.
// The EXT version is better as it allows glXSwapInterval to be called per // The EXT version is better as it allows glXSwapInterval to be called per
...@@ -208,12 +212,26 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -208,12 +212,26 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
XFree(candidates); XFree(candidates);
} }
const auto &eglAttributes = display->getAttributeMap();
if (mHasARBCreateContext) if (mHasARBCreateContext)
{ {
mContext = initializeContext(mContextConfig, display->getAttributeMap()); egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext);
if (error.isError())
{
return error;
}
} }
else else
{ {
if (eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) ==
EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
{
return egl::Error(EGL_NOT_INITIALIZED,
"Cannot create an OpenGL ES platform on GLX without the "
"GLX_ARB_create_context extension.");
}
XVisualInfo visualTemplate; XVisualInfo visualTemplate;
visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID); visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
...@@ -228,11 +246,13 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -228,11 +246,13 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
mContext = mGLX.createContext(&visuals[0], nullptr, true); mContext = mGLX.createContext(&visuals[0], nullptr, true);
XFree(visuals); XFree(visuals);
}
if (!mContext) if (!mContext)
{ {
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context."); return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
} }
}
ASSERT(mContext);
// FunctionsGL and DisplayGL need to make a few GL calls, for example to // FunctionsGL and DisplayGL need to make a few GL calls, for example to
// query the version of the context so we need to make the context current. // query the version of the context so we need to make the context current.
...@@ -341,33 +361,50 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device) ...@@ -341,33 +361,50 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device)
return egl::Error(EGL_BAD_DISPLAY); return egl::Error(EGL_BAD_DISPLAY);
} }
glx::Context DisplayGLX::initializeContext(glx::FBConfig config, egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
const egl::AttributeMap &eglAttributes) const egl::AttributeMap &eglAttributes,
glx::Context *context)
{ {
// Create a context of the requested version, if any. int profileMask = 0;
EGLint requestedMajorVersion =
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); EGLint requestedDisplayType =
EGLint requestedMinorVersion = eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE) {
if (!mHasEXTCreateContextES2Profile)
{ {
std::vector<int> contextAttributes; return egl::Error(EGL_NOT_INITIALIZED,
contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB); "Cannot create an OpenGL ES platform on GLX without the "
contextAttributes.push_back(requestedMajorVersion); "GLX_EXT_create_context_es_profile extension.");
}
contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB); ASSERT(mHasARBCreateContextProfile);
contextAttributes.push_back(requestedMinorVersion); profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
}
contextAttributes.push_back(None); // Create a context of the requested version, if any.
return createContextAttribs(config, contextAttributes); gl::Version requestedVersion(
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE),
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
if (static_cast<EGLint>(requestedVersion.major) != EGL_DONT_CARE &&
static_cast<EGLint>(requestedVersion.minor) != EGL_DONT_CARE)
{
if (!(profileMask & GLX_CONTEXT_ES2_PROFILE_BIT_EXT) &&
requestedVersion >= gl::Version(3, 2))
{
profileMask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
}
return createContextAttribs(config, requestedVersion, profileMask, context);
} }
// It is commonly assumed that glXCreateContextAttrib will create a context // It is commonly assumed that glXCreateContextAttrib will create a context
// of the highest version possible but it is not specified in the spec and // of the highest version possible but it is not specified in the spec and
// is not true on the Mesa drivers. Instead we try to create a context per // is not true on the Mesa drivers. Instead we try to create a context per
// desktop GL version until we succeed, starting from newer version. // GL version until we succeed, starting from newer version. When the default
// platform is selected, if no desktop context can be created, we fallback to
// an ES context.
// clang-format off // clang-format off
const gl::Version desktopVersions[] = { const gl::Version desktopVersionsFrom3_2[] = {
gl::Version(4, 5), gl::Version(4, 5),
gl::Version(4, 4), gl::Version(4, 4),
gl::Version(4, 3), gl::Version(4, 3),
...@@ -376,6 +413,8 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config, ...@@ -376,6 +413,8 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
gl::Version(4, 0), gl::Version(4, 0),
gl::Version(3, 3), gl::Version(3, 3),
gl::Version(3, 2), gl::Version(3, 2),
};
const gl::Version desktopVersionsPre3_2[] = {
gl::Version(3, 1), gl::Version(3, 1),
gl::Version(3, 0), gl::Version(3, 0),
gl::Version(2, 0), gl::Version(2, 0),
...@@ -386,36 +425,52 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config, ...@@ -386,36 +425,52 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
gl::Version(1, 1), gl::Version(1, 1),
gl::Version(1, 0), gl::Version(1, 0),
}; };
const gl::Version esVersionsFrom2_0[] = {
gl::Version(3, 2),
gl::Version(3, 1),
gl::Version(3, 0),
gl::Version(2, 0),
};
// clang-format on // clang-format on
bool useProfile = mGLX.hasExtension("GLX_ARB_create_context_profile"); // NOTE: below we return as soon as we're able to create a context so the
for (size_t i = 0; i < ArraySize(desktopVersions); ++i) // "error" variable is EGL_SUCCESS when returned contrary to the common idiom
// of returning "error" when there is an actual error.
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
{ {
const auto &version = desktopVersions[i]; for (auto &version : desktopVersionsFrom3_2)
std::vector<int> contextAttributes;
contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
contextAttributes.push_back(version.major);
contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
contextAttributes.push_back(version.minor);
if (useProfile && version >= gl::Version(3, 2))
{ {
contextAttributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB); egl::Error error =
contextAttributes.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB); createContextAttribs(config, version, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, context);
if (!error.isError())
{
return error;
}
}
for (auto &version : desktopVersionsPre3_2)
{
egl::Error error = createContextAttribs(config, version, 0, context);
if (!error.isError())
{
return error;
}
}
} }
contextAttributes.push_back(None); if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
auto context = createContextAttribs(config, contextAttributes); {
for (auto &version : esVersionsFrom2_0)
if (context) {
egl::Error error =
createContextAttribs(config, version, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, context);
if (!error.isError())
{ {
return context; return error;
}
} }
} }
return nullptr; return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
} }
egl::ConfigSet DisplayGLX::generateConfigs() const egl::ConfigSet DisplayGLX::generateConfigs() const
...@@ -760,15 +815,37 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const ...@@ -760,15 +815,37 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
return result; return result;
} }
glx::Context DisplayGLX::createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
gl::Version version,
int profileMask,
glx::Context *context) const
{ {
std::vector<int> attribs;
attribs.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
attribs.push_back(version.major);
attribs.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
attribs.push_back(version.minor);
if (profileMask != 0 && mHasARBCreateContextProfile)
{
attribs.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
attribs.push_back(profileMask);
}
attribs.push_back(None);
// When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can // When creating a context with glXCreateContextAttribsARB, a variety of X11 errors can
// be generated. To prevent these errors from crashing our process, we simply ignore // be generated. To prevent these errors from crashing our process, we simply ignore
// them and only look if GLXContext was created. // them and only look if GLXContext was created.
auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors); auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
auto context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data()); *context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
XSetErrorHandler(oldErrorHandler); XSetErrorHandler(oldErrorHandler);
return context; if (!*context)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
}
return egl::Error(EGL_SUCCESS);
} }
} }
...@@ -89,13 +89,18 @@ class DisplayGLX : public DisplayGL ...@@ -89,13 +89,18 @@ class DisplayGLX : public DisplayGL
private: private:
const FunctionsGL *getFunctionsGL() const override; const FunctionsGL *getFunctionsGL() const override;
glx::Context initializeContext(glx::FBConfig config, const egl::AttributeMap &eglAttributes); egl::Error initializeContext(glx::FBConfig config,
const egl::AttributeMap &eglAttributes,
glx::Context *context);
void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
void generateCaps(egl::Caps *outCaps) const override; void generateCaps(egl::Caps *outCaps) const override;
int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const; int getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const;
glx::Context createContextAttribs(glx::FBConfig, const std::vector<int> &attribs) const; egl::Error createContextAttribs(glx::FBConfig,
gl::Version version,
int profileMask,
glx::Context *context) const;
FunctionsGL *mFunctionsGL; FunctionsGL *mFunctionsGL;
...@@ -112,6 +117,8 @@ class DisplayGLX : public DisplayGL ...@@ -112,6 +117,8 @@ class DisplayGLX : public DisplayGL
bool mIsMesa; bool mIsMesa;
bool mHasMultisample; bool mHasMultisample;
bool mHasARBCreateContext; bool mHasARBCreateContext;
bool mHasARBCreateContextProfile;
bool mHasEXTCreateContextES2Profile;
enum class SwapControl enum class SwapControl
{ {
......
...@@ -116,6 +116,9 @@ ...@@ -116,6 +116,9 @@
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 #define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 #define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
// GLX_EXT_create_context_es2_profile
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
// GLX_EXT_texture_from_pixmap // GLX_EXT_texture_from_pixmap
#define GLX_TEXTURE_1D_BIT_EXT 0x00000001 #define GLX_TEXTURE_1D_BIT_EXT 0x00000001
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 #define GLX_TEXTURE_2D_BIT_EXT 0x00000002
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment