indirect_glx.c revision af69d88d
13464ebd5Sriastradh/*
23464ebd5Sriastradh * Copyright © 2010 Intel Corporation
33464ebd5Sriastradh *
43464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
53464ebd5Sriastradh * copy of this software and associated documentation files (the "Soft-
63464ebd5Sriastradh * ware"), to deal in the Software without restriction, including without
73464ebd5Sriastradh * limitation the rights to use, copy, modify, merge, publish, distribute,
83464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the
93464ebd5Sriastradh * Software is furnished to do so, provided that the above copyright
103464ebd5Sriastradh * notice(s) and this permission notice appear in all copies of the Soft-
113464ebd5Sriastradh * ware and that both the above copyright notice(s) and this permission
123464ebd5Sriastradh * notice appear in supporting documentation.
133464ebd5Sriastradh *
143464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
153464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
163464ebd5Sriastradh * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
173464ebd5Sriastradh * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
183464ebd5Sriastradh * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
193464ebd5Sriastradh * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
203464ebd5Sriastradh * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
213464ebd5Sriastradh * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
223464ebd5Sriastradh * MANCE OF THIS SOFTWARE.
233464ebd5Sriastradh *
243464ebd5Sriastradh * Except as contained in this notice, the name of a copyright holder shall
253464ebd5Sriastradh * not be used in advertising or otherwise to promote the sale, use or
263464ebd5Sriastradh * other dealings in this Software without prior written authorization of
273464ebd5Sriastradh * the copyright holder.
283464ebd5Sriastradh *
293464ebd5Sriastradh * Authors:
303464ebd5Sriastradh *   Kristian Høgsberg (krh@bitplanet.net)
313464ebd5Sriastradh */
323464ebd5Sriastradh
333464ebd5Sriastradh#include "glapi.h"
343464ebd5Sriastradh#include "glxclient.h"
353464ebd5Sriastradh
36af69d88dSmrg#ifndef GLX_USE_APPLEGL
37af69d88dSmrg
383464ebd5Sriastradhextern struct _glapi_table *__glXNewIndirectAPI(void);
393464ebd5Sriastradh
403464ebd5Sriastradh/*
413464ebd5Sriastradh** All indirect rendering contexts will share the same indirect dispatch table.
423464ebd5Sriastradh*/
433464ebd5Sriastradhstatic struct _glapi_table *IndirectAPI = NULL;
443464ebd5Sriastradh
453464ebd5Sriastradhstatic void
463464ebd5Sriastradhindirect_destroy_context(struct glx_context *gc)
473464ebd5Sriastradh{
483464ebd5Sriastradh   __glXFreeVertexArrayState(gc);
493464ebd5Sriastradh
50af69d88dSmrg   free((char *) gc->vendor);
51af69d88dSmrg   free((char *) gc->renderer);
52af69d88dSmrg   free((char *) gc->version);
53af69d88dSmrg   free((char *) gc->extensions);
543464ebd5Sriastradh   __glFreeAttributeState(gc);
55af69d88dSmrg   free((char *) gc->buf);
56af69d88dSmrg   free((char *) gc->client_state_private);
57af69d88dSmrg   free((char *) gc);
583464ebd5Sriastradh}
593464ebd5Sriastradh
603464ebd5Sriastradhstatic Bool
613464ebd5SriastradhSendMakeCurrentRequest(Display * dpy, CARD8 opcode,
623464ebd5Sriastradh                       GLXContextID gc_id, GLXContextTag gc_tag,
633464ebd5Sriastradh                       GLXDrawable draw, GLXDrawable read,
64af69d88dSmrg                       GLXContextTag *out_tag)
653464ebd5Sriastradh{
66af69d88dSmrg   xGLXMakeCurrentReply reply;
673464ebd5Sriastradh   Bool ret;
683464ebd5Sriastradh
693464ebd5Sriastradh   LockDisplay(dpy);
703464ebd5Sriastradh
713464ebd5Sriastradh   if (draw == read) {
723464ebd5Sriastradh      xGLXMakeCurrentReq *req;
733464ebd5Sriastradh
743464ebd5Sriastradh      GetReq(GLXMakeCurrent, req);
753464ebd5Sriastradh      req->reqType = opcode;
763464ebd5Sriastradh      req->glxCode = X_GLXMakeCurrent;
773464ebd5Sriastradh      req->drawable = draw;
783464ebd5Sriastradh      req->context = gc_id;
793464ebd5Sriastradh      req->oldContextTag = gc_tag;
803464ebd5Sriastradh   }
813464ebd5Sriastradh   else {
823464ebd5Sriastradh      struct glx_display *priv = __glXInitialize(dpy);
833464ebd5Sriastradh
843464ebd5Sriastradh      /* If the server can support the GLX 1.3 version, we should
853464ebd5Sriastradh       * perfer that.  Not only that, some servers support GLX 1.3 but
863464ebd5Sriastradh       * not the SGI extension.
873464ebd5Sriastradh       */
883464ebd5Sriastradh
893464ebd5Sriastradh      if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
903464ebd5Sriastradh         xGLXMakeContextCurrentReq *req;
913464ebd5Sriastradh
923464ebd5Sriastradh         GetReq(GLXMakeContextCurrent, req);
933464ebd5Sriastradh         req->reqType = opcode;
943464ebd5Sriastradh         req->glxCode = X_GLXMakeContextCurrent;
953464ebd5Sriastradh         req->drawable = draw;
963464ebd5Sriastradh         req->readdrawable = read;
973464ebd5Sriastradh         req->context = gc_id;
983464ebd5Sriastradh         req->oldContextTag = gc_tag;
993464ebd5Sriastradh      }
1003464ebd5Sriastradh      else {
1013464ebd5Sriastradh         xGLXVendorPrivateWithReplyReq *vpreq;
1023464ebd5Sriastradh         xGLXMakeCurrentReadSGIReq *req;
1033464ebd5Sriastradh
1043464ebd5Sriastradh         GetReqExtra(GLXVendorPrivateWithReply,
1053464ebd5Sriastradh                     sz_xGLXMakeCurrentReadSGIReq -
1063464ebd5Sriastradh                     sz_xGLXVendorPrivateWithReplyReq, vpreq);
1073464ebd5Sriastradh         req = (xGLXMakeCurrentReadSGIReq *) vpreq;
1083464ebd5Sriastradh         req->reqType = opcode;
1093464ebd5Sriastradh         req->glxCode = X_GLXVendorPrivateWithReply;
1103464ebd5Sriastradh         req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
1113464ebd5Sriastradh         req->drawable = draw;
1123464ebd5Sriastradh         req->readable = read;
1133464ebd5Sriastradh         req->context = gc_id;
1143464ebd5Sriastradh         req->oldContextTag = gc_tag;
1153464ebd5Sriastradh      }
1163464ebd5Sriastradh   }
1173464ebd5Sriastradh
118af69d88dSmrg   ret = _XReply(dpy, (xReply *) &reply, 0, False);
119af69d88dSmrg
120af69d88dSmrg   if (out_tag)
121af69d88dSmrg      *out_tag = reply.contextTag;
1223464ebd5Sriastradh
1233464ebd5Sriastradh   UnlockDisplay(dpy);
1243464ebd5Sriastradh   SyncHandle();
1253464ebd5Sriastradh
1263464ebd5Sriastradh   return ret;
1273464ebd5Sriastradh}
1283464ebd5Sriastradh
1293464ebd5Sriastradhstatic int
1303464ebd5Sriastradhindirect_bind_context(struct glx_context *gc, struct glx_context *old,
1313464ebd5Sriastradh		      GLXDrawable draw, GLXDrawable read)
1323464ebd5Sriastradh{
1333464ebd5Sriastradh   GLXContextTag tag;
1343464ebd5Sriastradh   __GLXattribute *state;
1353464ebd5Sriastradh   Display *dpy = gc->psc->dpy;
1363464ebd5Sriastradh   int opcode = __glXSetupForCommand(dpy);
137af69d88dSmrg   Bool sent;
1383464ebd5Sriastradh
1393464ebd5Sriastradh   if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
1403464ebd5Sriastradh      tag = old->currentContextTag;
1413464ebd5Sriastradh      old->currentContextTag = 0;
1423464ebd5Sriastradh   } else {
1433464ebd5Sriastradh      tag = 0;
1443464ebd5Sriastradh   }
1453464ebd5Sriastradh
146af69d88dSmrg   sent = SendMakeCurrentRequest(dpy, opcode, gc->xid, tag, draw, read,
147af69d88dSmrg				 &gc->currentContextTag);
1483464ebd5Sriastradh
1493464ebd5Sriastradh   if (!IndirectAPI)
1503464ebd5Sriastradh      IndirectAPI = __glXNewIndirectAPI();
1513464ebd5Sriastradh   _glapi_set_dispatch(IndirectAPI);
1523464ebd5Sriastradh
1533464ebd5Sriastradh   state = gc->client_state_private;
1543464ebd5Sriastradh   if (state->array_state == NULL) {
1553464ebd5Sriastradh      glGetString(GL_EXTENSIONS);
1563464ebd5Sriastradh      glGetString(GL_VERSION);
1573464ebd5Sriastradh      __glXInitVertexArrayState(gc);
1583464ebd5Sriastradh   }
1593464ebd5Sriastradh
160af69d88dSmrg   return !sent;
1613464ebd5Sriastradh}
1623464ebd5Sriastradh
1633464ebd5Sriastradhstatic void
1643464ebd5Sriastradhindirect_unbind_context(struct glx_context *gc, struct glx_context *new)
1653464ebd5Sriastradh{
1663464ebd5Sriastradh   Display *dpy = gc->psc->dpy;
1673464ebd5Sriastradh   int opcode = __glXSetupForCommand(dpy);
1683464ebd5Sriastradh
1693464ebd5Sriastradh   if (gc == new)
1703464ebd5Sriastradh      return;
1713464ebd5Sriastradh
1723464ebd5Sriastradh   /* We are either switching to no context, away from a indirect
1733464ebd5Sriastradh    * context to a direct context or from one dpy to another and have
1743464ebd5Sriastradh    * to send a request to the dpy to unbind the previous context.
1753464ebd5Sriastradh    */
1763464ebd5Sriastradh   if (!new || new->isDirect || new->psc->dpy != dpy) {
1773464ebd5Sriastradh      SendMakeCurrentRequest(dpy, opcode, None,
178af69d88dSmrg			     gc->currentContextTag, None, None, NULL);
1793464ebd5Sriastradh      gc->currentContextTag = 0;
1803464ebd5Sriastradh   }
1813464ebd5Sriastradh}
1823464ebd5Sriastradh
1833464ebd5Sriastradhstatic void
1843464ebd5Sriastradhindirect_wait_gl(struct glx_context *gc)
1853464ebd5Sriastradh{
1863464ebd5Sriastradh   xGLXWaitGLReq *req;
1873464ebd5Sriastradh   Display *dpy = gc->currentDpy;
1883464ebd5Sriastradh
1893464ebd5Sriastradh   /* Flush any pending commands out */
1903464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
1913464ebd5Sriastradh
1923464ebd5Sriastradh   /* Send the glXWaitGL request */
1933464ebd5Sriastradh   LockDisplay(dpy);
1943464ebd5Sriastradh   GetReq(GLXWaitGL, req);
1953464ebd5Sriastradh   req->reqType = gc->majorOpcode;
1963464ebd5Sriastradh   req->glxCode = X_GLXWaitGL;
1973464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
1983464ebd5Sriastradh   UnlockDisplay(dpy);
1993464ebd5Sriastradh   SyncHandle();
2003464ebd5Sriastradh}
2013464ebd5Sriastradh
2023464ebd5Sriastradhstatic void
2033464ebd5Sriastradhindirect_wait_x(struct glx_context *gc)
2043464ebd5Sriastradh{
2053464ebd5Sriastradh   xGLXWaitXReq *req;
2063464ebd5Sriastradh   Display *dpy = gc->currentDpy;
2073464ebd5Sriastradh
2083464ebd5Sriastradh   /* Flush any pending commands out */
2093464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
2103464ebd5Sriastradh
2113464ebd5Sriastradh   LockDisplay(dpy);
2123464ebd5Sriastradh   GetReq(GLXWaitX, req);
2133464ebd5Sriastradh   req->reqType = gc->majorOpcode;
2143464ebd5Sriastradh   req->glxCode = X_GLXWaitX;
2153464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2163464ebd5Sriastradh   UnlockDisplay(dpy);
2173464ebd5Sriastradh   SyncHandle();
2183464ebd5Sriastradh}
2193464ebd5Sriastradh
2203464ebd5Sriastradhstatic void
2213464ebd5Sriastradhindirect_use_x_font(struct glx_context *gc,
2223464ebd5Sriastradh		    Font font, int first, int count, int listBase)
2233464ebd5Sriastradh{
2243464ebd5Sriastradh   xGLXUseXFontReq *req;
2253464ebd5Sriastradh   Display *dpy = gc->currentDpy;
2263464ebd5Sriastradh
2273464ebd5Sriastradh   /* Flush any pending commands out */
2283464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
2293464ebd5Sriastradh
2303464ebd5Sriastradh   /* Send the glXUseFont request */
2313464ebd5Sriastradh   LockDisplay(dpy);
2323464ebd5Sriastradh   GetReq(GLXUseXFont, req);
2333464ebd5Sriastradh   req->reqType = gc->majorOpcode;
2343464ebd5Sriastradh   req->glxCode = X_GLXUseXFont;
2353464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2363464ebd5Sriastradh   req->font = font;
2373464ebd5Sriastradh   req->first = first;
2383464ebd5Sriastradh   req->count = count;
2393464ebd5Sriastradh   req->listBase = listBase;
2403464ebd5Sriastradh   UnlockDisplay(dpy);
2413464ebd5Sriastradh   SyncHandle();
2423464ebd5Sriastradh}
2433464ebd5Sriastradh
2443464ebd5Sriastradhstatic void
2453464ebd5Sriastradhindirect_bind_tex_image(Display * dpy,
2463464ebd5Sriastradh			GLXDrawable drawable,
2473464ebd5Sriastradh			int buffer, const int *attrib_list)
2483464ebd5Sriastradh{
2493464ebd5Sriastradh   xGLXVendorPrivateReq *req;
2503464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
2513464ebd5Sriastradh   CARD32 *drawable_ptr;
2523464ebd5Sriastradh   INT32 *buffer_ptr;
2533464ebd5Sriastradh   CARD32 *num_attrib_ptr;
2543464ebd5Sriastradh   CARD32 *attrib_ptr;
2553464ebd5Sriastradh   CARD8 opcode;
2563464ebd5Sriastradh   unsigned int i;
2573464ebd5Sriastradh
2583464ebd5Sriastradh   i = 0;
2593464ebd5Sriastradh   if (attrib_list) {
2603464ebd5Sriastradh      while (attrib_list[i * 2] != None)
2613464ebd5Sriastradh         i++;
2623464ebd5Sriastradh   }
2633464ebd5Sriastradh
2643464ebd5Sriastradh   opcode = __glXSetupForCommand(dpy);
2653464ebd5Sriastradh   if (!opcode)
2663464ebd5Sriastradh      return;
2673464ebd5Sriastradh
2683464ebd5Sriastradh   LockDisplay(dpy);
2693464ebd5Sriastradh   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
2703464ebd5Sriastradh   req->reqType = opcode;
2713464ebd5Sriastradh   req->glxCode = X_GLXVendorPrivate;
2723464ebd5Sriastradh   req->vendorCode = X_GLXvop_BindTexImageEXT;
2733464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2743464ebd5Sriastradh
2753464ebd5Sriastradh   drawable_ptr = (CARD32 *) (req + 1);
2763464ebd5Sriastradh   buffer_ptr = (INT32 *) (drawable_ptr + 1);
2773464ebd5Sriastradh   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2783464ebd5Sriastradh   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
2793464ebd5Sriastradh
2803464ebd5Sriastradh   *drawable_ptr = drawable;
2813464ebd5Sriastradh   *buffer_ptr = buffer;
2823464ebd5Sriastradh   *num_attrib_ptr = (CARD32) i;
2833464ebd5Sriastradh
2843464ebd5Sriastradh   i = 0;
2853464ebd5Sriastradh   if (attrib_list) {
2863464ebd5Sriastradh      while (attrib_list[i * 2] != None) {
2873464ebd5Sriastradh         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2883464ebd5Sriastradh         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2893464ebd5Sriastradh         i++;
2903464ebd5Sriastradh      }
2913464ebd5Sriastradh   }
2923464ebd5Sriastradh
2933464ebd5Sriastradh   UnlockDisplay(dpy);
2943464ebd5Sriastradh   SyncHandle();
2953464ebd5Sriastradh}
2963464ebd5Sriastradh
2973464ebd5Sriastradhstatic void
2983464ebd5Sriastradhindirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
2993464ebd5Sriastradh{
3003464ebd5Sriastradh   xGLXVendorPrivateReq *req;
3013464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
3023464ebd5Sriastradh   CARD32 *drawable_ptr;
3033464ebd5Sriastradh   INT32 *buffer_ptr;
3043464ebd5Sriastradh   CARD8 opcode;
3053464ebd5Sriastradh
3063464ebd5Sriastradh   opcode = __glXSetupForCommand(dpy);
3073464ebd5Sriastradh   if (!opcode)
3083464ebd5Sriastradh      return;
3093464ebd5Sriastradh
3103464ebd5Sriastradh   LockDisplay(dpy);
3113464ebd5Sriastradh   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
3123464ebd5Sriastradh   req->reqType = opcode;
3133464ebd5Sriastradh   req->glxCode = X_GLXVendorPrivate;
3143464ebd5Sriastradh   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
3153464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
3163464ebd5Sriastradh
3173464ebd5Sriastradh   drawable_ptr = (CARD32 *) (req + 1);
3183464ebd5Sriastradh   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3193464ebd5Sriastradh
3203464ebd5Sriastradh   *drawable_ptr = drawable;
3213464ebd5Sriastradh   *buffer_ptr = buffer;
3223464ebd5Sriastradh
3233464ebd5Sriastradh   UnlockDisplay(dpy);
3243464ebd5Sriastradh   SyncHandle();
3253464ebd5Sriastradh}
3263464ebd5Sriastradh
3273464ebd5Sriastradhstatic const struct glx_context_vtable indirect_context_vtable = {
328af69d88dSmrg   .destroy             = indirect_destroy_context,
329af69d88dSmrg   .bind                = indirect_bind_context,
330af69d88dSmrg   .unbind              = indirect_unbind_context,
331af69d88dSmrg   .wait_gl             = indirect_wait_gl,
332af69d88dSmrg   .wait_x              = indirect_wait_x,
333af69d88dSmrg   .use_x_font          = indirect_use_x_font,
334af69d88dSmrg   .bind_tex_image      = indirect_bind_tex_image,
335af69d88dSmrg   .release_tex_image   = indirect_release_tex_image,
336af69d88dSmrg   .get_proc_address    = NULL,
3373464ebd5Sriastradh};
3383464ebd5Sriastradh
3393464ebd5Sriastradh/**
3403464ebd5Sriastradh * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
3413464ebd5Sriastradh * function called \c __glXAllocateClientState that allocates the memory and
3423464ebd5Sriastradh * does all the initialization (including the pixel pack / unpack).
343af69d88dSmrg *
344af69d88dSmrg * \note
345af69d88dSmrg * This function is \b not the place to validate the context creation
346af69d88dSmrg * parameters.  It is just the allocator for the \c glx_context.
3473464ebd5Sriastradh */
3483464ebd5Sriastradh_X_HIDDEN struct glx_context *
3493464ebd5Sriastradhindirect_create_context(struct glx_screen *psc,
3503464ebd5Sriastradh			struct glx_config *mode,
3513464ebd5Sriastradh			struct glx_context *shareList, int renderType)
3523464ebd5Sriastradh{
3533464ebd5Sriastradh   struct glx_context *gc;
3543464ebd5Sriastradh   int bufSize;
3553464ebd5Sriastradh   CARD8 opcode;
3563464ebd5Sriastradh   __GLXattribute *state;
3573464ebd5Sriastradh
3583464ebd5Sriastradh   opcode = __glXSetupForCommand(psc->dpy);
3593464ebd5Sriastradh   if (!opcode) {
3603464ebd5Sriastradh      return NULL;
3613464ebd5Sriastradh   }
3623464ebd5Sriastradh
3633464ebd5Sriastradh   /* Allocate our context record */
364af69d88dSmrg   gc = calloc(1, sizeof *gc);
3653464ebd5Sriastradh   if (!gc) {
3663464ebd5Sriastradh      /* Out of memory */
3673464ebd5Sriastradh      return NULL;
3683464ebd5Sriastradh   }
3693464ebd5Sriastradh
3703464ebd5Sriastradh   glx_context_init(gc, psc, mode);
3713464ebd5Sriastradh   gc->isDirect = GL_FALSE;
3723464ebd5Sriastradh   gc->vtable = &indirect_context_vtable;
373af69d88dSmrg   state = calloc(1, sizeof(struct __GLXattributeRec));
374af69d88dSmrg   gc->renderType = renderType;
375af69d88dSmrg
3763464ebd5Sriastradh   if (state == NULL) {
3773464ebd5Sriastradh      /* Out of memory */
378af69d88dSmrg      free(gc);
3793464ebd5Sriastradh      return NULL;
3803464ebd5Sriastradh   }
3813464ebd5Sriastradh   gc->client_state_private = state;
3823464ebd5Sriastradh   state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
3833464ebd5Sriastradh
3843464ebd5Sriastradh   /*
3853464ebd5Sriastradh    ** Create a temporary buffer to hold GLX rendering commands.  The size
3863464ebd5Sriastradh    ** of the buffer is selected so that the maximum number of GLX rendering
3873464ebd5Sriastradh    ** commands can fit in a single X packet and still have room in the X
3883464ebd5Sriastradh    ** packet for the GLXRenderReq header.
3893464ebd5Sriastradh    */
3903464ebd5Sriastradh
3913464ebd5Sriastradh   bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
392af69d88dSmrg   gc->buf = malloc(bufSize);
3933464ebd5Sriastradh   if (!gc->buf) {
394af69d88dSmrg      free(gc->client_state_private);
395af69d88dSmrg      free(gc);
3963464ebd5Sriastradh      return NULL;
3973464ebd5Sriastradh   }
3983464ebd5Sriastradh   gc->bufSize = bufSize;
3993464ebd5Sriastradh
4003464ebd5Sriastradh   /* Fill in the new context */
4013464ebd5Sriastradh   gc->renderMode = GL_RENDER;
4023464ebd5Sriastradh
4033464ebd5Sriastradh   state->storePack.alignment = 4;
4043464ebd5Sriastradh   state->storeUnpack.alignment = 4;
4053464ebd5Sriastradh
4063464ebd5Sriastradh   gc->attributes.stackPointer = &gc->attributes.stack[0];
4073464ebd5Sriastradh
4083464ebd5Sriastradh   /*
4093464ebd5Sriastradh    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
4103464ebd5Sriastradh    */
4113464ebd5Sriastradh   gc->fillImage = __glFillImage;
4123464ebd5Sriastradh   gc->pc = gc->buf;
4133464ebd5Sriastradh   gc->bufEnd = gc->buf + bufSize;
4143464ebd5Sriastradh   gc->isDirect = GL_FALSE;
4153464ebd5Sriastradh   if (__glXDebug) {
4163464ebd5Sriastradh      /*
4173464ebd5Sriastradh       ** Set limit register so that there will be one command per packet
4183464ebd5Sriastradh       */
4193464ebd5Sriastradh      gc->limit = gc->buf;
4203464ebd5Sriastradh   }
4213464ebd5Sriastradh   else {
4223464ebd5Sriastradh      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
4233464ebd5Sriastradh   }
4243464ebd5Sriastradh   gc->majorOpcode = opcode;
4253464ebd5Sriastradh
4263464ebd5Sriastradh   /*
4273464ebd5Sriastradh    ** Constrain the maximum drawing command size allowed to be
4283464ebd5Sriastradh    ** transfered using the X_GLXRender protocol request.  First
4293464ebd5Sriastradh    ** constrain by a software limit, then constrain by the protocl
4303464ebd5Sriastradh    ** limit.
4313464ebd5Sriastradh    */
4323464ebd5Sriastradh   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
4333464ebd5Sriastradh      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
4343464ebd5Sriastradh   }
4353464ebd5Sriastradh   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
4363464ebd5Sriastradh      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
4373464ebd5Sriastradh   }
4383464ebd5Sriastradh   gc->maxSmallRenderCommandSize = bufSize;
4393464ebd5Sriastradh
4403464ebd5Sriastradh
4413464ebd5Sriastradh   return gc;
4423464ebd5Sriastradh}
4433464ebd5Sriastradh
444af69d88dSmrg_X_HIDDEN struct glx_context *
445af69d88dSmrgindirect_create_context_attribs(struct glx_screen *base,
446af69d88dSmrg				struct glx_config *config_base,
447af69d88dSmrg				struct glx_context *shareList,
448af69d88dSmrg				unsigned num_attribs,
449af69d88dSmrg				const uint32_t *attribs,
450af69d88dSmrg				unsigned *error)
451af69d88dSmrg{
452af69d88dSmrg   int renderType = GLX_RGBA_TYPE;
453af69d88dSmrg   unsigned i;
454af69d88dSmrg
455af69d88dSmrg   /* The error parameter is only used on the server so that correct GLX
456af69d88dSmrg    * protocol errors can be generated.  On the client, it can be ignored.
457af69d88dSmrg    */
458af69d88dSmrg   (void) error;
459af69d88dSmrg
460af69d88dSmrg   /* All of the attribute validation for indirect contexts is handled on the
461af69d88dSmrg    * server, so there's not much to do here. Still, we need to parse the
462af69d88dSmrg    * attributes to correctly set renderType.
463af69d88dSmrg    */
464af69d88dSmrg   for (i = 0; i < num_attribs; i++) {
465af69d88dSmrg      if (attribs[i * 2] == GLX_RENDER_TYPE)
466af69d88dSmrg         renderType = attribs[i * 2 + 1];
467af69d88dSmrg   }
468af69d88dSmrg
469af69d88dSmrg   return indirect_create_context(base, config_base, shareList, renderType);
470af69d88dSmrg}
471af69d88dSmrg
472af69d88dSmrgstatic const struct glx_screen_vtable indirect_screen_vtable = {
473af69d88dSmrg   .create_context         = indirect_create_context,
474af69d88dSmrg   .create_context_attribs = indirect_create_context_attribs,
475af69d88dSmrg   .query_renderer_integer = NULL,
476af69d88dSmrg   .query_renderer_string  = NULL,
4773464ebd5Sriastradh};
4783464ebd5Sriastradh
4793464ebd5Sriastradh_X_HIDDEN struct glx_screen *
4803464ebd5Sriastradhindirect_create_screen(int screen, struct glx_display * priv)
4813464ebd5Sriastradh{
4823464ebd5Sriastradh   struct glx_screen *psc;
4833464ebd5Sriastradh
484af69d88dSmrg   psc = calloc(1, sizeof *psc);
4853464ebd5Sriastradh   if (psc == NULL)
4863464ebd5Sriastradh      return NULL;
4873464ebd5Sriastradh
4883464ebd5Sriastradh   glx_screen_init(psc, screen, priv);
4893464ebd5Sriastradh   psc->vtable = &indirect_screen_vtable;
4903464ebd5Sriastradh
4913464ebd5Sriastradh   return psc;
4923464ebd5Sriastradh}
493af69d88dSmrg
494af69d88dSmrg#endif
495