Merge branch '7.8'
[mesa.git] / progs / xdemos / sharedtex.c
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
58 Error(const char *msg)
59 {
60 fprintf(stderr, "sharedtex error: %s\n", msg);
61 exit(1);
62 }
63
64
65 static void
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
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
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
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
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
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 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
305 int
306 main(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 }