Home | History | Annotate | Download | only in x11
      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 Hgsberg (krh (at) redhat.com)
     31  */
     32 
     33 
     34 #define NEED_REPLIES
     35 #include <X11/Xlibint.h>
     36 #include <X11/extensions/Xext.h>
     37 #include <X11/extensions/extutil.h>
     38 #include "xf86drm.h"
     39 #include "va_dri2.h"
     40 #include "va_dri2str.h"
     41 #include "va_dri2tokens.h"
     42 
     43 #ifndef DRI2DriverDRI
     44 #define DRI2DriverDRI 0
     45 #endif
     46 
     47 static int
     48 VA_DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code);
     49 
     50 static char va_dri2ExtensionName[] = DRI2_NAME;
     51 static XExtensionInfo _va_dri2_info_data;
     52 static XExtensionInfo *va_dri2Info = &_va_dri2_info_data;
     53 static XEXT_GENERATE_CLOSE_DISPLAY (VA_DRI2CloseDisplay, va_dri2Info)
     54 static /* const */ XExtensionHooks va_dri2ExtensionHooks = {
     55     NULL,				/* create_gc */
     56     NULL,				/* copy_gc */
     57     NULL,				/* flush_gc */
     58     NULL,				/* free_gc */
     59     NULL,				/* create_font */
     60     NULL,				/* free_font */
     61     VA_DRI2CloseDisplay,		/* close_display */
     62     NULL,				/* wire_to_event */
     63     NULL,				/* event_to_wire */
     64     VA_DRI2Error,			/* error */
     65     NULL,				/* error_string */
     66 };
     67 
     68 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, va_dri2Info,
     69 				   va_dri2ExtensionName,
     70 				   &va_dri2ExtensionHooks,
     71 				   0, NULL)
     72 
     73 static int
     74 VA_DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
     75 {
     76     /*
     77      * If the X drawable was destroyed before the VA drawable, the DRI2 drawable
     78      * will be gone by the time we call VA_DRI2DestroyDrawable(). So, simply
     79      * ignore BadDrawable errors in that case.
     80      */
     81     if (err->majorCode == codes->major_opcode &&
     82         err->errorCode == BadDrawable &&
     83         err->minorCode == X_DRI2DestroyDrawable)
     84 	return True;
     85 
     86     return False;
     87 }
     88 
     89 Bool VA_DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase)
     90 {
     91     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
     92 
     93     if (XextHasExtension(info)) {
     94 	*eventBase = info->codes->first_event;
     95 	*errorBase = info->codes->first_error;
     96 	return True;
     97     }
     98 
     99     return False;
    100 }
    101 
    102 Bool VA_DRI2QueryVersion(Display *dpy, int *major, int *minor)
    103 {
    104     XExtDisplayInfo *info = DRI2FindDisplay (dpy);
    105     xDRI2QueryVersionReply rep;
    106     xDRI2QueryVersionReq *req;
    107 
    108     XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
    109 
    110     LockDisplay(dpy);
    111     GetReq(DRI2QueryVersion, req);
    112     req->reqType = info->codes->major_opcode;
    113     req->dri2ReqType = X_DRI2QueryVersion;
    114     req->majorVersion = DRI2_MAJOR;
    115     req->minorVersion = DRI2_MINOR;
    116     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    117 	UnlockDisplay(dpy);
    118 	SyncHandle();
    119 	return False;
    120     }
    121     *major = rep.majorVersion;
    122     *minor = rep.minorVersion;
    123     UnlockDisplay(dpy);
    124     SyncHandle();
    125 
    126     return True;
    127 }
    128 
    129 Bool VA_DRI2Connect(Display *dpy, XID window,
    130 		 char **driverName, char **deviceName)
    131 {
    132     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    133     xDRI2ConnectReply rep;
    134     xDRI2ConnectReq *req;
    135 
    136     XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
    137 
    138     LockDisplay(dpy);
    139     GetReq(DRI2Connect, req);
    140     req->reqType = info->codes->major_opcode;
    141     req->dri2ReqType = X_DRI2Connect;
    142     req->window = window;
    143     req->driverType = DRI2DriverDRI;
    144     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    145 	UnlockDisplay(dpy);
    146 	SyncHandle();
    147 	return False;
    148     }
    149 
    150     if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
    151 	UnlockDisplay(dpy);
    152 	SyncHandle();
    153 	return False;
    154     }
    155 
    156     *driverName = Xmalloc(rep.driverNameLength + 1);
    157     if (*driverName == NULL) {
    158 	_XEatData(dpy,
    159 		  ((rep.driverNameLength + 3) & ~3) +
    160 		  ((rep.deviceNameLength + 3) & ~3));
    161 	UnlockDisplay(dpy);
    162 	SyncHandle();
    163 	return False;
    164     }
    165     _XReadPad(dpy, *driverName, rep.driverNameLength);
    166     (*driverName)[rep.driverNameLength] = '\0';
    167 
    168     *deviceName = Xmalloc(rep.deviceNameLength + 1);
    169     if (*deviceName == NULL) {
    170 	Xfree(*driverName);
    171 	_XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
    172 	UnlockDisplay(dpy);
    173 	SyncHandle();
    174 	return False;
    175     }
    176     _XReadPad(dpy, *deviceName, rep.deviceNameLength);
    177     (*deviceName)[rep.deviceNameLength] = '\0';
    178 
    179     UnlockDisplay(dpy);
    180     SyncHandle();
    181 
    182     return True;
    183 }
    184 
    185 Bool VA_DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic)
    186 {
    187     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    188     xDRI2AuthenticateReq *req;
    189     xDRI2AuthenticateReply rep;
    190 
    191     XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
    192 
    193     LockDisplay(dpy);
    194     GetReq(DRI2Authenticate, req);
    195     req->reqType = info->codes->major_opcode;
    196     req->dri2ReqType = X_DRI2Authenticate;
    197     req->window = window;
    198     req->magic = magic;
    199 
    200     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    201 	UnlockDisplay(dpy);
    202 	SyncHandle();
    203 	return False;
    204     }
    205 
    206     UnlockDisplay(dpy);
    207     SyncHandle();
    208 
    209     return rep.authenticated;
    210 }
    211 
    212 void VA_DRI2CreateDrawable(Display *dpy, XID drawable)
    213 {
    214     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    215     xDRI2CreateDrawableReq *req;
    216 
    217     XextSimpleCheckExtension (dpy, info, va_dri2ExtensionName);
    218 
    219     LockDisplay(dpy);
    220     GetReq(DRI2CreateDrawable, req);
    221     req->reqType = info->codes->major_opcode;
    222     req->dri2ReqType = X_DRI2CreateDrawable;
    223     req->drawable = drawable;
    224     UnlockDisplay(dpy);
    225     SyncHandle();
    226 }
    227 
    228 void VA_DRI2DestroyDrawable(Display *dpy, XID drawable)
    229 {
    230     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    231     xDRI2DestroyDrawableReq *req;
    232 
    233     XextSimpleCheckExtension (dpy, info, va_dri2ExtensionName);
    234 
    235     XSync(dpy, False);
    236 
    237     LockDisplay(dpy);
    238     GetReq(DRI2DestroyDrawable, req);
    239     req->reqType = info->codes->major_opcode;
    240     req->dri2ReqType = X_DRI2DestroyDrawable;
    241     req->drawable = drawable;
    242     UnlockDisplay(dpy);
    243     SyncHandle();
    244 }
    245 
    246 VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
    247 			   int *width, int *height,
    248 			   unsigned int *attachments, int count,
    249 			   int *outCount)
    250 {
    251     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    252     xDRI2GetBuffersReply rep;
    253     xDRI2GetBuffersReq *req;
    254     VA_DRI2Buffer *buffers;
    255     xDRI2Buffer repBuffer;
    256     CARD32 *p;
    257     int i;
    258 
    259     XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
    260 
    261     LockDisplay(dpy);
    262     GetReqExtra(DRI2GetBuffers, count * 4, req);
    263     req->reqType = info->codes->major_opcode;
    264     req->dri2ReqType = X_DRI2GetBuffers;
    265     req->drawable = drawable;
    266     req->count = count;
    267     p = (CARD32 *) &req[1];
    268     for (i = 0; i < count; i++)
    269 	p[i] = attachments[i];
    270 
    271     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    272 	UnlockDisplay(dpy);
    273 	SyncHandle();
    274 	return NULL;
    275     }
    276 
    277     *width = rep.width;
    278     *height = rep.height;
    279     *outCount = rep.count;
    280 
    281     buffers = Xmalloc(rep.count * sizeof buffers[0]);
    282     if (buffers == NULL) {
    283 	_XEatData(dpy, rep.count * sizeof repBuffer);
    284 	UnlockDisplay(dpy);
    285 	SyncHandle();
    286 	return NULL;
    287     }
    288 
    289     for (i = 0; i < rep.count; i++) {
    290 	_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
    291 	buffers[i].attachment = repBuffer.attachment;
    292 	buffers[i].name = repBuffer.name;
    293 	buffers[i].pitch = repBuffer.pitch;
    294 	buffers[i].cpp = repBuffer.cpp;
    295 	buffers[i].flags = repBuffer.flags;
    296     }
    297 
    298     UnlockDisplay(dpy);
    299     SyncHandle();
    300 
    301     return buffers;
    302 }
    303 
    304 void VA_DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region,
    305 		    CARD32 dest, CARD32 src)
    306 {
    307     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    308     xDRI2CopyRegionReq *req;
    309     xDRI2CopyRegionReply rep;
    310 
    311     XextSimpleCheckExtension (dpy, info, va_dri2ExtensionName);
    312 
    313     LockDisplay(dpy);
    314     GetReq(DRI2CopyRegion, req);
    315     req->reqType = info->codes->major_opcode;
    316     req->dri2ReqType = X_DRI2CopyRegion;
    317     req->drawable = drawable;
    318     req->region = region;
    319     req->dest = dest;
    320     req->src = src;
    321 
    322     _XReply(dpy, (xReply *)&rep, 0, xFalse);
    323 
    324     UnlockDisplay(dpy);
    325     SyncHandle();
    326 }
    327 
    328 static void
    329 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
    330               CARD64 remainder)
    331 {
    332     req->target_msc_hi = target >> 32;
    333     req->target_msc_lo = target & 0xffffffff;
    334     req->divisor_hi = divisor >> 32;
    335     req->divisor_lo = divisor & 0xffffffff;
    336     req->remainder_hi = remainder >> 32;
    337     req->remainder_lo = remainder & 0xffffffff;
    338 }
    339 
    340 static CARD64
    341 vals_to_card64(CARD32 lo, CARD32 hi)
    342 {
    343     return (CARD64)hi << 32 | lo;
    344 }
    345 
    346 void VA_DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
    347                         CARD64 divisor, CARD64 remainder, CARD64 *count)
    348 {
    349     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    350     xDRI2SwapBuffersReq *req;
    351     xDRI2SwapBuffersReply rep;
    352 
    353     XextSimpleCheckExtension (dpy, info, va_dri2ExtensionName);
    354 
    355     LockDisplay(dpy);
    356     GetReq(DRI2SwapBuffers, req);
    357     req->reqType = info->codes->major_opcode;
    358     req->dri2ReqType = X_DRI2SwapBuffers;
    359     req->drawable = drawable;
    360     load_swap_req(req, target_msc, divisor, remainder);
    361 
    362     _XReply(dpy, (xReply *)&rep, 0, xFalse);
    363 
    364     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
    365 
    366     UnlockDisplay(dpy);
    367     SyncHandle();
    368 }
    369