indirect_glx.c revision 01e04c3f
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
3301e04c3fSmrg#include <stdbool.h>
3401e04c3fSmrg
353464ebd5Sriastradh#include "glapi.h"
363464ebd5Sriastradh#include "glxclient.h"
373464ebd5Sriastradh
3801e04c3fSmrg#include "util/debug.h"
3901e04c3fSmrg
40af69d88dSmrg#ifndef GLX_USE_APPLEGL
41af69d88dSmrg
423464ebd5Sriastradhextern struct _glapi_table *__glXNewIndirectAPI(void);
433464ebd5Sriastradh
443464ebd5Sriastradh/*
453464ebd5Sriastradh** All indirect rendering contexts will share the same indirect dispatch table.
463464ebd5Sriastradh*/
473464ebd5Sriastradhstatic struct _glapi_table *IndirectAPI = NULL;
483464ebd5Sriastradh
493464ebd5Sriastradhstatic void
503464ebd5Sriastradhindirect_destroy_context(struct glx_context *gc)
513464ebd5Sriastradh{
523464ebd5Sriastradh   __glXFreeVertexArrayState(gc);
533464ebd5Sriastradh
54af69d88dSmrg   free((char *) gc->vendor);
55af69d88dSmrg   free((char *) gc->renderer);
56af69d88dSmrg   free((char *) gc->version);
57af69d88dSmrg   free((char *) gc->extensions);
583464ebd5Sriastradh   __glFreeAttributeState(gc);
59af69d88dSmrg   free((char *) gc->buf);
60af69d88dSmrg   free((char *) gc->client_state_private);
61af69d88dSmrg   free((char *) gc);
623464ebd5Sriastradh}
633464ebd5Sriastradh
643464ebd5Sriastradhstatic Bool
6501e04c3fSmrgSendMakeCurrentRequest(Display * dpy, GLXContextID gc_id,
6601e04c3fSmrg                       GLXContextTag gc_tag, GLXDrawable draw,
6701e04c3fSmrg                       GLXDrawable read, GLXContextTag *out_tag)
683464ebd5Sriastradh{
69af69d88dSmrg   xGLXMakeCurrentReply reply;
703464ebd5Sriastradh   Bool ret;
7101e04c3fSmrg   int opcode = __glXSetupForCommand(dpy);
723464ebd5Sriastradh
733464ebd5Sriastradh   LockDisplay(dpy);
743464ebd5Sriastradh
753464ebd5Sriastradh   if (draw == read) {
763464ebd5Sriastradh      xGLXMakeCurrentReq *req;
773464ebd5Sriastradh
783464ebd5Sriastradh      GetReq(GLXMakeCurrent, req);
793464ebd5Sriastradh      req->reqType = opcode;
803464ebd5Sriastradh      req->glxCode = X_GLXMakeCurrent;
813464ebd5Sriastradh      req->drawable = draw;
823464ebd5Sriastradh      req->context = gc_id;
833464ebd5Sriastradh      req->oldContextTag = gc_tag;
843464ebd5Sriastradh   }
853464ebd5Sriastradh   else {
863464ebd5Sriastradh      struct glx_display *priv = __glXInitialize(dpy);
873464ebd5Sriastradh
883464ebd5Sriastradh      /* If the server can support the GLX 1.3 version, we should
893464ebd5Sriastradh       * perfer that.  Not only that, some servers support GLX 1.3 but
903464ebd5Sriastradh       * not the SGI extension.
913464ebd5Sriastradh       */
923464ebd5Sriastradh
933464ebd5Sriastradh      if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
943464ebd5Sriastradh         xGLXMakeContextCurrentReq *req;
953464ebd5Sriastradh
963464ebd5Sriastradh         GetReq(GLXMakeContextCurrent, req);
973464ebd5Sriastradh         req->reqType = opcode;
983464ebd5Sriastradh         req->glxCode = X_GLXMakeContextCurrent;
993464ebd5Sriastradh         req->drawable = draw;
1003464ebd5Sriastradh         req->readdrawable = read;
1013464ebd5Sriastradh         req->context = gc_id;
1023464ebd5Sriastradh         req->oldContextTag = gc_tag;
1033464ebd5Sriastradh      }
1043464ebd5Sriastradh      else {
1053464ebd5Sriastradh         xGLXVendorPrivateWithReplyReq *vpreq;
1063464ebd5Sriastradh         xGLXMakeCurrentReadSGIReq *req;
1073464ebd5Sriastradh
1083464ebd5Sriastradh         GetReqExtra(GLXVendorPrivateWithReply,
1093464ebd5Sriastradh                     sz_xGLXMakeCurrentReadSGIReq -
1103464ebd5Sriastradh                     sz_xGLXVendorPrivateWithReplyReq, vpreq);
1113464ebd5Sriastradh         req = (xGLXMakeCurrentReadSGIReq *) vpreq;
1123464ebd5Sriastradh         req->reqType = opcode;
1133464ebd5Sriastradh         req->glxCode = X_GLXVendorPrivateWithReply;
1143464ebd5Sriastradh         req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
1153464ebd5Sriastradh         req->drawable = draw;
1163464ebd5Sriastradh         req->readable = read;
1173464ebd5Sriastradh         req->context = gc_id;
1183464ebd5Sriastradh         req->oldContextTag = gc_tag;
1193464ebd5Sriastradh      }
1203464ebd5Sriastradh   }
1213464ebd5Sriastradh
122af69d88dSmrg   ret = _XReply(dpy, (xReply *) &reply, 0, False);
123af69d88dSmrg
124af69d88dSmrg   if (out_tag)
125af69d88dSmrg      *out_tag = reply.contextTag;
1263464ebd5Sriastradh
1273464ebd5Sriastradh   UnlockDisplay(dpy);
1283464ebd5Sriastradh   SyncHandle();
1293464ebd5Sriastradh
1303464ebd5Sriastradh   return ret;
1313464ebd5Sriastradh}
1323464ebd5Sriastradh
1333464ebd5Sriastradhstatic int
1343464ebd5Sriastradhindirect_bind_context(struct glx_context *gc, struct glx_context *old,
1353464ebd5Sriastradh		      GLXDrawable draw, GLXDrawable read)
1363464ebd5Sriastradh{
1373464ebd5Sriastradh   GLXContextTag tag;
1383464ebd5Sriastradh   Display *dpy = gc->psc->dpy;
139af69d88dSmrg   Bool sent;
1403464ebd5Sriastradh
1413464ebd5Sriastradh   if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
1423464ebd5Sriastradh      tag = old->currentContextTag;
1433464ebd5Sriastradh      old->currentContextTag = 0;
1443464ebd5Sriastradh   } else {
1453464ebd5Sriastradh      tag = 0;
1463464ebd5Sriastradh   }
1473464ebd5Sriastradh
14801e04c3fSmrg   sent = SendMakeCurrentRequest(dpy, gc->xid, tag, draw, read,
149af69d88dSmrg				 &gc->currentContextTag);
1503464ebd5Sriastradh
1513464ebd5Sriastradh   if (!IndirectAPI)
1523464ebd5Sriastradh      IndirectAPI = __glXNewIndirectAPI();
1533464ebd5Sriastradh   _glapi_set_dispatch(IndirectAPI);
1543464ebd5Sriastradh
155af69d88dSmrg   return !sent;
1563464ebd5Sriastradh}
1573464ebd5Sriastradh
1583464ebd5Sriastradhstatic void
1593464ebd5Sriastradhindirect_unbind_context(struct glx_context *gc, struct glx_context *new)
1603464ebd5Sriastradh{
1613464ebd5Sriastradh   Display *dpy = gc->psc->dpy;
1623464ebd5Sriastradh
1633464ebd5Sriastradh   if (gc == new)
1643464ebd5Sriastradh      return;
1653464ebd5Sriastradh
16601e04c3fSmrg   /* We are either switching to no context, away from an indirect
1673464ebd5Sriastradh    * context to a direct context or from one dpy to another and have
1683464ebd5Sriastradh    * to send a request to the dpy to unbind the previous context.
1693464ebd5Sriastradh    */
1703464ebd5Sriastradh   if (!new || new->isDirect || new->psc->dpy != dpy) {
17101e04c3fSmrg      SendMakeCurrentRequest(dpy, None, gc->currentContextTag, None, None,
17201e04c3fSmrg                             NULL);
1733464ebd5Sriastradh      gc->currentContextTag = 0;
1743464ebd5Sriastradh   }
1753464ebd5Sriastradh}
1763464ebd5Sriastradh
1773464ebd5Sriastradhstatic void
1783464ebd5Sriastradhindirect_wait_gl(struct glx_context *gc)
1793464ebd5Sriastradh{
1803464ebd5Sriastradh   xGLXWaitGLReq *req;
1813464ebd5Sriastradh   Display *dpy = gc->currentDpy;
1823464ebd5Sriastradh
1833464ebd5Sriastradh   /* Flush any pending commands out */
1843464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
1853464ebd5Sriastradh
1863464ebd5Sriastradh   /* Send the glXWaitGL request */
1873464ebd5Sriastradh   LockDisplay(dpy);
1883464ebd5Sriastradh   GetReq(GLXWaitGL, req);
1893464ebd5Sriastradh   req->reqType = gc->majorOpcode;
1903464ebd5Sriastradh   req->glxCode = X_GLXWaitGL;
1913464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
1923464ebd5Sriastradh   UnlockDisplay(dpy);
1933464ebd5Sriastradh   SyncHandle();
1943464ebd5Sriastradh}
1953464ebd5Sriastradh
1963464ebd5Sriastradhstatic void
1973464ebd5Sriastradhindirect_wait_x(struct glx_context *gc)
1983464ebd5Sriastradh{
1993464ebd5Sriastradh   xGLXWaitXReq *req;
2003464ebd5Sriastradh   Display *dpy = gc->currentDpy;
2013464ebd5Sriastradh
2023464ebd5Sriastradh   /* Flush any pending commands out */
2033464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
2043464ebd5Sriastradh
2053464ebd5Sriastradh   LockDisplay(dpy);
2063464ebd5Sriastradh   GetReq(GLXWaitX, req);
2073464ebd5Sriastradh   req->reqType = gc->majorOpcode;
2083464ebd5Sriastradh   req->glxCode = X_GLXWaitX;
2093464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2103464ebd5Sriastradh   UnlockDisplay(dpy);
2113464ebd5Sriastradh   SyncHandle();
2123464ebd5Sriastradh}
2133464ebd5Sriastradh
2143464ebd5Sriastradhstatic void
2153464ebd5Sriastradhindirect_use_x_font(struct glx_context *gc,
2163464ebd5Sriastradh		    Font font, int first, int count, int listBase)
2173464ebd5Sriastradh{
2183464ebd5Sriastradh   xGLXUseXFontReq *req;
2193464ebd5Sriastradh   Display *dpy = gc->currentDpy;
2203464ebd5Sriastradh
2213464ebd5Sriastradh   /* Flush any pending commands out */
2223464ebd5Sriastradh   __glXFlushRenderBuffer(gc, gc->pc);
2233464ebd5Sriastradh
2243464ebd5Sriastradh   /* Send the glXUseFont request */
2253464ebd5Sriastradh   LockDisplay(dpy);
2263464ebd5Sriastradh   GetReq(GLXUseXFont, req);
2273464ebd5Sriastradh   req->reqType = gc->majorOpcode;
2283464ebd5Sriastradh   req->glxCode = X_GLXUseXFont;
2293464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2303464ebd5Sriastradh   req->font = font;
2313464ebd5Sriastradh   req->first = first;
2323464ebd5Sriastradh   req->count = count;
2333464ebd5Sriastradh   req->listBase = listBase;
2343464ebd5Sriastradh   UnlockDisplay(dpy);
2353464ebd5Sriastradh   SyncHandle();
2363464ebd5Sriastradh}
2373464ebd5Sriastradh
2383464ebd5Sriastradhstatic void
2393464ebd5Sriastradhindirect_bind_tex_image(Display * dpy,
2403464ebd5Sriastradh			GLXDrawable drawable,
2413464ebd5Sriastradh			int buffer, const int *attrib_list)
2423464ebd5Sriastradh{
2433464ebd5Sriastradh   xGLXVendorPrivateReq *req;
2443464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
2453464ebd5Sriastradh   CARD32 *drawable_ptr;
2463464ebd5Sriastradh   INT32 *buffer_ptr;
2473464ebd5Sriastradh   CARD32 *num_attrib_ptr;
2483464ebd5Sriastradh   CARD32 *attrib_ptr;
2493464ebd5Sriastradh   CARD8 opcode;
2503464ebd5Sriastradh   unsigned int i;
2513464ebd5Sriastradh
2523464ebd5Sriastradh   i = 0;
2533464ebd5Sriastradh   if (attrib_list) {
2543464ebd5Sriastradh      while (attrib_list[i * 2] != None)
2553464ebd5Sriastradh         i++;
2563464ebd5Sriastradh   }
2573464ebd5Sriastradh
2583464ebd5Sriastradh   opcode = __glXSetupForCommand(dpy);
2593464ebd5Sriastradh   if (!opcode)
2603464ebd5Sriastradh      return;
2613464ebd5Sriastradh
2623464ebd5Sriastradh   LockDisplay(dpy);
2633464ebd5Sriastradh   GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
2643464ebd5Sriastradh   req->reqType = opcode;
2653464ebd5Sriastradh   req->glxCode = X_GLXVendorPrivate;
2663464ebd5Sriastradh   req->vendorCode = X_GLXvop_BindTexImageEXT;
2673464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
2683464ebd5Sriastradh
2693464ebd5Sriastradh   drawable_ptr = (CARD32 *) (req + 1);
2703464ebd5Sriastradh   buffer_ptr = (INT32 *) (drawable_ptr + 1);
2713464ebd5Sriastradh   num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
2723464ebd5Sriastradh   attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
2733464ebd5Sriastradh
2743464ebd5Sriastradh   *drawable_ptr = drawable;
2753464ebd5Sriastradh   *buffer_ptr = buffer;
2763464ebd5Sriastradh   *num_attrib_ptr = (CARD32) i;
2773464ebd5Sriastradh
2783464ebd5Sriastradh   i = 0;
2793464ebd5Sriastradh   if (attrib_list) {
2803464ebd5Sriastradh      while (attrib_list[i * 2] != None) {
2813464ebd5Sriastradh         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
2823464ebd5Sriastradh         *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
2833464ebd5Sriastradh         i++;
2843464ebd5Sriastradh      }
2853464ebd5Sriastradh   }
2863464ebd5Sriastradh
2873464ebd5Sriastradh   UnlockDisplay(dpy);
2883464ebd5Sriastradh   SyncHandle();
2893464ebd5Sriastradh}
2903464ebd5Sriastradh
2913464ebd5Sriastradhstatic void
2923464ebd5Sriastradhindirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
2933464ebd5Sriastradh{
2943464ebd5Sriastradh   xGLXVendorPrivateReq *req;
2953464ebd5Sriastradh   struct glx_context *gc = __glXGetCurrentContext();
2963464ebd5Sriastradh   CARD32 *drawable_ptr;
2973464ebd5Sriastradh   INT32 *buffer_ptr;
2983464ebd5Sriastradh   CARD8 opcode;
2993464ebd5Sriastradh
3003464ebd5Sriastradh   opcode = __glXSetupForCommand(dpy);
3013464ebd5Sriastradh   if (!opcode)
3023464ebd5Sriastradh      return;
3033464ebd5Sriastradh
3043464ebd5Sriastradh   LockDisplay(dpy);
3053464ebd5Sriastradh   GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
3063464ebd5Sriastradh   req->reqType = opcode;
3073464ebd5Sriastradh   req->glxCode = X_GLXVendorPrivate;
3083464ebd5Sriastradh   req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
3093464ebd5Sriastradh   req->contextTag = gc->currentContextTag;
3103464ebd5Sriastradh
3113464ebd5Sriastradh   drawable_ptr = (CARD32 *) (req + 1);
3123464ebd5Sriastradh   buffer_ptr = (INT32 *) (drawable_ptr + 1);
3133464ebd5Sriastradh
3143464ebd5Sriastradh   *drawable_ptr = drawable;
3153464ebd5Sriastradh   *buffer_ptr = buffer;
3163464ebd5Sriastradh
3173464ebd5Sriastradh   UnlockDisplay(dpy);
3183464ebd5Sriastradh   SyncHandle();
3193464ebd5Sriastradh}
3203464ebd5Sriastradh
3213464ebd5Sriastradhstatic const struct glx_context_vtable indirect_context_vtable = {
322af69d88dSmrg   .destroy             = indirect_destroy_context,
323af69d88dSmrg   .bind                = indirect_bind_context,
324af69d88dSmrg   .unbind              = indirect_unbind_context,
325af69d88dSmrg   .wait_gl             = indirect_wait_gl,
326af69d88dSmrg   .wait_x              = indirect_wait_x,
327af69d88dSmrg   .use_x_font          = indirect_use_x_font,
328af69d88dSmrg   .bind_tex_image      = indirect_bind_tex_image,
329af69d88dSmrg   .release_tex_image   = indirect_release_tex_image,
330af69d88dSmrg   .get_proc_address    = NULL,
3313464ebd5Sriastradh};
3323464ebd5Sriastradh
3333464ebd5Sriastradh/**
3343464ebd5Sriastradh * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
3353464ebd5Sriastradh * function called \c __glXAllocateClientState that allocates the memory and
3363464ebd5Sriastradh * does all the initialization (including the pixel pack / unpack).
337af69d88dSmrg *
338af69d88dSmrg * \note
339af69d88dSmrg * This function is \b not the place to validate the context creation
340af69d88dSmrg * parameters.  It is just the allocator for the \c glx_context.
3413464ebd5Sriastradh */
3423464ebd5Sriastradh_X_HIDDEN struct glx_context *
3433464ebd5Sriastradhindirect_create_context(struct glx_screen *psc,
3443464ebd5Sriastradh			struct glx_config *mode,
3453464ebd5Sriastradh			struct glx_context *shareList, int renderType)
3463464ebd5Sriastradh{
3473464ebd5Sriastradh   struct glx_context *gc;
3483464ebd5Sriastradh   int bufSize;
3493464ebd5Sriastradh   CARD8 opcode;
3503464ebd5Sriastradh   __GLXattribute *state;
3513464ebd5Sriastradh
3523464ebd5Sriastradh   opcode = __glXSetupForCommand(psc->dpy);
3533464ebd5Sriastradh   if (!opcode) {
3543464ebd5Sriastradh      return NULL;
3553464ebd5Sriastradh   }
3563464ebd5Sriastradh
3573464ebd5Sriastradh   /* Allocate our context record */
358af69d88dSmrg   gc = calloc(1, sizeof *gc);
3593464ebd5Sriastradh   if (!gc) {
3603464ebd5Sriastradh      /* Out of memory */
3613464ebd5Sriastradh      return NULL;
3623464ebd5Sriastradh   }
3633464ebd5Sriastradh
3643464ebd5Sriastradh   glx_context_init(gc, psc, mode);
3653464ebd5Sriastradh   gc->isDirect = GL_FALSE;
3663464ebd5Sriastradh   gc->vtable = &indirect_context_vtable;
367af69d88dSmrg   state = calloc(1, sizeof(struct __GLXattributeRec));
368af69d88dSmrg   gc->renderType = renderType;
369af69d88dSmrg
3703464ebd5Sriastradh   if (state == NULL) {
3713464ebd5Sriastradh      /* Out of memory */
372af69d88dSmrg      free(gc);
3733464ebd5Sriastradh      return NULL;
3743464ebd5Sriastradh   }
3753464ebd5Sriastradh   gc->client_state_private = state;
37601e04c3fSmrg   state->NoDrawArraysProtocol = env_var_as_boolean("LIBGL_NO_DRAWARRAYS", false);
3773464ebd5Sriastradh
3783464ebd5Sriastradh   /*
3793464ebd5Sriastradh    ** Create a temporary buffer to hold GLX rendering commands.  The size
3803464ebd5Sriastradh    ** of the buffer is selected so that the maximum number of GLX rendering
3813464ebd5Sriastradh    ** commands can fit in a single X packet and still have room in the X
3823464ebd5Sriastradh    ** packet for the GLXRenderReq header.
3833464ebd5Sriastradh    */
3843464ebd5Sriastradh
3853464ebd5Sriastradh   bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
386af69d88dSmrg   gc->buf = malloc(bufSize);
3873464ebd5Sriastradh   if (!gc->buf) {
388af69d88dSmrg      free(gc->client_state_private);
389af69d88dSmrg      free(gc);
3903464ebd5Sriastradh      return NULL;
3913464ebd5Sriastradh   }
3923464ebd5Sriastradh   gc->bufSize = bufSize;
3933464ebd5Sriastradh
3943464ebd5Sriastradh   /* Fill in the new context */
3953464ebd5Sriastradh   gc->renderMode = GL_RENDER;
3963464ebd5Sriastradh
3973464ebd5Sriastradh   state->storePack.alignment = 4;
3983464ebd5Sriastradh   state->storeUnpack.alignment = 4;
3993464ebd5Sriastradh
4003464ebd5Sriastradh   gc->attributes.stackPointer = &gc->attributes.stack[0];
4013464ebd5Sriastradh
4023464ebd5Sriastradh   /*
4033464ebd5Sriastradh    ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
4043464ebd5Sriastradh    */
4053464ebd5Sriastradh   gc->fillImage = __glFillImage;
4063464ebd5Sriastradh   gc->pc = gc->buf;
4073464ebd5Sriastradh   gc->bufEnd = gc->buf + bufSize;
4083464ebd5Sriastradh   gc->isDirect = GL_FALSE;
4093464ebd5Sriastradh   if (__glXDebug) {
4103464ebd5Sriastradh      /*
4113464ebd5Sriastradh       ** Set limit register so that there will be one command per packet
4123464ebd5Sriastradh       */
4133464ebd5Sriastradh      gc->limit = gc->buf;
4143464ebd5Sriastradh   }
4153464ebd5Sriastradh   else {
4163464ebd5Sriastradh      gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
4173464ebd5Sriastradh   }
4183464ebd5Sriastradh   gc->majorOpcode = opcode;
4193464ebd5Sriastradh
4203464ebd5Sriastradh   /*
4213464ebd5Sriastradh    ** Constrain the maximum drawing command size allowed to be
4223464ebd5Sriastradh    ** transfered using the X_GLXRender protocol request.  First
4233464ebd5Sriastradh    ** constrain by a software limit, then constrain by the protocl
4243464ebd5Sriastradh    ** limit.
4253464ebd5Sriastradh    */
4263464ebd5Sriastradh   if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
4273464ebd5Sriastradh      bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
4283464ebd5Sriastradh   }
4293464ebd5Sriastradh   if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
4303464ebd5Sriastradh      bufSize = __GLX_MAX_RENDER_CMD_SIZE;
4313464ebd5Sriastradh   }
4323464ebd5Sriastradh   gc->maxSmallRenderCommandSize = bufSize;
4333464ebd5Sriastradh
4343464ebd5Sriastradh
4353464ebd5Sriastradh   return gc;
4363464ebd5Sriastradh}
4373464ebd5Sriastradh
438af69d88dSmrg_X_HIDDEN struct glx_context *
439af69d88dSmrgindirect_create_context_attribs(struct glx_screen *base,
440af69d88dSmrg				struct glx_config *config_base,
441af69d88dSmrg				struct glx_context *shareList,
442af69d88dSmrg				unsigned num_attribs,
443af69d88dSmrg				const uint32_t *attribs,
444af69d88dSmrg				unsigned *error)
445af69d88dSmrg{
446af69d88dSmrg   int renderType = GLX_RGBA_TYPE;
447af69d88dSmrg   unsigned i;
448af69d88dSmrg
449af69d88dSmrg   /* The error parameter is only used on the server so that correct GLX
450af69d88dSmrg    * protocol errors can be generated.  On the client, it can be ignored.
451af69d88dSmrg    */
452af69d88dSmrg   (void) error;
453af69d88dSmrg
454af69d88dSmrg   /* All of the attribute validation for indirect contexts is handled on the
455af69d88dSmrg    * server, so there's not much to do here. Still, we need to parse the
456af69d88dSmrg    * attributes to correctly set renderType.
457af69d88dSmrg    */
458af69d88dSmrg   for (i = 0; i < num_attribs; i++) {
459af69d88dSmrg      if (attribs[i * 2] == GLX_RENDER_TYPE)
460af69d88dSmrg         renderType = attribs[i * 2 + 1];
461af69d88dSmrg   }
462af69d88dSmrg
463af69d88dSmrg   return indirect_create_context(base, config_base, shareList, renderType);
464af69d88dSmrg}
465af69d88dSmrg
466af69d88dSmrgstatic const struct glx_screen_vtable indirect_screen_vtable = {
467af69d88dSmrg   .create_context         = indirect_create_context,
468af69d88dSmrg   .create_context_attribs = indirect_create_context_attribs,
469af69d88dSmrg   .query_renderer_integer = NULL,
470af69d88dSmrg   .query_renderer_string  = NULL,
4713464ebd5Sriastradh};
4723464ebd5Sriastradh
4733464ebd5Sriastradh_X_HIDDEN struct glx_screen *
4743464ebd5Sriastradhindirect_create_screen(int screen, struct glx_display * priv)
4753464ebd5Sriastradh{
4763464ebd5Sriastradh   struct glx_screen *psc;
4773464ebd5Sriastradh
478af69d88dSmrg   psc = calloc(1, sizeof *psc);
4793464ebd5Sriastradh   if (psc == NULL)
4803464ebd5Sriastradh      return NULL;
4813464ebd5Sriastradh
4823464ebd5Sriastradh   glx_screen_init(psc, screen, priv);
4833464ebd5Sriastradh   psc->vtable = &indirect_screen_vtable;
4843464ebd5Sriastradh
4853464ebd5Sriastradh   return psc;
4863464ebd5Sriastradh}
487af69d88dSmrg
488af69d88dSmrg#endif
489