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)
case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
#if defined(ANGLE_PLATFORM_WINDOWS)
impl = new rx::DisplayWGL();
#elif defined(ANGLE_USE_X11)
impl = new rx::DisplayGLX();
#else
// No GLES support on this platform, fail display creation.
impl = nullptr;
......
......@@ -65,6 +65,8 @@ DisplayGLX::DisplayGLX()
mIsMesa(false),
mHasMultisample(false),
mHasARBCreateContext(false),
mHasARBCreateContextProfile(false),
mHasEXTCreateContextES2Profile(false),
mSwapControl(SwapControl::Absent),
mMinSwapInterval(0),
mMaxSwapInterval(0),
......@@ -104,6 +106,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
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.
// The EXT version is better as it allows glXSwapInterval to be called per
......@@ -208,12 +212,26 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
XFree(candidates);
}
const auto &eglAttributes = display->getAttributeMap();
if (mHasARBCreateContext)
{
mContext = initializeContext(mContextConfig, display->getAttributeMap());
egl::Error error = initializeContext(mContextConfig, eglAttributes, &mContext);
if (error.isError())
{
return error;
}
}
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;
visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
......@@ -228,11 +246,13 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
mContext = mGLX.createContext(&visuals[0], nullptr, true);
XFree(visuals);
if (!mContext)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
}
}
if (!mContext)
{
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
// query the version of the context so we need to make the context current.
......@@ -341,33 +361,50 @@ egl::Error DisplayGLX::getDevice(DeviceImpl **device)
return egl::Error(EGL_BAD_DISPLAY);
}
glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
const egl::AttributeMap &eglAttributes)
egl::Error DisplayGLX::initializeContext(glx::FBConfig config,
const egl::AttributeMap &eglAttributes,
glx::Context *context)
{
// Create a context of the requested version, if any.
EGLint requestedMajorVersion =
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
EGLint requestedMinorVersion =
eglAttributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
if (requestedMajorVersion != EGL_DONT_CARE && requestedMinorVersion != EGL_DONT_CARE)
int profileMask = 0;
EGLint requestedDisplayType =
eglAttributes.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
if (requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
{
std::vector<int> contextAttributes;
contextAttributes.push_back(GLX_CONTEXT_MAJOR_VERSION_ARB);
contextAttributes.push_back(requestedMajorVersion);
if (!mHasEXTCreateContextES2Profile)
{
return egl::Error(EGL_NOT_INITIALIZED,
"Cannot create an OpenGL ES platform on GLX without the "
"GLX_EXT_create_context_es_profile extension.");
}
contextAttributes.push_back(GLX_CONTEXT_MINOR_VERSION_ARB);
contextAttributes.push_back(requestedMinorVersion);
ASSERT(mHasARBCreateContextProfile);
profileMask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
}
contextAttributes.push_back(None);
return createContextAttribs(config, contextAttributes);
// Create a context of the requested version, if any.
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
// 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
// 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
const gl::Version desktopVersions[] = {
const gl::Version desktopVersionsFrom3_2[] = {
gl::Version(4, 5),
gl::Version(4, 4),
gl::Version(4, 3),
......@@ -376,6 +413,8 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
gl::Version(4, 0),
gl::Version(3, 3),
gl::Version(3, 2),
};
const gl::Version desktopVersionsPre3_2[] = {
gl::Version(3, 1),
gl::Version(3, 0),
gl::Version(2, 0),
......@@ -386,36 +425,52 @@ glx::Context DisplayGLX::initializeContext(glx::FBConfig config,
gl::Version(1, 1),
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
bool useProfile = mGLX.hasExtension("GLX_ARB_create_context_profile");
for (size_t i = 0; i < ArraySize(desktopVersions); ++i)
// NOTE: below we return as soon as we're able to create a context so the
// "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];
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))
for (auto &version : desktopVersionsFrom3_2)
{
egl::Error error =
createContextAttribs(config, version, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, context);
if (!error.isError())
{
return error;
}
}
for (auto &version : desktopVersionsPre3_2)
{
contextAttributes.push_back(GLX_CONTEXT_PROFILE_MASK_ARB);
contextAttributes.push_back(GLX_CONTEXT_CORE_PROFILE_BIT_ARB);
egl::Error error = createContextAttribs(config, version, 0, context);
if (!error.isError())
{
return error;
}
}
}
contextAttributes.push_back(None);
auto context = createContextAttribs(config, contextAttributes);
if (context)
if (requestedDisplayType != EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
{
for (auto &version : esVersionsFrom2_0)
{
return context;
egl::Error error =
createContextAttribs(config, version, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, context);
if (!error.isError())
{
return error;
}
}
}
return nullptr;
return egl::Error(EGL_NOT_INITIALIZED, "Could not create a backing OpenGL context.");
}
egl::ConfigSet DisplayGLX::generateConfigs() const
......@@ -760,15 +815,37 @@ int DisplayGLX::getGLXFBConfigAttrib(glx::FBConfig config, int attrib) const
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
// be generated. To prevent these errors from crashing our process, we simply ignore
// them and only look if GLXContext was created.
auto oldErrorHandler = XSetErrorHandler(IgnoreX11Errors);
auto context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
*context = mGLX.createContextAttribsARB(mContextConfig, nullptr, True, attribs.data());
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
private:
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 generateCaps(egl::Caps *outCaps) const override;
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;
......@@ -112,6 +117,8 @@ class DisplayGLX : public DisplayGL
bool mIsMesa;
bool mHasMultisample;
bool mHasARBCreateContext;
bool mHasARBCreateContextProfile;
bool mHasEXTCreateContextES2Profile;
enum class SwapControl
{
......
......@@ -116,6 +116,9 @@
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#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
#define GLX_TEXTURE_1D_BIT_EXT 0x00000001
#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