1/* 2 * Test sharing of texture objects by two rendering contexts. 3 * In particular, test that changing a texture object in one context 4 * effects the texture in the second context. 5 * 6 * Brian Paul 7 * 30 Apr 2008 8 * 9 * Copyright (C) 2008 Brian Paul All Rights Reserved. 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a 12 * copy of this software and associated documentation files (the "Software"), 13 * to deal in the Software without restriction, including without limitation 14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 * and/or sell copies of the Software, and to permit persons to whom the 16 * Software is furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice shall be included 19 * in all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 */ 28 29 30#include <GL/gl.h> 31#include <GL/glx.h> 32#include <assert.h> 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include <unistd.h> 37#include <X11/keysym.h> 38 39 40#define MAX_CONTEXTS 2 41 42#define TEX_SIZE 32 43 44static const char *DisplayName = NULL; 45static Display *Dpy; 46static XVisualInfo *VisInfo; 47static Window Win; 48static GLXContext Contexts[MAX_CONTEXTS]; 49static int WinWidth = 300, WinHeight = 300; 50 51static int DrawContext = 0, TexContext = 1; 52 53static GLuint TexObj = 0; 54static GLboolean NewTexture = GL_FALSE; 55 56 57static void 58Error(const char *msg) 59{ 60 fprintf(stderr, "sharedtex error: %s\n", msg); 61 exit(1); 62} 63 64 65static void 66CreateWindow(const char *name) 67{ 68 int attrib[] = { GLX_RGBA, 69 GLX_RED_SIZE, 1, 70 GLX_GREEN_SIZE, 1, 71 GLX_BLUE_SIZE, 1, 72 GLX_DOUBLEBUFFER, 73 None }; 74 int scrnum; 75 XSetWindowAttributes attr; 76 unsigned long mask; 77 Window root; 78 int xpos = 0, ypos = 0; 79 static int n = 0; 80 81 scrnum = DefaultScreen(Dpy); 82 root = RootWindow(Dpy, scrnum); 83 84 VisInfo = glXChooseVisual(Dpy, scrnum, attrib); 85 if (!VisInfo) { 86 Error("Unable to find RGB, double-buffered visual"); 87 } 88 89 /* window attributes */ 90 xpos = (n % 10) * 100; 91 ypos = (n / 10) * 100; 92 n++; 93 94 attr.background_pixel = 0; 95 attr.border_pixel = 0; 96 attr.colormap = XCreateColormap(Dpy, root, VisInfo->visual, AllocNone); 97 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; 98 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 99 100 Win = XCreateWindow(Dpy, root, xpos, ypos, WinWidth, WinHeight, 101 0, VisInfo->depth, InputOutput, 102 VisInfo->visual, mask, &attr); 103 if (!Win) { 104 Error("Couldn't create window"); 105 } 106 107 { 108 XSizeHints sizehints; 109 sizehints.x = xpos; 110 sizehints.y = ypos; 111 sizehints.width = WinWidth; 112 sizehints.height = WinHeight; 113 sizehints.flags = USSize | USPosition; 114 XSetNormalHints(Dpy, Win, &sizehints); 115 XSetStandardProperties(Dpy, Win, name, name, 116 None, (char **)NULL, 0, &sizehints); 117 } 118 119 XMapWindow(Dpy, Win); 120} 121 122 123/** 124 * Change texture image, using TexContext 125 */ 126static void 127ModifyTexture(void) 128{ 129 GLuint tex[TEX_SIZE][TEX_SIZE]; 130 GLuint c0, c1; 131 int i, j; 132 133 if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) { 134 Error("glXMakeCurrent failed"); 135 } 136 137 /* choose two random colors */ 138 c0 = rand() & 0xffffffff; 139 c1 = rand() & 0xffffffff; 140 141 for (i = 0; i < TEX_SIZE; i++) { 142 for (j = 0; j < TEX_SIZE; j++) { 143 if (((i / 4) ^ (j / 4)) & 1) { 144 tex[i][j] = c0; 145 } 146 else { 147 tex[i][j] = c1; 148 } 149 } 150 } 151 152 glBindTexture(GL_TEXTURE_2D, TexObj); 153 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, 154 GL_RGBA, GL_UNSIGNED_BYTE, tex); 155 156 NewTexture = GL_TRUE; 157} 158 159 160static void 161InitContext(void) 162{ 163 glGenTextures(1, &TexObj); 164 assert(TexObj); 165 glBindTexture(GL_TEXTURE_2D, TexObj); 166 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 168 glEnable(GL_TEXTURE_2D); 169 170 printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER)); 171} 172 173 174static void 175Setup(void) 176{ 177 int i; 178 179 Dpy = XOpenDisplay(DisplayName); 180 if (!Dpy) { 181 Error("Unable to open display"); 182 } 183 184 CreateWindow("sharedtex"); 185 186 for (i = 0; i < MAX_CONTEXTS; i++) { 187 GLXContext share = i > 0 ? Contexts[0] : 0; 188 189 Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True); 190 if (!Contexts[i]) { 191 Error("Unable to create GLX context"); 192 } 193 194 if (!glXMakeCurrent(Dpy, Win, Contexts[i])) { 195 Error("glXMakeCurrent failed"); 196 } 197 198 InitContext(); 199 } 200 201 ModifyTexture(); 202} 203 204 205/** 206 * Redraw window, using DrawContext 207 */ 208static void 209Redraw(void) 210{ 211 static float rot = 0.0; 212 float ar; 213 214 rot += 1.0; 215 216 if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) { 217 Error("glXMakeCurrent failed"); 218 } 219 220 glViewport(0, 0, WinWidth, WinHeight); 221 ar = (float) WinWidth / (float) WinHeight; 222 glMatrixMode(GL_PROJECTION); 223 glLoadIdentity(); 224 glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0); 225 glMatrixMode(GL_MODELVIEW); 226 227 glShadeModel(GL_FLAT); 228 glClearColor(0.5, 0.5, 0.5, 1.0); 229 glClear(GL_COLOR_BUFFER_BIT); 230 231 glPushMatrix(); 232 glRotatef(rot, 0, 0, 1); 233 glScalef(0.7, 0.7, 0.7); 234 235 if (NewTexture) { 236 /* rebind to get new contents */ 237 glBindTexture(GL_TEXTURE_2D, TexObj); 238 NewTexture = GL_FALSE; 239 } 240 241 /* draw textured quad */ 242 glBegin(GL_POLYGON); 243 glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 ); 244 glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 ); 245 glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 ); 246 glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 ); 247 glEnd(); 248 249 glPopMatrix(); 250 251 if (Win) 252 glXSwapBuffers(Dpy, Win); 253} 254 255 256static void 257EventLoop(void) 258{ 259 while (1) { 260 while (XPending(Dpy) > 0) { 261 XEvent event; 262 XNextEvent(Dpy, &event); 263 264 switch (event.type) { 265 case Expose: 266 Redraw(); 267 break; 268 case ConfigureNotify: 269 WinWidth = event.xconfigure.width; 270 WinHeight = event.xconfigure.height; 271 break; 272 case KeyPress: 273 { 274 char buf[100]; 275 KeySym keySym; 276 XComposeStatus stat; 277 XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); 278 switch (keySym) { 279 case XK_Escape: 280 exit(0); 281 break; 282 case XK_t: 283 case XK_T: 284 ModifyTexture(); 285 break; 286 default: 287 ; 288 } 289 } 290 Redraw(); 291 break; 292 default: 293 /*no-op*/ ; 294 } 295 } 296 297 Redraw(); 298 usleep(10000); 299 } 300} 301 302 303 304 305int 306main(int argc, char *argv[]) 307{ 308 int i; 309 310 for (i = 1; i < argc; i++) { 311 if (strcmp(argv[i], "-display") == 0 && i < argc) { 312 DisplayName = argv[i+1]; 313 i++; 314 } 315 } 316 317 Setup(); 318 319 printf("Press 't' to change texture image/colors\n"); 320 321 EventLoop(); 322 323 return 0; 324} 325