1/* 2 * Create several OpenGL rendering contexts, sharing textures, display 3 * lists, etc. Exercise binding, deleting, etc. 4 * 5 * Brian Paul 6 * 21 December 2004 7 */ 8 9 10#include <GL/gl.h> 11#include <GL/glx.h> 12#include <assert.h> 13#include <stdio.h> 14#include <stdlib.h> 15#include <string.h> 16#include <unistd.h> 17#include <X11/keysym.h> 18 19 20/* 21 * Each display/window/context: 22 */ 23struct context { 24 char DisplayName[1000]; 25 Display *Dpy; 26 Window Win; 27 GLXContext Context; 28}; 29 30 31#define MAX_CONTEXTS 200 32static struct context Contexts[MAX_CONTEXTS]; 33static int NumContexts = 0; 34 35 36static void 37Error(const char *display, const char *msg) 38{ 39 fprintf(stderr, "Error on display %s - %s\n", display, msg); 40 exit(1); 41} 42 43 44static struct context * 45CreateContext(const char *displayName, const char *name) 46{ 47 Display *dpy; 48 Window win; 49 GLXContext ctx; 50 int attrib[] = { GLX_RGBA, 51 GLX_RED_SIZE, 1, 52 GLX_GREEN_SIZE, 1, 53 GLX_BLUE_SIZE, 1, 54 GLX_DOUBLEBUFFER, 55 None }; 56 int scrnum; 57 XSetWindowAttributes attr; 58 unsigned long mask; 59 Window root; 60 XVisualInfo *visinfo; 61 int width = 90, height = 90; 62 int xpos = 0, ypos = 0; 63 64 if (NumContexts >= MAX_CONTEXTS) 65 return NULL; 66 67 dpy = XOpenDisplay(displayName); 68 if (!dpy) { 69 Error(displayName, "Unable to open display"); 70 return NULL; 71 } 72 73 scrnum = DefaultScreen(dpy); 74 root = RootWindow(dpy, scrnum); 75 76 visinfo = glXChooseVisual(dpy, scrnum, attrib); 77 if (!visinfo) { 78 Error(displayName, "Unable to find RGB, double-buffered visual"); 79 return NULL; 80 } 81 82 /* window attributes */ 83 xpos = (NumContexts % 10) * 100; 84 ypos = (NumContexts / 10) * 100; 85 attr.background_pixel = 0; 86 attr.border_pixel = 0; 87 attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); 88 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 89 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 90 91 win = XCreateWindow(dpy, root, xpos, ypos, width, height, 92 0, visinfo->depth, InputOutput, 93 visinfo->visual, mask, &attr); 94 if (!win) { 95 Error(displayName, "Couldn't create window"); 96 return NULL; 97 } 98 99 { 100 XSizeHints sizehints; 101 sizehints.x = xpos; 102 sizehints.y = ypos; 103 sizehints.width = width; 104 sizehints.height = height; 105 sizehints.flags = USSize | USPosition; 106 XSetNormalHints(dpy, win, &sizehints); 107 XSetStandardProperties(dpy, win, name, name, 108 None, (char **)NULL, 0, &sizehints); 109 } 110 111 if (NumContexts == 0) { 112 ctx = glXCreateContext(dpy, visinfo, NULL, True); 113 } 114 else { 115 /* share textures & dlists with 0th context */ 116 ctx = glXCreateContext(dpy, visinfo, Contexts[0].Context, True); 117 } 118 if (!ctx) { 119 Error(displayName, "Couldn't create GLX context"); 120 return NULL; 121 } 122 123 XMapWindow(dpy, win); 124 125 if (!glXMakeCurrent(dpy, win, ctx)) { 126 Error(displayName, "glXMakeCurrent failed"); 127 return NULL; 128 } 129 130 if (NumContexts == 0) { 131 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); 132 } 133 134 /* save the info for this context */ 135 { 136 struct context *h = &Contexts[NumContexts]; 137 strcpy(h->DisplayName, name); 138 h->Dpy = dpy; 139 h->Win = win; 140 h->Context = ctx; 141 NumContexts++; 142 return &Contexts[NumContexts-1]; 143 } 144} 145 146 147static void 148MakeCurrent(int i) 149{ 150 if (!glXMakeCurrent(Contexts[i].Dpy, Contexts[i].Win, Contexts[i].Context)) { 151 fprintf(stderr, "glXMakeCurrent failed!\n"); 152 } 153} 154 155 156 157static void 158DestroyContext(int i) 159{ 160 XDestroyWindow(Contexts[i].Dpy, Contexts[i].Win); 161 glXDestroyContext(Contexts[i].Dpy, Contexts[i].Context); 162 XCloseDisplay(Contexts[i].Dpy); 163} 164 165 166int 167main(int argc, char *argv[]) 168{ 169 char *dpyName = NULL; 170 int i; 171 GLuint t; 172 GLint tb; 173 174 for (i = 0; i < 2; i++) { 175 CreateContext(dpyName, "context"); 176 } 177 178 /* Create texture and bind it in context 0 */ 179 MakeCurrent(0); 180 glGenTextures(1, &t); 181 printf("Generated texture ID %u\n", t); 182 assert(!glIsTexture(t)); 183 glBindTexture(GL_TEXTURE_2D, t); 184 assert(glIsTexture(t)); 185 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 186 assert(tb == t); 187 188 /* Bind texture in context 1 */ 189 MakeCurrent(1); 190 assert(glIsTexture(t)); 191 glBindTexture(GL_TEXTURE_2D, t); 192 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 193 assert(tb == t); 194 195 /* Delete texture from context 0 */ 196 MakeCurrent(0); 197 glDeleteTextures(1, &t); 198 assert(!glIsTexture(t)); 199 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 200 printf("After delete, binding = %d\n", tb); 201 202 /* Check texture state from context 1 */ 203 MakeCurrent(1); 204 assert(!glIsTexture(t)); 205 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 206 printf("In second context, binding = %d\n", tb); 207 glBindTexture(GL_TEXTURE_2D, 0); 208 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb); 209 assert(tb == 0); 210 211 212 for (i = 0; i < NumContexts; i++) { 213 DestroyContext(i); 214 } 215 216 printf("Success!\n"); 217 218 return 0; 219} 220