Commit f229cb9b by Corentin Wallez

Add a FunctionsGLX class to dynamically load the GLX entry points

BUG=angleproject:892 Change-Id: I516b7d859100cb065871de8e328585a9ca817499 Reviewed-on: https://chromium-review.googlesource.com/270123Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 6fce6df7
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FunctionsGLX.cpp: Implements the FunctionsGLX class.
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
#include <dlfcn.h>
#include <algorithm>
#include "libANGLE/Error.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace rx
{
template<typename T>
static bool GetProc(PFNGLXGETPROCADDRESSPROC getProc, T *member, const char *name)
{
*member = reinterpret_cast<T>(getProc(reinterpret_cast<const GLubyte*>(name)));
return *member != nullptr;
}
FunctionsGLX::FunctionsGLX()
: majorVersion(0),
minorVersion(0),
getProc(nullptr),
destroyContext(nullptr),
makeCurrent(nullptr),
swapBuffers(nullptr),
queryExtension(nullptr),
queryVersion(nullptr),
queryExtensionsString(nullptr),
getFBConfigs(nullptr),
chooseFBConfig(nullptr),
getFBConfigAttrib(nullptr),
getVisualFromFBConfig(nullptr),
createWindow(nullptr),
destroyWindow(nullptr),
createPbuffer(nullptr),
destroyPbuffer(nullptr),
createContextAttribsARB(nullptr),
mLibHandle(nullptr)
{
}
FunctionsGLX::~FunctionsGLX()
{
terminate();
}
egl::Error FunctionsGLX::initialize(Display *xDisplay)
{
terminate();
mLibHandle = dlopen("libGL.so.1", RTLD_NOW);
if (!mLibHandle)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not dlopen libGL.so.1: %s", dlerror());
}
getProc = reinterpret_cast<PFNGLXGETPROCADDRESSPROC>(dlsym(mLibHandle, "glXGetProcAddress"));
if (!getProc)
{
getProc = reinterpret_cast<PFNGLXGETPROCADDRESSPROC>(dlsym(mLibHandle, "glXGetProcAddressARB"));
}
if (!getProc)
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not retrieve glXGetProcAddress");
}
#define GET_PROC_OR_ERROR(MEMBER, NAME) \
if (!GetProc(getProc, MEMBER, NAME)) \
{ \
return egl::Error(EGL_NOT_INITIALIZED, "Could not load GLX entry point " NAME); \
}
// GLX 1.0
GET_PROC_OR_ERROR(&destroyContext, "glXDestroyContext");
GET_PROC_OR_ERROR(&makeCurrent, "glXMakeCurrent");
GET_PROC_OR_ERROR(&swapBuffers, "glXSwapBuffers");
GET_PROC_OR_ERROR(&queryExtension, "glXQueryExtension");
GET_PROC_OR_ERROR(&queryVersion, "glXQueryVersion");
// GLX 1.1
GET_PROC_OR_ERROR(&queryExtensionsString, "glXQueryExtensionsString");
// Check we have a working GLX
{
int errorBase;
int eventBase;
if (!queryExtension(xDisplay, &errorBase, &eventBase))
{
return egl::Error(EGL_NOT_INITIALIZED, "GLX is not present.");
}
}
// Check we have a supported version of GLX
if (!queryVersion(xDisplay, &majorVersion, &minorVersion))
{
return egl::Error(EGL_NOT_INITIALIZED, "Could not query the GLX version.");
}
if (majorVersion != 1 || minorVersion < 3)
{
return egl::Error(EGL_NOT_INITIALIZED, "Unsupported GLX version (requires at least 1.3).");
}
const char *extensions = queryExtensionsString(xDisplay, DefaultScreen(xDisplay));
if (!extensions)
{
return egl::Error(EGL_NOT_INITIALIZED, "glXQueryExtensionsString returned NULL");
}
mExtensions = TokenizeExtensionsString(extensions);
// GLX 1.3
GET_PROC_OR_ERROR(&getFBConfigs, "glXGetFBConfigs");
GET_PROC_OR_ERROR(&chooseFBConfig, "glXChooseFBConfig");
GET_PROC_OR_ERROR(&getFBConfigAttrib, "glXGetFBConfigAttrib");
GET_PROC_OR_ERROR(&getVisualFromFBConfig, "glXGetVisualFromFBConfig");
GET_PROC_OR_ERROR(&createWindow, "glXCreateWindow");
GET_PROC_OR_ERROR(&destroyWindow, "glXDestroyWindow");
GET_PROC_OR_ERROR(&createPbuffer, "glXCreatePbuffer");
GET_PROC_OR_ERROR(&destroyPbuffer, "glXDestroyPbuffer");
// Extensions
if (hasExtension("GLX_ARB_create_context"))
{
GET_PROC_OR_ERROR(&createContextAttribsARB, "glXCreateContextAttribsARB");
}
else
{
createContextAttribsARB = nullptr;
}
#undef GET_PROC_OR_ERROR
return egl::Error(EGL_SUCCESS);
}
void FunctionsGLX::terminate()
{
if (mLibHandle)
{
dlclose(mLibHandle);
mLibHandle = nullptr;
}
}
bool FunctionsGLX::hasExtension(const char *extension) const
{
return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
}
}
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// FunctionsGLX.h: Defines the FunctionsGLX class to load functions and data from GLX
#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
#include <string>
#include <vector>
#include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"
namespace rx
{
class FunctionsGLX : angle::NonCopyable
{
public:
FunctionsGLX();
~FunctionsGLX();
// Load data from GLX, can be called multiple times
egl::Error initialize(Display *xDisplay);
void terminate();
bool hasExtension(const char *extension) const;
int majorVersion;
int minorVersion;
PFNGLXGETPROCADDRESSPROC getProc;
// GLX 1.0
PFNGLXDESTROYCONTEXTPROC destroyContext;
PFNGLXMAKECURRENTPROC makeCurrent;
PFNGLXSWAPBUFFERSPROC swapBuffers;
PFNGLXQUERYEXTENSIONPROC queryExtension;
PFNGLXQUERYVERSIONPROC queryVersion;
// GLX 1.1
PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsString;
//GLX 1.3
PFNGLXGETFBCONFIGSPROC getFBConfigs;
PFNGLXCHOOSEFBCONFIGPROC chooseFBConfig;
PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttrib;
PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfig;
PFNGLXCREATEWINDOWPROC createWindow;
PFNGLXDESTROYWINDOWPROC destroyWindow;
PFNGLXCREATEPBUFFERPROC createPbuffer;
PFNGLXDESTROYPBUFFERPROC destroyPbuffer;
// GLX_ARB_create_context
PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARB;
private:
void *mLibHandle;
std::vector<std::string> mExtensions;
};
}
#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLX_H_
......@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_GL_GLX_WINDOWSURFACEGLX_H_
#include "libANGLE/renderer/gl/SurfaceGL.h"
#include "libANGLE/renderer/gl/glx/platform_glx.h"
namespace rx
{
......
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// functionsglx_typedefs.h: Typedefs of GLX functions.
#ifndef LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
#define LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
#include "libANGLE/renderer/gl/glx/platform_glx.h"
namespace rx
{
// Only the functions of GLX 1.2 and earlier need to be typdefed; the other
// functions are already typedefed in glx.h
// GLX 1.0
typedef XVisualInfo *(*PFNGLXCHOOSEVISUALPROC) (Display *dpy, int screen, int *attribList);
typedef GLXContext (*PFNGLXCREATECONTEXTPROC) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
typedef void (*PFNGLXDESTROYCONTEXTPROC) (Display *dpy, GLXContext ctx);
typedef Bool (*PFNGLXMAKECURRENTPROC) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
typedef void (*PFNGLXCOPYCONTEXTPROC) (Display *dpy, GLXContext src, GLXContext dst, unsigned long mask);
typedef void (*PFNGLXSWAPBUFFERSPROC) (Display *dpy, GLXDrawable drawable);
typedef GLXPixmap (*PFNGLXCREATEGLXPIXMAPPROC) (Display *dpy, XVisualInfo *visual, Pixmap pixmap);
typedef void (*PFNGLXDESTROYGLXPIXMAPPROC) (Display *dpy, GLXPixmap pixmap);
typedef Bool (*PFNGLXQUERYEXTENSIONPROC) (Display *dpy, int *errorb, int *event);
typedef Bool (*PFNGLXQUERYVERSIONPROC) (Display *dpy, int *maj, int *min);
typedef Bool (*PFNGLXISDIRECTPROC) (Display *dpy, GLXContext ctx);
typedef int (*PFNGLXGETCONFIGPROC) (Display *dpy, XVisualInfo *visual, int attrib, int *value);
typedef GLXContext (*PFNGLXGETCURRENTCONTEXTPROC) ();
typedef GLXDrawable (*PFNGLXGETCURRENTDRAWABLEPROC) ();
typedef void (*PFNGLXWAITGLPROC) ();
typedef void (*PFNGLXWAITXPROC) ();
typedef void (*PFNGLXUSEXFONT) (Font font, int first, int count, int list);
// GLX 1.1
typedef const char *(*PFNGLXQUERYEXTENSIONSSTRINGPROC) (Display *dpy, int screen);
typedef const char *(*PFNGLXQUERYSERVERSTRINGPROC) (Display *dpy, int screen, int name);
typedef const char *(*PFNGLXGETCLIENTSTRINGPROC) (Display *dpy, int name);
// GLX 1.2
typedef Display *(*PFNGLXGETCURRENTDISPLAYPROC) ();
}
#endif // LIBANGLE_RENDERER_GL_GLX_FUNCTIONSGLXTYPEDEFS_H_
//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// platform_glx.h: Includes specific to GLX.
#ifndef LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
#define LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
// HACK(cwallez) this is a horrible hack to prevent glx from including GL/glext.h
// as it causes a bunch of conflicts (macro redefinition, etc) with GLES2/gl2ext.h
#define __glext_h_ 1
#include <GL/glx.h>
#undef __glext_h_
#endif // LIBANGLE_RENDERER_GL_GLX_PLATFORMGLX_H_
......@@ -437,8 +437,12 @@
[
'libANGLE/renderer/gl/glx/DisplayGLX.cpp',
'libANGLE/renderer/gl/glx/DisplayGLX.h',
'libANGLE/renderer/gl/glx/FunctionsGLX.cpp',
'libANGLE/renderer/gl/glx/FunctionsGLX.h',
'libANGLE/renderer/gl/glx/WindowSurfaceGLX.cpp',
'libANGLE/renderer/gl/glx/WindowSurfaceGLX.h',
'libANGLE/renderer/gl/glx/functionsglx_typedefs.h',
'libANGLE/renderer/gl/glx/platform_glx.h',
],
'libglesv2_sources':
[
......
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