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)
36 #include "glxclient.h"
38 #include "util/debug.h"
40 #ifndef GLX_USE_APPLEGL
42 extern struct _glapi_table
*__glXNewIndirectAPI(void);
45 ** All indirect rendering contexts will share the same indirect dispatch table.
47 static struct _glapi_table
*IndirectAPI
= NULL
;
50 indirect_destroy_context(struct glx_context
*gc
)
52 __glXFreeVertexArrayState(gc
);
54 free((char *) gc
->vendor
);
55 free((char *) gc
->renderer
);
56 free((char *) gc
->version
);
57 free((char *) gc
->extensions
);
58 __glFreeAttributeState(gc
);
59 free((char *) gc
->buf
);
60 free((char *) gc
->client_state_private
);
65 indirect_bind_context(struct glx_context
*gc
, struct glx_context
*old
,
66 GLXDrawable draw
, GLXDrawable read
)
68 __GLXattribute
*state
= gc
->client_state_private
;
71 IndirectAPI
= __glXNewIndirectAPI();
72 _glapi_set_dispatch(IndirectAPI
);
74 /* The indirect vertex array state must to be initialised after we
75 * have setup the context, as it needs to query server attributes.
77 * At the point this is called gc->currentDpy is not initialized
78 * nor is the thread's current context actually set. Hence the
79 * cleverness before the GetString calls.
81 if (state
&& state
->array_state
== NULL
) {
82 gc
->currentDpy
= gc
->psc
->dpy
;
83 __glXSetCurrentContext(gc
);
84 __glXSetCurrentContext(gc
);
85 __indirect_glGetString(GL_EXTENSIONS
);
86 __indirect_glGetString(GL_VERSION
);
87 __glXInitVertexArrayState(gc
);
90 if (state
!= NULL
&& state
->array_state
!= NULL
)
97 indirect_unbind_context(struct glx_context
*gc
, struct glx_context
*new)
102 indirect_wait_gl(struct glx_context
*gc
)
105 Display
*dpy
= gc
->currentDpy
;
107 /* Flush any pending commands out */
108 __glXFlushRenderBuffer(gc
, gc
->pc
);
110 /* Send the glXWaitGL request */
112 GetReq(GLXWaitGL
, req
);
113 req
->reqType
= gc
->majorOpcode
;
114 req
->glxCode
= X_GLXWaitGL
;
115 req
->contextTag
= gc
->currentContextTag
;
121 indirect_wait_x(struct glx_context
*gc
)
124 Display
*dpy
= gc
->currentDpy
;
126 /* Flush any pending commands out */
127 __glXFlushRenderBuffer(gc
, gc
->pc
);
130 GetReq(GLXWaitX
, req
);
131 req
->reqType
= gc
->majorOpcode
;
132 req
->glxCode
= X_GLXWaitX
;
133 req
->contextTag
= gc
->currentContextTag
;
139 indirect_use_x_font(struct glx_context
*gc
,
140 Font font
, int first
, int count
, int listBase
)
142 xGLXUseXFontReq
*req
;
143 Display
*dpy
= gc
->currentDpy
;
145 /* Flush any pending commands out */
146 __glXFlushRenderBuffer(gc
, gc
->pc
);
148 /* Send the glXUseFont request */
150 GetReq(GLXUseXFont
, req
);
151 req
->reqType
= gc
->majorOpcode
;
152 req
->glxCode
= X_GLXUseXFont
;
153 req
->contextTag
= gc
->currentContextTag
;
157 req
->listBase
= listBase
;
163 indirect_bind_tex_image(Display
* dpy
,
164 GLXDrawable drawable
,
165 int buffer
, const int *attrib_list
)
167 xGLXVendorPrivateReq
*req
;
168 struct glx_context
*gc
= __glXGetCurrentContext();
169 CARD32
*drawable_ptr
;
171 CARD32
*num_attrib_ptr
;
178 while (attrib_list
[i
* 2] != None
)
182 opcode
= __glXSetupForCommand(dpy
);
187 GetReqExtra(GLXVendorPrivate
, 12 + 8 * i
, req
);
188 req
->reqType
= opcode
;
189 req
->glxCode
= X_GLXVendorPrivate
;
190 req
->vendorCode
= X_GLXvop_BindTexImageEXT
;
191 req
->contextTag
= gc
->currentContextTag
;
193 drawable_ptr
= (CARD32
*) (req
+ 1);
194 buffer_ptr
= (INT32
*) (drawable_ptr
+ 1);
195 num_attrib_ptr
= (CARD32
*) (buffer_ptr
+ 1);
196 attrib_ptr
= (CARD32
*) (num_attrib_ptr
+ 1);
198 *drawable_ptr
= drawable
;
199 *buffer_ptr
= buffer
;
200 *num_attrib_ptr
= (CARD32
) i
;
204 while (attrib_list
[i
* 2] != None
) {
205 *attrib_ptr
++ = (CARD32
) attrib_list
[i
* 2 + 0];
206 *attrib_ptr
++ = (CARD32
) attrib_list
[i
* 2 + 1];
216 indirect_release_tex_image(Display
* dpy
, GLXDrawable drawable
, int buffer
)
218 xGLXVendorPrivateReq
*req
;
219 struct glx_context
*gc
= __glXGetCurrentContext();
220 CARD32
*drawable_ptr
;
224 opcode
= __glXSetupForCommand(dpy
);
229 GetReqExtra(GLXVendorPrivate
, sizeof(CARD32
) + sizeof(INT32
), req
);
230 req
->reqType
= opcode
;
231 req
->glxCode
= X_GLXVendorPrivate
;
232 req
->vendorCode
= X_GLXvop_ReleaseTexImageEXT
;
233 req
->contextTag
= gc
->currentContextTag
;
235 drawable_ptr
= (CARD32
*) (req
+ 1);
236 buffer_ptr
= (INT32
*) (drawable_ptr
+ 1);
238 *drawable_ptr
= drawable
;
239 *buffer_ptr
= buffer
;
245 static const struct glx_context_vtable indirect_context_vtable
= {
246 .destroy
= indirect_destroy_context
,
247 .bind
= indirect_bind_context
,
248 .unbind
= indirect_unbind_context
,
249 .wait_gl
= indirect_wait_gl
,
250 .wait_x
= indirect_wait_x
,
251 .use_x_font
= indirect_use_x_font
,
252 .bind_tex_image
= indirect_bind_tex_image
,
253 .release_tex_image
= indirect_release_tex_image
,
254 .get_proc_address
= NULL
,
258 * \todo Eliminate \c __glXInitVertexArrayState. Replace it with a new
259 * function called \c __glXAllocateClientState that allocates the memory and
260 * does all the initialization (including the pixel pack / unpack).
263 * This function is \b not the place to validate the context creation
264 * parameters. It is just the allocator for the \c glx_context.
266 _X_HIDDEN
struct glx_context
*
267 indirect_create_context(struct glx_screen
*psc
,
268 struct glx_config
*mode
,
269 struct glx_context
*shareList
, int renderType
)
271 struct glx_context
*gc
;
274 __GLXattribute
*state
;
276 opcode
= __glXSetupForCommand(psc
->dpy
);
281 /* Allocate our context record */
282 gc
= calloc(1, sizeof *gc
);
288 glx_context_init(gc
, psc
, mode
);
289 gc
->isDirect
= GL_FALSE
;
290 gc
->vtable
= &indirect_context_vtable
;
291 state
= calloc(1, sizeof(struct __GLXattributeRec
));
292 gc
->renderType
= renderType
;
299 gc
->client_state_private
= state
;
300 state
->NoDrawArraysProtocol
= env_var_as_boolean("LIBGL_NO_DRAWARRAYS", false);
303 ** Create a temporary buffer to hold GLX rendering commands. The size
304 ** of the buffer is selected so that the maximum number of GLX rendering
305 ** commands can fit in a single X packet and still have room in the X
306 ** packet for the GLXRenderReq header.
309 bufSize
= (XMaxRequestSize(psc
->dpy
) * 4) - sz_xGLXRenderReq
;
310 gc
->buf
= malloc(bufSize
);
312 free(gc
->client_state_private
);
316 gc
->bufSize
= bufSize
;
318 /* Fill in the new context */
319 gc
->renderMode
= GL_RENDER
;
321 state
->storePack
.alignment
= 4;
322 state
->storeUnpack
.alignment
= 4;
324 gc
->attributes
.stackPointer
= &gc
->attributes
.stack
[0];
327 gc
->bufEnd
= gc
->buf
+ bufSize
;
328 gc
->isDirect
= GL_FALSE
;
331 ** Set limit register so that there will be one command per packet
336 gc
->limit
= gc
->buf
+ bufSize
- __GLX_BUFFER_LIMIT_SIZE
;
338 gc
->majorOpcode
= opcode
;
341 ** Constrain the maximum drawing command size allowed to be
342 ** transfered using the X_GLXRender protocol request. First
343 ** constrain by a software limit, then constrain by the protocl
346 if (bufSize
> __GLX_RENDER_CMD_SIZE_LIMIT
) {
347 bufSize
= __GLX_RENDER_CMD_SIZE_LIMIT
;
349 if (bufSize
> __GLX_MAX_RENDER_CMD_SIZE
) {
350 bufSize
= __GLX_MAX_RENDER_CMD_SIZE
;
352 gc
->maxSmallRenderCommandSize
= bufSize
;
358 _X_HIDDEN
struct glx_context
*
359 indirect_create_context_attribs(struct glx_screen
*base
,
360 struct glx_config
*config_base
,
361 struct glx_context
*shareList
,
362 unsigned num_attribs
,
363 const uint32_t *attribs
,
366 int renderType
= GLX_RGBA_TYPE
;
369 /* The error parameter is only used on the server so that correct GLX
370 * protocol errors can be generated. On the client, it can be ignored.
374 /* All of the attribute validation for indirect contexts is handled on the
375 * server, so there's not much to do here. Still, we need to parse the
376 * attributes to correctly set renderType.
378 for (i
= 0; i
< num_attribs
; i
++) {
379 if (attribs
[i
* 2] == GLX_RENDER_TYPE
)
380 renderType
= attribs
[i
* 2 + 1];
383 return indirect_create_context(base
, config_base
, shareList
, renderType
);
386 static const struct glx_screen_vtable indirect_screen_vtable
= {
387 .create_context
= indirect_create_context
,
388 .create_context_attribs
= indirect_create_context_attribs
,
389 .query_renderer_integer
= NULL
,
390 .query_renderer_string
= NULL
,
393 _X_HIDDEN
struct glx_screen
*
394 indirect_create_screen(int screen
, struct glx_display
* priv
)
396 struct glx_screen
*psc
;
398 psc
= calloc(1, sizeof *psc
);
402 glx_screen_init(psc
, screen
, priv
);
403 psc
->vtable
= &indirect_screen_vtable
;