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 
44 static const char *DisplayName = NULL;
45 static Display *Dpy;
46 static XVisualInfo *VisInfo;
47 static Window Win;
48 static GLXContext Contexts[MAX_CONTEXTS];
49 static int WinWidth = 300, WinHeight = 300;
50 
51 static int DrawContext = 0, TexContext = 1;
52 
53 static GLuint TexObj = 0;
54 static GLboolean NewTexture = GL_FALSE;
55 
56 
57 static void
Error(const char * msg)58 Error(const char *msg)
59 {
60    fprintf(stderr, "sharedtex error: %s\n", msg);
61    exit(1);
62 }
63 
64 
65 static void
CreateWindow(const char * name)66 CreateWindow(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  */
126 static void
ModifyTexture(void)127 ModifyTexture(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 
160 static void
InitContext(void)161 InitContext(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 
174 static void
Setup(void)175 Setup(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  */
208 static void
Redraw(void)209 Redraw(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 
256 static void
EventLoop(void)257 EventLoop(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                case XK_t:
282                case XK_T:
283                   ModifyTexture();
284                   break;
285                default:
286                   ;
287                }
288             }
289             Redraw();
290             break;
291          default:
292             /*no-op*/ ;
293          }
294       }
295 
296       Redraw();
297       usleep(10000);
298    }
299 }
300 
301 
302 
303 
304 int
main(int argc,char * argv[])305 main(int argc, char *argv[])
306 {
307    int i;
308 
309    for (i = 1; i < argc; i++) {
310       if (strcmp(argv[i], "-display") == 0 && i < argc) {
311          DisplayName = argv[i+1];
312          i++;
313       }
314    }
315 
316    Setup();
317 
318    printf("Press 't' to change texture image/colors\n");
319 
320    EventLoop();
321 
322    return 0;
323 }
324