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#define NEED_REPLIES 35#include <X11/Xlibint.h> 36#include <X11/extensions/Xext.h> 37#include <X11/extensions/extutil.h> 38#include <X11/extensions/dri2proto.h> 39#include "xf86drm.h" 40#include "dri2.h" 41 42static char dri2ExtensionName[] = DRI2_NAME; 43static XExtensionInfo *dri2Info; 44static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) 45static /* const */ XExtensionHooks dri2ExtensionHooks = { 46 NULL, /* create_gc */ 47 NULL, /* copy_gc */ 48 NULL, /* flush_gc */ 49 NULL, /* free_gc */ 50 NULL, /* create_font */ 51 NULL, /* free_font */ 52 DRI2CloseDisplay, /* close_display */ 53 NULL, /* wire_to_event */ 54 NULL, /* event_to_wire */ 55 NULL, /* error */ 56 NULL, /* error_string */ 57}; 58 59static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, 60 dri2ExtensionName, 61 &dri2ExtensionHooks, 62 0, NULL) 63 64Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase) 65{ 66 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 67 68 if (XextHasExtension(info)) { 69 *eventBase = info->codes->first_event; 70 *errorBase = info->codes->first_error; 71 return True; 72 } 73 74 return False; 75} 76 77Bool DRI2QueryVersion(Display *dpy, int *major, int *minor) 78{ 79 XExtDisplayInfo *info = DRI2FindDisplay (dpy); 80 xDRI2QueryVersionReply rep; 81 xDRI2QueryVersionReq *req; 82 83 XextCheckExtension (dpy, info, dri2ExtensionName, False); 84 85 LockDisplay(dpy); 86 GetReq(DRI2QueryVersion, req); 87 req->reqType = info->codes->major_opcode; 88 req->dri2ReqType = X_DRI2QueryVersion; 89 req->majorVersion = DRI2_MAJOR; 90 req->minorVersion = DRI2_MINOR; 91 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 92 UnlockDisplay(dpy); 93 SyncHandle(); 94 return False; 95 } 96 *major = rep.majorVersion; 97 *minor = rep.minorVersion; 98 UnlockDisplay(dpy); 99 SyncHandle(); 100 101 return True; 102} 103 104Bool DRI2Connect(Display *dpy, XID window, 105 char **driverName, char **deviceName) 106{ 107 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 108 xDRI2ConnectReply rep; 109 xDRI2ConnectReq *req; 110 111 XextCheckExtension (dpy, info, dri2ExtensionName, False); 112 113 LockDisplay(dpy); 114 GetReq(DRI2Connect, req); 115 req->reqType = info->codes->major_opcode; 116 req->dri2ReqType = X_DRI2Connect; 117 req->window = window; 118 req->driverType = DRI2DriverDRI; 119 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 120 UnlockDisplay(dpy); 121 SyncHandle(); 122 return False; 123 } 124 125 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { 126 UnlockDisplay(dpy); 127 SyncHandle(); 128 return False; 129 } 130 131 *driverName = Xmalloc(rep.driverNameLength + 1); 132 if (*driverName == NULL) { 133 _XEatData(dpy, 134 ((rep.driverNameLength + 3) & ~3) + 135 ((rep.deviceNameLength + 3) & ~3)); 136 UnlockDisplay(dpy); 137 SyncHandle(); 138 return False; 139 } 140 _XReadPad(dpy, *driverName, rep.driverNameLength); 141 (*driverName)[rep.driverNameLength] = '\0'; 142 143 *deviceName = Xmalloc(rep.deviceNameLength + 1); 144 if (*deviceName == NULL) { 145 Xfree(*driverName); 146 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); 147 UnlockDisplay(dpy); 148 SyncHandle(); 149 return False; 150 } 151 _XReadPad(dpy, *deviceName, rep.deviceNameLength); 152 (*deviceName)[rep.deviceNameLength] = '\0'; 153 154 UnlockDisplay(dpy); 155 SyncHandle(); 156 157 return True; 158} 159 160Bool DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic) 161{ 162 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 163 xDRI2AuthenticateReq *req; 164 xDRI2AuthenticateReply rep; 165 166 XextCheckExtension (dpy, info, dri2ExtensionName, False); 167 168 LockDisplay(dpy); 169 GetReq(DRI2Authenticate, req); 170 req->reqType = info->codes->major_opcode; 171 req->dri2ReqType = X_DRI2Authenticate; 172 req->window = window; 173 req->magic = magic; 174 175 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 176 UnlockDisplay(dpy); 177 SyncHandle(); 178 return False; 179 } 180 181 UnlockDisplay(dpy); 182 SyncHandle(); 183 184 return rep.authenticated; 185} 186 187void DRI2CreateDrawable(Display *dpy, XID drawable) 188{ 189 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 190 xDRI2CreateDrawableReq *req; 191 192 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 193 194 LockDisplay(dpy); 195 GetReq(DRI2CreateDrawable, req); 196 req->reqType = info->codes->major_opcode; 197 req->dri2ReqType = X_DRI2CreateDrawable; 198 req->drawable = drawable; 199 UnlockDisplay(dpy); 200 SyncHandle(); 201} 202 203void DRI2DestroyDrawable(Display *dpy, XID drawable) 204{ 205 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 206 xDRI2DestroyDrawableReq *req; 207 208 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 209 210 XSync(dpy, False); 211 212 LockDisplay(dpy); 213 GetReq(DRI2DestroyDrawable, req); 214 req->reqType = info->codes->major_opcode; 215 req->dri2ReqType = X_DRI2DestroyDrawable; 216 req->drawable = drawable; 217 UnlockDisplay(dpy); 218 SyncHandle(); 219} 220 221DRI2Buffer *DRI2GetBuffers(Display *dpy, XID drawable, 222 int *width, int *height, 223 unsigned int *attachments, int count, 224 int *outCount) 225{ 226 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 227 xDRI2GetBuffersReply rep; 228 xDRI2GetBuffersReq *req; 229 DRI2Buffer *buffers; 230 xDRI2Buffer repBuffer; 231 CARD32 *p; 232 int i; 233 234 XextCheckExtension (dpy, info, dri2ExtensionName, False); 235 236 LockDisplay(dpy); 237 GetReqExtra(DRI2GetBuffers, count * 4, req); 238 req->reqType = info->codes->major_opcode; 239 req->dri2ReqType = X_DRI2GetBuffers; 240 req->drawable = drawable; 241 req->count = count; 242 p = (CARD32 *) &req[1]; 243 for (i = 0; i < count; i++) 244 p[i] = attachments[i]; 245 246 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 247 UnlockDisplay(dpy); 248 SyncHandle(); 249 return NULL; 250 } 251 252 *width = rep.width; 253 *height = rep.height; 254 *outCount = rep.count; 255 256 buffers = Xmalloc(rep.count * sizeof buffers[0]); 257 if (buffers == NULL) { 258 _XEatData(dpy, rep.count * sizeof repBuffer); 259 UnlockDisplay(dpy); 260 SyncHandle(); 261 return NULL; 262 } 263 264 for (i = 0; i < rep.count; i++) { 265 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 266 buffers[i].attachment = repBuffer.attachment; 267 buffers[i].name = repBuffer.name; 268 buffers[i].pitch = repBuffer.pitch; 269 buffers[i].cpp = repBuffer.cpp; 270 buffers[i].flags = repBuffer.flags; 271 } 272 273 UnlockDisplay(dpy); 274 SyncHandle(); 275 276 return buffers; 277} 278 279void DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region, 280 CARD32 dest, CARD32 src) 281{ 282 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 283 xDRI2CopyRegionReq *req; 284 xDRI2CopyRegionReply rep; 285 286 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 287 288 LockDisplay(dpy); 289 GetReq(DRI2CopyRegion, req); 290 req->reqType = info->codes->major_opcode; 291 req->dri2ReqType = X_DRI2CopyRegion; 292 req->drawable = drawable; 293 req->region = region; 294 req->dest = dest; 295 req->src = src; 296 297 _XReply(dpy, (xReply *)&rep, 0, xFalse); 298 299 UnlockDisplay(dpy); 300 SyncHandle(); 301} 302