1848b8605Smrg/* 2848b8605Smrg * Copyright © 2008 Red Hat, Inc. 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Soft- 6848b8605Smrg * ware"), to deal in the Software without restriction, including without 7848b8605Smrg * limitation the rights to use, copy, modify, merge, publish, distribute, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, provided that the above copyright 10848b8605Smrg * notice(s) and this permission notice appear in all copies of the Soft- 11848b8605Smrg * ware and that both the above copyright notice(s) and this permission 12848b8605Smrg * notice appear in supporting documentation. 13848b8605Smrg * 14848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16848b8605Smrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17848b8605Smrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18848b8605Smrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19848b8605Smrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20848b8605Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21848b8605Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22848b8605Smrg * MANCE OF THIS SOFTWARE. 23848b8605Smrg * 24848b8605Smrg * Except as contained in this notice, the name of a copyright holder shall 25848b8605Smrg * not be used in advertising or otherwise to promote the sale, use or 26848b8605Smrg * other dealings in this Software without prior written authorization of 27848b8605Smrg * the copyright holder. 28848b8605Smrg * 29848b8605Smrg * Authors: 30848b8605Smrg * Kristian Høgsberg (krh@redhat.com) 31848b8605Smrg */ 32848b8605Smrg 33848b8605Smrg 34848b8605Smrg#ifdef GLX_DIRECT_RENDERING 35848b8605Smrg 36848b8605Smrg#include <stdio.h> 37848b8605Smrg#include <X11/Xlibint.h> 38848b8605Smrg#include <X11/extensions/Xext.h> 39848b8605Smrg#include <X11/extensions/extutil.h> 40848b8605Smrg#include <X11/extensions/dri2proto.h> 41848b8605Smrg#include "dri2.h" 42848b8605Smrg#include "glxclient.h" 43848b8605Smrg#include "GL/glxext.h" 44848b8605Smrg 45848b8605Smrg/* Allow the build to work with an older versions of dri2proto.h and 46848b8605Smrg * dri2tokens.h. 47848b8605Smrg */ 48848b8605Smrg#if DRI2_MINOR < 1 49848b8605Smrg#undef DRI2_MINOR 50848b8605Smrg#define DRI2_MINOR 1 51848b8605Smrg#define X_DRI2GetBuffersWithFormat 7 52848b8605Smrg#endif 53848b8605Smrg 54848b8605Smrg 55848b8605Smrgstatic char dri2ExtensionName[] = DRI2_NAME; 56b8e80941Smrgstatic XExtensionInfo _dri2Info_data; 57b8e80941Smrgstatic XExtensionInfo *dri2Info = &_dri2Info_data; 58848b8605Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) 59848b8605Smrg 60848b8605Smrgstatic Bool 61848b8605SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire); 62848b8605Smrgstatic Status 63848b8605SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire); 64848b8605Smrgstatic int 65848b8605SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code); 66848b8605Smrg 67848b8605Smrgstatic /* const */ XExtensionHooks dri2ExtensionHooks = { 68848b8605Smrg NULL, /* create_gc */ 69848b8605Smrg NULL, /* copy_gc */ 70848b8605Smrg NULL, /* flush_gc */ 71848b8605Smrg NULL, /* free_gc */ 72848b8605Smrg NULL, /* create_font */ 73848b8605Smrg NULL, /* free_font */ 74848b8605Smrg DRI2CloseDisplay, /* close_display */ 75848b8605Smrg DRI2WireToEvent, /* wire_to_event */ 76848b8605Smrg DRI2EventToWire, /* event_to_wire */ 77848b8605Smrg DRI2Error, /* error */ 78848b8605Smrg NULL, /* error_string */ 79848b8605Smrg}; 80848b8605Smrg 81848b8605Smrgstatic XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, 82848b8605Smrg dri2Info, 83848b8605Smrg dri2ExtensionName, 84848b8605Smrg &dri2ExtensionHooks, 85848b8605Smrg 0, NULL) 86848b8605Smrg 87848b8605Smrgstatic Bool 88848b8605SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) 89848b8605Smrg{ 90848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 91848b8605Smrg struct glx_drawable *glxDraw; 92848b8605Smrg 93848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 94848b8605Smrg 95848b8605Smrg switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { 96848b8605Smrg 97848b8605Smrg case DRI2_BufferSwapComplete: 98848b8605Smrg { 99848b8605Smrg GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 100848b8605Smrg xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire; 101848b8605Smrg __GLXDRIdrawable *pdraw; 102848b8605Smrg 103848b8605Smrg pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable); 104848b8605Smrg if (pdraw == NULL) 105848b8605Smrg return False; 106848b8605Smrg 107848b8605Smrg /* Ignore swap events if we're not looking for them */ 108848b8605Smrg aevent->type = dri2GetSwapEventType(dpy, awire->drawable); 109848b8605Smrg if(!aevent->type) 110848b8605Smrg return False; 111848b8605Smrg 112848b8605Smrg aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 113848b8605Smrg aevent->send_event = (awire->type & 0x80) != 0; 114848b8605Smrg aevent->display = dpy; 115848b8605Smrg aevent->drawable = awire->drawable; 116848b8605Smrg switch (awire->event_type) { 117848b8605Smrg case DRI2_EXCHANGE_COMPLETE: 118848b8605Smrg aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL; 119848b8605Smrg break; 120848b8605Smrg case DRI2_BLIT_COMPLETE: 121848b8605Smrg aevent->event_type = GLX_COPY_COMPLETE_INTEL; 122848b8605Smrg break; 123848b8605Smrg case DRI2_FLIP_COMPLETE: 124848b8605Smrg aevent->event_type = GLX_FLIP_COMPLETE_INTEL; 125848b8605Smrg break; 126848b8605Smrg default: 127848b8605Smrg /* unknown swap completion type */ 128848b8605Smrg return False; 129848b8605Smrg } 130848b8605Smrg aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 131848b8605Smrg aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 132848b8605Smrg 133848b8605Smrg glxDraw = GetGLXDrawable(dpy, pdraw->drawable); 134848b8605Smrg if (glxDraw != NULL) { 135848b8605Smrg if (awire->sbc < glxDraw->lastEventSbc) 136848b8605Smrg glxDraw->eventSbcWrap += 0x100000000; 137848b8605Smrg glxDraw->lastEventSbc = awire->sbc; 138848b8605Smrg aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 139848b8605Smrg } else { 140848b8605Smrg aevent->sbc = awire->sbc; 141848b8605Smrg } 142848b8605Smrg 143848b8605Smrg return True; 144848b8605Smrg } 145848b8605Smrg case DRI2_InvalidateBuffers: 146848b8605Smrg { 147848b8605Smrg xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; 148848b8605Smrg 149848b8605Smrg dri2InvalidateBuffers(dpy, awire->drawable); 150848b8605Smrg return False; 151848b8605Smrg } 152848b8605Smrg default: 153848b8605Smrg /* client doesn't support server event */ 154848b8605Smrg break; 155848b8605Smrg } 156848b8605Smrg 157848b8605Smrg return False; 158848b8605Smrg} 159848b8605Smrg 160848b8605Smrg/* We don't actually support this. It doesn't make sense for clients to 161848b8605Smrg * send each other DRI2 events. 162848b8605Smrg */ 163848b8605Smrgstatic Status 164848b8605SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire) 165848b8605Smrg{ 166848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 167848b8605Smrg 168848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 169848b8605Smrg 170848b8605Smrg switch (event->type) { 171848b8605Smrg default: 172848b8605Smrg /* client doesn't support server event */ 173848b8605Smrg break; 174848b8605Smrg } 175848b8605Smrg 176848b8605Smrg return Success; 177848b8605Smrg} 178848b8605Smrg 179848b8605Smrgstatic int 180848b8605SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code) 181848b8605Smrg{ 182848b8605Smrg if (err->majorCode == codes->major_opcode && 183848b8605Smrg err->errorCode == BadDrawable && 184848b8605Smrg err->minorCode == X_DRI2CopyRegion) 185848b8605Smrg return True; 186848b8605Smrg 187848b8605Smrg /* If the X drawable was destroyed before the GLX drawable, the 188848b8605Smrg * DRI2 drawble will be gone by the time we call 189848b8605Smrg * DRI2DestroyDrawable. So just ignore BadDrawable here. */ 190848b8605Smrg if (err->majorCode == codes->major_opcode && 191848b8605Smrg err->errorCode == BadDrawable && 192848b8605Smrg err->minorCode == X_DRI2DestroyDrawable) 193848b8605Smrg return True; 194848b8605Smrg 195848b8605Smrg /* If the server is non-local DRI2Connect will raise BadRequest. 196848b8605Smrg * Swallow this so that DRI2Connect can signal this in its return code */ 197848b8605Smrg if (err->majorCode == codes->major_opcode && 198848b8605Smrg err->minorCode == X_DRI2Connect && 199848b8605Smrg err->errorCode == BadRequest) { 200848b8605Smrg *ret_code = False; 201848b8605Smrg return True; 202848b8605Smrg } 203848b8605Smrg 204848b8605Smrg return False; 205848b8605Smrg} 206848b8605Smrg 207848b8605SmrgBool 208848b8605SmrgDRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) 209848b8605Smrg{ 210848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 211848b8605Smrg 212848b8605Smrg if (XextHasExtension(info)) { 213848b8605Smrg *eventBase = info->codes->first_event; 214848b8605Smrg *errorBase = info->codes->first_error; 215848b8605Smrg return True; 216848b8605Smrg } 217848b8605Smrg 218848b8605Smrg return False; 219848b8605Smrg} 220848b8605Smrg 221848b8605SmrgBool 222848b8605SmrgDRI2QueryVersion(Display * dpy, int *major, int *minor) 223848b8605Smrg{ 224848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 225848b8605Smrg xDRI2QueryVersionReply rep; 226848b8605Smrg xDRI2QueryVersionReq *req; 227848b8605Smrg int i, nevents; 228848b8605Smrg 229848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 230848b8605Smrg 231848b8605Smrg LockDisplay(dpy); 232848b8605Smrg GetReq(DRI2QueryVersion, req); 233848b8605Smrg req->reqType = info->codes->major_opcode; 234848b8605Smrg req->dri2ReqType = X_DRI2QueryVersion; 235848b8605Smrg req->majorVersion = DRI2_MAJOR; 236848b8605Smrg req->minorVersion = DRI2_MINOR; 237848b8605Smrg if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 238848b8605Smrg UnlockDisplay(dpy); 239848b8605Smrg SyncHandle(); 240848b8605Smrg return False; 241848b8605Smrg } 242848b8605Smrg *major = rep.majorVersion; 243848b8605Smrg *minor = rep.minorVersion; 244848b8605Smrg UnlockDisplay(dpy); 245848b8605Smrg SyncHandle(); 246848b8605Smrg 247848b8605Smrg switch (rep.minorVersion) { 248848b8605Smrg case 1: 249848b8605Smrg nevents = 0; 250848b8605Smrg break; 251848b8605Smrg case 2: 252848b8605Smrg nevents = 1; 253848b8605Smrg break; 254848b8605Smrg case 3: 255848b8605Smrg default: 256848b8605Smrg nevents = 2; 257848b8605Smrg break; 258848b8605Smrg } 259848b8605Smrg 260848b8605Smrg for (i = 0; i < nevents; i++) { 261848b8605Smrg XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent); 262848b8605Smrg XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire); 263848b8605Smrg } 264848b8605Smrg 265848b8605Smrg return True; 266848b8605Smrg} 267848b8605Smrg 268848b8605SmrgBool 269848b8605SmrgDRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) 270848b8605Smrg{ 271848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 272848b8605Smrg xDRI2ConnectReply rep; 273848b8605Smrg xDRI2ConnectReq *req; 274848b8605Smrg 275848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 276848b8605Smrg 277848b8605Smrg LockDisplay(dpy); 278848b8605Smrg GetReq(DRI2Connect, req); 279848b8605Smrg req->reqType = info->codes->major_opcode; 280848b8605Smrg req->dri2ReqType = X_DRI2Connect; 281848b8605Smrg req->window = window; 282848b8605Smrg 283848b8605Smrg req->driverType = DRI2DriverDRI; 284848b8605Smrg { 285848b8605Smrg char *prime = getenv("DRI_PRIME"); 286848b8605Smrg if (prime) { 287848b8605Smrg uint32_t primeid; 288848b8605Smrg errno = 0; 289848b8605Smrg primeid = strtoul(prime, NULL, 0); 290848b8605Smrg if (errno == 0) 291848b8605Smrg req->driverType |= 292848b8605Smrg ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift); 293848b8605Smrg } 294848b8605Smrg } 295848b8605Smrg 296848b8605Smrg if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 297848b8605Smrg UnlockDisplay(dpy); 298848b8605Smrg SyncHandle(); 299848b8605Smrg return False; 300848b8605Smrg } 301848b8605Smrg 302848b8605Smrg if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { 303848b8605Smrg UnlockDisplay(dpy); 304848b8605Smrg SyncHandle(); 305848b8605Smrg return False; 306848b8605Smrg } 307848b8605Smrg 308848b8605Smrg *driverName = malloc(rep.driverNameLength + 1); 309848b8605Smrg if (*driverName == NULL) { 310848b8605Smrg _XEatData(dpy, 311848b8605Smrg ((rep.driverNameLength + 3) & ~3) + 312848b8605Smrg ((rep.deviceNameLength + 3) & ~3)); 313848b8605Smrg UnlockDisplay(dpy); 314848b8605Smrg SyncHandle(); 315848b8605Smrg return False; 316848b8605Smrg } 317848b8605Smrg _XReadPad(dpy, *driverName, rep.driverNameLength); 318848b8605Smrg (*driverName)[rep.driverNameLength] = '\0'; 319848b8605Smrg 320848b8605Smrg *deviceName = malloc(rep.deviceNameLength + 1); 321848b8605Smrg if (*deviceName == NULL) { 322848b8605Smrg free(*driverName); 323848b8605Smrg _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); 324848b8605Smrg UnlockDisplay(dpy); 325848b8605Smrg SyncHandle(); 326848b8605Smrg return False; 327848b8605Smrg } 328848b8605Smrg _XReadPad(dpy, *deviceName, rep.deviceNameLength); 329848b8605Smrg (*deviceName)[rep.deviceNameLength] = '\0'; 330848b8605Smrg 331848b8605Smrg UnlockDisplay(dpy); 332848b8605Smrg SyncHandle(); 333848b8605Smrg 334848b8605Smrg return True; 335848b8605Smrg} 336848b8605Smrg 337848b8605SmrgBool 338848b8605SmrgDRI2Authenticate(Display * dpy, XID window, drm_magic_t magic) 339848b8605Smrg{ 340848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 341848b8605Smrg xDRI2AuthenticateReq *req; 342848b8605Smrg xDRI2AuthenticateReply rep; 343848b8605Smrg 344848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 345848b8605Smrg 346848b8605Smrg LockDisplay(dpy); 347848b8605Smrg GetReq(DRI2Authenticate, req); 348848b8605Smrg req->reqType = info->codes->major_opcode; 349848b8605Smrg req->dri2ReqType = X_DRI2Authenticate; 350848b8605Smrg req->window = window; 351848b8605Smrg req->magic = magic; 352848b8605Smrg 353848b8605Smrg if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 354848b8605Smrg UnlockDisplay(dpy); 355848b8605Smrg SyncHandle(); 356848b8605Smrg return False; 357848b8605Smrg } 358848b8605Smrg 359848b8605Smrg UnlockDisplay(dpy); 360848b8605Smrg SyncHandle(); 361848b8605Smrg 362848b8605Smrg return rep.authenticated; 363848b8605Smrg} 364848b8605Smrg 365848b8605Smrgvoid 366848b8605SmrgDRI2CreateDrawable(Display * dpy, XID drawable) 367848b8605Smrg{ 368848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 369848b8605Smrg xDRI2CreateDrawableReq *req; 370848b8605Smrg 371848b8605Smrg XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 372848b8605Smrg 373848b8605Smrg LockDisplay(dpy); 374848b8605Smrg GetReq(DRI2CreateDrawable, req); 375848b8605Smrg req->reqType = info->codes->major_opcode; 376848b8605Smrg req->dri2ReqType = X_DRI2CreateDrawable; 377848b8605Smrg req->drawable = drawable; 378848b8605Smrg UnlockDisplay(dpy); 379848b8605Smrg SyncHandle(); 380848b8605Smrg} 381848b8605Smrg 382848b8605Smrgvoid 383848b8605SmrgDRI2DestroyDrawable(Display * dpy, XID drawable) 384848b8605Smrg{ 385848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 386848b8605Smrg xDRI2DestroyDrawableReq *req; 387848b8605Smrg 388848b8605Smrg XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 389848b8605Smrg 390848b8605Smrg XSync(dpy, False); 391848b8605Smrg 392848b8605Smrg LockDisplay(dpy); 393848b8605Smrg GetReq(DRI2DestroyDrawable, req); 394848b8605Smrg req->reqType = info->codes->major_opcode; 395848b8605Smrg req->dri2ReqType = X_DRI2DestroyDrawable; 396848b8605Smrg req->drawable = drawable; 397848b8605Smrg UnlockDisplay(dpy); 398848b8605Smrg SyncHandle(); 399848b8605Smrg} 400848b8605Smrg 401848b8605SmrgDRI2Buffer * 402848b8605SmrgDRI2GetBuffers(Display * dpy, XID drawable, 403848b8605Smrg int *width, int *height, 404848b8605Smrg unsigned int *attachments, int count, int *outCount) 405848b8605Smrg{ 406848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 407848b8605Smrg xDRI2GetBuffersReply rep; 408848b8605Smrg xDRI2GetBuffersReq *req; 409848b8605Smrg DRI2Buffer *buffers; 410848b8605Smrg xDRI2Buffer repBuffer; 411848b8605Smrg CARD32 *p; 412848b8605Smrg int i; 413848b8605Smrg 414848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 415848b8605Smrg 416848b8605Smrg LockDisplay(dpy); 417848b8605Smrg GetReqExtra(DRI2GetBuffers, count * 4, req); 418848b8605Smrg req->reqType = info->codes->major_opcode; 419848b8605Smrg req->dri2ReqType = X_DRI2GetBuffers; 420848b8605Smrg req->drawable = drawable; 421848b8605Smrg req->count = count; 422848b8605Smrg p = (CARD32 *) & req[1]; 423848b8605Smrg for (i = 0; i < count; i++) 424848b8605Smrg p[i] = attachments[i]; 425848b8605Smrg 426848b8605Smrg if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 427848b8605Smrg UnlockDisplay(dpy); 428848b8605Smrg SyncHandle(); 429848b8605Smrg return NULL; 430848b8605Smrg } 431848b8605Smrg 432848b8605Smrg *width = rep.width; 433848b8605Smrg *height = rep.height; 434848b8605Smrg *outCount = rep.count; 435848b8605Smrg 436848b8605Smrg buffers = malloc(rep.count * sizeof buffers[0]); 437848b8605Smrg if (buffers == NULL) { 438848b8605Smrg _XEatData(dpy, rep.count * sizeof repBuffer); 439848b8605Smrg UnlockDisplay(dpy); 440848b8605Smrg SyncHandle(); 441848b8605Smrg return NULL; 442848b8605Smrg } 443848b8605Smrg 444848b8605Smrg for (i = 0; i < rep.count; i++) { 445848b8605Smrg _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 446848b8605Smrg buffers[i].attachment = repBuffer.attachment; 447848b8605Smrg buffers[i].name = repBuffer.name; 448848b8605Smrg buffers[i].pitch = repBuffer.pitch; 449848b8605Smrg buffers[i].cpp = repBuffer.cpp; 450848b8605Smrg buffers[i].flags = repBuffer.flags; 451848b8605Smrg } 452848b8605Smrg 453848b8605Smrg UnlockDisplay(dpy); 454848b8605Smrg SyncHandle(); 455848b8605Smrg 456848b8605Smrg return buffers; 457848b8605Smrg} 458848b8605Smrg 459848b8605Smrg 460848b8605SmrgDRI2Buffer * 461848b8605SmrgDRI2GetBuffersWithFormat(Display * dpy, XID drawable, 462848b8605Smrg int *width, int *height, 463848b8605Smrg unsigned int *attachments, int count, int *outCount) 464848b8605Smrg{ 465848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 466848b8605Smrg xDRI2GetBuffersReply rep; 467848b8605Smrg xDRI2GetBuffersReq *req; 468848b8605Smrg DRI2Buffer *buffers; 469848b8605Smrg xDRI2Buffer repBuffer; 470848b8605Smrg CARD32 *p; 471848b8605Smrg int i; 472848b8605Smrg 473848b8605Smrg XextCheckExtension(dpy, info, dri2ExtensionName, False); 474848b8605Smrg 475848b8605Smrg LockDisplay(dpy); 476848b8605Smrg GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); 477848b8605Smrg req->reqType = info->codes->major_opcode; 478848b8605Smrg req->dri2ReqType = X_DRI2GetBuffersWithFormat; 479848b8605Smrg req->drawable = drawable; 480848b8605Smrg req->count = count; 481848b8605Smrg p = (CARD32 *) & req[1]; 482848b8605Smrg for (i = 0; i < (count * 2); i++) 483848b8605Smrg p[i] = attachments[i]; 484848b8605Smrg 485848b8605Smrg if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 486848b8605Smrg UnlockDisplay(dpy); 487848b8605Smrg SyncHandle(); 488848b8605Smrg return NULL; 489848b8605Smrg } 490848b8605Smrg 491848b8605Smrg *width = rep.width; 492848b8605Smrg *height = rep.height; 493848b8605Smrg *outCount = rep.count; 494848b8605Smrg 495848b8605Smrg buffers = malloc(rep.count * sizeof buffers[0]); 496848b8605Smrg if (buffers == NULL) { 497848b8605Smrg _XEatData(dpy, rep.count * sizeof repBuffer); 498848b8605Smrg UnlockDisplay(dpy); 499848b8605Smrg SyncHandle(); 500848b8605Smrg return NULL; 501848b8605Smrg } 502848b8605Smrg 503848b8605Smrg for (i = 0; i < rep.count; i++) { 504848b8605Smrg _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 505848b8605Smrg buffers[i].attachment = repBuffer.attachment; 506848b8605Smrg buffers[i].name = repBuffer.name; 507848b8605Smrg buffers[i].pitch = repBuffer.pitch; 508848b8605Smrg buffers[i].cpp = repBuffer.cpp; 509848b8605Smrg buffers[i].flags = repBuffer.flags; 510848b8605Smrg } 511848b8605Smrg 512848b8605Smrg UnlockDisplay(dpy); 513848b8605Smrg SyncHandle(); 514848b8605Smrg 515848b8605Smrg return buffers; 516848b8605Smrg} 517848b8605Smrg 518848b8605Smrg 519848b8605Smrgvoid 520848b8605SmrgDRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, 521848b8605Smrg CARD32 dest, CARD32 src) 522848b8605Smrg{ 523848b8605Smrg XExtDisplayInfo *info = DRI2FindDisplay(dpy); 524848b8605Smrg xDRI2CopyRegionReq *req; 525848b8605Smrg xDRI2CopyRegionReply rep; 526848b8605Smrg 527848b8605Smrg XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 528848b8605Smrg 529848b8605Smrg LockDisplay(dpy); 530848b8605Smrg GetReq(DRI2CopyRegion, req); 531848b8605Smrg req->reqType = info->codes->major_opcode; 532848b8605Smrg req->dri2ReqType = X_DRI2CopyRegion; 533848b8605Smrg req->drawable = drawable; 534848b8605Smrg req->region = region; 535848b8605Smrg req->dest = dest; 536848b8605Smrg req->src = src; 537848b8605Smrg 538848b8605Smrg _XReply(dpy, (xReply *) & rep, 0, xFalse); 539848b8605Smrg 540848b8605Smrg UnlockDisplay(dpy); 541848b8605Smrg SyncHandle(); 542848b8605Smrg} 543848b8605Smrg 544848b8605Smrg#endif /* GLX_DIRECT_RENDERING */ 545