aboutsummaryrefslogtreecommitdiffstats
path: root/src/test-native
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-02-23 14:51:06 +0100
committerSven Gothel <[email protected]>2014-02-23 14:51:06 +0100
commit3352601e0860584509adf2b76f993d03893ded4b (patch)
tree974fccc8c0eb2f5ad9d4ffd741dfc35869ed67b5 /src/test-native
parentf51933f0ebe9ae030c26c066e59a728ce08b8559 (diff)
parentc67de337a8aaf52e36104c3f13e273aa19d21f1f (diff)
Merge branch 'master' into stash_glyphcache
Conflicts: make/scripts/tests.sh src/jogl/classes/com/jogamp/graph/curve/OutlineShape.java src/jogl/classes/com/jogamp/graph/curve/Region.java src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java src/jogl/classes/com/jogamp/graph/curve/opengl/Renderer.java src/jogl/classes/com/jogamp/graph/curve/opengl/TextRenderer.java src/jogl/classes/com/jogamp/graph/font/Font.java src/jogl/classes/com/jogamp/opengl/math/VectorUtil.java src/jogl/classes/jogamp/graph/curve/text/GlyphShape.java src/jogl/classes/jogamp/graph/curve/text/GlyphString.java src/jogl/classes/jogamp/graph/font/typecast/TypecastFont.java src/jogl/classes/jogamp/graph/font/typecast/TypecastGlyph.java src/jogl/classes/jogamp/graph/font/typecast/TypecastRenderer.java
Diffstat (limited to 'src/test-native')
-rw-r--r--src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c34
-rw-r--r--src/test-native/contextRetargetDrawable01.c154
-rw-r--r--src/test-native/contextRetargetDrawable02.c382
-rw-r--r--src/test-native/displayMultiple02_mch.c130
-rw-r--r--src/test-native/displayMultiple02_new_mch.c199
-rw-r--r--src/test-native/glExtensionsListGL2.c2
-rw-r--r--src/test-native/glExtensionsListGL3.c25
-rwxr-xr-xsrc/test-native/make.sh4
8 files changed, 922 insertions, 8 deletions
diff --git a/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c b/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c
new file mode 100644
index 000000000..9144e965b
--- /dev/null
+++ b/src/test-native/Bug907GetAllWindowNamesViaMessageDispatch.c
@@ -0,0 +1,34 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <wingdi.h>
+#include <stddef.h>
+#include <stdio.h>
+
+BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
+{
+ static int i = 0;
+ char buffer[255];
+ BOOL bRet = SendMessageTimeout(hwnd, WM_GETTEXT, 255, (LPARAM)buffer,
+ SMTO_ABORTIFHUNG, 1000/*ms*/, NULL);
+ if(bRet == 0) {
+ fprintf(stderr,"#%4d: FAILURE!\n", i++); fflush(stderr);
+ return FALSE;
+ } else {
+ fprintf(stderr,"#%4d: GOT: %s\n", i++, buffer); fflush(stderr);
+ return TRUE;
+ }
+}
+
+int main(int argc, char **argv)
+{
+ BOOL bRet = EnumWindows(EnumWindowsProc, 0);
+ if(bRet == 0)
+ {
+ fprintf(stderr,"ERROR!");
+ exit(EXIT_FAILURE);
+ }
+ fprintf(stderr,"SUCCESS!");
+ exit(EXIT_SUCCESS);
+}
diff --git a/src/test-native/contextRetargetDrawable01.c b/src/test-native/contextRetargetDrawable01.c
new file mode 100644
index 000000000..bad6c661f
--- /dev/null
+++ b/src/test-native/contextRetargetDrawable01.c
@@ -0,0 +1,154 @@
+/**
+ * compile with: gcc -o contextRetargetDrawable01 contextRetargetDrawable01.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI = NULL;
+
+static void testRetarget();
+
+static const char * msg = "contextRetargetDrawable01";
+
+static const useconds_t demodelay = 2 * 1000 * 1000;
+
+int main(int nargs, char **vargs) {
+ _glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB("glXSwapIntervalSGI");
+ if(NULL == _glXSwapIntervalSGI) {
+ fprintf(stderr, "No glXSwapIntervalSGI avail, bail out\n");
+ return 1;
+ }
+ testRetarget();
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval);
+
+static void testRetarget() {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = disp1;
+ // disp2 = XOpenDisplay(NULL);
+ createGLWin(disp2, 300, 300, &win2, &ctx2);
+
+ fprintf(stderr, "%s: Use #1.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 1); // OK
+
+ fprintf(stderr, "%s: Use #1.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 1); // OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Retarget Drawable\n", msg);
+ {
+ Window _win = win2;
+ win2 = win1;
+ win1 = _win;
+ }
+
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ glXMakeContextCurrent(disp1, 0, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ if( disp1 != disp2 ) {
+ XCloseDisplay(disp1);
+ }
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ glXMakeContextCurrent(disp2, 0, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Exit - OK\n", msg);
+}
+
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval)
+{
+ glXMakeContextCurrent(dpy, win, win, ctx);
+ glViewport(0, 0, width, height);
+ if(0 < swapInterval) {
+ fprintf(stderr, "%s: glXSwapIntervalSGI(1)\n", msg);
+ _glXSwapIntervalSGI(1); // offending op after retargeting drawable
+ }
+ fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ glClearColor(c, c, c, 0.0f);
+ glClearDepth(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
diff --git a/src/test-native/contextRetargetDrawable02.c b/src/test-native/contextRetargetDrawable02.c
new file mode 100644
index 000000000..3d0807b78
--- /dev/null
+++ b/src/test-native/contextRetargetDrawable02.c
@@ -0,0 +1,382 @@
+/**
+ * compile with: gcc -o contextRetargetDrawable02 contextRetargetDrawable02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+typedef int bool;
+#define true 1
+#define false 0
+
+static PFNGLXSWAPINTERVALSGIPROC _glXSwapIntervalSGI = NULL;
+
+static void testRetarget(bool reverse);
+
+static const char * msg = "contextRetargetDrawable01";
+
+static const useconds_t demodelay = 2 * 1000 * 1000;
+
+int main(int nargs, char **vargs) {
+ _glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB("glXSwapIntervalSGI");
+ if(NULL == _glXSwapIntervalSGI) {
+ fprintf(stderr, "No glXSwapIntervalSGI avail, bail out\n");
+ return 1;
+ }
+ testRetarget(false);
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval);
+
+static void testRetarget(bool reverse) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = disp1;
+ // disp2 = XOpenDisplay(NULL);
+ createGLWin(disp2, 300, 300, &win2, &ctx2);
+
+ fprintf(stderr, "%s: Use #1.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 1); // OK
+
+ fprintf(stderr, "%s: Use #1.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 1); // OK
+
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Retarget Drawable\n", msg);
+ {
+ GLXContext _ctx = ctx2;
+ ctx2 = ctx1;
+ ctx1 = _ctx;
+ }
+
+ /**
+ if(reverse) {
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+ } else {
+ fprintf(stderr, "%s: Use #2.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.0f, 0); // no setSwapInterval - OK
+
+ fprintf(stderr, "%s: Use #2.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 1.0f, 0); // no setSwapInterval - OK
+ }
+ usleep( demodelay ); */
+
+ if(reverse) {
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+ } else {
+ fprintf(stderr, "%s: Use #3.1\n", msg);
+ useGL(disp1, win1, ctx1, 200, 200, 0.1f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+
+ fprintf(stderr, "%s: Use #3.2\n", msg);
+ useGL(disp2, win2, ctx2, 300, 300, 0.9f, 1); // setSwapInterval - crash on Mesa 8.0.4 DRI2
+ }
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+ usleep( demodelay );
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ glXMakeContextCurrent(disp1, 0, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ if( disp1 != disp2 ) {
+ XCloseDisplay(disp1);
+ }
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ glXMakeContextCurrent(disp2, 0, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Exit - OK\n", msg);
+}
+
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height, float c, int swapInterval)
+{
+ glXMakeContextCurrent(dpy, win, win, ctx);
+ glViewport(0, 0, width, height);
+ if(0 < swapInterval) {
+ fprintf(stderr, "%s: glXSwapIntervalSGI(1)\n", msg);
+ _glXSwapIntervalSGI(1); // offending op after retargeting drawable
+ }
+ fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
+ glClearColor(c, c, c, 0.0f);
+ glClearDepth(1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+}
+
+static volatile bool ctxErrorOccurred = false;
+static int ctxErrorHandler( Display *dpy, XErrorEvent *e )
+{
+ const char * errnoStr = strerror(errno);
+ char errCodeStr[80];
+ char reqCodeStr[80];
+
+ snprintf(errCodeStr, sizeof(errCodeStr), "%d", e->request_code);
+ XGetErrorDatabaseText(dpy, "XRequest", errCodeStr, "Unknown", reqCodeStr, sizeof(reqCodeStr));
+ XGetErrorText(dpy, e->error_code, errCodeStr, sizeof(errCodeStr));
+
+ fprintf(stderr, "X11 Error: %d - %s, dpy %p, id %x, # %d: %d:%d %s\n",
+ e->error_code, errCodeStr, e->display, (int)e->resourceid, (int)e->serial,
+ (int)e->request_code, (int)e->minor_code, reqCodeStr);
+ fflush(stderr);
+
+ ctxErrorOccurred = true;
+ return 0;
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 8 bits per color and a 16 bit depth buffer */
+static int visual_attribs[] = {
+ GLX_X_RENDERABLE , True,
+ GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE , GLX_RGBA_BIT,
+ GLX_RED_SIZE , 8,
+ GLX_GREEN_SIZE , 8,
+ GLX_BLUE_SIZE , 8,
+ GLX_DEPTH_SIZE , 16,
+ GLX_DOUBLEBUFFER , True,
+ GLX_STEREO , False,
+ GLX_TRANSPARENT_TYPE, GLX_NONE,
+ //GLX_SAMPLE_BUFFERS , 1,
+ //GLX_SAMPLES , 4,
+ None };
+
+static int context_attribs[] = {
+ GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+ GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+ GLX_RENDER_TYPE , GLX_RGBA_TYPE,
+ GLX_CONTEXT_FLAGS_ARB , 0,
+ // GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
+ None };
+
+static bool isExtensionSupported(const char *extList, const char *extension);
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int glx_major, glx_minor;
+
+ // FBConfigs were added in GLX version 1.3.
+ if ( !glXQueryVersion( dpy, &glx_major, &glx_minor ) ||
+ ( ( glx_major == 1 ) && ( glx_minor < 3 ) ) || ( glx_major < 1 ) )
+ {
+ printf( "Invalid GLX version" );
+ exit(1);
+ }
+
+ int fbcount;
+ GLXFBConfig *fbc = glXChooseFBConfig( dpy, DefaultScreen( dpy ),
+ visual_attribs, &fbcount );
+ if ( !fbc || 0 == fbcount )
+ {
+ printf( "Failed to retrieve a framebuffer config\n" );
+ exit(1);
+ }
+ printf( "Found %d matching FB configs.\n", fbcount );
+
+ GLXFBConfig bestFbc = fbc[ 0 ];
+ int bestFbcID = 0;
+ if( 0 != glXGetFBConfigAttrib( dpy, bestFbc, GLX_FBCONFIG_ID, &bestFbcID ) ) {
+ printf( "Invalid FBConfigID\n" );
+ exit(1);
+ }
+ printf( "Chosen FBConfigID = 0x%x\n", bestFbcID);
+
+ XVisualInfo *vi = glXGetVisualFromFBConfig( dpy, bestFbc );
+ printf( "Chosen visual ID = 0x%x\n", (int) vi->visualid );
+
+ XSetWindowAttributes swa;
+ Colormap cmap;
+ swa.colormap = cmap = XCreateColormap( dpy,
+ RootWindow( dpy, vi->screen ),
+ vi->visual, AllocNone );
+ swa.background_pixmap = None ;
+ swa.border_pixel = 0;
+ swa.event_mask = StructureNotifyMask;
+
+ printf( "Creating window\n" );
+ Window win = XCreateWindow( dpy, RootWindow( dpy, vi->screen ),
+ 0, 0, width, height, 0, vi->depth, InputOutput,
+ vi->visual,
+ CWBorderPixel|CWColormap|CWEventMask, &swa );
+ if ( !win )
+ {
+ printf( "Failed to create window.\n" );
+ exit(1);
+ }
+
+ // Done with the visual info data
+ XFree( vi );
+
+ XStoreName( dpy, win, "GL Window" );
+
+ XMapWindow( dpy, win );
+
+ *rWin = win;
+
+ GLXContext ctx0 = glXCreateNewContext( dpy, bestFbc, GLX_RGBA_TYPE, 0, True );
+ if( !ctx0 ) {
+ printf( "Failed to create intermediate old OpenGL context\n" );
+ exit(1);
+ }
+ glXMakeContextCurrent(dpy, win, win, ctx0);
+
+
+ // Get the default screen's GLX extension list
+ const char *glxExts01 = glXQueryExtensionsString( dpy,
+ DefaultScreen( dpy ) );
+ const char *glxExts02 = glXGetClientString( dpy, GLX_EXTENSIONS);
+ const char *glxExts03 = glXQueryServerString( dpy, DefaultScreen( dpy ), GLX_EXTENSIONS);
+
+ // NOTE: It is not necessary to create or make current to a context before
+ // calling glXGetProcAddressARB
+ PFNGLXCREATECONTEXTATTRIBSARBPROC _glXCreateContextAttribsARB = 0;
+ _glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+ glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
+
+ // Check for the GLX_ARB_create_context extension string and the function.
+ // If either is not present, use GLX 1.3 context creation method.
+ bool isGLX_ARB_create_contextAvail = isExtensionSupported( glxExts01, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts02, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts03, "GLX_ARB_create_context" );
+
+ glXMakeContextCurrent(dpy, 0, 0, 0);
+
+ GLXContext ctx = 0;
+
+ // Install an X error handler so the application won't exit if GL 3.0
+ // context allocation fails.
+ //
+ // Note this error handler is global. All display connections in all threads
+ // of a process use the same error handler, so be sure to guard against other
+ // threads issuing X commands while this code is running.
+ int (*oldHandler)(Display*, XErrorEvent*) =
+ XSetErrorHandler(&ctxErrorHandler);
+
+ if ( !isGLX_ARB_create_contextAvail || !_glXCreateContextAttribsARB )
+ {
+ printf( "glXCreateContextAttribsARB() not found (ext %d, func %p)"
+ " ... using old-style GLX context\n", isGLX_ARB_create_contextAvail, _glXCreateContextAttribsARB );
+ printf( "extensions 01: %s\n", glxExts01);
+ printf( "extensions 02: %s\n", glxExts02);
+ printf( "extensions 03: %s\n", glxExts03);
+ ctx = ctx0;
+ }
+
+ // If it does, try to get a GL 3.0 context!
+ else
+ {
+ printf( "Creating context\n" );
+ XSync( dpy, False );
+ ctxErrorOccurred = false;
+ ctx = _glXCreateContextAttribsARB( dpy, bestFbc, 0, True, context_attribs );
+ XSync( dpy, False );
+
+ if ( !ctxErrorOccurred && ctx ) {
+ printf( "Created GL 3.0 context\n" );
+ glXDestroyContext(dpy, ctx0); // get rid of old ctx
+ } else
+ {
+ // Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
+ // When a context version below 3.0 is requested, implementations will
+ // return the newest context version compatible with OpenGL versions less
+ // than version 3.0.
+ // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
+ context_attribs[1] = 1;
+ // GLX_CONTEXT_MINOR_VERSION_ARB = 0
+ context_attribs[3] = 0;
+
+ printf( "Failed to create GL 3.0 context (err %d, ctx %p)"
+ " ... using old-style GLX context\n", ctxErrorOccurred, (void*)ctx );
+ ctx = ctx0;
+
+ ctxErrorOccurred = false;
+ }
+ }
+
+ // Sync to ensure any errors generated are processed.
+ XSync( dpy, False );
+
+ // Restore the original error handler
+ XSetErrorHandler( oldHandler );
+
+ if ( ctxErrorOccurred || !ctx )
+ {
+ printf( "Failed to create an OpenGL context\n" );
+ exit(1);
+ }
+
+ XFree( fbc );
+
+ *rCtx = ctx;
+}
+
+// Helper to check for extension string presence. Adapted from:
+// http://www.opengl.org/resources/features/OGLextensions/
+static bool isExtensionSupported(const char *extList, const char *extension)
+{
+
+ const char *start;
+ const char *where, *terminator;
+
+ /* Extension names should not have spaces. */
+ where = strchr(extension, ' ');
+ if ( where || *extension == '\0' )
+ return false;
+
+ /* It takes a bit of care to be fool-proof about parsing the
+ OpenGL extensions string. Don't be fooled by sub-strings,
+ etc. */
+ for ( start = extList; ; ) {
+ where = strstr( start, extension );
+
+ if ( !where )
+ break;
+
+ terminator = where + strlen( extension );
+
+ if ( where == start || *(where - 1) == ' ' )
+ if ( *terminator == ' ' || *terminator == '\0' )
+ return true;
+
+ start = terminator;
+ }
+
+ return false;
+}
+
diff --git a/src/test-native/displayMultiple02_mch.c b/src/test-native/displayMultiple02_mch.c
new file mode 100644
index 000000000..c2ab25fbb
--- /dev/null
+++ b/src/test-native/displayMultiple02_mch.c
@@ -0,0 +1,130 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+ int arg=1;
+ while(arg<nargs) {
+ if(0 == strcmp(vargs[arg], "-xlock")) {
+ useXLockDisplay = 1;
+ }
+ arg++;
+ }
+ fprintf(stderr, "-xlock (XLockDisplay): %d\n", useXLockDisplay);
+
+ if( useXLockDisplay ) {
+ XInitThreads();
+ }
+ testOrder(0, "Normal order");
+ testOrder(1, "Reverse order");
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XLockDisplay(dpy);
+ }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XUnlockDisplay(dpy);
+ }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp1);
+ createGLWin(disp1, 200, 200, &win1, &ctx1);
+ useGL(disp1, win1, ctx1, 200, 200);
+ XUNLOCKDISPLAY(disp1);
+
+ if(reverseDestroyOrder) {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.1\n", msg);
+ glXMakeCurrent(disp1, 0, 0);
+ fprintf(stderr, "%s: Destroy #1.2\n", msg);
+ glXDestroyContext(disp1, ctx1);
+ fprintf(stderr, "%s: Destroy #1.3\n", msg);
+ XUNLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.4\n", msg);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ } else {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ glXMakeCurrent(disp1, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ XUNLOCKDISPLAY(disp1);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ }
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+ glXMakeCurrent(dpy, win, ctx);
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearDepth(1.0f);
+ glViewport(0, 0, width, height);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/displayMultiple02_new_mch.c b/src/test-native/displayMultiple02_new_mch.c
new file mode 100644
index 000000000..f64d41472
--- /dev/null
+++ b/src/test-native/displayMultiple02_new_mch.c
@@ -0,0 +1,199 @@
+/**
+ * compile with: gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+ */
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+static void testOrder(int reverseDestroyOrder, const char * msg);
+
+static int useXLockDisplay = 0;
+
+int main(int nargs, char **vargs) {
+ int arg=1;
+ while(arg<nargs) {
+ if(0 == strcmp(vargs[arg], "-xlock")) {
+ useXLockDisplay = 1;
+ }
+ arg++;
+ }
+ fprintf(stderr, "-xlock (XLockDisplay): %d\n", useXLockDisplay);
+
+ if( useXLockDisplay ) {
+ XInitThreads();
+ }
+ testOrder(0, "Normal order");
+ testOrder(1, "Reverse order");
+ return 0;
+}
+
+static void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx);
+static void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height);
+
+static void XLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XLockDisplay(dpy);
+ }
+}
+static void XUNLOCKDISPLAY(Display *dpy) {
+ if( useXLockDisplay ) {
+ XUnlockDisplay(dpy);
+ }
+}
+
+void testOrder(int reverseDestroyOrder, const char * msg) {
+ int major, minor;
+ Display *disp1;
+ Window win1;
+ GLXContext ctx1;
+
+ Display *disp2;
+ Window win2;
+ GLXContext ctx2;
+
+ fprintf(stderr, "%s: Create #1\n", msg);
+ disp1 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp1);
+ createGLWinNew(disp1, 200, 200, &win1, &ctx1);
+ useGL(disp1, win1, ctx1, 200, 200);
+ XUNLOCKDISPLAY(disp1);
+
+ fprintf(stderr, "%s: Create #2\n", msg);
+ disp2 = XOpenDisplay(NULL);
+ XLOCKDISPLAY(disp2);
+ createGLWinNew(disp2, 300, 300, &win2, &ctx2);
+ useGL(disp2, win2, ctx2, 300, 300);
+ XUNLOCKDISPLAY(disp2);
+
+ if(reverseDestroyOrder) {
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ XLOCKDISPLAY(disp2);
+ glXMakeCurrent(disp2, 0, 0);
+ glXDestroyContext(disp2, ctx2);
+ XUNLOCKDISPLAY(disp2);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.1\n", msg);
+ glXMakeCurrent(disp1, 0, 0);
+ fprintf(stderr, "%s: Destroy #1.2\n", msg);
+ glXDestroyContext(disp1, ctx1);
+ fprintf(stderr, "%s: Destroy #1.3\n", msg);
+ XUNLOCKDISPLAY(disp1);
+ fprintf(stderr, "%s: Destroy #1.4\n", msg);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+ } else {
+ fprintf(stderr, "%s: Destroy #1.0\n", msg);
+ XLOCKDISPLAY(disp1);
+ glXMakeCurrent(disp1, 0, 0);
+ glXDestroyContext(disp1, ctx1);
+ XUNLOCKDISPLAY(disp1);
+ XCloseDisplay(disp1);
+ fprintf(stderr, "%s: Destroy #1.X\n", msg);
+
+ fprintf(stderr, "%s: Destroy #2.0\n", msg);
+ XLOCKDISPLAY(disp2);
+ fprintf(stderr, "%s: Destroy #2.1\n", msg);
+ glXMakeCurrent(disp2, 0, 0);
+ fprintf(stderr, "%s: Destroy #2.2\n", msg);
+ glXDestroyContext(disp2, ctx2);
+ fprintf(stderr, "%s: Destroy #2.3\n", msg);
+ XUNLOCKDISPLAY(disp2);
+ fprintf(stderr, "%s: Destroy #2.4\n", msg);
+ XCloseDisplay(disp2);
+ fprintf(stderr, "%s: Destroy #2.X\n", msg);
+ }
+
+ fprintf(stderr, "%s: Success - no bug\n", msg);
+}
+
+/* attributes for a double buffered visual in RGBA format with at least
+ * 4 bits per color and a 16 bit depth buffer */
+static int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4,
+ GLX_BLUE_SIZE, 4,
+ GLX_DEPTH_SIZE, 16,
+ None };
+static int attrListDblNew[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DOUBLEBUFFER, True,
+ GLX_BUFFER_SIZE, 24,
+ GLX_DEPTH_SIZE, 24,
+ None };
+
+void createGLWin(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ XVisualInfo *vi = glXChooseVisual(dpy, screen, attrListDbl);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ /* create a GLX context */
+ *rCtx = glXCreateContext(dpy, vi, 0, GL_TRUE);
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void createGLWinNew(Display *dpy, int width, int height, Window *rWin, GLXContext *rCtx)
+{
+ int screen = DefaultScreen(dpy);
+ Colormap cmap;
+ XSetWindowAttributes attr;
+
+ // create configs
+ int nelements;
+ GLXFBConfig *fbconfigs = glXChooseFBConfig(dpy,screen,attrListDblNew,&nelements );
+
+ // get visual
+ XVisualInfo *vi = glXGetVisualFromFBConfig(dpy,*fbconfigs);
+
+ /* create a GLX context */
+ *rCtx = glXCreateNewContext(dpy, *fbconfigs, GLX_RGBA_TYPE, 0, GL_TRUE);
+
+ /* create a color map */
+ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
+ attr.colormap = cmap;
+ attr.border_pixel = 0;
+
+ /* create a window in window mode*/
+ attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask |
+ StructureNotifyMask;
+ *rWin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
+ 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual,
+ CWBorderPixel | CWColormap | CWEventMask, &attr);
+
+ XMapRaised(dpy, *rWin);
+}
+
+void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
+{
+ glXMakeCurrent(dpy, win, ctx);
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearDepth(1.0f);
+ glViewport(0, 0, width, height);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glXSwapBuffers(dpy, win);
+ glXMakeCurrent(dpy, 0, 0);
+}
+
diff --git a/src/test-native/glExtensionsListGL2.c b/src/test-native/glExtensionsListGL2.c
index 89815e9c0..ea47b8c69 100644
--- a/src/test-native/glExtensionsListGL2.c
+++ b/src/test-native/glExtensionsListGL2.c
@@ -77,6 +77,8 @@ void useGL(Display *dpy, Window win, GLXContext ctx, int width, int height)
glXMakeCurrent(dpy, win, ctx);
fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
fprintf(stderr, "GL_NUM_EXTENSIONS: %d\n", n);
diff --git a/src/test-native/glExtensionsListGL3.c b/src/test-native/glExtensionsListGL3.c
index c531577e8..5875c10bc 100644
--- a/src/test-native/glExtensionsListGL3.c
+++ b/src/test-native/glExtensionsListGL3.c
@@ -59,6 +59,8 @@ void dumpGLExtension() {
int i, n;
fprintf(stderr, "GL_VENDOR: %s\n", glGetString(GL_VENDOR));
+ fprintf(stderr, "GL_VERSION: %s\n", glGetString(GL_VERSION));
+ fprintf(stderr, "GL_RENDERER: %s\n", glGetString(GL_RENDERER));
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
fprintf(stderr, "GL_NUM_EXTENSIONS: %d\n", n);
@@ -153,9 +155,6 @@ int main (int argc, char ** argv)
GLXFBConfig bestFbc = fbc[ best_fbc ];
- // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
- XFree( fbc );
-
// Get a visual
XVisualInfo *vi = glXGetVisualFromFBConfig( display, bestFbc );
printf( "Chosen visual ID = 0x%x\n", (int) vi->visualid );
@@ -190,8 +189,9 @@ int main (int argc, char ** argv)
XMapWindow( display, win );
// Get the default screen's GLX extension list
- const char *glxExts = glXQueryExtensionsString( display,
- DefaultScreen( display ) );
+ const char *glxExts01 = glXQueryExtensionsString( display, DefaultScreen( display ) );
+ const char *glxExts02 = glXGetClientString( display, GLX_EXTENSIONS);
+ const char *glxExts03 = glXQueryServerString( display, DefaultScreen( display ), GLX_EXTENSIONS);
// NOTE: It is not necessary to create or make current to a context before
// calling glXGetProcAddressARB
@@ -213,11 +213,16 @@ int main (int argc, char ** argv)
// Check for the GLX_ARB_create_context extension string and the function.
// If either is not present, use GLX 1.3 context creation method.
- if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
- !glXCreateContextAttribsARB )
+ bool isGLX_ARB_create_contextAvail = isExtensionSupported( glxExts01, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts02, "GLX_ARB_create_context" ) ||
+ isExtensionSupported( glxExts03, "GLX_ARB_create_context" );
+ if ( !isGLX_ARB_create_contextAvail || !glXCreateContextAttribsARB )
{
printf( "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
+ printf( "extensions 01: %s\n", glxExts01);
+ printf( "extensions 02: %s\n", glxExts02);
+ printf( "extensions 03: %s\n", glxExts03);
ctx = glXCreateNewContext( display, bestFbc, GLX_RGBA_TYPE, 0, True );
}
@@ -229,7 +234,8 @@ int main (int argc, char ** argv)
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
GLX_RENDER_TYPE , GLX_RGBA_TYPE,
- GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+ // GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
None
};
@@ -261,6 +267,9 @@ int main (int argc, char ** argv)
}
}
+ // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
+ XFree( fbc );
+
// Sync to ensure any errors generated are processed.
XSync( display, False );
diff --git a/src/test-native/make.sh b/src/test-native/make.sh
index 20bd49e4a..c6d47ff03 100755
--- a/src/test-native/make.sh
+++ b/src/test-native/make.sh
@@ -2,5 +2,9 @@
gcc -o displayMultiple01 displayMultiple01.c -lX11 -lGL
gcc -o displayMultiple02 displayMultiple02.c -lX11 -lGL
+gcc -o displayMultiple02_mch displayMultiple02_mch.c -lX11 -lGL
+gcc -o displayMultiple02_new_mch displayMultiple02_new_mch.c -lX11 -lGL
gcc -o glExtensionsListGL2 glExtensionsListGL2.c -lX11 -lGL
gcc -o glExtensionsListGL3 glExtensionsListGL3.c -lX11 -lGL
+gcc -o contextRetargetDrawable01 contextRetargetDrawable01.c -lX11 -lGL
+gcc -o contextRetargetDrawable02 contextRetargetDrawable02.c -lX11 -lGL