1/* 2 * Copyright © 2008 Red Hat, Inc. 3 * Copyright © 2010-2015 NVIDIA Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Soft- 7 * ware"), to deal in the Software without restriction, including without 8 * limitation the rights to use, copy, modify, merge, publish, distribute, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, provided that the above copyright 11 * notice(s) and this permission notice appear in all copies of the Soft- 12 * ware and that both the above copyright notice(s) and this permission 13 * notice appear in supporting documentation. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 17 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 18 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 19 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 20 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 23 * MANCE OF THIS SOFTWARE. 24 * 25 * Except as contained in this notice, the name of a copyright holder shall 26 * not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization of 28 * the copyright holder. 29 * 30 * Authors: 31 * Kristian Høgsberg (krh@redhat.com) 32 * Modified for VDPAU by Aaron Plattner (aplattner@nvidia.com) 33 * and José Hiram Soltren (jsoltren@nvidia.com) 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#define NEED_REPLIES 41#include <X11/Xlibint.h> 42#include <X11/extensions/Xext.h> 43#include <X11/extensions/extutil.h> 44#include <X11/extensions/dri2proto.h> 45#include "mesa_dri2.h" 46#include "util.h" 47 48static char dri2ExtensionName[] = DRI2_NAME; 49static XExtensionInfo *dri2Info; 50 51static /* const */ XExtensionHooks dri2ExtensionHooks = { 52 NULL, /* create_gc */ 53 NULL, /* copy_gc */ 54 NULL, /* flush_gc */ 55 NULL, /* free_gc */ 56 NULL, /* create_font */ 57 NULL, /* free_font */ 58 NULL, /* close_display */ 59 NULL, /* wire_to_event */ 60 NULL, /* event_to_wire */ 61 NULL, /* error */ 62 NULL, /* error_string */ 63}; 64 65static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, 66 dri2Info, 67 dri2ExtensionName, 68 &dri2ExtensionHooks, 69 0, NULL) 70 71Bool 72_vdp_DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) 73{ 74 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 75 76 if (XextHasExtension(info)) { 77 *eventBase = info->codes->first_event; 78 *errorBase = info->codes->first_error; 79 return True; 80 } 81 82 if (dri2Info) { 83 if (info) { 84 XextRemoveDisplay(dri2Info, dpy); 85 } 86 XextDestroyExtension(dri2Info); 87 dri2Info = NULL; 88 } 89 90 return False; 91} 92 93Bool 94_vdp_DRI2QueryVersion(Display * dpy, int *major, int *minor) 95{ 96 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 97 xDRI2QueryVersionReply rep; 98 xDRI2QueryVersionReq *req; 99 100 XextCheckExtension(dpy, info, dri2ExtensionName, False); 101 102 LockDisplay(dpy); 103 GetReq(DRI2QueryVersion, req); 104 req->reqType = info->codes->major_opcode; 105 req->dri2ReqType = X_DRI2QueryVersion; 106 req->majorVersion = DRI2_MAJOR; 107 req->minorVersion = DRI2_MINOR; 108 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 109 UnlockDisplay(dpy); 110 SyncHandle(); 111 return False; 112 } 113 *major = rep.majorVersion; 114 *minor = rep.minorVersion; 115 UnlockDisplay(dpy); 116 SyncHandle(); 117 118 return True; 119} 120 121Bool 122_vdp_DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) 123{ 124 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 125 xDRI2ConnectReply rep; 126 xDRI2ConnectReq *req; 127 128 XextCheckExtension(dpy, info, dri2ExtensionName, False); 129 130 LockDisplay(dpy); 131 GetReq(DRI2Connect, req); 132 req->reqType = info->codes->major_opcode; 133 req->dri2ReqType = X_DRI2Connect; 134 req->window = window; 135 req->driverType = DRI2DriverVDPAU; 136#ifdef DRI2DriverPrimeShift 137 { 138 char *prime = getenv_wrapper("DRI_PRIME"); 139 if (prime) { 140 unsigned int primeid; 141 errno = 0; 142 primeid = strtoul(prime, NULL, 0); 143 if (errno == 0) 144 req->driverType |= 145 ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift); 146 } 147 } 148#endif 149 150 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 151 UnlockDisplay(dpy); 152 SyncHandle(); 153 return False; 154 } 155 156 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { 157 UnlockDisplay(dpy); 158 SyncHandle(); 159 return False; 160 } 161 162 *driverName = Xmalloc(rep.driverNameLength + 1); 163 if (*driverName == NULL) { 164 _XEatData(dpy, 165 ((rep.driverNameLength + 3) & ~3) + 166 ((rep.deviceNameLength + 3) & ~3)); 167 UnlockDisplay(dpy); 168 SyncHandle(); 169 return False; 170 } 171 _XReadPad(dpy, *driverName, rep.driverNameLength); 172 (*driverName)[rep.driverNameLength] = '\0'; 173 174 *deviceName = Xmalloc(rep.deviceNameLength + 1); 175 if (*deviceName == NULL) { 176 Xfree(*driverName); 177 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); 178 UnlockDisplay(dpy); 179 SyncHandle(); 180 return False; 181 } 182 _XReadPad(dpy, *deviceName, rep.deviceNameLength); 183 (*deviceName)[rep.deviceNameLength] = '\0'; 184 185 UnlockDisplay(dpy); 186 SyncHandle(); 187 188 return True; 189} 190 191void 192_vdp_DRI2RemoveExtension(Display * dpy) 193{ 194 XextRemoveDisplay(dri2Info, dpy); 195 XextDestroyExtension(dri2Info); 196 dri2Info = NULL; 197} 198