132001f49Smrg/* 232001f49Smrg * Create several OpenGL rendering contexts, sharing textures, display 332001f49Smrg * lists, etc. Exercise binding, deleting, etc. 432001f49Smrg * 532001f49Smrg * Brian Paul 632001f49Smrg * 21 December 2004 732001f49Smrg */ 832001f49Smrg 932001f49Smrg 1032001f49Smrg#include <GL/gl.h> 1132001f49Smrg#include <GL/glx.h> 1232001f49Smrg#include <assert.h> 1332001f49Smrg#include <stdio.h> 1432001f49Smrg#include <stdlib.h> 1532001f49Smrg#include <string.h> 1632001f49Smrg#include <unistd.h> 1732001f49Smrg#include <X11/keysym.h> 1832001f49Smrg 1932001f49Smrg 2032001f49Smrg/* 2132001f49Smrg * Each display/window/context: 2232001f49Smrg */ 2332001f49Smrgstruct context { 2432001f49Smrg char DisplayName[1000]; 2532001f49Smrg Display *Dpy; 2632001f49Smrg Window Win; 2732001f49Smrg GLXContext Context; 2832001f49Smrg}; 2932001f49Smrg 3032001f49Smrg 3132001f49Smrg#define MAX_CONTEXTS 200 3232001f49Smrgstatic struct context Contexts[MAX_CONTEXTS]; 3332001f49Smrgstatic int NumContexts = 0; 3432001f49Smrg 3532001f49Smrg 3632001f49Smrgstatic void 3732001f49SmrgError(const char *display, const char *msg) 3832001f49Smrg{ 3932001f49Smrg fprintf(stderr, "Error on display %s - %s\n", display, msg); 4032001f49Smrg exit(1); 4132001f49Smrg} 4232001f49Smrg 4332001f49Smrg 4432001f49Smrgstatic struct context * 4532001f49SmrgCreateContext(const char *displayName, const char *name) 4632001f49Smrg{ 4732001f49Smrg Display *dpy; 4832001f49Smrg Window win; 4932001f49Smrg GLXContext ctx; 5032001f49Smrg int attrib[] = { GLX_RGBA, 5132001f49Smrg GLX_RED_SIZE, 1, 5232001f49Smrg GLX_GREEN_SIZE, 1, 5332001f49Smrg GLX_BLUE_SIZE, 1, 5432001f49Smrg GLX_DOUBLEBUFFER, 5532001f49Smrg None }; 5632001f49Smrg int scrnum; 5732001f49Smrg XSetWindowAttributes attr; 5832001f49Smrg unsigned long mask; 5932001f49Smrg Window root; 6032001f49Smrg XVisualInfo *visinfo; 6132001f49Smrg int width = 90, height = 90; 6232001f49Smrg int xpos = 0, ypos = 0; 6332001f49Smrg 6432001f49Smrg if (NumContexts >= MAX_CONTEXTS) 6532001f49Smrg return NULL; 6632001f49Smrg 6732001f49Smrg dpy = XOpenDisplay(displayName); 6832001f49Smrg if (!dpy) { 6932001f49Smrg Error(displayName, "Unable to open display"); 7032001f49Smrg return NULL; 7132001f49Smrg } 7232001f49Smrg 7332001f49Smrg scrnum = DefaultScreen(dpy); 7432001f49Smrg root = RootWindow(dpy, scrnum); 7532001f49Smrg 7632001f49Smrg visinfo = glXChooseVisual(dpy, scrnum, attrib); 7732001f49Smrg if (!visinfo) { 7832001f49Smrg Error(displayName, "Unable to find RGB, double-buffered visual"); 7932001f49Smrg return NULL; 8032001f49Smrg } 8132001f49Smrg 8232001f49Smrg /* window attributes */ 8332001f49Smrg xpos = (NumContexts % 10) * 100; 8432001f49Smrg ypos = (NumContexts / 10) * 100; 8532001f49Smrg attr.background_pixel = 0; 8632001f49Smrg attr.border_pixel = 0; 8732001f49Smrg attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); 8832001f49Smrg attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 8932001f49Smrg mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 9032001f49Smrg 9132001f49Smrg win = XCreateWindow(dpy, root, xpos, ypos, width, height, 9232001f49Smrg 0, visinfo->depth, InputOutput, 9332001f49Smrg visinfo->visual, mask, &attr); 9432001f49Smrg if (!win) { 9532001f49Smrg Error(displayName, "Couldn't create window"); 9632001f49Smrg return NULL; 9732001f49Smrg } 9832001f49Smrg 9932001f49Smrg { 10032001f49Smrg XSizeHints sizehints; 10132001f49Smrg sizehints.x = xpos; 10232001f49Smrg sizehints.y = ypos; 10332001f49Smrg sizehints.width = width; 10432001f49Smrg sizehints.height = height; 10532001f49Smrg sizehints.flags = USSize | USPosition; 10632001f49Smrg XSetNormalHints(dpy, win, &sizehints); 10732001f49Smrg XSetStandardProperties(dpy, win, name, name, 10832001f49Smrg None, (char **)NULL, 0, &sizehints); 10932001f49Smrg } 11032001f49Smrg 11132001f49Smrg if (NumContexts == 0) { 11232001f49Smrg ctx = glXCreateContext(dpy, visinfo, NULL, True); 11332001f49Smrg } 11432001f49Smrg else { 11532001f49Smrg /* share textures & dlists with 0th context */ 11632001f49Smrg ctx = glXCreateContext(dpy, visinfo, Contexts[0].Context, True); 11732001f49Smrg } 11832001f49Smrg if (!ctx) { 11932001f49Smrg Error(displayName, "Couldn't create GLX context"); 12032001f49Smrg return NULL; 12132001f49Smrg } 12232001f49Smrg 12332001f49Smrg XMapWindow(dpy, win); 12432001f49Smrg 12532001f49Smrg if (!glXMakeCurrent(dpy, win, ctx)) { 12632001f49Smrg Error(displayName, "glXMakeCurrent failed"); 12732001f49Smrg return NULL; 12832001f49Smrg } 12932001f49Smrg 13032001f49Smrg if (NumContexts == 0) { 13132001f49Smrg printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 13232001f49Smrg } 13332001f49Smrg 13432001f49Smrg /* save the info for this context */ 13532001f49Smrg { 13632001f49Smrg struct context *h = &Contexts[NumContexts]; 13732001f49Smrg strcpy(h->DisplayName, name); 13832001f49Smrg h->Dpy = dpy; 13932001f49Smrg h->Win = win; 14032001f49Smrg h->Context = ctx; 14132001f49Smrg NumContexts++; 14232001f49Smrg return &Contexts[NumContexts-1]; 14332001f49Smrg } 14432001f49Smrg} 14532001f49Smrg 14632001f49Smrg 14732001f49Smrgstatic void 14832001f49SmrgMakeCurrent(int i) 14932001f49Smrg{ 15032001f49Smrg if (!glXMakeCurrent(Contexts[i].Dpy, Contexts[i].Win, Contexts[i].Context)) { 15132001f49Smrg fprintf(stderr, "glXMakeCurrent failed!\n"); 15232001f49Smrg } 15332001f49Smrg} 15432001f49Smrg 15532001f49Smrg 15632001f49Smrg 15732001f49Smrgstatic void 15832001f49SmrgDestroyContext(int i) 15932001f49Smrg{ 16032001f49Smrg XDestroyWindow(Contexts[i].Dpy, Contexts[i].Win); 16132001f49Smrg glXDestroyContext(Contexts[i].Dpy, Contexts[i].Context); 16232001f49Smrg XCloseDisplay(Contexts[i].Dpy); 16332001f49Smrg} 16432001f49Smrg 16532001f49Smrg 16632001f49Smrgint 16732001f49Smrgmain(int argc, char *argv[]) 16832001f49Smrg{ 16932001f49Smrg char *dpyName = NULL; 17032001f49Smrg int i; 17132001f49Smrg GLuint t; 17232001f49Smrg GLint tb; 17332001f49Smrg 17432001f49Smrg for (i = 0; i < 2; i++) { 17532001f49Smrg CreateContext(dpyName, "context"); 17632001f49Smrg } 17732001f49Smrg 17832001f49Smrg /* Create texture and bind it in context 0 */ 17932001f49Smrg MakeCurrent(0); 18032001f49Smrg glGenTextures(1, &t); 18132001f49Smrg printf("Generated texture ID %u\n", t); 18232001f49Smrg assert(!glIsTexture(t)); 18332001f49Smrg glBindTexture(GL_TEXTURE_2D, t); 18432001f49Smrg assert(glIsTexture(t)); 18532001f49Smrg glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 18632001f49Smrg assert(tb == t); 18732001f49Smrg 18832001f49Smrg /* Bind texture in context 1 */ 18932001f49Smrg MakeCurrent(1); 19032001f49Smrg assert(glIsTexture(t)); 19132001f49Smrg glBindTexture(GL_TEXTURE_2D, t); 19232001f49Smrg glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 19332001f49Smrg assert(tb == t); 19432001f49Smrg 19532001f49Smrg /* Delete texture from context 0 */ 19632001f49Smrg MakeCurrent(0); 19732001f49Smrg glDeleteTextures(1, &t); 19832001f49Smrg assert(!glIsTexture(t)); 19932001f49Smrg glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 20032001f49Smrg printf("After delete, binding = %d\n", tb); 20132001f49Smrg 20232001f49Smrg /* Check texture state from context 1 */ 20332001f49Smrg MakeCurrent(1); 20432001f49Smrg assert(!glIsTexture(t)); 20532001f49Smrg glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 20632001f49Smrg printf("In second context, binding = %d\n", tb); 20732001f49Smrg glBindTexture(GL_TEXTURE_2D, 0); 20832001f49Smrg glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 20932001f49Smrg assert(tb == 0); 21032001f49Smrg 21132001f49Smrg 21232001f49Smrg for (i = 0; i < NumContexts; i++) { 21332001f49Smrg DestroyContext(i); 21432001f49Smrg } 21532001f49Smrg 21632001f49Smrg printf("Success!\n"); 21732001f49Smrg 21832001f49Smrg return 0; 21932001f49Smrg} 220