Merge branch 'gallium-0.1' into gallium-tex-surfaces
[mesa.git] / progs / tests / jkrahntest.c
1 /* $Id: jkrahntest.c,v 1.2 2006/01/30 17:12:10 brianp Exp $ */
2
3 /* This is a good test for glXSwapBuffers on non-current windows,
4 * and the glXCopyContext function. Fixed several Mesa/DRI bugs with
5 * this program on 15 June 2002.
6 *
7 * Joe's comments follow:
8 *
9 * I have tried some different approaches for being able to
10 * draw to multiple windows using one context, or a copied
11 * context. Mesa/indirect rendering works to use one context
12 * for multiple windows, but crashes with glXCopyContext.
13 * DRI is badly broken, at least for ATI.
14 *
15 * I also noticed that glXMakeCurrent allows a window and context
16 * from different visuals to be attached (haven't tested recently).
17 *
18 * Joe Krahn <jkrahn@nc.rr.com>
19 */
20
21 #include <GL/glx.h>
22 #include <GL/gl.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <math.h>
28
29 #ifndef M_PI
30 #define M_PI 3.14159
31 #endif
32
33 #define DEGTOR (M_PI/180.0)
34
35 static int AttributeList[] = { GLX_RGBA, GLX_DOUBLEBUFFER, None };
36
37 int main(int argc, char **argv)
38 {
39 Window win1, win2;
40 XVisualInfo *vi;
41 XSetWindowAttributes swa;
42 Display *dpy;
43 GLXContext ctx1, ctx2;
44 float angle;
45 int test;
46
47 if (argc < 2) {
48 fprintf(stderr, "This program tests GLX context switching.\n");
49 fprintf(stderr, "Usage: cxbug <n>\n");
50 fprintf(stderr, "Where n is:\n");
51 fprintf(stderr, "\t1) Use two contexts and swap only when the context is current (typical case).\n");
52 fprintf(stderr, "\t2) Use two contexts and swap at the same time.\n");
53 fprintf(stderr, "\t\t Used to crash Mesa & nVidia, and DRI artifacts. Seems OK now.\n");
54 fprintf(stderr, "\t3) Use one context, but only swap when a context is current.\n");
55 fprintf(stderr, "\t\t Serious artifacts for DRI at least with ATI.\n");
56 fprintf(stderr, "\t4) Use one context, swap both windows at the same time, so the left\n");
57 fprintf(stderr, "\t\t window has no context at swap time. Severe artifacts for DRI.\n");
58 fprintf(stderr, "\t5) Use two contexts, copying one to the other when switching windows.\n");
59 fprintf(stderr, "\t\t DRI gives an error, indirect rendering crashes server.\n");
60
61 exit(1);
62 }
63 test = atoi(argv[1]);
64
65 /* get a connection */
66 dpy = XOpenDisplay(NULL);
67
68 /* Get an appropriate visual */
69 vi = glXChooseVisual(dpy, DefaultScreen(dpy), AttributeList);
70 if (vi == 0) {
71 fprintf(stderr, "No matching visuals found.\n");
72 exit(-1);
73 }
74
75 /* Create two GLX contexts, with list sharing */
76 ctx1 = glXCreateContext(dpy, vi, 0, True);
77 ctx2 = glXCreateContext(dpy, vi, ctx1, True);
78
79 /* create a colormap */
80 swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
81 vi->visual, AllocNone);
82 swa.border_pixel = 0;
83
84 /* Create two windows */
85 win1 = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
86 10, 10, 200, 200,
87 0, vi->depth, InputOutput, vi->visual,
88 CWBorderPixel | CWColormap, &swa);
89 XStoreName(dpy, win1, "Test [L]");
90 XMapWindow(dpy, win1);
91 XMoveWindow(dpy, win1, 10, 10); /* Initial requested x,y may not be honored */
92 {
93 XSizeHints sizehints;
94 static const char *name = "window";
95 sizehints.x = 10;
96 sizehints.y = 10;
97 sizehints.width = 200;
98 sizehints.height = 200;
99 sizehints.flags = USSize | USPosition;
100 XSetNormalHints(dpy, win1, &sizehints);
101 XSetStandardProperties(dpy, win1, name, name,
102 None, (char **)NULL, 0, &sizehints);
103 }
104
105
106 win2 = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
107 250, 10, 200, 200,
108 0, vi->depth, InputOutput, vi->visual,
109 CWBorderPixel | CWColormap, &swa);
110 XStoreName(dpy, win1, "Test [R]");
111 XMapWindow(dpy, win2);
112 XMoveWindow(dpy, win2, 260, 10);
113 {
114 XSizeHints sizehints;
115 static const char *name = "window";
116 sizehints.x = 10;
117 sizehints.y = 10;
118 sizehints.width = 200;
119 sizehints.height = 200;
120 sizehints.flags = USSize | USPosition;
121 XSetNormalHints(dpy, win2, &sizehints);
122 XSetStandardProperties(dpy, win2, name, name,
123 None, (char **)NULL, 0, &sizehints);
124 }
125
126
127 /* Now draw some spinning things */
128 for (angle = 0; angle < 360*4; angle += 10.0) {
129 /* Connect the context to window 1 */
130 glXMakeCurrent(dpy, win1, ctx1);
131
132 /* Clear and draw in window 1 */
133 glDrawBuffer(GL_BACK);
134 glClearColor(1, 1, 0, 1);
135 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
136 glColor3f(1, 0, 0);
137 glBegin(GL_TRIANGLES);
138 glVertex2f(0, 0);
139 glVertex2f(cos(angle * DEGTOR), sin(angle * DEGTOR));
140 glVertex2f(cos((angle + 20.0) * DEGTOR),
141 sin((angle + 20.0) * DEGTOR));
142 glEnd();
143 glFlush();
144
145 if (test == 1 || test == 3 || test == 5)
146 glXSwapBuffers(dpy, win1);
147
148 if (test == 5)
149 glXCopyContext(dpy, ctx1, ctx2, GL_ALL_ATTRIB_BITS);
150 /* Connect the context to window 2 */
151 if (test == 3 || test == 4) {
152 glXMakeCurrent(dpy, win2, ctx1);
153 } else {
154 glXMakeCurrent(dpy, win2, ctx2);
155 }
156
157 /* Clear and draw in window 2 */
158 glDrawBuffer(GL_BACK);
159 glClearColor(0, 0, 1, 1);
160 glClear(GL_COLOR_BUFFER_BIT);
161 glColor3f(1, 1, 0);
162 glBegin(GL_TRIANGLES);
163 glVertex2f(0, 0);
164 glVertex2f(cos(angle * DEGTOR), sin(angle * DEGTOR));
165 glVertex2f(cos((angle + 20.0) * DEGTOR),
166 sin((angle + 20.0) * DEGTOR));
167 glEnd();
168 glFlush();
169
170 /* Swap buffers */
171 if (test == 2 || test == 4)
172 glXSwapBuffers(dpy, win1);
173 glXSwapBuffers(dpy, win2);
174
175 /* wait a while */
176 glXWaitX();
177 usleep(20000);
178 }
179
180 return 0;
181 }