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