2 * Copyright © 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Soft-
6 * ware"), to deal in the Software without restriction, including without
7 * limitation the rights to use, copy, modify, merge, publish, distribute,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, provided that the above copyright
10 * notice(s) and this permission notice appear in all copies of the Soft-
11 * ware and that both the above copyright notice(s) and this permission
12 * notice appear in supporting documentation.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22 * MANCE OF THIS SOFTWARE.
24 * Except as contained in this notice, the name of a copyright holder shall
25 * not be used in advertising or otherwise to promote the sale, use or
26 * other dealings in this Software without prior written authorization of
27 * the copyright holder.
30 * Kristian Høgsberg (krh@bitplanet.net)
34 #include "glxclient.h"
36 #ifndef GLX_USE_APPLEGL
38 extern struct _glapi_table
*__glXNewIndirectAPI(void);
41 ** All indirect rendering contexts will share the same indirect dispatch table.
43 static struct _glapi_table
*IndirectAPI
= NULL
;
46 indirect_destroy_context(struct glx_context
*gc
)
48 __glXFreeVertexArrayState(gc
);
50 free((char *) gc
->vendor
);
51 free((char *) gc
->renderer
);
52 free((char *) gc
->version
);
53 free((char *) gc
->extensions
);
54 __glFreeAttributeState(gc
);
55 free((char *) gc
->buf
);
56 free((char *) gc
->client_state_private
);
61 SendMakeCurrentRequest(Display
* dpy
, CARD8 opcode
,
62 GLXContextID gc_id
, GLXContextTag gc_tag
,
63 GLXDrawable draw
, GLXDrawable read
,
64 GLXContextTag
*out_tag
)
66 xGLXMakeCurrentReply reply
;
72 xGLXMakeCurrentReq
*req
;
74 GetReq(GLXMakeCurrent
, req
);
75 req
->reqType
= opcode
;
76 req
->glxCode
= X_GLXMakeCurrent
;
79 req
->oldContextTag
= gc_tag
;
82 struct glx_display
*priv
= __glXInitialize(dpy
);
84 /* If the server can support the GLX 1.3 version, we should
85 * perfer that. Not only that, some servers support GLX 1.3 but
86 * not the SGI extension.
89 if ((priv
->majorVersion
> 1) || (priv
->minorVersion
>= 3)) {
90 xGLXMakeContextCurrentReq
*req
;
92 GetReq(GLXMakeContextCurrent
, req
);
93 req
->reqType
= opcode
;
94 req
->glxCode
= X_GLXMakeContextCurrent
;
96 req
->readdrawable
= read
;
98 req
->oldContextTag
= gc_tag
;
101 xGLXVendorPrivateWithReplyReq
*vpreq
;
102 xGLXMakeCurrentReadSGIReq
*req
;
104 GetReqExtra(GLXVendorPrivateWithReply
,
105 sz_xGLXMakeCurrentReadSGIReq
-
106 sz_xGLXVendorPrivateWithReplyReq
, vpreq
);
107 req
= (xGLXMakeCurrentReadSGIReq
*) vpreq
;
108 req
->reqType
= opcode
;
109 req
->glxCode
= X_GLXVendorPrivateWithReply
;
110 req
->vendorCode
= X_GLXvop_MakeCurrentReadSGI
;
111 req
->drawable
= draw
;
112 req
->readable
= read
;
113 req
->context
= gc_id
;
114 req
->oldContextTag
= gc_tag
;
118 ret
= _XReply(dpy
, (xReply
*) &reply
, 0, False
);
121 *out_tag
= reply
.contextTag
;
130 indirect_bind_context(struct glx_context
*gc
, struct glx_context
*old
,
131 GLXDrawable draw
, GLXDrawable read
)
134 __GLXattribute
*state
;
135 Display
*dpy
= gc
->psc
->dpy
;
136 int opcode
= __glXSetupForCommand(dpy
);
139 if (old
!= &dummyContext
&& !old
->isDirect
&& old
->psc
->dpy
== dpy
) {
140 tag
= old
->currentContextTag
;
141 old
->currentContextTag
= 0;
146 sent
= SendMakeCurrentRequest(dpy
, opcode
, gc
->xid
, tag
, draw
, read
,
147 &gc
->currentContextTag
);
150 IndirectAPI
= __glXNewIndirectAPI();
151 _glapi_set_dispatch(IndirectAPI
);
153 state
= gc
->client_state_private
;
154 if (state
->array_state
== NULL
) {
155 glGetString(GL_EXTENSIONS
);
156 glGetString(GL_VERSION
);
157 __glXInitVertexArrayState(gc
);
164 indirect_unbind_context(struct glx_context
*gc
, struct glx_context
*new)
166 Display
*dpy
= gc
->psc
->dpy
;
167 int opcode
= __glXSetupForCommand(dpy
);
172 /* We are either switching to no context, away from a indirect
173 * context to a direct context or from one dpy to another and have
174 * to send a request to the dpy to unbind the previous context.
176 if (!new || new->isDirect
|| new->psc
->dpy
!= dpy
) {
177 SendMakeCurrentRequest(dpy
, opcode
, None
,
178 gc
->currentContextTag
, None
, None
, NULL
);
179 gc
->currentContextTag
= 0;
184 indirect_wait_gl(struct glx_context
*gc
)
187 Display
*dpy
= gc
->currentDpy
;
189 /* Flush any pending commands out */
190 __glXFlushRenderBuffer(gc
, gc
->pc
);
192 /* Send the glXWaitGL request */
194 GetReq(GLXWaitGL
, req
);
195 req
->reqType
= gc
->majorOpcode
;
196 req
->glxCode
= X_GLXWaitGL
;
197 req
->contextTag
= gc
->currentContextTag
;
203 indirect_wait_x(struct glx_context
*gc
)
206 Display
*dpy
= gc
->currentDpy
;
208 /* Flush any pending commands out */
209 __glXFlushRenderBuffer(gc
, gc
->pc
);
212 GetReq(GLXWaitX
, req
);
213 req
->reqType
= gc
->majorOpcode
;
214 req
->glxCode
= X_GLXWaitX
;
215 req
->contextTag
= gc
->currentContextTag
;
221 indirect_use_x_font(struct glx_context
*gc
,
222 Font font
, int first
, int count
, int listBase
)
224 xGLXUseXFontReq
*req
;
225 Display
*dpy
= gc
->currentDpy
;
227 /* Flush any pending commands out */
228 __glXFlushRenderBuffer(gc
, gc
->pc
);
230 /* Send the glXUseFont request */
232 GetReq(GLXUseXFont
, req
);
233 req
->reqType
= gc
->majorOpcode
;
234 req
->glxCode
= X_GLXUseXFont
;
235 req
->contextTag
= gc
->currentContextTag
;
239 req
->listBase
= listBase
;
245 indirect_bind_tex_image(Display
* dpy
,
246 GLXDrawable drawable
,
247 int buffer
, const int *attrib_list
)
249 xGLXVendorPrivateReq
*req
;
250 struct glx_context
*gc
= __glXGetCurrentContext();
251 CARD32
*drawable_ptr
;
253 CARD32
*num_attrib_ptr
;
260 while (attrib_list
[i
* 2] != None
)
264 opcode
= __glXSetupForCommand(dpy
);
269 GetReqExtra(GLXVendorPrivate
, 12 + 8 * i
, req
);
270 req
->reqType
= opcode
;
271 req
->glxCode
= X_GLXVendorPrivate
;
272 req
->vendorCode
= X_GLXvop_BindTexImageEXT
;
273 req
->contextTag
= gc
->currentContextTag
;
275 drawable_ptr
= (CARD32
*) (req
+ 1);
276 buffer_ptr
= (INT32
*) (drawable_ptr
+ 1);
277 num_attrib_ptr
= (CARD32
*) (buffer_ptr
+ 1);
278 attrib_ptr
= (CARD32
*) (num_attrib_ptr
+ 1);
280 *drawable_ptr
= drawable
;
281 *buffer_ptr
= buffer
;
282 *num_attrib_ptr
= (CARD32
) i
;
286 while (attrib_list
[i
* 2] != None
) {
287 *attrib_ptr
++ = (CARD32
) attrib_list
[i
* 2 + 0];
288 *attrib_ptr
++ = (CARD32
) attrib_list
[i
* 2 + 1];
298 indirect_release_tex_image(Display
* dpy
, GLXDrawable drawable
, int buffer
)
300 xGLXVendorPrivateReq
*req
;
301 struct glx_context
*gc
= __glXGetCurrentContext();
302 CARD32
*drawable_ptr
;
306 opcode
= __glXSetupForCommand(dpy
);
311 GetReqExtra(GLXVendorPrivate
, sizeof(CARD32
) + sizeof(INT32
), req
);
312 req
->reqType
= opcode
;
313 req
->glxCode
= X_GLXVendorPrivate
;
314 req
->vendorCode
= X_GLXvop_ReleaseTexImageEXT
;
315 req
->contextTag
= gc
->currentContextTag
;
317 drawable_ptr
= (CARD32
*) (req
+ 1);
318 buffer_ptr
= (INT32
*) (drawable_ptr
+ 1);
320 *drawable_ptr
= drawable
;
321 *buffer_ptr
= buffer
;
327 static const struct glx_context_vtable indirect_context_vtable
= {
328 .destroy
= indirect_destroy_context
,
329 .bind
= indirect_bind_context
,
330 .unbind
= indirect_unbind_context
,
331 .wait_gl
= indirect_wait_gl
,
332 .wait_x
= indirect_wait_x
,
333 .use_x_font
= indirect_use_x_font
,
334 .bind_tex_image
= indirect_bind_tex_image
,
335 .release_tex_image
= indirect_release_tex_image
,
336 .get_proc_address
= NULL
,
340 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
341 * function called \c __glXAllocateClientState that allocates the memory and
342 * does all the initialization (including the pixel pack / unpack).
345 * This function is \b not the place to validate the context creation
346 * parameters. It is just the allocator for the \c glx_context.
348 _X_HIDDEN
struct glx_context
*
349 indirect_create_context(struct glx_screen
*psc
,
350 struct glx_config
*mode
,
351 struct glx_context
*shareList
, int renderType
)
353 struct glx_context
*gc
;
356 __GLXattribute
*state
;
358 opcode
= __glXSetupForCommand(psc
->dpy
);
363 /* Allocate our context record */
364 gc
= calloc(1, sizeof *gc
);
370 glx_context_init(gc
, psc
, mode
);
371 gc
->isDirect
= GL_FALSE
;
372 gc
->vtable
= &indirect_context_vtable
;
373 state
= calloc(1, sizeof(struct __GLXattributeRec
));
374 gc
->renderType
= renderType
;
381 gc
->client_state_private
= state
;
382 state
->NoDrawArraysProtocol
= (getenv("LIBGL_NO_DRAWARRAYS") != NULL
);
385 ** Create a temporary buffer to hold GLX rendering commands. The size
386 ** of the buffer is selected so that the maximum number of GLX rendering
387 ** commands can fit in a single X packet and still have room in the X
388 ** packet for the GLXRenderReq header.
391 bufSize
= (XMaxRequestSize(psc
->dpy
) * 4) - sz_xGLXRenderReq
;
392 gc
->buf
= malloc(bufSize
);
394 free(gc
->client_state_private
);
398 gc
->bufSize
= bufSize
;
400 /* Fill in the new context */
401 gc
->renderMode
= GL_RENDER
;
403 state
->storePack
.alignment
= 4;
404 state
->storeUnpack
.alignment
= 4;
406 gc
->attributes
.stackPointer
= &gc
->attributes
.stack
[0];
409 ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
411 gc
->fillImage
= __glFillImage
;
413 gc
->bufEnd
= gc
->buf
+ bufSize
;
414 gc
->isDirect
= GL_FALSE
;
417 ** Set limit register so that there will be one command per packet
422 gc
->limit
= gc
->buf
+ bufSize
- __GLX_BUFFER_LIMIT_SIZE
;
424 gc
->majorOpcode
= opcode
;
427 ** Constrain the maximum drawing command size allowed to be
428 ** transfered using the X_GLXRender protocol request. First
429 ** constrain by a software limit, then constrain by the protocl
432 if (bufSize
> __GLX_RENDER_CMD_SIZE_LIMIT
) {
433 bufSize
= __GLX_RENDER_CMD_SIZE_LIMIT
;
435 if (bufSize
> __GLX_MAX_RENDER_CMD_SIZE
) {
436 bufSize
= __GLX_MAX_RENDER_CMD_SIZE
;
438 gc
->maxSmallRenderCommandSize
= bufSize
;
444 _X_HIDDEN
struct glx_context
*
445 indirect_create_context_attribs(struct glx_screen
*base
,
446 struct glx_config
*config_base
,
447 struct glx_context
*shareList
,
448 unsigned num_attribs
,
449 const uint32_t *attribs
,
452 int renderType
= GLX_RGBA_TYPE
;
455 /* The error parameter is only used on the server so that correct GLX
456 * protocol errors can be generated. On the client, it can be ignored.
460 /* All of the attribute validation for indirect contexts is handled on the
461 * server, so there's not much to do here. Still, we need to parse the
462 * attributes to correctly set renderType.
464 for (i
= 0; i
< num_attribs
; i
++) {
465 if (attribs
[i
* 2] == GLX_RENDER_TYPE
)
466 renderType
= attribs
[i
* 2 + 1];
469 return indirect_create_context(base
, config_base
, shareList
, renderType
);
472 static const struct glx_screen_vtable indirect_screen_vtable
= {
473 .create_context
= indirect_create_context
,
474 .create_context_attribs
= indirect_create_context_attribs
,
475 .query_renderer_integer
= NULL
,
476 .query_renderer_string
= NULL
,
479 _X_HIDDEN
struct glx_screen
*
480 indirect_create_screen(int screen
, struct glx_display
* priv
)
482 struct glx_screen
*psc
;
484 psc
= calloc(1, sizeof *psc
);
488 glx_screen_init(psc
, screen
, priv
);
489 psc
->vtable
= &indirect_screen_vtable
;