Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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 "glapi.h"
  34. #include "glxclient.h"
  35.  
  36. extern struct _glapi_table *__glXNewIndirectAPI(void);
  37.  
  38. /*
  39. ** All indirect rendering contexts will share the same indirect dispatch table.
  40. */
  41. static struct _glapi_table *IndirectAPI = NULL;
  42.  
  43. static void
  44. indirect_destroy_context(struct glx_context *gc)
  45. {
  46.    __glXFreeVertexArrayState(gc);
  47.  
  48.    free((char *) gc->vendor);
  49.    free((char *) gc->renderer);
  50.    free((char *) gc->version);
  51.    free((char *) gc->extensions);
  52.    __glFreeAttributeState(gc);
  53.    free((char *) gc->buf);
  54.    free((char *) gc->client_state_private);
  55.    free((char *) gc);
  56. }
  57.  
  58. static Bool
  59. SendMakeCurrentRequest(Display * dpy, CARD8 opcode,
  60.                        GLXContextID gc_id, GLXContextTag gc_tag,
  61.                        GLXDrawable draw, GLXDrawable read,
  62.                        xGLXMakeCurrentReply * reply)
  63. {
  64.    Bool ret;
  65.  
  66.    LockDisplay(dpy);
  67.  
  68.    if (draw == read) {
  69.       xGLXMakeCurrentReq *req;
  70.  
  71.       GetReq(GLXMakeCurrent, req);
  72.       req->reqType = opcode;
  73.       req->glxCode = X_GLXMakeCurrent;
  74.       req->drawable = draw;
  75.       req->context = gc_id;
  76.       req->oldContextTag = gc_tag;
  77.    }
  78.    else {
  79.       struct glx_display *priv = __glXInitialize(dpy);
  80.  
  81.       /* If the server can support the GLX 1.3 version, we should
  82.        * perfer that.  Not only that, some servers support GLX 1.3 but
  83.        * not the SGI extension.
  84.        */
  85.  
  86.       if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) {
  87.          xGLXMakeContextCurrentReq *req;
  88.  
  89.          GetReq(GLXMakeContextCurrent, req);
  90.          req->reqType = opcode;
  91.          req->glxCode = X_GLXMakeContextCurrent;
  92.          req->drawable = draw;
  93.          req->readdrawable = read;
  94.          req->context = gc_id;
  95.          req->oldContextTag = gc_tag;
  96.       }
  97.       else {
  98.          xGLXVendorPrivateWithReplyReq *vpreq;
  99.          xGLXMakeCurrentReadSGIReq *req;
  100.  
  101.          GetReqExtra(GLXVendorPrivateWithReply,
  102.                      sz_xGLXMakeCurrentReadSGIReq -
  103.                      sz_xGLXVendorPrivateWithReplyReq, vpreq);
  104.          req = (xGLXMakeCurrentReadSGIReq *) vpreq;
  105.          req->reqType = opcode;
  106.          req->glxCode = X_GLXVendorPrivateWithReply;
  107.          req->vendorCode = X_GLXvop_MakeCurrentReadSGI;
  108.          req->drawable = draw;
  109.          req->readable = read;
  110.          req->context = gc_id;
  111.          req->oldContextTag = gc_tag;
  112.       }
  113.    }
  114.  
  115.    ret = _XReply(dpy, (xReply *) reply, 0, False);
  116.  
  117.    UnlockDisplay(dpy);
  118.    SyncHandle();
  119.  
  120.    return ret;
  121. }
  122.  
  123. static int
  124. indirect_bind_context(struct glx_context *gc, struct glx_context *old,
  125.                       GLXDrawable draw, GLXDrawable read)
  126. {
  127.    xGLXMakeCurrentReply reply;
  128.    GLXContextTag tag;
  129.    __GLXattribute *state;
  130.    Display *dpy = gc->psc->dpy;
  131.    int opcode = __glXSetupForCommand(dpy);
  132.  
  133.    if (old != &dummyContext && !old->isDirect && old->psc->dpy == dpy) {
  134.       tag = old->currentContextTag;
  135.       old->currentContextTag = 0;
  136.    } else {
  137.       tag = 0;
  138.    }
  139.  
  140.    SendMakeCurrentRequest(dpy, opcode, gc->xid, tag, draw, read, &reply);
  141.  
  142.    if (!IndirectAPI)
  143.       IndirectAPI = __glXNewIndirectAPI();
  144.    _glapi_set_dispatch(IndirectAPI);
  145.  
  146.    gc->currentContextTag = reply.contextTag;
  147.    state = gc->client_state_private;
  148.    if (state->array_state == NULL) {
  149.       glGetString(GL_EXTENSIONS);
  150.       glGetString(GL_VERSION);
  151.       __glXInitVertexArrayState(gc);
  152.    }
  153.  
  154.    return Success;
  155. }
  156.  
  157. static void
  158. indirect_unbind_context(struct glx_context *gc, struct glx_context *new)
  159. {
  160.    Display *dpy = gc->psc->dpy;
  161.    int opcode = __glXSetupForCommand(dpy);
  162.    xGLXMakeCurrentReply reply;
  163.  
  164.    if (gc == new)
  165.       return;
  166.    
  167.    /* We are either switching to no context, away from a indirect
  168.     * context to a direct context or from one dpy to another and have
  169.     * to send a request to the dpy to unbind the previous context.
  170.     */
  171.    if (!new || new->isDirect || new->psc->dpy != dpy) {
  172.       SendMakeCurrentRequest(dpy, opcode, None,
  173.                              gc->currentContextTag, None, None, &reply);
  174.       gc->currentContextTag = 0;
  175.    }
  176. }
  177.  
  178. static void
  179. indirect_wait_gl(struct glx_context *gc)
  180. {
  181.    xGLXWaitGLReq *req;
  182.    Display *dpy = gc->currentDpy;
  183.  
  184.    /* Flush any pending commands out */
  185.    __glXFlushRenderBuffer(gc, gc->pc);
  186.  
  187.    /* Send the glXWaitGL request */
  188.    LockDisplay(dpy);
  189.    GetReq(GLXWaitGL, req);
  190.    req->reqType = gc->majorOpcode;
  191.    req->glxCode = X_GLXWaitGL;
  192.    req->contextTag = gc->currentContextTag;
  193.    UnlockDisplay(dpy);
  194.    SyncHandle();
  195. }
  196.  
  197. static void
  198. indirect_wait_x(struct glx_context *gc)
  199. {
  200.    xGLXWaitXReq *req;
  201.    Display *dpy = gc->currentDpy;
  202.  
  203.    /* Flush any pending commands out */
  204.    __glXFlushRenderBuffer(gc, gc->pc);
  205.  
  206.    LockDisplay(dpy);
  207.    GetReq(GLXWaitX, req);
  208.    req->reqType = gc->majorOpcode;
  209.    req->glxCode = X_GLXWaitX;
  210.    req->contextTag = gc->currentContextTag;
  211.    UnlockDisplay(dpy);
  212.    SyncHandle();
  213. }
  214.  
  215. static void
  216. indirect_use_x_font(struct glx_context *gc,
  217.                     Font font, int first, int count, int listBase)
  218. {
  219.    xGLXUseXFontReq *req;
  220.    Display *dpy = gc->currentDpy;
  221.  
  222.    /* Flush any pending commands out */
  223.    __glXFlushRenderBuffer(gc, gc->pc);
  224.  
  225.    /* Send the glXUseFont request */
  226.    LockDisplay(dpy);
  227.    GetReq(GLXUseXFont, req);
  228.    req->reqType = gc->majorOpcode;
  229.    req->glxCode = X_GLXUseXFont;
  230.    req->contextTag = gc->currentContextTag;
  231.    req->font = font;
  232.    req->first = first;
  233.    req->count = count;
  234.    req->listBase = listBase;
  235.    UnlockDisplay(dpy);
  236.    SyncHandle();
  237. }
  238.  
  239. static void
  240. indirect_bind_tex_image(Display * dpy,
  241.                         GLXDrawable drawable,
  242.                         int buffer, const int *attrib_list)
  243. {
  244.    xGLXVendorPrivateReq *req;
  245.    struct glx_context *gc = __glXGetCurrentContext();
  246.    CARD32 *drawable_ptr;
  247.    INT32 *buffer_ptr;
  248.    CARD32 *num_attrib_ptr;
  249.    CARD32 *attrib_ptr;
  250.    CARD8 opcode;
  251.    unsigned int i;
  252.  
  253.    i = 0;
  254.    if (attrib_list) {
  255.       while (attrib_list[i * 2] != None)
  256.          i++;
  257.    }
  258.  
  259.    opcode = __glXSetupForCommand(dpy);
  260.    if (!opcode)
  261.       return;
  262.  
  263.    LockDisplay(dpy);
  264.    GetReqExtra(GLXVendorPrivate, 12 + 8 * i, req);
  265.    req->reqType = opcode;
  266.    req->glxCode = X_GLXVendorPrivate;
  267.    req->vendorCode = X_GLXvop_BindTexImageEXT;
  268.    req->contextTag = gc->currentContextTag;
  269.  
  270.    drawable_ptr = (CARD32 *) (req + 1);
  271.    buffer_ptr = (INT32 *) (drawable_ptr + 1);
  272.    num_attrib_ptr = (CARD32 *) (buffer_ptr + 1);
  273.    attrib_ptr = (CARD32 *) (num_attrib_ptr + 1);
  274.  
  275.    *drawable_ptr = drawable;
  276.    *buffer_ptr = buffer;
  277.    *num_attrib_ptr = (CARD32) i;
  278.  
  279.    i = 0;
  280.    if (attrib_list) {
  281.       while (attrib_list[i * 2] != None) {
  282.          *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 0];
  283.          *attrib_ptr++ = (CARD32) attrib_list[i * 2 + 1];
  284.          i++;
  285.       }
  286.    }
  287.  
  288.    UnlockDisplay(dpy);
  289.    SyncHandle();
  290. }
  291.  
  292. static void
  293. indirect_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
  294. {
  295.    xGLXVendorPrivateReq *req;
  296.    struct glx_context *gc = __glXGetCurrentContext();
  297.    CARD32 *drawable_ptr;
  298.    INT32 *buffer_ptr;
  299.    CARD8 opcode;
  300.  
  301.    opcode = __glXSetupForCommand(dpy);
  302.    if (!opcode)
  303.       return;
  304.  
  305.    LockDisplay(dpy);
  306.    GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32), req);
  307.    req->reqType = opcode;
  308.    req->glxCode = X_GLXVendorPrivate;
  309.    req->vendorCode = X_GLXvop_ReleaseTexImageEXT;
  310.    req->contextTag = gc->currentContextTag;
  311.  
  312.    drawable_ptr = (CARD32 *) (req + 1);
  313.    buffer_ptr = (INT32 *) (drawable_ptr + 1);
  314.  
  315.    *drawable_ptr = drawable;
  316.    *buffer_ptr = buffer;
  317.  
  318.    UnlockDisplay(dpy);
  319.    SyncHandle();
  320. }
  321.  
  322. static const struct glx_context_vtable indirect_context_vtable = {
  323.    indirect_destroy_context,
  324.    indirect_bind_context,
  325.    indirect_unbind_context,
  326.    indirect_wait_gl,
  327.    indirect_wait_x,
  328.    indirect_use_x_font,
  329.    indirect_bind_tex_image,
  330.    indirect_release_tex_image,
  331.    NULL, /* get_proc_address */
  332. };
  333.  
  334. /**
  335.  * \todo Eliminate \c __glXInitVertexArrayState.  Replace it with a new
  336.  * function called \c __glXAllocateClientState that allocates the memory and
  337.  * does all the initialization (including the pixel pack / unpack).
  338.  *
  339.  * \note
  340.  * This function is \b not the place to validate the context creation
  341.  * parameters.  It is just the allocator for the \c glx_context.
  342.  */
  343. _X_HIDDEN struct glx_context *
  344. indirect_create_context(struct glx_screen *psc,
  345.                         struct glx_config *mode,
  346.                         struct glx_context *shareList, int renderType)
  347. {
  348.    struct glx_context *gc;
  349.    int bufSize;
  350.    CARD8 opcode;
  351.    __GLXattribute *state;
  352.  
  353.    opcode = __glXSetupForCommand(psc->dpy);
  354.    if (!opcode) {
  355.       return NULL;
  356.    }
  357.  
  358.    /* Allocate our context record */
  359.    gc = calloc(1, sizeof *gc);
  360.    if (!gc) {
  361.       /* Out of memory */
  362.       return NULL;
  363.    }
  364.  
  365.    glx_context_init(gc, psc, mode);
  366.    gc->isDirect = GL_FALSE;
  367.    gc->vtable = &indirect_context_vtable;
  368.    state = calloc(1, sizeof(struct __GLXattributeRec));
  369.    gc->renderType = renderType;
  370.  
  371.    if (state == NULL) {
  372.       /* Out of memory */
  373.       free(gc);
  374.       return NULL;
  375.    }
  376.    gc->client_state_private = state;
  377.    state->NoDrawArraysProtocol = (getenv("LIBGL_NO_DRAWARRAYS") != NULL);
  378.  
  379.    /*
  380.     ** Create a temporary buffer to hold GLX rendering commands.  The size
  381.     ** of the buffer is selected so that the maximum number of GLX rendering
  382.     ** commands can fit in a single X packet and still have room in the X
  383.     ** packet for the GLXRenderReq header.
  384.     */
  385.  
  386.    bufSize = (XMaxRequestSize(psc->dpy) * 4) - sz_xGLXRenderReq;
  387.    gc->buf = malloc(bufSize);
  388.    if (!gc->buf) {
  389.       free(gc->client_state_private);
  390.       free(gc);
  391.       return NULL;
  392.    }
  393.    gc->bufSize = bufSize;
  394.  
  395.    /* Fill in the new context */
  396.    gc->renderMode = GL_RENDER;
  397.  
  398.    state->storePack.alignment = 4;
  399.    state->storeUnpack.alignment = 4;
  400.  
  401.    gc->attributes.stackPointer = &gc->attributes.stack[0];
  402.  
  403.    /*
  404.     ** PERFORMANCE NOTE: A mode dependent fill image can speed things up.
  405.     */
  406.    gc->fillImage = __glFillImage;
  407.    gc->pc = gc->buf;
  408.    gc->bufEnd = gc->buf + bufSize;
  409.    gc->isDirect = GL_FALSE;
  410.    if (__glXDebug) {
  411.       /*
  412.        ** Set limit register so that there will be one command per packet
  413.        */
  414.       gc->limit = gc->buf;
  415.    }
  416.    else {
  417.       gc->limit = gc->buf + bufSize - __GLX_BUFFER_LIMIT_SIZE;
  418.    }
  419.    gc->majorOpcode = opcode;
  420.  
  421.    /*
  422.     ** Constrain the maximum drawing command size allowed to be
  423.     ** transfered using the X_GLXRender protocol request.  First
  424.     ** constrain by a software limit, then constrain by the protocl
  425.     ** limit.
  426.     */
  427.    if (bufSize > __GLX_RENDER_CMD_SIZE_LIMIT) {
  428.       bufSize = __GLX_RENDER_CMD_SIZE_LIMIT;
  429.    }
  430.    if (bufSize > __GLX_MAX_RENDER_CMD_SIZE) {
  431.       bufSize = __GLX_MAX_RENDER_CMD_SIZE;
  432.    }
  433.    gc->maxSmallRenderCommandSize = bufSize;
  434.    
  435.  
  436.    return gc;
  437. }
  438.  
  439. _X_HIDDEN struct glx_context *
  440. indirect_create_context_attribs(struct glx_screen *base,
  441.                                 struct glx_config *config_base,
  442.                                 struct glx_context *shareList,
  443.                                 unsigned num_attribs,
  444.                                 const uint32_t *attribs,
  445.                                 unsigned *error)
  446. {
  447.    int renderType = GLX_RGBA_TYPE;
  448.    unsigned i;
  449.  
  450.    /* The error parameter is only used on the server so that correct GLX
  451.     * protocol errors can be generated.  On the client, it can be ignored.
  452.     */
  453.    (void) error;
  454.  
  455.    /* All of the attribute validation for indirect contexts is handled on the
  456.     * server, so there's not much to do here. Still, we need to parse the
  457.     * attributes to correctly set renderType.
  458.     */
  459.    for (i = 0; i < num_attribs; i++) {
  460.       if (attribs[i * 2] == GLX_RENDER_TYPE)
  461.          renderType = attribs[i * 2 + 1];
  462.    }
  463.  
  464.    return indirect_create_context(base, config_base, shareList, renderType);
  465. }
  466.  
  467. struct glx_screen_vtable indirect_screen_vtable = {
  468.    indirect_create_context,
  469.    indirect_create_context_attribs
  470. };
  471.  
  472. _X_HIDDEN struct glx_screen *
  473. indirect_create_screen(int screen, struct glx_display * priv)
  474. {
  475.    struct glx_screen *psc;
  476.  
  477.    psc = calloc(1, sizeof *psc);
  478.    if (psc == NULL)
  479.       return NULL;
  480.  
  481.    glx_screen_init(psc, screen, priv);
  482.    psc->vtable = &indirect_screen_vtable;
  483.  
  484.    return psc;
  485. }
  486.