overkill 32 bits avx2 assembly code
[mini2dgl.git] / glx.c
blob3b99c505932ae2896612e38edf41fa3e6d7218f8
1 #ifndef GLX_C
2 #define GLX_C
3 /*{{{void glXSwapBuffers(Display *dpy, GLXDrawable drawable)*/
4 #define DO_COPY false
5 void glXSwapBuffers(Display *dpy, GLXDrawable drawable)
7 struct drawable_t *d;
8 XWindowAttributes attrs;
9 XShmSegmentInfo info;
10 XImage *img;
11 Bool r;
12 GC gc;
14 ONCE_AND_ENTER;
15 TRACE("dpy=0x%x:drawable=0x%x", dpy, drawable);
16 if (!glx_extension_enabled) {
17 TRACE("glx extension not initialized");
18 goto leave;
20 XLockDisplay(dpy);
21 d = get_synced_drawable_noxlock(dpy, drawable, DO_COPY);
22 if (d == 0) {
23 LOG("ERROR:unable to get a synced drawable 0x%x from display %p", drawable, dpy);
24 goto unlock_x;
26 memset(&info, 0, sizeof(info));
27 img = XShmCreateImage(dpy, d->visual, d->depth, ZPixmap,
28 d->shm.m, &info, d->width, d->height);
29 if (img == 0) {
30 LOG("ERROR:unable to get a xshm image from drawable 0x%x", drawable);
31 goto unlock_x;
33 TRACE("XShmCreateImage=%p", img);
34 memset(&info, 0, sizeof(info));
35 info.shmid = d->shm.id;
36 info.shmaddr = d->shm.m;
37 info.readOnly = 0;
38 r = XShmAttach(dpy, &info);
39 if (!r) {
40 LOG("ERROR:drawable=0x%x:unable to attach the xserver to the ipc shared memory segment id=%d", drawable, d->shm.id);
41 goto destroy_img;
43 gc = XDefaultGC(dpy, d->screen);
44 r = XShmPutImage(dpy, drawable, gc, img, 0, 0, 0, 0, d->width,
45 d->height, False);
46 if (!r)
47 LOG("ERROR:drawable=0x%x:unable to put the ximage from the ipc shared memory segment id=%d", drawable, d->shm.id);
48 r = XShmDetach(dpy, &info);
49 if (!r)
50 LOG("ERROR:drawable=0x%x:unable to detach the ximage from the ipc shared memory segment id=%d", drawable, d->shm.id);
51 /* our "back buffer" is now undefined */
52 destroy_img:
53 XDestroyImage(img);
54 unlock_x:
55 XUnlockDisplay(dpy);
56 leave:
57 LEAVE;
59 #undef DO_COPY
60 /*}}}*/
61 /*{{{*/GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems)
63 void *r;
65 ONCE_AND_ENTER;
66 TRACE("dpy=%p:screen=%d:attrib_list=%p:nelement=%p", dpy, screen, attribList, nitems);
67 if (!glx_extension_enabled) {
68 TRACE("glx extension not initialized");
69 r = 0;
70 goto leave;
72 if (nitems != 0)
73 *nitems = 0;
74 r = 0;
75 leave:
76 LEAVE;
77 return r;
78 }/*}}}*/
79 /*{{{*/XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config)
81 void *r;
83 ONCE_AND_ENTER;
84 TRACE("dpy=%p:config=%p", dpy, config);
85 if (!glx_extension_enabled) {
86 TRACE("glx extension not initialized");
87 r = 0;
88 goto leave;
90 r = 0;
91 leave:
92 LEAVE;
93 return 0;
94 }/*}}}*/
95 /*{{{*/Display *glXGetCurrentDisplay(void)
97 Display * r;
98 struct thd_data_t *self_data;
100 ONCE_AND_ENTER;
101 TRACE("void");
102 if (!glx_extension_enabled) {
103 TRACE("glx extension not initialized");
104 r = 0;
105 goto leave;
107 self_data = self_data_get();
108 if (self_data->ctx == 0) {
109 TRACE("the calling thread has no current context");
110 r = 0;
111 goto leave;
113 TRACE("the current thread has a current context, returning its dpy %p", self_data->ctx->current.dpy);
114 r = self_data->ctx->current.dpy;
115 leave:
116 LEAVE;
117 return r;
118 }/*}}}*/
119 /*{{{*/GLXDrawable glXGetCurrentDrawable(void)
121 int r;
122 struct thd_data_t *self_data;
124 ONCE_AND_ENTER;
125 TRACE("void");
126 if (!glx_extension_enabled) {
127 TRACE("glx extension not initialized");
128 r = None;
129 goto leave;
131 self_data = self_data_get();
132 if (self_data->ctx == 0) {
133 TRACE("the calling thread has no current context");
134 r = None;
135 goto leave;
137 TRACE("the current thread has a current context %p, returning its drawable 0x%x", self_data->ctx, self_data->ctx->drawable);
138 r = self_data->ctx->drawable;
139 leave:
140 LEAVE;
141 return r;
142 }/*}}}*/
143 /*{{{*/GLXContext glXGetCurrentContext(void)
145 GLXContext r;
146 struct thd_data_t *self_data;
148 ONCE_AND_ENTER;
149 TRACE("void");
150 if (!glx_extension_enabled) {
151 TRACE("glx extension not initialized");
152 r = 0;
153 goto leave;
155 self_data = self_data_get();
156 if (self_data->ctx == 0) {
157 TRACE("the calling thread has no current context");
158 r = 0;
159 goto leave;
161 TRACE("the calling thread has a current context %p", self_data->ctx);
162 r = (GLXContext)self_data->ctx;
163 leave:
164 LEAVE;
165 return r;
166 }/*}}}*/
167 /*{{{ XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList) */
169 * We don't validate the default visual against the client attribList,
170 * because the steam client have very reasonable demands.
171 * That said, if the screen default visual in not BGRA, we don't know how to
172 * draw anything.
174 XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *attribList)
176 XVisualInfo *r;
177 Visual *default_visual;
178 VisualID default_visual_id;
179 XVisualInfo template;
180 int n;
182 ONCE_AND_ENTER;
183 TRACE("dpy=%p:screen=%d:attrib_list=%p", dpy, screen, attribList);
184 if (!glx_extension_enabled) {
185 TRACE("glx extension not initialized");
186 r = 0;
187 goto leave;
189 attribList_parse(attribList);
190 XLockDisplay(dpy);
191 default_visual = XDefaultVisual(dpy, screen);
192 if (default_visual == 0) {
193 LOG("ERROR:unable to get the default visual, continuing");
194 r = 0;
195 goto x_unlock;
197 default_visual_id = XVisualIDFromVisual(default_visual);
198 TRACE("default visual id=%d", default_visual_id);
199 memset(&template, 0, sizeof(template));
200 template.visualid = default_visual_id;
201 r = XGetVisualInfo(dpy, VisualIDMask, &template, &n);
202 /* should have only 1 visual */
203 if (r == 0)
204 LOG("ERROR:unable to get the default visual info, continuing");
205 else
206 printf_visualinfo(__func__, r);
207 x_unlock:
208 XUnlockDisplay(dpy);
209 leave:
210 LEAVE;
211 return r;
212 }/*}}}*/
213 /*{{{*/GLXContext glXCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct)
215 struct ctx_t *c;
217 ONCE_AND_ENTER;
218 TRACE("dpy=%p:visi=%p:shareList=%p:direct=%d", dpy, vis, shareList, direct);
219 if (!glx_extension_enabled) {
220 TRACE("glx extension not initialized");
221 c = 0;
222 goto leave;
224 c = calloc(1, sizeof(*c));
225 c->create.dpy = dpy;
226 memcpy(&c->create.visinf, vis, sizeof(*vis));
227 TRACE("created context is %p with the following visual:", c);
228 printf_visualinfo(__func__, vis);
230 /* non zero defaults */
231 c->color.red = 1.;
232 c->color.green = 1.;
233 c->color.blue = 1.;
234 c->color.alpha = 1.;
236 c->drawable = None;
237 c->read = None;
238 leave:
239 LEAVE;
240 return (GLXContext)c;
241 }/*}}}*/
242 /*{{{*/Bool glXQueryExtension(Display *dpy, int *errorb, int *event)
244 Bool r0;
245 Bool r1;
246 int major;
247 int minor;
248 Bool shared_pixmap_supported;
250 ONCE_AND_ENTER;
251 TRACE("dpy=%p:errorBase=%p:eventBase=%p", dpy, errorb, event);
252 /* '0' should tell the client to avoid to use it */
253 if (errorb != 0)
254 *errorb = 0;
255 if (event != 0)
256 *event = 0; /* specs: unsused */
257 XLockDisplay(dpy);
258 r1 = XShmQueryExtension(dpy);
259 if (!r1) {
260 r0 = False;
261 LOG("ERROR:unable to query the xserver MIT-SHM extension");
262 goto leave;
264 r1 = XShmQueryVersion(dpy, &major, &minor, &shared_pixmap_supported);
265 if (!r1) {
266 r0 = False;
267 LOG("ERROR:xshm:unable to query shared pixmap support");
268 goto leave;
270 if (!shared_pixmap_supported) {
271 r0 = False;
272 LOG("ERROR:xshm:shared pixmap unsupported");
273 goto leave;
275 r0 = True;
276 /* we are initialized from here */
277 glx_extension_enabled = true;
278 LOG("MIT-SHM %d.%d extension enabled", major, minor);
279 leave:
280 XUnlockDisplay(dpy);
281 LEAVE;
282 return r0;
283 }/*}}}*/
284 /*{{{*/Bool glXIsDirect(Display *dpy, GLXContext ctx)
286 Bool r;
288 ONCE_AND_ENTER;
289 TRACE("dpy=%p:ctx=%p", dpy, ctx);
290 if (!glx_extension_enabled) {
291 TRACE("glx extension not initialized");
292 r = False;
293 goto leave;
295 if (ctx == 0) {
296 r = False;
297 goto leave;
299 r = True;
300 leave:
301 LEAVE;
302 return r;
303 }/*}}}*/
304 /*{{{*/void (*glXGetProcAddress(const GLubyte *procname))(void)
306 void (*r)(void);
308 ONCE_AND_ENTER;
309 TRACE("procName=%s", procname);
310 if (!glx_extension_enabled) {
311 TRACE("glx extension not initialized");
312 r = 0;
313 goto leave;
315 r = 0;
316 leave:
317 LEAVE;
318 return r;
319 }/*}}}*/
320 /*{{{*/void glXDestroyContext(Display *dpy, GLXContext ctx)
322 struct ctx_t *c;
324 ONCE_AND_ENTER;
325 TRACE("dpy=%p:ctx=%p", dpy, ctx);
326 if (!glx_extension_enabled) {
327 TRACE("glx extension not initialized");
328 goto leave;
330 c = (struct ctx_t *)ctx;
331 if (!c->current.attached) {
332 TRACE("freeing context");
333 ctx_free(dpy, (struct ctx_t*)ctx);
334 goto leave;
336 TRACE("tagging context as \"destroyed\"");
337 c->destroyed = true;
338 leave:
339 LEAVE;
340 }/*}}}*/
341 /*{{{*/Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx)
343 struct ctx_t *new_ctx;
344 Bool r;
345 struct thd_data_t *self_data;
346 struct ctx_t *prev_ctx;
348 ONCE_AND_ENTER;
349 new_ctx = (struct ctx_t*)ctx;
350 TRACE("dpy=%p:drawable=0x%x:ctx=%p", dpy, drawable, ctx);
351 if (!glx_extension_enabled) {
352 TRACE("glx extension not initialized");
353 r = False;
354 goto leave;
356 self_data = self_data_get();
357 if (self_data != 0)
358 prev_ctx = self_data->ctx;
359 else
360 prev_ctx = 0;
361 if (drawable == None) {
362 if (new_ctx != 0) {
363 TRACE("invalid:None drawable with non zero context");
364 r = False;
365 goto leave;
366 } else { /* new_ctx == 0 */
367 self_detach_ctx_with(dpy, self_data);
368 /* XXX: flush/finish draw here */
369 if (prev_ctx->destroyed) {
370 TRACE("previous context %p, which we did detach, is tagged destroyed and is current to no thread, freeing", prev_ctx);
371 ctx_free(dpy, prev_ctx);
372 } else
373 prev_ctx->drawable = None;
374 r = True;
375 goto leave;
378 /* drawable != None */
379 if (new_ctx == 0) {
380 LOG("ERROR:context is 0 from a not-None drawable");
381 r = False;
382 goto leave;
384 /* drawable != None && new_ctx != 0 */
385 if (new_ctx->destroyed) {
386 TRACE("new context %p is tagged destroyed then it cannot becomme current to the self thread", new_ctx);
387 r = False;
388 goto leave;
390 if (new_ctx == prev_ctx) { /* only force update the drawable */
391 TRACE("context %p is already current to self thread, only updating drawable to 0x%x", new_ctx, drawable);
392 goto update_drawable;
394 if (new_ctx->current.attached) {
395 TRACE("new context %p is already current to thread 0x%x", new_ctx, new_ctx->current.thd);
396 r = False;
397 goto leave;
399 /* drawable != None && new_ctx != 0 && new_ctx != prev_ctx */
400 if (prev_ctx != 0) {
401 TRACE("previous context %p", prev_ctx);
402 self_detach_ctx_with(dpy, self_data);
403 /* XXX: flush/finish draw here */
404 if (prev_ctx->destroyed) {
405 TRACE("previous context %p, which we did detach, is tagged destroyed and is current to no thread, freeing", prev_ctx);
406 ctx_free(dpy, prev_ctx);
407 } else
408 prev_ctx->drawable = None;
410 /* drawable != None && new_ctx != 0 && prev_ctx == 0 */
411 self_attach_ctx(dpy, new_ctx);
412 update_drawable:
413 new_ctx->drawable = drawable;
414 TRACE("current context %p was replaced by context %p with drawable 0x%u", prev_ctx, new_ctx, new_ctx->drawable);
415 r = True;
416 leave:
417 if (r == True && new_ctx != 0) {/* for setting the viewport the first time */
418 if (!new_ctx->was_already_made_current) {
419 TRACE("%p:first time ever attached to a thread:setting the viewport to drawable full size");
420 ctx_viewport_set_to_drawable_sz(dpy, new_ctx);
421 new_ctx->was_already_made_current = true;
424 LEAVE;
425 return r;
426 }/*}}}*/
427 /*{{{*/Bool glXMakeContextCurrent(Display *dpy, GLXDrawable drawable, GLXDrawable read, GLXContext ctx)
429 /* deny this code path for now */
430 return False;
431 }/*}}}*/
432 #endif