3 /*{{{void glXSwapBuffers(Display *dpy, GLXDrawable drawable)*/
5 void glXSwapBuffers(Display
*dpy
, GLXDrawable drawable
)
8 XWindowAttributes attrs
;
15 TRACE("dpy=0x%x:drawable=0x%x", dpy
, drawable
);
16 if (!glx_extension_enabled
) {
17 TRACE("glx extension not initialized");
21 d
= get_synced_drawable_noxlock(dpy
, drawable
, DO_COPY
);
23 LOG("ERROR:unable to get a synced drawable 0x%x from display %p", drawable
, dpy
);
26 memset(&info
, 0, sizeof(info
));
27 img
= XShmCreateImage(dpy
, d
->visual
, d
->depth
, ZPixmap
,
28 d
->shm
.m
, &info
, d
->width
, d
->height
);
30 LOG("ERROR:unable to get a xshm image from drawable 0x%x", drawable
);
33 TRACE("XShmCreateImage=%p", img
);
34 memset(&info
, 0, sizeof(info
));
35 info
.shmid
= d
->shm
.id
;
36 info
.shmaddr
= d
->shm
.m
;
38 r
= XShmAttach(dpy
, &info
);
40 LOG("ERROR:drawable=0x%x:unable to attach the xserver to the ipc shared memory segment id=%d", drawable
, d
->shm
.id
);
43 gc
= XDefaultGC(dpy
, d
->screen
);
44 r
= XShmPutImage(dpy
, drawable
, gc
, img
, 0, 0, 0, 0, d
->width
,
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
);
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 */
61 /*{{{*/GLXFBConfig
*glXChooseFBConfig(Display
*dpy
, int screen
, const int *attribList
, int *nitems
)
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");
79 /*{{{*/XVisualInfo
*glXGetVisualFromFBConfig(Display
*dpy
, GLXFBConfig config
)
84 TRACE("dpy=%p:config=%p", dpy
, config
);
85 if (!glx_extension_enabled
) {
86 TRACE("glx extension not initialized");
95 /*{{{*/Display
*glXGetCurrentDisplay(void)
98 struct thd_data_t
*self_data
;
102 if (!glx_extension_enabled
) {
103 TRACE("glx extension not initialized");
107 self_data
= self_data_get();
108 if (self_data
->ctx
== 0) {
109 TRACE("the calling thread has no current context");
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
;
119 /*{{{*/GLXDrawable
glXGetCurrentDrawable(void)
122 struct thd_data_t
*self_data
;
126 if (!glx_extension_enabled
) {
127 TRACE("glx extension not initialized");
131 self_data
= self_data_get();
132 if (self_data
->ctx
== 0) {
133 TRACE("the calling thread has no current context");
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
;
143 /*{{{*/GLXContext
glXGetCurrentContext(void)
146 struct thd_data_t
*self_data
;
150 if (!glx_extension_enabled
) {
151 TRACE("glx extension not initialized");
155 self_data
= self_data_get();
156 if (self_data
->ctx
== 0) {
157 TRACE("the calling thread has no current context");
161 TRACE("the calling thread has a current context %p", self_data
->ctx
);
162 r
= (GLXContext
)self_data
->ctx
;
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
174 XVisualInfo
*glXChooseVisual(Display
*dpy
, int screen
, int *attribList
)
177 Visual
*default_visual
;
178 VisualID default_visual_id
;
179 XVisualInfo
template;
183 TRACE("dpy=%p:screen=%d:attrib_list=%p", dpy
, screen
, attribList
);
184 if (!glx_extension_enabled
) {
185 TRACE("glx extension not initialized");
189 attribList_parse(attribList
);
191 default_visual
= XDefaultVisual(dpy
, screen
);
192 if (default_visual
== 0) {
193 LOG("ERROR:unable to get the default visual, continuing");
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 */
204 LOG("ERROR:unable to get the default visual info, continuing");
206 printf_visualinfo(__func__
, r
);
213 /*{{{*/GLXContext
glXCreateContext(Display
*dpy
, XVisualInfo
*vis
, GLXContext shareList
, Bool direct
)
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");
224 c
= calloc(1, sizeof(*c
));
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 */
240 return (GLXContext
)c
;
242 /*{{{*/Bool
glXQueryExtension(Display
*dpy
, int *errorb
, int *event
)
248 Bool shared_pixmap_supported
;
251 TRACE("dpy=%p:errorBase=%p:eventBase=%p", dpy
, errorb
, event
);
252 /* '0' should tell the client to avoid to use it */
256 *event
= 0; /* specs: unsused */
258 r1
= XShmQueryExtension(dpy
);
261 LOG("ERROR:unable to query the xserver MIT-SHM extension");
264 r1
= XShmQueryVersion(dpy
, &major
, &minor
, &shared_pixmap_supported
);
267 LOG("ERROR:xshm:unable to query shared pixmap support");
270 if (!shared_pixmap_supported
) {
272 LOG("ERROR:xshm:shared pixmap unsupported");
276 /* we are initialized from here */
277 glx_extension_enabled
= true;
278 LOG("MIT-SHM %d.%d extension enabled", major
, minor
);
284 /*{{{*/Bool
glXIsDirect(Display
*dpy
, GLXContext ctx
)
289 TRACE("dpy=%p:ctx=%p", dpy
, ctx
);
290 if (!glx_extension_enabled
) {
291 TRACE("glx extension not initialized");
304 /*{{{*/void (*glXGetProcAddress(const GLubyte
*procname
))(void)
309 TRACE("procName=%s", procname
);
310 if (!glx_extension_enabled
) {
311 TRACE("glx extension not initialized");
320 /*{{{*/void glXDestroyContext(Display
*dpy
, GLXContext ctx
)
325 TRACE("dpy=%p:ctx=%p", dpy
, ctx
);
326 if (!glx_extension_enabled
) {
327 TRACE("glx extension not initialized");
330 c
= (struct ctx_t
*)ctx
;
331 if (!c
->current
.attached
) {
332 TRACE("freeing context");
333 ctx_free(dpy
, (struct ctx_t
*)ctx
);
336 TRACE("tagging context as \"destroyed\"");
341 /*{{{*/Bool
glXMakeCurrent(Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
343 struct ctx_t
*new_ctx
;
345 struct thd_data_t
*self_data
;
346 struct ctx_t
*prev_ctx
;
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");
356 self_data
= self_data_get();
358 prev_ctx
= self_data
->ctx
;
361 if (drawable
== None
) {
363 TRACE("invalid:None drawable with non zero context");
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
);
373 prev_ctx
->drawable
= None
;
378 /* drawable != None */
380 LOG("ERROR:context is 0 from a not-None drawable");
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
);
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
);
399 /* drawable != None && new_ctx != 0 && new_ctx != prev_ctx */
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
);
408 prev_ctx
->drawable
= None
;
410 /* drawable != None && new_ctx != 0 && prev_ctx == 0 */
411 self_attach_ctx(dpy
, new_ctx
);
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
);
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;
427 /*{{{*/Bool
glXMakeContextCurrent(Display
*dpy
, GLXDrawable drawable
, GLXDrawable read
, GLXContext ctx
)
429 /* deny this code path for now */