lwjgl/src/native/linux/opengl/extgl_glx.c

282 lines
12 KiB
C

/*
* Copyright (c) 2002-2008 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <dlfcn.h>
#include "extgl_glx.h"
glXGetFBConfigsPROC lwjgl_glXGetFBConfigs = NULL;
glXChooseFBConfigPROC lwjgl_glXChooseFBConfig = NULL;
glXGetFBConfigAttribPROC lwjgl_glXGetFBConfigAttrib = NULL;
glXGetVisualFromFBConfigPROC lwjgl_glXGetVisualFromFBConfig = NULL;
glXCreateWindowPROC lwjgl_glXCreateWindow = NULL;
glXDestroyWindowPROC lwjgl_glXDestroyWindow = NULL;
glXCreatePixmapPROC lwjgl_glXCreatePixmap = NULL;
glXDestroyPixmapPROC lwjgl_glXDestroyPixmap = NULL;
glXCreatePbufferPROC lwjgl_glXCreatePbuffer = NULL;
glXDestroyPbufferPROC lwjgl_glXDestroyPbuffer = NULL;
glXQueryDrawablePROC lwjgl_glXQueryDrawable = NULL;
glXCreateNewContextPROC lwjgl_glXCreateNewContext = NULL;
glXMakeContextCurrentPROC lwjgl_glXMakeContextCurrent = NULL;
glXGetCurrentReadDrawablePROC lwjgl_glXGetCurrentReadDrawable = NULL;
glXGetCurrentDisplayPROC lwjgl_glXGetCurrentDisplay = NULL;
glXQueryContextPROC lwjgl_glXQueryContext = NULL;
glXSelectEventPROC lwjgl_glXSelectEvent = NULL;
glXGetSelectedEventPROC lwjgl_glXGetSelectedEvent = NULL;
glXChooseVisualPROC lwjgl_glXChooseVisual = NULL;
glXCopyContextPROC lwjgl_glXCopyContext = NULL;
glXCreateContextPROC lwjgl_glXCreateContext = NULL;
glXCreateGLXPixmapPROC lwjgl_glXCreateGLXPixmap = NULL;
glXDestroyContextPROC lwjgl_glXDestroyContext = NULL;
glXDestroyGLXPixmapPROC lwjgl_glXDestroyGLXPixmap = NULL;
glXGetConfigPROC lwjgl_glXGetConfig = NULL;
glXGetCurrentContextPROC lwjgl_glXGetCurrentContext = NULL;
glXGetCurrentDrawablePROC lwjgl_glXGetCurrentDrawable = NULL;
glXIsDirectPROC lwjgl_glXIsDirect = NULL;
glXMakeCurrentPROC lwjgl_glXMakeCurrent = NULL;
glXQueryExtensionPROC lwjgl_glXQueryExtension = NULL;
glXQueryVersionPROC lwjgl_glXQueryVersion = NULL;
glXSwapBuffersPROC lwjgl_glXSwapBuffers = NULL;
glXUseXFontPROC lwjgl_glXUseXFont = NULL;
glXWaitGLPROC lwjgl_glXWaitGL = NULL;
glXWaitXPROC lwjgl_glXWaitX = NULL;
glXGetClientStringPROC lwjgl_glXGetClientString = NULL;
glXQueryServerStringPROC lwjgl_glXQueryServerString = NULL;
glXQueryExtensionsStringPROC lwjgl_glXQueryExtensionsString = NULL;
/* GLX_SGI_swap_control */
glXSwapIntervalSGIPROC lwjgl_glXSwapIntervalSGI = NULL;
/* GLX_EXT_swap_control */
glXSwapIntervalEXTPROC lwjgl_glXSwapIntervalEXT = NULL;
/* GLX_ARB_create_context */
glXCreateContextAttribsARBPROC lwjgl_glXCreateContextAttribsARB = NULL;
/* GLX_NV_present_video */
glXEnumerateVideoDevicesNVPROC lwjgl_glXEnumerateVideoDevicesNV = NULL;
glXBindVideoDeviceNVPROC lwjgl_glXBindVideoDeviceNV = NULL;
/* GLX_NV_video_capture */
glXBindVideoCaptureDeviceNVPROC lwjgl_glXBindVideoCaptureDeviceNV = NULL;
glXEnumerateVideoCaptureDevicesNVPROC lwjgl_glXEnumerateVideoCaptureDevicesNV = NULL;
glXLockVideoCaptureDeviceNVPROC lwjgl_glXLockVideoCaptureDeviceNV = NULL;
glXQueryVideoCaptureDeviceNVPROC lwjgl_glXQueryVideoCaptureDeviceNV = NULL;
glXReleaseVideoCaptureDeviceNVPROC lwjgl_glXReleaseVideoCaptureDeviceNV = NULL;
static void * lib_gl_handle = NULL;
typedef void * (APIENTRY * glXGetProcAddressARBPROC) (const GLubyte *procName);
static glXGetProcAddressARBPROC lwjgl_glXGetProcAddressARB;
static GLXExtensions symbols_flags;
/** returns true if the extention is available */
static inline bool GLXQueryExtension(const GLubyte *exts, const char *name) {
return extgl_QueryExtension(exts, name);
}
static void extgl_InitGLX13() {
ExtFunction functions[] = {
{"glXGetFBConfigs", (void*)&lwjgl_glXGetFBConfigs},
{"glXChooseFBConfig", (void*)&lwjgl_glXChooseFBConfig},
{"glXGetFBConfigAttrib", (void*)&lwjgl_glXGetFBConfigAttrib},
{"glXGetVisualFromFBConfig", (void*)&lwjgl_glXGetVisualFromFBConfig},
{"glXCreateWindow", (void*)&lwjgl_glXCreateWindow},
{"glXDestroyWindow", (void*)&lwjgl_glXDestroyWindow},
{"glXCreatePixmap", (void*)&lwjgl_glXCreatePixmap},
{"glXDestroyPixmap", (void*)&lwjgl_glXDestroyPixmap},
{"glXCreatePbuffer", (void*)&lwjgl_glXCreatePbuffer},
{"glXDestroyPbuffer", (void*)&lwjgl_glXDestroyPbuffer},
{"glXQueryDrawable", (void*)&lwjgl_glXQueryDrawable},
{"glXCreateNewContext", (void*)&lwjgl_glXCreateNewContext},
{"glXMakeContextCurrent", (void*)&lwjgl_glXMakeContextCurrent},
{"glXGetCurrentReadDrawable", (void*)&lwjgl_glXGetCurrentReadDrawable},
{"glXGetCurrentDisplay", (void*)&lwjgl_glXGetCurrentDisplay},
{"glXQueryContext", (void*)&lwjgl_glXQueryContext},
{"glXSelectEvent", (void*)&lwjgl_glXSelectEvent},
{"glXGetSelectedEvent", (void*)&lwjgl_glXGetSelectedEvent}};
symbols_flags.GLX13 = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLX12(void) {
ExtFunction functions[] = {
{"glXChooseVisual", (void*)&lwjgl_glXChooseVisual},
{"glXCopyContext", (void*)&lwjgl_glXCopyContext},
{"glXCreateContext", (void*)&lwjgl_glXCreateContext},
{"glXCreateGLXPixmap", (void*)&lwjgl_glXCreateGLXPixmap},
{"glXDestroyContext", (void*)&lwjgl_glXDestroyContext},
{"glXDestroyGLXPixmap", (void*)&lwjgl_glXDestroyGLXPixmap},
{"glXGetConfig", (void*)&lwjgl_glXGetConfig},
{"glXGetCurrentContext", (void*)&lwjgl_glXGetCurrentContext},
{"glXGetCurrentDrawable", (void*)&lwjgl_glXGetCurrentDrawable},
{"glXIsDirect", (void*)&lwjgl_glXIsDirect},
{"glXMakeCurrent", (void*)&lwjgl_glXMakeCurrent},
{"glXQueryExtension", (void*)&lwjgl_glXQueryExtension},
{"glXQueryVersion", (void*)&lwjgl_glXQueryVersion},
{"glXSwapBuffers", (void*)&lwjgl_glXSwapBuffers},
{"glXUseXFont", (void*)&lwjgl_glXUseXFont},
{"glXWaitGL", (void*)&lwjgl_glXWaitGL},
{"glXWaitX", (void*)&lwjgl_glXWaitX},
{"glXGetClientString", (void*)&lwjgl_glXGetClientString},
{"glXQueryServerString", (void*)&lwjgl_glXQueryServerString},
{"glXQueryExtensionsString", (void*)&lwjgl_glXQueryExtensionsString}};
symbols_flags.GLX12 = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXSGISwapControl() {
ExtFunction functions[] = {
{"glXSwapIntervalSGI", (void*)&lwjgl_glXSwapIntervalSGI}};
symbols_flags.GLX_SGI_swap_control = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXEXTSwapControl() {
ExtFunction functions[] = {
{"glXSwapIntervalEXT", (void*)&lwjgl_glXSwapIntervalEXT}};
symbols_flags.GLX_EXT_swap_control = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXARBCreateContext() {
ExtFunction functions[] = {
{"glXCreateContextAttribsARB", (void*)&lwjgl_glXCreateContextAttribsARB}};
symbols_flags.GLX_ARB_create_context = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXNVPresentVideo() {
ExtFunction functions[] = {
{ "glXEnumerateVideoDevicesNV", (void*)&lwjgl_glXEnumerateVideoDevicesNV },
{ "glXBindVideoDeviceNV", (void*)&lwjgl_glXBindVideoDeviceNV }
};
symbols_flags.GLX_NV_present_video = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXNVVideoCapture() {
ExtFunction functions[] = {
{ "glXBindVideoCaptureDeviceNV", (void*)&lwjgl_glXBindVideoCaptureDeviceNV },
{ "glXEnumerateVideoCaptureDevicesNV", (void*)&lwjgl_glXEnumerateVideoCaptureDevicesNV },
{ "glXLockVideoCaptureDeviceNV", (void*)&lwjgl_glXLockVideoCaptureDeviceNV },
{ "glXQueryVideoCaptureDeviceNV", (void*)&lwjgl_glXQueryVideoCaptureDeviceNV },
{ "glXReleaseVideoCaptureDeviceNV", (void*)&lwjgl_glXReleaseVideoCaptureDeviceNV }
};
symbols_flags.GLX_NV_video_capture = extgl_InitializeFunctions(sizeof(functions)/sizeof(ExtFunction), functions);
}
static void extgl_InitGLXSupportedExtensions(Display *disp, int screen, GLXExtensions *extension_flags) {
const GLubyte *exts = (const GLubyte *)lwjgl_glXQueryExtensionsString(disp, screen);
/* extension_flags.GLX_EXT_visual_info = GLXQueryExtension(exts, "GLX_EXT_visual_info");
extension_flags.GLX_EXT_visual_rating = GLXQueryExtension(exts, "GLX_EXT_visual_rating");*/
extension_flags->GLX_SGI_swap_control = symbols_flags.GLX_SGI_swap_control && GLXQueryExtension(exts, "GLX_SGI_swap_control");
extension_flags->GLX_EXT_swap_control = symbols_flags.GLX_EXT_swap_control && GLXQueryExtension(exts, "GLX_EXT_swap_control");
extension_flags->GLX_ARB_multisample = GLXQueryExtension(exts, "GLX_ARB_multisample");
extension_flags->GLX_ARB_fbconfig_float = GLXQueryExtension(exts, "GLX_ARB_fbconfig_float");
extension_flags->GLX_EXT_fbconfig_packed_float = GLXQueryExtension(exts, "GLX_EXT_fbconfig_packed_float");
extension_flags->GLX_ARB_framebuffer_sRGB = GLXQueryExtension(exts, "GLX_ARB_framebuffer_sRGB") || GLXQueryExtension(exts, "GLX_EXT_framebuffer_sRGB");
extension_flags->GLX_ARB_create_context = GLXQueryExtension(exts, "GLX_ARB_create_context");
extension_flags->GLX_NV_multisample_coverage = GLXQueryExtension(exts, "GLX_NV_multisample_coverage");
extension_flags->GLX_NV_present_video = GLXQueryExtension(exts, "GLX_NV_present_video");
extension_flags->GLX_NV_video_capture = GLXQueryExtension(exts, "GLX_NV_video_capture");
}
bool extgl_Open(JNIEnv *env) {
if (lib_gl_handle != NULL)
return true;
/*
* Actually we don't need the RTLD_GLOBAL flag, since the symbols
* we load should be private to us. However, according to the
* documentation at
*
* http://dri.sourceforge.net/doc/DRIuserguide.html
*
* DRI drivers need this flag to work properly
*/
#ifdef __OpenBSD__
lib_gl_handle = dlopen("libGL.so", RTLD_LAZY | RTLD_GLOBAL);
#else
lib_gl_handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);
#endif
if (lib_gl_handle == NULL) {
throwFormattedException(env, "Error loading libGL.so.1: %s", dlerror());
return false;
}
lwjgl_glXGetProcAddressARB = (glXGetProcAddressARBPROC)dlsym(lib_gl_handle, "glXGetProcAddressARB");
if (lwjgl_glXGetProcAddressARB == NULL) {
extgl_Close();
throwException(env, "Could not get address of glXGetProcAddressARB");
return false;
}
/* Unlike Windows, GLX function addresses are context-independent
* so we only have to initialize the addresses once at load
*/
extgl_InitGLX12();
extgl_InitGLX13();
extgl_InitGLXSGISwapControl();
extgl_InitGLXEXTSwapControl();
extgl_InitGLXARBCreateContext();
extgl_InitGLXNVPresentVideo();
extgl_InitGLXNVVideoCapture();
return true;
}
void *extgl_GetProcAddress(const char *name) {
void *t = (void*)lwjgl_glXGetProcAddressARB((const GLubyte*)name);
if (t == NULL) {
t = dlsym(lib_gl_handle, name);
}
return t;
}
void extgl_Close(void) {
dlclose(lib_gl_handle);
lib_gl_handle = NULL;
}
bool extgl_InitGLX(Display *disp, int screen, GLXExtensions *extension_flags) {
int major, minor;
/* Assume glx ver >= 1.2 */
// Check GLX 1.2 symbols available
if (!symbols_flags.GLX12)
return false;
if (lwjgl_glXQueryVersion(disp, &major, &minor) != True)
return false;
bool glx12 = major > 1 || (major == 1 && minor >= 2);
// Check GLX 1.2 version
if (!glx12)
return false;
extension_flags->GLX12 = glx12;
extension_flags->GLX13 = major > 1 || (major == 1 && minor >= 3);
extension_flags->GLX14 = major > 1 || (major == 1 && minor >= 4);
extgl_InitGLXSupportedExtensions(disp, screen, extension_flags);
return true;
}