Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2008 Red Hat, Inc.
  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@redhat.com)
  31.  */
  32.  
  33.  
  34. #ifdef GLX_DIRECT_RENDERING
  35.  
  36. #include <stdio.h>
  37. #include <X11/Xlibint.h>
  38. #include <X11/extensions/Xext.h>
  39. #include <X11/extensions/extutil.h>
  40. #include <X11/extensions/dri2proto.h>
  41. #include "xf86drm.h"
  42. #include "dri2.h"
  43. #include "glxclient.h"
  44. #include "GL/glxext.h"
  45.  
  46. /* Allow the build to work with an older versions of dri2proto.h and
  47.  * dri2tokens.h.
  48.  */
  49. #if DRI2_MINOR < 1
  50. #undef DRI2_MINOR
  51. #define DRI2_MINOR 1
  52. #define X_DRI2GetBuffersWithFormat 7
  53. #endif
  54.  
  55.  
  56. static char dri2ExtensionName[] = DRI2_NAME;
  57. static XExtensionInfo *dri2Info;
  58. static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
  59.  
  60. static Bool
  61. DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
  62. static Status
  63. DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
  64. static int
  65. DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
  66.  
  67. static /* const */ XExtensionHooks dri2ExtensionHooks = {
  68.   NULL,                   /* create_gc */
  69.   NULL,                   /* copy_gc */
  70.   NULL,                   /* flush_gc */
  71.   NULL,                   /* free_gc */
  72.   NULL,                   /* create_font */
  73.   NULL,                   /* free_font */
  74.   DRI2CloseDisplay,       /* close_display */
  75.   DRI2WireToEvent,        /* wire_to_event */
  76.   DRI2EventToWire,        /* event_to_wire */
  77.   DRI2Error,              /* error */
  78.   NULL,                   /* error_string */
  79. };
  80.  
  81. static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
  82.                                    dri2Info,
  83.                                    dri2ExtensionName,
  84.                                    &dri2ExtensionHooks,
  85.                                    0, NULL)
  86.  
  87. static Bool
  88. DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
  89. {
  90.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  91.    struct glx_drawable *glxDraw;
  92.  
  93.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  94.  
  95.    switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
  96.  
  97. #ifdef X_DRI2SwapBuffers
  98.    case DRI2_BufferSwapComplete:
  99.    {
  100.       GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
  101.       xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire;
  102.       __GLXDRIdrawable *pdraw;
  103.  
  104.       pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable);
  105.  
  106.       /* Ignore swap events if we're not looking for them */
  107.       aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
  108.       if(!aevent->type)
  109.          return False;
  110.  
  111.       aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
  112.       aevent->send_event = (awire->type & 0x80) != 0;
  113.       aevent->display = dpy;
  114.       aevent->drawable = awire->drawable;
  115.       switch (awire->event_type) {
  116.       case DRI2_EXCHANGE_COMPLETE:
  117.          aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
  118.          break;
  119.       case DRI2_BLIT_COMPLETE:
  120.          aevent->event_type = GLX_COPY_COMPLETE_INTEL;
  121.          break;
  122.       case DRI2_FLIP_COMPLETE:
  123.          aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
  124.          break;
  125.       default:
  126.          /* unknown swap completion type */
  127.          return False;
  128.       }
  129.       aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
  130.       aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
  131.  
  132.       glxDraw = GetGLXDrawable(dpy, pdraw->drawable);
  133.       if (awire->sbc < glxDraw->lastEventSbc)
  134.          glxDraw->eventSbcWrap += 0x100000000;
  135.       glxDraw->lastEventSbc = awire->sbc;
  136.       aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
  137.  
  138.       return True;
  139.    }
  140. #endif
  141. #ifdef DRI2_InvalidateBuffers
  142.    case DRI2_InvalidateBuffers:
  143.    {
  144.       xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
  145.  
  146.       dri2InvalidateBuffers(dpy, awire->drawable);
  147.       return False;
  148.    }
  149. #endif
  150.    default:
  151.       /* client doesn't support server event */
  152.       break;
  153.    }
  154.  
  155.    return False;
  156. }
  157.  
  158. /* We don't actually support this.  It doesn't make sense for clients to
  159.  * send each other DRI2 events.
  160.  */
  161. static Status
  162. DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
  163. {
  164.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  165.  
  166.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  167.  
  168.    switch (event->type) {
  169.    default:
  170.       /* client doesn't support server event */
  171.       break;
  172.    }
  173.  
  174.    return Success;
  175. }
  176.  
  177. static int
  178. DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
  179. {
  180.     if (err->majorCode == codes->major_opcode &&
  181.         err->errorCode == BadDrawable &&
  182.         err->minorCode == X_DRI2CopyRegion)
  183.         return True;
  184.  
  185.     /* If the X drawable was destroyed before the GLX drawable, the
  186.      * DRI2 drawble will be gone by the time we call
  187.      * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
  188.     if (err->majorCode == codes->major_opcode &&
  189.         err->errorCode == BadDrawable &&
  190.         err->minorCode == X_DRI2DestroyDrawable)
  191.         return True;
  192.  
  193.     /* If the server is non-local DRI2Connect will raise BadRequest.
  194.      * Swallow this so that DRI2Connect can signal this in its return code */
  195.     if (err->majorCode == codes->major_opcode &&
  196.         err->minorCode == X_DRI2Connect &&
  197.         err->errorCode == BadRequest) {
  198.         *ret_code = False;
  199.         return True;
  200.     }
  201.  
  202.     return False;
  203. }
  204.  
  205. Bool
  206. DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
  207. {
  208.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  209.  
  210.    if (XextHasExtension(info)) {
  211.       *eventBase = info->codes->first_event;
  212.       *errorBase = info->codes->first_error;
  213.       return True;
  214.    }
  215.  
  216.    return False;
  217. }
  218.  
  219. Bool
  220. DRI2QueryVersion(Display * dpy, int *major, int *minor)
  221. {
  222.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  223.    xDRI2QueryVersionReply rep;
  224.    xDRI2QueryVersionReq *req;
  225.    int i, nevents;
  226.  
  227.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  228.  
  229.    LockDisplay(dpy);
  230.    GetReq(DRI2QueryVersion, req);
  231.    req->reqType = info->codes->major_opcode;
  232.    req->dri2ReqType = X_DRI2QueryVersion;
  233.    req->majorVersion = DRI2_MAJOR;
  234.    req->minorVersion = DRI2_MINOR;
  235.    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
  236.       UnlockDisplay(dpy);
  237.       SyncHandle();
  238.       return False;
  239.    }
  240.    *major = rep.majorVersion;
  241.    *minor = rep.minorVersion;
  242.    UnlockDisplay(dpy);
  243.    SyncHandle();
  244.  
  245.    switch (rep.minorVersion) {
  246.    case 1:
  247.            nevents = 0;
  248.            break;
  249.    case 2:
  250.            nevents = 1;
  251.            break;
  252.    case 3:
  253.    default:
  254.            nevents = 2;
  255.            break;
  256.    }
  257.        
  258.    for (i = 0; i < nevents; i++) {
  259.        XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
  260.        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
  261.    }
  262.  
  263.    return True;
  264. }
  265.  
  266. Bool
  267. DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
  268. {
  269.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  270.    xDRI2ConnectReply rep;
  271.    xDRI2ConnectReq *req;
  272.  
  273.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  274.  
  275.    LockDisplay(dpy);
  276.    GetReq(DRI2Connect, req);
  277.    req->reqType = info->codes->major_opcode;
  278.    req->dri2ReqType = X_DRI2Connect;
  279.    req->window = window;
  280.  
  281.    req->driverType = DRI2DriverDRI;
  282. #ifdef DRI2DriverPrimeShift
  283.    {
  284.       char *prime = getenv("DRI_PRIME");
  285.       if (prime) {
  286.          uint32_t primeid;
  287.          errno = 0;
  288.          primeid = strtoul(prime, NULL, 0);
  289.          if (errno == 0)
  290.             req->driverType |=
  291.                ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
  292.       }
  293.    }
  294. #endif
  295.  
  296.    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
  297.       UnlockDisplay(dpy);
  298.       SyncHandle();
  299.       return False;
  300.    }
  301.  
  302.    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
  303.       UnlockDisplay(dpy);
  304.       SyncHandle();
  305.       return False;
  306.    }
  307.  
  308.    *driverName = malloc(rep.driverNameLength + 1);
  309.    if (*driverName == NULL) {
  310.       _XEatData(dpy,
  311.                 ((rep.driverNameLength + 3) & ~3) +
  312.                 ((rep.deviceNameLength + 3) & ~3));
  313.       UnlockDisplay(dpy);
  314.       SyncHandle();
  315.       return False;
  316.    }
  317.    _XReadPad(dpy, *driverName, rep.driverNameLength);
  318.    (*driverName)[rep.driverNameLength] = '\0';
  319.  
  320.    *deviceName = malloc(rep.deviceNameLength + 1);
  321.    if (*deviceName == NULL) {
  322.       free(*driverName);
  323.       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
  324.       UnlockDisplay(dpy);
  325.       SyncHandle();
  326.       return False;
  327.    }
  328.    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
  329.    (*deviceName)[rep.deviceNameLength] = '\0';
  330.  
  331.    UnlockDisplay(dpy);
  332.    SyncHandle();
  333.  
  334.    return True;
  335. }
  336.  
  337. Bool
  338. DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
  339. {
  340.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  341.    xDRI2AuthenticateReq *req;
  342.    xDRI2AuthenticateReply rep;
  343.  
  344.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  345.  
  346.    LockDisplay(dpy);
  347.    GetReq(DRI2Authenticate, req);
  348.    req->reqType = info->codes->major_opcode;
  349.    req->dri2ReqType = X_DRI2Authenticate;
  350.    req->window = window;
  351.    req->magic = magic;
  352.  
  353.    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
  354.       UnlockDisplay(dpy);
  355.       SyncHandle();
  356.       return False;
  357.    }
  358.  
  359.    UnlockDisplay(dpy);
  360.    SyncHandle();
  361.  
  362.    return rep.authenticated;
  363. }
  364.  
  365. void
  366. DRI2CreateDrawable(Display * dpy, XID drawable)
  367. {
  368.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  369.    xDRI2CreateDrawableReq *req;
  370.  
  371.    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
  372.  
  373.    LockDisplay(dpy);
  374.    GetReq(DRI2CreateDrawable, req);
  375.    req->reqType = info->codes->major_opcode;
  376.    req->dri2ReqType = X_DRI2CreateDrawable;
  377.    req->drawable = drawable;
  378.    UnlockDisplay(dpy);
  379.    SyncHandle();
  380. }
  381.  
  382. void
  383. DRI2DestroyDrawable(Display * dpy, XID drawable)
  384. {
  385.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  386.    xDRI2DestroyDrawableReq *req;
  387.  
  388.    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
  389.  
  390.    XSync(dpy, False);
  391.  
  392.    LockDisplay(dpy);
  393.    GetReq(DRI2DestroyDrawable, req);
  394.    req->reqType = info->codes->major_opcode;
  395.    req->dri2ReqType = X_DRI2DestroyDrawable;
  396.    req->drawable = drawable;
  397.    UnlockDisplay(dpy);
  398.    SyncHandle();
  399. }
  400.  
  401. DRI2Buffer *
  402. DRI2GetBuffers(Display * dpy, XID drawable,
  403.                int *width, int *height,
  404.                unsigned int *attachments, int count, int *outCount)
  405. {
  406.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  407.    xDRI2GetBuffersReply rep;
  408.    xDRI2GetBuffersReq *req;
  409.    DRI2Buffer *buffers;
  410.    xDRI2Buffer repBuffer;
  411.    CARD32 *p;
  412.    int i;
  413.  
  414.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  415.  
  416.    LockDisplay(dpy);
  417.    GetReqExtra(DRI2GetBuffers, count * 4, req);
  418.    req->reqType = info->codes->major_opcode;
  419.    req->dri2ReqType = X_DRI2GetBuffers;
  420.    req->drawable = drawable;
  421.    req->count = count;
  422.    p = (CARD32 *) & req[1];
  423.    for (i = 0; i < count; i++)
  424.       p[i] = attachments[i];
  425.  
  426.    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
  427.       UnlockDisplay(dpy);
  428.       SyncHandle();
  429.       return NULL;
  430.    }
  431.  
  432.    *width = rep.width;
  433.    *height = rep.height;
  434.    *outCount = rep.count;
  435.  
  436.    buffers = malloc(rep.count * sizeof buffers[0]);
  437.    if (buffers == NULL) {
  438.       _XEatData(dpy, rep.count * sizeof repBuffer);
  439.       UnlockDisplay(dpy);
  440.       SyncHandle();
  441.       return NULL;
  442.    }
  443.  
  444.    for (i = 0; i < rep.count; i++) {
  445.       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
  446.       buffers[i].attachment = repBuffer.attachment;
  447.       buffers[i].name = repBuffer.name;
  448.       buffers[i].pitch = repBuffer.pitch;
  449.       buffers[i].cpp = repBuffer.cpp;
  450.       buffers[i].flags = repBuffer.flags;
  451.    }
  452.  
  453.    UnlockDisplay(dpy);
  454.    SyncHandle();
  455.  
  456.    return buffers;
  457. }
  458.  
  459.  
  460. DRI2Buffer *
  461. DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
  462.                          int *width, int *height,
  463.                          unsigned int *attachments, int count, int *outCount)
  464. {
  465.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  466.    xDRI2GetBuffersReply rep;
  467.    xDRI2GetBuffersReq *req;
  468.    DRI2Buffer *buffers;
  469.    xDRI2Buffer repBuffer;
  470.    CARD32 *p;
  471.    int i;
  472.  
  473.    XextCheckExtension(dpy, info, dri2ExtensionName, False);
  474.  
  475.    LockDisplay(dpy);
  476.    GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
  477.    req->reqType = info->codes->major_opcode;
  478.    req->dri2ReqType = X_DRI2GetBuffersWithFormat;
  479.    req->drawable = drawable;
  480.    req->count = count;
  481.    p = (CARD32 *) & req[1];
  482.    for (i = 0; i < (count * 2); i++)
  483.       p[i] = attachments[i];
  484.  
  485.    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
  486.       UnlockDisplay(dpy);
  487.       SyncHandle();
  488.       return NULL;
  489.    }
  490.  
  491.    *width = rep.width;
  492.    *height = rep.height;
  493.    *outCount = rep.count;
  494.  
  495.    buffers = malloc(rep.count * sizeof buffers[0]);
  496.    if (buffers == NULL) {
  497.       _XEatData(dpy, rep.count * sizeof repBuffer);
  498.       UnlockDisplay(dpy);
  499.       SyncHandle();
  500.       return NULL;
  501.    }
  502.  
  503.    for (i = 0; i < rep.count; i++) {
  504.       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
  505.       buffers[i].attachment = repBuffer.attachment;
  506.       buffers[i].name = repBuffer.name;
  507.       buffers[i].pitch = repBuffer.pitch;
  508.       buffers[i].cpp = repBuffer.cpp;
  509.       buffers[i].flags = repBuffer.flags;
  510.    }
  511.  
  512.    UnlockDisplay(dpy);
  513.    SyncHandle();
  514.  
  515.    return buffers;
  516. }
  517.  
  518.  
  519. void
  520. DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
  521.                CARD32 dest, CARD32 src)
  522. {
  523.    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
  524.    xDRI2CopyRegionReq *req;
  525.    xDRI2CopyRegionReply rep;
  526.  
  527.    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
  528.  
  529.    LockDisplay(dpy);
  530.    GetReq(DRI2CopyRegion, req);
  531.    req->reqType = info->codes->major_opcode;
  532.    req->dri2ReqType = X_DRI2CopyRegion;
  533.    req->drawable = drawable;
  534.    req->region = region;
  535.    req->dest = dest;
  536.    req->src = src;
  537.  
  538.    _XReply(dpy, (xReply *) & rep, 0, xFalse);
  539.  
  540.    UnlockDisplay(dpy);
  541.    SyncHandle();
  542. }
  543.  
  544. #endif /* GLX_DIRECT_RENDERING */
  545.