Commit 50ff85e5 by Corentin Wallez

DisplayGLX: add support for complete lack of extensions

We thought we could rely on GLX_create_context_attrib being present but this is not the case with VM drivers. Instead we fallback to creating contexts with glXCreateContext that doesn't offer control on which version and profile the context will have. Likewise we may not always be able to use the multisample but we can safely assume that the number of samples and sample buffers are zero in this case. BUG=angleproject:1206 Change-Id: I888c69e609764994baf86386c9683b3edeb320f7 Reviewed-on: https://chromium-review.googlesource.com/312230Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent a37c6137
......@@ -62,6 +62,8 @@ DisplayGLX::DisplayGLX()
mDummyPbuffer(0),
mUsesNewXDisplay(false),
mIsMesa(false),
mHasMultisample(false),
mHasARBCreateContext(false),
mSwapControl(SwapControl::Absent),
mMinSwapInterval(0),
mMaxSwapInterval(0),
......@@ -98,20 +100,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
}
// Check we have the needed extensions
{
if (mGLX.minorVersion == 3 && !mGLX.hasExtension("GLX_ARB_multisample"))
{
return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_multisample.");
}
// Require ARB_create_context which has been supported since Mesa 9 unconditionnaly
// and is present in Mesa 8 in an almost always on compile flag. Also assume proprietary
// drivers have it.
if (!mGLX.hasExtension("GLX_ARB_create_context"))
{
return egl::Error(EGL_NOT_INITIALIZED, "GLX doesn't support ARB_create_context.");
}
}
mHasMultisample = mGLX.minorVersion > 3 || mGLX.hasExtension("GLX_ARB_multisample");
mHasARBCreateContext = mGLX.hasExtension("GLX_ARB_create_context");
// Choose the swap_control extension to use, if any.
// The EXT version is better as it allows glXSwapInterval to be called per
......@@ -188,7 +178,27 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
XFree(candidates);
}
mContext = initializeContext(mContextConfig, display->getAttributeMap());
if (mHasARBCreateContext)
{
mContext = initializeContext(mContextConfig, display->getAttributeMap());
}
else
{
XVisualInfo visualTemplate;
visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
int numVisuals = 0;
XVisualInfo *visuals = XGetVisualInfo(xDisplay, VisualIDMask, &visualTemplate, &numVisuals);
if (numVisuals <= 0)
{
return egl::Error(EGL_NOT_INITIALIZED,
"Could not get the visual info from the fb config");
}
ASSERT(numVisuals == 1);
mContext = mGLX.createContext(&visuals[0], nullptr, true);
XFree(visuals);
}
if (!mContext)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not create GL context.");
......@@ -383,8 +393,6 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
egl::ConfigSet configs;
configIdToGLXConfig.clear();
bool hasSwapControl = mGLX.hasExtension("GLX_EXT_swap_control");
const gl::Version &maxVersion = getMaxSupportedESVersion();
ASSERT(maxVersion >= gl::Version(2, 0));
bool supportsES3 = maxVersion >= gl::Version(3, 0);
......@@ -397,8 +405,9 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
int contextDepthSize = getGLXFBConfigAttrib(mContextConfig, GLX_DEPTH_SIZE);
int contextStencilSize = getGLXFBConfigAttrib(mContextConfig, GLX_STENCIL_SIZE);
int contextSamples = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES);
int contextSampleBuffers = getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS);
int contextSamples = mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLES) : 0;
int contextSampleBuffers =
mHasMultisample ? getGLXFBConfigAttrib(mContextConfig, GLX_SAMPLE_BUFFERS) : 0;
int contextAccumRedSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_RED_SIZE);
int contextAccumGreenSize = getGLXFBConfigAttrib(mContextConfig, GLX_ACCUM_GREEN_SIZE);
......@@ -459,8 +468,9 @@ egl::ConfigSet DisplayGLX::generateConfigs() const
config.bufferSize = config.redSize + config.greenSize + config.blueSize + config.alphaSize;
// Multisample and accumulation buffers
int samples = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES);
int sampleBuffers = getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS);
int samples = mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLES) : 0;
int sampleBuffers =
mHasMultisample ? getGLXFBConfigAttrib(glxConfig, GLX_SAMPLE_BUFFERS) : 0;
int accumRedSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_RED_SIZE);
int accumGreenSize = getGLXFBConfigAttrib(glxConfig, GLX_ACCUM_GREEN_SIZE);
......
......@@ -102,6 +102,8 @@ class DisplayGLX : public DisplayGL
bool mUsesNewXDisplay;
bool mIsMesa;
bool mHasMultisample;
bool mHasARBCreateContext;
enum class SwapControl
{
......
......@@ -35,33 +35,35 @@ static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
struct FunctionsGLX::GLXFunctionTable
{
GLXFunctionTable()
: destroyContextPtr(nullptr),
makeCurrentPtr(nullptr),
swapBuffersPtr(nullptr),
queryExtensionPtr(nullptr),
queryVersionPtr(nullptr),
getCurrentContextPtr(nullptr),
getCurrentDrawablePtr(nullptr),
waitXPtr(nullptr),
waitGLPtr(nullptr),
queryExtensionsStringPtr(nullptr),
getFBConfigsPtr(nullptr),
chooseFBConfigPtr(nullptr),
getFBConfigAttribPtr(nullptr),
getVisualFromFBConfigPtr(nullptr),
createWindowPtr(nullptr),
destroyWindowPtr(nullptr),
createPbufferPtr(nullptr),
destroyPbufferPtr(nullptr),
queryDrawablePtr(nullptr),
createContextAttribsARBPtr(nullptr),
swapIntervalEXTPtr(nullptr),
swapIntervalMESAPtr(nullptr),
swapIntervalSGIPtr(nullptr)
: createContextPtr(nullptr),
destroyContextPtr(nullptr),
makeCurrentPtr(nullptr),
swapBuffersPtr(nullptr),
queryExtensionPtr(nullptr),
queryVersionPtr(nullptr),
getCurrentContextPtr(nullptr),
getCurrentDrawablePtr(nullptr),
waitXPtr(nullptr),
waitGLPtr(nullptr),
queryExtensionsStringPtr(nullptr),
getFBConfigsPtr(nullptr),
chooseFBConfigPtr(nullptr),
getFBConfigAttribPtr(nullptr),
getVisualFromFBConfigPtr(nullptr),
createWindowPtr(nullptr),
destroyWindowPtr(nullptr),
createPbufferPtr(nullptr),
destroyPbufferPtr(nullptr),
queryDrawablePtr(nullptr),
createContextAttribsARBPtr(nullptr),
swapIntervalEXTPtr(nullptr),
swapIntervalMESAPtr(nullptr),
swapIntervalSGIPtr(nullptr)
{
}
// GLX 1.0
PFNGLXCREATECONTEXTPROC createContextPtr;
PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
PFNGLXMAKECURRENTPROC makeCurrentPtr;
PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
......@@ -161,6 +163,7 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
#endif
// GLX 1.0
GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
......@@ -263,6 +266,12 @@ int FunctionsGLX::getScreen() const
// GLX functions
// GLX 1.0
glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
{
GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
GLXContext context = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
return reinterpret_cast<glx::Context>(context);
}
void FunctionsGLX::destroyContext(glx::Context context) const
{
GLXContext ctx = reinterpret_cast<GLXContext>(context);
......
......@@ -37,6 +37,7 @@ class FunctionsGLX
PFNGETPROCPROC getProc;
// GLX 1.0
glx::Context createContext(XVisualInfo *visual, glx::Context share, bool direct) const;
void destroyContext(glx::Context context) const;
Bool makeCurrent(glx::Drawable drawable, glx::Context context) const;
void swapBuffers(glx::Drawable drawable) const;
......
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