glx: Lift sending the MakeCurrent request to top-level code
[mesa.git] / src / glx / indirect_glx.c
1 /*
2 * Copyright © 2010 Intel Corporation
3 *
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.
13 *
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.
23 *
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.
28 *
29 * Authors:
30 * Kristian Høgsberg (krh@bitplanet.net)
31 */
32
33 #include <stdbool.h>
34
35 #include "glapi.h"
36 #include "glxclient.h"
37 #include "indirect.h"
38 #include "util/debug.h"
39
40 #ifndef GLX_USE_APPLEGL
41
42 extern struct _glapi_table *__glXNewIndirectAPI(void);
43
44 /*
45 ** All indirect rendering contexts will share the same indirect dispatch table.
46 */
47 static struct _glapi_table *IndirectAPI = NULL;
48
49 static void
50 indirect_destroy_context(struct glx_context *gc)
51 {
52 __glXFreeVertexArrayState(gc);
53
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);
61 free((char *) gc);
62 }
63
64 static int
65 indirect_bind_context(struct glx_context *gc, struct glx_context *old,
66 GLXDrawable draw, GLXDrawable read)
67 {
68 __GLXattribute *state = gc->client_state_private;
69
70 if (!IndirectAPI)
71 IndirectAPI = __glXNewIndirectAPI();
72 _glapi_set_dispatch(IndirectAPI);
73
74 /* The indirect vertex array state must to be initialised after we
75 * have setup the context, as it needs to query server attributes.
76 *
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.
80 */
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);
88 }
89
90 if (state != NULL && state->array_state != NULL)
91 return Success;
92
93 return BadAlloc;
94 }
95
96 static void
97 indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
98 {
99 }
100
101 static void
102 indirect_wait_gl(struct glx_context *gc)
103 {
104 xGLXWaitGLReq *req;
105 Display *dpy = gc->currentDpy;
106
107 /* Flush any pending commands out */
108 __glXFlushRenderBuffer(gc, gc->pc);
109
110 /* Send the glXWaitGL request */
111 LockDisplay(dpy);
112 GetReq(GLXWaitGL, req);
113 req->reqType = gc->majorOpcode;
114 req->glxCode = X_GLXWaitGL;
115 req->contextTag = gc->currentContextTag;
116 UnlockDisplay(dpy);
117 SyncHandle();
118 }
119
120 static void
121 indirect_wait_x(struct glx_context *gc)
122 {
123 xGLXWaitXReq *req;
124 Display *dpy = gc->currentDpy;
125
126 /* Flush any pending commands out */
127 __glXFlushRenderBuffer(gc, gc->pc);
128
129 LockDisplay(dpy);
130 GetReq(GLXWaitX, req);
131 req->reqType = gc->majorOpcode;
132 req->glxCode = X_GLXWaitX;
133 req->contextTag = gc->currentContextTag;
134 UnlockDisplay(dpy);
135 SyncHandle();
136 }
137
138 static void
139 indirect_use_x_font(struct glx_context *gc,
140 Font font, int first, int count, int listBase)
141 {
142 xGLXUseXFontReq *req;
143 Display *dpy = gc->currentDpy;
144
145 /* Flush any pending commands out */
146 __glXFlushRenderBuffer(gc, gc->pc);
147
148 /* Send the glXUseFont request */
149 LockDisplay(dpy);
150 GetReq(GLXUseXFont, req);
151 req->reqType = gc->majorOpcode;
152 req->glxCode = X_GLXUseXFont;
153 req->contextTag = gc->currentContextTag;
154 req->font = font;
155 req->first = first;
156 req->count = count;
157 req->listBase = listBase;
158 UnlockDisplay(dpy);
159 SyncHandle();
160 }
161
162 static void
163 indirect_bind_tex_image(Display * dpy,
164 GLXDrawable drawable,
165 int buffer, const int *attrib_list)
166 {
167 xGLXVendorPrivateReq *req;
168 struct glx_context *gc = __glXGetCurrentContext();
169 CARD32 *drawable_ptr;
170 INT32 *buffer_ptr;
171 CARD32 *num_attrib_ptr;
172 CARD32 *attrib_ptr;
173 CARD8 opcode;
174 unsigned int i;
175
176 i = 0;
177 if (attrib_list) {
178 while (attrib_list[i * 2] != None)
179 i++;
180 }
181
182 opcode = __glXSetupForCommand(dpy);
183 if (!opcode)
184 return;
185
186 LockDisplay(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;
192
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);
197
198 *drawable_ptr = drawable;
199 *buffer_ptr = buffer;
200 *num_attrib_ptr = (CARD32) i;
201
202 i = 0;
203 if (attrib_list) {
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];
207 i++;
208 }
209 }
210
211 UnlockDisplay(dpy);
212 SyncHandle();
213 }
214
215 static void
216 indirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
217 {
218 xGLXVendorPrivateReq *req;
219 struct glx_context *gc = __glXGetCurrentContext();
220 CARD32 *drawable_ptr;
221 INT32 *buffer_ptr;
222 CARD8 opcode;
223
224 opcode = __glXSetupForCommand(dpy);
225 if (!opcode)
226 return;
227
228 LockDisplay(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;
234
235 drawable_ptr = (CARD32 *) (req + 1);
236 buffer_ptr = (INT32 *) (drawable_ptr + 1);
237
238 *drawable_ptr = drawable;
239 *buffer_ptr = buffer;
240
241 UnlockDisplay(dpy);
242 SyncHandle();
243 }
244
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,
255 };
256
257 /**
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).
261 *
262 * \note
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.
265 */
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)
270 {
271 struct glx_context *gc;
272 int bufSize;
273 CARD8 opcode;
274 __GLXattribute *state;
275
276 opcode = __glXSetupForCommand(psc->dpy);
277 if (!opcode) {
278 return NULL;
279 }
280
281 /* Allocate our context record */
282 gc = calloc(1, sizeof *gc);
283 if (!gc) {
284 /* Out of memory */
285 return NULL;
286 }
287
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;
293
294 if (state == NULL) {
295 /* Out of memory */
296 free(gc);
297 return NULL;
298 }
299 gc->client_state_private = state;
300 state->NoDrawArraysProtocol = env_var_as_boolean("LIBGL_NO_DRAWARRAYS", false);
301
302 /*
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.
307 */
308
309 bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
310 gc->buf = malloc(bufSize);
311 if (!gc->buf) {
312 free(gc->client_state_private);
313 free(gc);
314 return NULL;
315 }
316 gc->bufSize = bufSize;
317
318 /* Fill in the new context */
319 gc->renderMode = GL_RENDER;
320
321 state->storePack.alignment = 4;
322 state->storeUnpack.alignment = 4;
323
324 gc->attributes.stackPointer = &gc->attributes.stack[0];
325
326 gc->pc = gc->buf;
327 gc->bufEnd = gc->buf + bufSize;
328 gc->isDirect = GL_FALSE;
329 if (__glXDebug) {
330 /*
331 ** Set limit register so that there will be one command per packet
332 */
333 gc->limit = gc->buf;
334 }
335 else {
336 gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
337 }
338 gc->majorOpcode = opcode;
339
340 /*
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
344 ** limit.
345 */
346 if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
347 bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
348 }
349 if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
350 bufSize = __GLX_MAX_RENDER_CMD_SIZE;
351 }
352 gc->maxSmallRenderCommandSize = bufSize;
353
354
355 return gc;
356 }
357
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,
364 unsigned *error)
365 {
366 int renderType = GLX_RGBA_TYPE;
367 unsigned i;
368
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.
371 */
372 (void) error;
373
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.
377 */
378 for (i = 0; i < num_attribs; i++) {
379 if (attribs[i * 2] == GLX_RENDER_TYPE)
380 renderType = attribs[i * 2 + 1];
381 }
382
383 return indirect_create_context(base, config_base, shareList, renderType);
384 }
385
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,
391 };
392
393 _X_HIDDEN struct glx_screen *
394 indirect_create_screen(int screen, struct glx_display * priv)
395 {
396 struct glx_screen *psc;
397
398 psc = calloc(1, sizeof *psc);
399 if (psc == NULL)
400 return NULL;
401
402 glx_screen_init(psc, screen, priv);
403 psc->vtable = &indirect_screen_vtable;
404
405 return psc;
406 }
407
408 #endif