dri2.c revision af69d88d
1cdc920a0Smrg/*
2cdc920a0Smrg * Copyright © 2008 Red Hat, Inc.
3cdc920a0Smrg *
4cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5cdc920a0Smrg * copy of this software and associated documentation files (the "Soft-
6cdc920a0Smrg * ware"), to deal in the Software without restriction, including without
7cdc920a0Smrg * limitation the rights to use, copy, modify, merge, publish, distribute,
8cdc920a0Smrg * and/or sell copies of the Software, and to permit persons to whom the
9cdc920a0Smrg * Software is furnished to do so, provided that the above copyright
10cdc920a0Smrg * notice(s) and this permission notice appear in all copies of the Soft-
11cdc920a0Smrg * ware and that both the above copyright notice(s) and this permission
12cdc920a0Smrg * notice appear in supporting documentation.
13cdc920a0Smrg *
14cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15cdc920a0Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
16cdc920a0Smrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
17cdc920a0Smrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
18cdc920a0Smrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
19cdc920a0Smrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20cdc920a0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21cdc920a0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
22cdc920a0Smrg * MANCE OF THIS SOFTWARE.
23cdc920a0Smrg *
24cdc920a0Smrg * Except as contained in this notice, the name of a copyright holder shall
25cdc920a0Smrg * not be used in advertising or otherwise to promote the sale, use or
26cdc920a0Smrg * other dealings in this Software without prior written authorization of
27cdc920a0Smrg * the copyright holder.
28cdc920a0Smrg *
29cdc920a0Smrg * Authors:
30cdc920a0Smrg *   Kristian Høgsberg (krh@redhat.com)
31cdc920a0Smrg */
32cdc920a0Smrg
33cdc920a0Smrg
34cdc920a0Smrg#ifdef GLX_DIRECT_RENDERING
35cdc920a0Smrg
36cdc920a0Smrg#include <stdio.h>
37cdc920a0Smrg#include <X11/Xlibint.h>
38cdc920a0Smrg#include <X11/extensions/Xext.h>
39cdc920a0Smrg#include <X11/extensions/extutil.h>
40cdc920a0Smrg#include <X11/extensions/dri2proto.h>
41cdc920a0Smrg#include "dri2.h"
42cdc920a0Smrg#include "glxclient.h"
43cdc920a0Smrg#include "GL/glxext.h"
44cdc920a0Smrg
45cdc920a0Smrg/* Allow the build to work with an older versions of dri2proto.h and
46cdc920a0Smrg * dri2tokens.h.
47cdc920a0Smrg */
48cdc920a0Smrg#if DRI2_MINOR < 1
49cdc920a0Smrg#undef DRI2_MINOR
50cdc920a0Smrg#define DRI2_MINOR 1
51cdc920a0Smrg#define X_DRI2GetBuffersWithFormat 7
52cdc920a0Smrg#endif
53cdc920a0Smrg
54cdc920a0Smrg
55cdc920a0Smrgstatic char dri2ExtensionName[] = DRI2_NAME;
56cdc920a0Smrgstatic XExtensionInfo *dri2Info;
57cdc920a0Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
58cdc920a0Smrg
59cdc920a0Smrgstatic Bool
60cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
61cdc920a0Smrgstatic Status
62cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
63cdc920a0Smrgstatic int
64cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
65cdc920a0Smrg
66cdc920a0Smrgstatic /* const */ XExtensionHooks dri2ExtensionHooks = {
67cdc920a0Smrg  NULL,                   /* create_gc */
68cdc920a0Smrg  NULL,                   /* copy_gc */
69cdc920a0Smrg  NULL,                   /* flush_gc */
70cdc920a0Smrg  NULL,                   /* free_gc */
71cdc920a0Smrg  NULL,                   /* create_font */
72cdc920a0Smrg  NULL,                   /* free_font */
73cdc920a0Smrg  DRI2CloseDisplay,       /* close_display */
74cdc920a0Smrg  DRI2WireToEvent,        /* wire_to_event */
75cdc920a0Smrg  DRI2EventToWire,        /* event_to_wire */
76cdc920a0Smrg  DRI2Error,              /* error */
77cdc920a0Smrg  NULL,                   /* error_string */
78cdc920a0Smrg};
79cdc920a0Smrg
80cdc920a0Smrgstatic XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
81cdc920a0Smrg                                   dri2Info,
82cdc920a0Smrg                                   dri2ExtensionName,
83cdc920a0Smrg                                   &dri2ExtensionHooks,
84cdc920a0Smrg                                   0, NULL)
85cdc920a0Smrg
86cdc920a0Smrgstatic Bool
87cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
88cdc920a0Smrg{
89cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
90af69d88dSmrg   struct glx_drawable *glxDraw;
91cdc920a0Smrg
92cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
93cdc920a0Smrg
94cdc920a0Smrg   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
95cdc920a0Smrg
96cdc920a0Smrg#ifdef X_DRI2SwapBuffers
97cdc920a0Smrg   case DRI2_BufferSwapComplete:
98cdc920a0Smrg   {
99cdc920a0Smrg      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
100af69d88dSmrg      xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire;
101af69d88dSmrg      __GLXDRIdrawable *pdraw;
102af69d88dSmrg
103af69d88dSmrg      pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable);
104af69d88dSmrg      if (pdraw == NULL)
105af69d88dSmrg         return False;
1063464ebd5Sriastradh
1073464ebd5Sriastradh      /* Ignore swap events if we're not looking for them */
1083464ebd5Sriastradh      aevent->type = dri2GetSwapEventType(dpy, awire->drawable);
1093464ebd5Sriastradh      if(!aevent->type)
1103464ebd5Sriastradh         return False;
1113464ebd5Sriastradh
112cdc920a0Smrg      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
113cdc920a0Smrg      aevent->send_event = (awire->type & 0x80) != 0;
114cdc920a0Smrg      aevent->display = dpy;
115cdc920a0Smrg      aevent->drawable = awire->drawable;
116cdc920a0Smrg      switch (awire->event_type) {
117cdc920a0Smrg      case DRI2_EXCHANGE_COMPLETE:
118cdc920a0Smrg	 aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
119cdc920a0Smrg	 break;
120cdc920a0Smrg      case DRI2_BLIT_COMPLETE:
121cdc920a0Smrg	 aevent->event_type = GLX_COPY_COMPLETE_INTEL;
122cdc920a0Smrg	 break;
123cdc920a0Smrg      case DRI2_FLIP_COMPLETE:
124cdc920a0Smrg	 aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
125cdc920a0Smrg	 break;
126cdc920a0Smrg      default:
127cdc920a0Smrg	 /* unknown swap completion type */
128cdc920a0Smrg	 return False;
129cdc920a0Smrg      }
130cdc920a0Smrg      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
131cdc920a0Smrg      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
132af69d88dSmrg
133af69d88dSmrg      glxDraw = GetGLXDrawable(dpy, pdraw->drawable);
134af69d88dSmrg      if (glxDraw != NULL) {
135af69d88dSmrg         if (awire->sbc < glxDraw->lastEventSbc)
136af69d88dSmrg            glxDraw->eventSbcWrap += 0x100000000;
137af69d88dSmrg         glxDraw->lastEventSbc = awire->sbc;
138af69d88dSmrg         aevent->sbc = awire->sbc + glxDraw->eventSbcWrap;
139af69d88dSmrg      } else {
140af69d88dSmrg         aevent->sbc = awire->sbc;
141af69d88dSmrg      }
142af69d88dSmrg
143cdc920a0Smrg      return True;
144cdc920a0Smrg   }
145cdc920a0Smrg#endif
146cdc920a0Smrg#ifdef DRI2_InvalidateBuffers
147cdc920a0Smrg   case DRI2_InvalidateBuffers:
148cdc920a0Smrg   {
149cdc920a0Smrg      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
150cdc920a0Smrg
151cdc920a0Smrg      dri2InvalidateBuffers(dpy, awire->drawable);
152cdc920a0Smrg      return False;
153cdc920a0Smrg   }
154cdc920a0Smrg#endif
155cdc920a0Smrg   default:
156cdc920a0Smrg      /* client doesn't support server event */
157cdc920a0Smrg      break;
158cdc920a0Smrg   }
159cdc920a0Smrg
160cdc920a0Smrg   return False;
161cdc920a0Smrg}
162cdc920a0Smrg
163cdc920a0Smrg/* We don't actually support this.  It doesn't make sense for clients to
164cdc920a0Smrg * send each other DRI2 events.
165cdc920a0Smrg */
166cdc920a0Smrgstatic Status
167cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
168cdc920a0Smrg{
169cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
170cdc920a0Smrg
171cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
172cdc920a0Smrg
173cdc920a0Smrg   switch (event->type) {
174cdc920a0Smrg   default:
175cdc920a0Smrg      /* client doesn't support server event */
176cdc920a0Smrg      break;
177cdc920a0Smrg   }
178cdc920a0Smrg
179cdc920a0Smrg   return Success;
180cdc920a0Smrg}
181cdc920a0Smrg
182cdc920a0Smrgstatic int
183cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
184cdc920a0Smrg{
185cdc920a0Smrg    if (err->majorCode == codes->major_opcode &&
186cdc920a0Smrg	err->errorCode == BadDrawable &&
187cdc920a0Smrg	err->minorCode == X_DRI2CopyRegion)
188cdc920a0Smrg	return True;
189cdc920a0Smrg
1903464ebd5Sriastradh    /* If the X drawable was destroyed before the GLX drawable, the
1913464ebd5Sriastradh     * DRI2 drawble will be gone by the time we call
1923464ebd5Sriastradh     * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
1933464ebd5Sriastradh    if (err->majorCode == codes->major_opcode &&
1943464ebd5Sriastradh	err->errorCode == BadDrawable &&
1953464ebd5Sriastradh	err->minorCode == X_DRI2DestroyDrawable)
1963464ebd5Sriastradh	return True;
1973464ebd5Sriastradh
1983464ebd5Sriastradh    /* If the server is non-local DRI2Connect will raise BadRequest.
1993464ebd5Sriastradh     * Swallow this so that DRI2Connect can signal this in its return code */
2003464ebd5Sriastradh    if (err->majorCode == codes->major_opcode &&
2013464ebd5Sriastradh        err->minorCode == X_DRI2Connect &&
2023464ebd5Sriastradh        err->errorCode == BadRequest) {
2033464ebd5Sriastradh	*ret_code = False;
2043464ebd5Sriastradh	return True;
2053464ebd5Sriastradh    }
2063464ebd5Sriastradh
207cdc920a0Smrg    return False;
208cdc920a0Smrg}
209cdc920a0Smrg
210cdc920a0SmrgBool
211cdc920a0SmrgDRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
212cdc920a0Smrg{
213cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
214cdc920a0Smrg
215cdc920a0Smrg   if (XextHasExtension(info)) {
216cdc920a0Smrg      *eventBase = info->codes->first_event;
217cdc920a0Smrg      *errorBase = info->codes->first_error;
218cdc920a0Smrg      return True;
219cdc920a0Smrg   }
220cdc920a0Smrg
221cdc920a0Smrg   return False;
222cdc920a0Smrg}
223cdc920a0Smrg
224cdc920a0SmrgBool
225cdc920a0SmrgDRI2QueryVersion(Display * dpy, int *major, int *minor)
226cdc920a0Smrg{
227cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
228cdc920a0Smrg   xDRI2QueryVersionReply rep;
229cdc920a0Smrg   xDRI2QueryVersionReq *req;
230cdc920a0Smrg   int i, nevents;
231cdc920a0Smrg
232cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
233cdc920a0Smrg
234cdc920a0Smrg   LockDisplay(dpy);
235cdc920a0Smrg   GetReq(DRI2QueryVersion, req);
236cdc920a0Smrg   req->reqType = info->codes->major_opcode;
237cdc920a0Smrg   req->dri2ReqType = X_DRI2QueryVersion;
238cdc920a0Smrg   req->majorVersion = DRI2_MAJOR;
239cdc920a0Smrg   req->minorVersion = DRI2_MINOR;
240cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
241cdc920a0Smrg      UnlockDisplay(dpy);
242cdc920a0Smrg      SyncHandle();
243cdc920a0Smrg      return False;
244cdc920a0Smrg   }
245cdc920a0Smrg   *major = rep.majorVersion;
246cdc920a0Smrg   *minor = rep.minorVersion;
247cdc920a0Smrg   UnlockDisplay(dpy);
248cdc920a0Smrg   SyncHandle();
249cdc920a0Smrg
250cdc920a0Smrg   switch (rep.minorVersion) {
251cdc920a0Smrg   case 1:
252cdc920a0Smrg	   nevents = 0;
253cdc920a0Smrg	   break;
254cdc920a0Smrg   case 2:
255cdc920a0Smrg	   nevents = 1;
256cdc920a0Smrg	   break;
257cdc920a0Smrg   case 3:
258cdc920a0Smrg   default:
259cdc920a0Smrg	   nevents = 2;
260cdc920a0Smrg	   break;
261cdc920a0Smrg   }
262cdc920a0Smrg
263cdc920a0Smrg   for (i = 0; i < nevents; i++) {
264cdc920a0Smrg       XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
265cdc920a0Smrg       XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
266cdc920a0Smrg   }
267cdc920a0Smrg
268cdc920a0Smrg   return True;
269cdc920a0Smrg}
270cdc920a0Smrg
271cdc920a0SmrgBool
272cdc920a0SmrgDRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
273cdc920a0Smrg{
274cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
275cdc920a0Smrg   xDRI2ConnectReply rep;
276cdc920a0Smrg   xDRI2ConnectReq *req;
277cdc920a0Smrg
278cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
279cdc920a0Smrg
280cdc920a0Smrg   LockDisplay(dpy);
281cdc920a0Smrg   GetReq(DRI2Connect, req);
282cdc920a0Smrg   req->reqType = info->codes->major_opcode;
283cdc920a0Smrg   req->dri2ReqType = X_DRI2Connect;
284cdc920a0Smrg   req->window = window;
285af69d88dSmrg
286cdc920a0Smrg   req->driverType = DRI2DriverDRI;
287af69d88dSmrg#ifdef DRI2DriverPrimeShift
288af69d88dSmrg   {
289af69d88dSmrg      char *prime = getenv("DRI_PRIME");
290af69d88dSmrg      if (prime) {
291af69d88dSmrg         uint32_t primeid;
292af69d88dSmrg         errno = 0;
293af69d88dSmrg         primeid = strtoul(prime, NULL, 0);
294af69d88dSmrg         if (errno == 0)
295af69d88dSmrg            req->driverType |=
296af69d88dSmrg               ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
297af69d88dSmrg      }
298af69d88dSmrg   }
299af69d88dSmrg#endif
300af69d88dSmrg
301cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
302cdc920a0Smrg      UnlockDisplay(dpy);
303cdc920a0Smrg      SyncHandle();
304cdc920a0Smrg      return False;
305cdc920a0Smrg   }
306cdc920a0Smrg
307cdc920a0Smrg   if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
308cdc920a0Smrg      UnlockDisplay(dpy);
309cdc920a0Smrg      SyncHandle();
310cdc920a0Smrg      return False;
311cdc920a0Smrg   }
312cdc920a0Smrg
313af69d88dSmrg   *driverName = malloc(rep.driverNameLength + 1);
314cdc920a0Smrg   if (*driverName == NULL) {
315cdc920a0Smrg      _XEatData(dpy,
316cdc920a0Smrg                ((rep.driverNameLength + 3) & ~3) +
317cdc920a0Smrg                ((rep.deviceNameLength + 3) & ~3));
318cdc920a0Smrg      UnlockDisplay(dpy);
319cdc920a0Smrg      SyncHandle();
320cdc920a0Smrg      return False;
321cdc920a0Smrg   }
322cdc920a0Smrg   _XReadPad(dpy, *driverName, rep.driverNameLength);
323cdc920a0Smrg   (*driverName)[rep.driverNameLength] = '\0';
324cdc920a0Smrg
325af69d88dSmrg   *deviceName = malloc(rep.deviceNameLength + 1);
326cdc920a0Smrg   if (*deviceName == NULL) {
327af69d88dSmrg      free(*driverName);
328cdc920a0Smrg      _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
329cdc920a0Smrg      UnlockDisplay(dpy);
330cdc920a0Smrg      SyncHandle();
331cdc920a0Smrg      return False;
332cdc920a0Smrg   }
333cdc920a0Smrg   _XReadPad(dpy, *deviceName, rep.deviceNameLength);
334cdc920a0Smrg   (*deviceName)[rep.deviceNameLength] = '\0';
335cdc920a0Smrg
336cdc920a0Smrg   UnlockDisplay(dpy);
337cdc920a0Smrg   SyncHandle();
338cdc920a0Smrg
339cdc920a0Smrg   return True;
340cdc920a0Smrg}
341cdc920a0Smrg
342cdc920a0SmrgBool
343cdc920a0SmrgDRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
344cdc920a0Smrg{
345cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
346cdc920a0Smrg   xDRI2AuthenticateReq *req;
347cdc920a0Smrg   xDRI2AuthenticateReply rep;
348cdc920a0Smrg
349cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
350cdc920a0Smrg
351cdc920a0Smrg   LockDisplay(dpy);
352cdc920a0Smrg   GetReq(DRI2Authenticate, req);
353cdc920a0Smrg   req->reqType = info->codes->major_opcode;
354cdc920a0Smrg   req->dri2ReqType = X_DRI2Authenticate;
355cdc920a0Smrg   req->window = window;
356cdc920a0Smrg   req->magic = magic;
357cdc920a0Smrg
358cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
359cdc920a0Smrg      UnlockDisplay(dpy);
360cdc920a0Smrg      SyncHandle();
361cdc920a0Smrg      return False;
362cdc920a0Smrg   }
363cdc920a0Smrg
364cdc920a0Smrg   UnlockDisplay(dpy);
365cdc920a0Smrg   SyncHandle();
366cdc920a0Smrg
367cdc920a0Smrg   return rep.authenticated;
368cdc920a0Smrg}
369cdc920a0Smrg
370cdc920a0Smrgvoid
371cdc920a0SmrgDRI2CreateDrawable(Display * dpy, XID drawable)
372cdc920a0Smrg{
373cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
374cdc920a0Smrg   xDRI2CreateDrawableReq *req;
375cdc920a0Smrg
376cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
377cdc920a0Smrg
378cdc920a0Smrg   LockDisplay(dpy);
379cdc920a0Smrg   GetReq(DRI2CreateDrawable, req);
380cdc920a0Smrg   req->reqType = info->codes->major_opcode;
381cdc920a0Smrg   req->dri2ReqType = X_DRI2CreateDrawable;
382cdc920a0Smrg   req->drawable = drawable;
383cdc920a0Smrg   UnlockDisplay(dpy);
384cdc920a0Smrg   SyncHandle();
385cdc920a0Smrg}
386cdc920a0Smrg
387cdc920a0Smrgvoid
388cdc920a0SmrgDRI2DestroyDrawable(Display * dpy, XID drawable)
389cdc920a0Smrg{
390cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
391cdc920a0Smrg   xDRI2DestroyDrawableReq *req;
392cdc920a0Smrg
393cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
394cdc920a0Smrg
395cdc920a0Smrg   XSync(dpy, False);
396cdc920a0Smrg
397cdc920a0Smrg   LockDisplay(dpy);
398cdc920a0Smrg   GetReq(DRI2DestroyDrawable, req);
399cdc920a0Smrg   req->reqType = info->codes->major_opcode;
400cdc920a0Smrg   req->dri2ReqType = X_DRI2DestroyDrawable;
401cdc920a0Smrg   req->drawable = drawable;
402cdc920a0Smrg   UnlockDisplay(dpy);
403cdc920a0Smrg   SyncHandle();
404cdc920a0Smrg}
405cdc920a0Smrg
406cdc920a0SmrgDRI2Buffer *
407cdc920a0SmrgDRI2GetBuffers(Display * dpy, XID drawable,
408cdc920a0Smrg               int *width, int *height,
409cdc920a0Smrg               unsigned int *attachments, int count, int *outCount)
410cdc920a0Smrg{
411cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
412cdc920a0Smrg   xDRI2GetBuffersReply rep;
413cdc920a0Smrg   xDRI2GetBuffersReq *req;
414cdc920a0Smrg   DRI2Buffer *buffers;
415cdc920a0Smrg   xDRI2Buffer repBuffer;
416cdc920a0Smrg   CARD32 *p;
417cdc920a0Smrg   int i;
418cdc920a0Smrg
419cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
420cdc920a0Smrg
421cdc920a0Smrg   LockDisplay(dpy);
422cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * 4, req);
423cdc920a0Smrg   req->reqType = info->codes->major_opcode;
424cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffers;
425cdc920a0Smrg   req->drawable = drawable;
426cdc920a0Smrg   req->count = count;
427cdc920a0Smrg   p = (CARD32 *) & req[1];
428cdc920a0Smrg   for (i = 0; i < count; i++)
429cdc920a0Smrg      p[i] = attachments[i];
430cdc920a0Smrg
431cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
432cdc920a0Smrg      UnlockDisplay(dpy);
433cdc920a0Smrg      SyncHandle();
434cdc920a0Smrg      return NULL;
435cdc920a0Smrg   }
436cdc920a0Smrg
437cdc920a0Smrg   *width = rep.width;
438cdc920a0Smrg   *height = rep.height;
439cdc920a0Smrg   *outCount = rep.count;
440cdc920a0Smrg
441af69d88dSmrg   buffers = malloc(rep.count * sizeof buffers[0]);
442cdc920a0Smrg   if (buffers == NULL) {
443cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
444cdc920a0Smrg      UnlockDisplay(dpy);
445cdc920a0Smrg      SyncHandle();
446cdc920a0Smrg      return NULL;
447cdc920a0Smrg   }
448cdc920a0Smrg
449cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
450cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
451cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
452cdc920a0Smrg      buffers[i].name = repBuffer.name;
453cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
454cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
455cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
456cdc920a0Smrg   }
457cdc920a0Smrg
458cdc920a0Smrg   UnlockDisplay(dpy);
459cdc920a0Smrg   SyncHandle();
460cdc920a0Smrg
461cdc920a0Smrg   return buffers;
462cdc920a0Smrg}
463cdc920a0Smrg
464cdc920a0Smrg
465cdc920a0SmrgDRI2Buffer *
466cdc920a0SmrgDRI2GetBuffersWithFormat(Display * dpy, XID drawable,
467cdc920a0Smrg                         int *width, int *height,
468cdc920a0Smrg                         unsigned int *attachments, int count, int *outCount)
469cdc920a0Smrg{
470cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
471cdc920a0Smrg   xDRI2GetBuffersReply rep;
472cdc920a0Smrg   xDRI2GetBuffersReq *req;
473cdc920a0Smrg   DRI2Buffer *buffers;
474cdc920a0Smrg   xDRI2Buffer repBuffer;
475cdc920a0Smrg   CARD32 *p;
476cdc920a0Smrg   int i;
477cdc920a0Smrg
478cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
479cdc920a0Smrg
480cdc920a0Smrg   LockDisplay(dpy);
481cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
482cdc920a0Smrg   req->reqType = info->codes->major_opcode;
483cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
484cdc920a0Smrg   req->drawable = drawable;
485cdc920a0Smrg   req->count = count;
486cdc920a0Smrg   p = (CARD32 *) & req[1];
487cdc920a0Smrg   for (i = 0; i < (count * 2); i++)
488cdc920a0Smrg      p[i] = attachments[i];
489cdc920a0Smrg
490cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
491cdc920a0Smrg      UnlockDisplay(dpy);
492cdc920a0Smrg      SyncHandle();
493cdc920a0Smrg      return NULL;
494cdc920a0Smrg   }
495cdc920a0Smrg
496cdc920a0Smrg   *width = rep.width;
497cdc920a0Smrg   *height = rep.height;
498cdc920a0Smrg   *outCount = rep.count;
499cdc920a0Smrg
500af69d88dSmrg   buffers = malloc(rep.count * sizeof buffers[0]);
501cdc920a0Smrg   if (buffers == NULL) {
502cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
503cdc920a0Smrg      UnlockDisplay(dpy);
504cdc920a0Smrg      SyncHandle();
505cdc920a0Smrg      return NULL;
506cdc920a0Smrg   }
507cdc920a0Smrg
508cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
509cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
510cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
511cdc920a0Smrg      buffers[i].name = repBuffer.name;
512cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
513cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
514cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
515cdc920a0Smrg   }
516cdc920a0Smrg
517cdc920a0Smrg   UnlockDisplay(dpy);
518cdc920a0Smrg   SyncHandle();
519cdc920a0Smrg
520cdc920a0Smrg   return buffers;
521cdc920a0Smrg}
522cdc920a0Smrg
523cdc920a0Smrg
524cdc920a0Smrgvoid
525cdc920a0SmrgDRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
526cdc920a0Smrg               CARD32 dest, CARD32 src)
527cdc920a0Smrg{
528cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
529cdc920a0Smrg   xDRI2CopyRegionReq *req;
530cdc920a0Smrg   xDRI2CopyRegionReply rep;
531cdc920a0Smrg
532cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
533cdc920a0Smrg
534cdc920a0Smrg   LockDisplay(dpy);
535cdc920a0Smrg   GetReq(DRI2CopyRegion, req);
536cdc920a0Smrg   req->reqType = info->codes->major_opcode;
537cdc920a0Smrg   req->dri2ReqType = X_DRI2CopyRegion;
538cdc920a0Smrg   req->drawable = drawable;
539cdc920a0Smrg   req->region = region;
540cdc920a0Smrg   req->dest = dest;
541cdc920a0Smrg   req->src = src;
542cdc920a0Smrg
543cdc920a0Smrg   _XReply(dpy, (xReply *) & rep, 0, xFalse);
544cdc920a0Smrg
545cdc920a0Smrg   UnlockDisplay(dpy);
546cdc920a0Smrg   SyncHandle();
547cdc920a0Smrg}
548cdc920a0Smrg
549cdc920a0Smrg#endif /* GLX_DIRECT_RENDERING */
550