st/xorg: Work around cursor reference counting bugs in older X servers.
[mesa.git] / progs / tests / texobjshare.c
1 /*
2 * Create several OpenGL rendering contexts, sharing textures, display
3 * lists, etc. Exercise binding, deleting, etc.
4 *
5 * Brian Paul
6 * 21 December 2004
7 */
8
9
10 #include <GL/gl.h>
11 #include <GL/glx.h>
12 #include <assert.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <X11/keysym.h>
18
19
20 /*
21 * Each display/window/context:
22 */
23 struct context {
24 char DisplayName[1000];
25 Display *Dpy;
26 Window Win;
27 GLXContext Context;
28 };
29
30
31 #define MAX_CONTEXTS 200
32 static struct context Contexts[MAX_CONTEXTS];
33 static int NumContexts = 0;
34
35
36 static void
37 Error(const char *display, const char *msg)
38 {
39 fprintf(stderr, "Error on display %s - %s\n", display, msg);
40 exit(1);
41 }
42
43
44 static struct context *
45 CreateContext(const char *displayName, const char *name)
46 {
47 Display *dpy;
48 Window win;
49 GLXContext ctx;
50 int attrib[] = { GLX_RGBA,
51 GLX_RED_SIZE, 1,
52 GLX_GREEN_SIZE, 1,
53 GLX_BLUE_SIZE, 1,
54 GLX_DOUBLEBUFFER,
55 None };
56 int scrnum;
57 XSetWindowAttributes attr;
58 unsigned long mask;
59 Window root;
60 XVisualInfo *visinfo;
61 int width = 90, height = 90;
62 int xpos = 0, ypos = 0;
63
64 if (NumContexts >= MAX_CONTEXTS)
65 return NULL;
66
67 dpy = XOpenDisplay(displayName);
68 if (!dpy) {
69 Error(displayName, "Unable to open display");
70 return NULL;
71 }
72
73 scrnum = DefaultScreen(dpy);
74 root = RootWindow(dpy, scrnum);
75
76 visinfo = glXChooseVisual(dpy, scrnum, attrib);
77 if (!visinfo) {
78 Error(displayName, "Unable to find RGB, double-buffered visual");
79 return NULL;
80 }
81
82 /* window attributes */
83 xpos = (NumContexts % 10) * 100;
84 ypos = (NumContexts / 10) * 100;
85 attr.background_pixel = 0;
86 attr.border_pixel = 0;
87 attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
88 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
89 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
90
91 win = XCreateWindow(dpy, root, xpos, ypos, width, height,
92 0, visinfo->depth, InputOutput,
93 visinfo->visual, mask, &attr);
94 if (!win) {
95 Error(displayName, "Couldn't create window");
96 return NULL;
97 }
98
99 {
100 XSizeHints sizehints;
101 sizehints.x = xpos;
102 sizehints.y = ypos;
103 sizehints.width = width;
104 sizehints.height = height;
105 sizehints.flags = USSize | USPosition;
106 XSetNormalHints(dpy, win, &sizehints);
107 XSetStandardProperties(dpy, win, name, name,
108 None, (char **)NULL, 0, &sizehints);
109 }
110
111 if (NumContexts == 0) {
112 ctx = glXCreateContext(dpy, visinfo, NULL, True);
113 }
114 else {
115 /* share textures & dlists with 0th context */
116 ctx = glXCreateContext(dpy, visinfo, Contexts[0].Context, True);
117 }
118 if (!ctx) {
119 Error(displayName, "Couldn't create GLX context");
120 return NULL;
121 }
122
123 XMapWindow(dpy, win);
124
125 if (!glXMakeCurrent(dpy, win, ctx)) {
126 Error(displayName, "glXMakeCurrent failed");
127 return NULL;
128 }
129
130 if (NumContexts == 0) {
131 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
132 }
133
134 /* save the info for this context */
135 {
136 struct context *h = &Contexts[NumContexts];
137 strcpy(h->DisplayName, name);
138 h->Dpy = dpy;
139 h->Win = win;
140 h->Context = ctx;
141 NumContexts++;
142 return &Contexts[NumContexts-1];
143 }
144 }
145
146
147 static void
148 MakeCurrent(int i)
149 {
150 if (!glXMakeCurrent(Contexts[i].Dpy, Contexts[i].Win, Contexts[i].Context)) {
151 fprintf(stderr, "glXMakeCurrent failed!\n");
152 }
153 }
154
155
156
157 static void
158 DestroyContext(int i)
159 {
160 XDestroyWindow(Contexts[i].Dpy, Contexts[i].Win);
161 glXDestroyContext(Contexts[i].Dpy, Contexts[i].Context);
162 XCloseDisplay(Contexts[i].Dpy);
163 }
164
165
166 int
167 main(int argc, char *argv[])
168 {
169 char *dpyName = NULL;
170 int i;
171 GLuint t;
172 GLint tb;
173
174 for (i = 0; i < 2; i++) {
175 CreateContext(dpyName, "context");
176 }
177
178 /* Create texture and bind it in context 0 */
179 MakeCurrent(0);
180 glGenTextures(1, &t);
181 printf("Generated texture ID %u\n", t);
182 assert(!glIsTexture(t));
183 glBindTexture(GL_TEXTURE_2D, t);
184 assert(glIsTexture(t));
185 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb);
186 assert(tb == t);
187
188 /* Bind texture in context 1 */
189 MakeCurrent(1);
190 assert(glIsTexture(t));
191 glBindTexture(GL_TEXTURE_2D, t);
192 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb);
193 assert(tb == t);
194
195 /* Delete texture from context 0 */
196 MakeCurrent(0);
197 glDeleteTextures(1, &t);
198 assert(!glIsTexture(t));
199 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb);
200 printf("After delete, binding = %d\n", tb);
201
202 /* Check texture state from context 1 */
203 MakeCurrent(1);
204 assert(!glIsTexture(t));
205 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb);
206 printf("In second context, binding = %d\n", tb);
207 glBindTexture(GL_TEXTURE_2D, 0);
208 glGetIntegerv(GL_TEXTURE_BINDING_2D, &tb);
209 assert(tb == 0);
210
211
212 for (i = 0; i < NumContexts; i++) {
213 DestroyContext(i);
214 }
215
216 printf("Success!\n");
217
218 return 0;
219 }