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;
5601e04c3fSmrgstatic XExtensionInfo _dri2Info_data;
5701e04c3fSmrgstatic XExtensionInfo *dri2Info = &_dri2Info_data;
58cdc920a0Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
59cdc920a0Smrg
60cdc920a0Smrgstatic Bool
61cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
62cdc920a0Smrgstatic Status
63cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
64cdc920a0Smrgstatic int
65cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
66cdc920a0Smrg
67cdc920a0Smrgstatic /* const */ XExtensionHooks dri2ExtensionHooks = {
68cdc920a0Smrg  NULL,                   /* create_gc */
69cdc920a0Smrg  NULL,                   /* copy_gc */
70cdc920a0Smrg  NULL,                   /* flush_gc */
71cdc920a0Smrg  NULL,                   /* free_gc */
72cdc920a0Smrg  NULL,                   /* create_font */
73cdc920a0Smrg  NULL,                   /* free_font */
74cdc920a0Smrg  DRI2CloseDisplay,       /* close_display */
75cdc920a0Smrg  DRI2WireToEvent,        /* wire_to_event */
76cdc920a0Smrg  DRI2EventToWire,        /* event_to_wire */
77cdc920a0Smrg  DRI2Error,              /* error */
78cdc920a0Smrg  NULL,                   /* error_string */
79cdc920a0Smrg};
80cdc920a0Smrg
81cdc920a0Smrgstatic XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
82cdc920a0Smrg                                   dri2Info,
83cdc920a0Smrg                                   dri2ExtensionName,
84cdc920a0Smrg                                   &dri2ExtensionHooks,
85cdc920a0Smrg                                   0, NULL)
86cdc920a0Smrg
87cdc920a0Smrgstatic Bool
88cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
89cdc920a0Smrg{
90cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
91af69d88dSmrg   struct glx_drawable *glxDraw;
92cdc920a0Smrg
93cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
94cdc920a0Smrg
95cdc920a0Smrg   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
96cdc920a0Smrg
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   case DRI2_InvalidateBuffers:
146cdc920a0Smrg   {
147cdc920a0Smrg      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
148cdc920a0Smrg
149cdc920a0Smrg      dri2InvalidateBuffers(dpy, awire->drawable);
150cdc920a0Smrg      return False;
151cdc920a0Smrg   }
152cdc920a0Smrg   default:
153cdc920a0Smrg      /* client doesn't support server event */
154cdc920a0Smrg      break;
155cdc920a0Smrg   }
156cdc920a0Smrg
157cdc920a0Smrg   return False;
158cdc920a0Smrg}
159cdc920a0Smrg
160cdc920a0Smrg/* We don't actually support this.  It doesn't make sense for clients to
161cdc920a0Smrg * send each other DRI2 events.
162cdc920a0Smrg */
163cdc920a0Smrgstatic Status
164cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
165cdc920a0Smrg{
166cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
167cdc920a0Smrg
168cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
169cdc920a0Smrg
170cdc920a0Smrg   switch (event->type) {
171cdc920a0Smrg   default:
172cdc920a0Smrg      /* client doesn't support server event */
173cdc920a0Smrg      break;
174cdc920a0Smrg   }
175cdc920a0Smrg
176cdc920a0Smrg   return Success;
177cdc920a0Smrg}
178cdc920a0Smrg
179cdc920a0Smrgstatic int
180cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
181cdc920a0Smrg{
182cdc920a0Smrg    if (err->majorCode == codes->major_opcode &&
183cdc920a0Smrg	err->errorCode == BadDrawable &&
184cdc920a0Smrg	err->minorCode == X_DRI2CopyRegion)
185cdc920a0Smrg	return True;
186cdc920a0Smrg
1873464ebd5Sriastradh    /* If the X drawable was destroyed before the GLX drawable, the
1883464ebd5Sriastradh     * DRI2 drawble will be gone by the time we call
1893464ebd5Sriastradh     * DRI2DestroyDrawable.  So just ignore BadDrawable here. */
1903464ebd5Sriastradh    if (err->majorCode == codes->major_opcode &&
1913464ebd5Sriastradh	err->errorCode == BadDrawable &&
1923464ebd5Sriastradh	err->minorCode == X_DRI2DestroyDrawable)
1933464ebd5Sriastradh	return True;
1943464ebd5Sriastradh
1953464ebd5Sriastradh    /* If the server is non-local DRI2Connect will raise BadRequest.
1963464ebd5Sriastradh     * Swallow this so that DRI2Connect can signal this in its return code */
1973464ebd5Sriastradh    if (err->majorCode == codes->major_opcode &&
1983464ebd5Sriastradh        err->minorCode == X_DRI2Connect &&
1993464ebd5Sriastradh        err->errorCode == BadRequest) {
2003464ebd5Sriastradh	*ret_code = False;
2013464ebd5Sriastradh	return True;
2023464ebd5Sriastradh    }
2033464ebd5Sriastradh
204cdc920a0Smrg    return False;
205cdc920a0Smrg}
206cdc920a0Smrg
207cdc920a0SmrgBool
208cdc920a0SmrgDRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
209cdc920a0Smrg{
210cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
211cdc920a0Smrg
212cdc920a0Smrg   if (XextHasExtension(info)) {
213cdc920a0Smrg      *eventBase = info->codes->first_event;
214cdc920a0Smrg      *errorBase = info->codes->first_error;
215cdc920a0Smrg      return True;
216cdc920a0Smrg   }
217cdc920a0Smrg
218cdc920a0Smrg   return False;
219cdc920a0Smrg}
220cdc920a0Smrg
221cdc920a0SmrgBool
222cdc920a0SmrgDRI2QueryVersion(Display * dpy, int *major, int *minor)
223cdc920a0Smrg{
224cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
225cdc920a0Smrg   xDRI2QueryVersionReply rep;
226cdc920a0Smrg   xDRI2QueryVersionReq *req;
227cdc920a0Smrg   int i, nevents;
228cdc920a0Smrg
229cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
230cdc920a0Smrg
231cdc920a0Smrg   LockDisplay(dpy);
232cdc920a0Smrg   GetReq(DRI2QueryVersion, req);
233cdc920a0Smrg   req->reqType = info->codes->major_opcode;
234cdc920a0Smrg   req->dri2ReqType = X_DRI2QueryVersion;
235cdc920a0Smrg   req->majorVersion = DRI2_MAJOR;
236cdc920a0Smrg   req->minorVersion = DRI2_MINOR;
237cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
238cdc920a0Smrg      UnlockDisplay(dpy);
239cdc920a0Smrg      SyncHandle();
240cdc920a0Smrg      return False;
241cdc920a0Smrg   }
242cdc920a0Smrg   *major = rep.majorVersion;
243cdc920a0Smrg   *minor = rep.minorVersion;
244cdc920a0Smrg   UnlockDisplay(dpy);
245cdc920a0Smrg   SyncHandle();
246cdc920a0Smrg
247cdc920a0Smrg   switch (rep.minorVersion) {
248cdc920a0Smrg   case 1:
249cdc920a0Smrg	   nevents = 0;
250cdc920a0Smrg	   break;
251cdc920a0Smrg   case 2:
252cdc920a0Smrg	   nevents = 1;
253cdc920a0Smrg	   break;
254cdc920a0Smrg   case 3:
255cdc920a0Smrg   default:
256cdc920a0Smrg	   nevents = 2;
257cdc920a0Smrg	   break;
258cdc920a0Smrg   }
259cdc920a0Smrg
260cdc920a0Smrg   for (i = 0; i < nevents; i++) {
261cdc920a0Smrg       XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
262cdc920a0Smrg       XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
263cdc920a0Smrg   }
264cdc920a0Smrg
265cdc920a0Smrg   return True;
266cdc920a0Smrg}
267cdc920a0Smrg
268cdc920a0SmrgBool
269cdc920a0SmrgDRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
270cdc920a0Smrg{
271cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
272cdc920a0Smrg   xDRI2ConnectReply rep;
273cdc920a0Smrg   xDRI2ConnectReq *req;
274cdc920a0Smrg
275cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
276cdc920a0Smrg
277cdc920a0Smrg   LockDisplay(dpy);
278cdc920a0Smrg   GetReq(DRI2Connect, req);
279cdc920a0Smrg   req->reqType = info->codes->major_opcode;
280cdc920a0Smrg   req->dri2ReqType = X_DRI2Connect;
281cdc920a0Smrg   req->window = window;
282af69d88dSmrg
283cdc920a0Smrg   req->driverType = DRI2DriverDRI;
284af69d88dSmrg   {
285af69d88dSmrg      char *prime = getenv("DRI_PRIME");
286af69d88dSmrg      if (prime) {
287af69d88dSmrg         uint32_t primeid;
288af69d88dSmrg         errno = 0;
289af69d88dSmrg         primeid = strtoul(prime, NULL, 0);
290af69d88dSmrg         if (errno == 0)
291af69d88dSmrg            req->driverType |=
292af69d88dSmrg               ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
293af69d88dSmrg      }
294af69d88dSmrg   }
295af69d88dSmrg
296cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
297cdc920a0Smrg      UnlockDisplay(dpy);
298cdc920a0Smrg      SyncHandle();
299cdc920a0Smrg      return False;
300cdc920a0Smrg   }
301cdc920a0Smrg
302cdc920a0Smrg   if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
303cdc920a0Smrg      UnlockDisplay(dpy);
304cdc920a0Smrg      SyncHandle();
305cdc920a0Smrg      return False;
306cdc920a0Smrg   }
307cdc920a0Smrg
308af69d88dSmrg   *driverName = malloc(rep.driverNameLength + 1);
309cdc920a0Smrg   if (*driverName == NULL) {
310cdc920a0Smrg      _XEatData(dpy,
311cdc920a0Smrg                ((rep.driverNameLength + 3) & ~3) +
312cdc920a0Smrg                ((rep.deviceNameLength + 3) & ~3));
313cdc920a0Smrg      UnlockDisplay(dpy);
314cdc920a0Smrg      SyncHandle();
315cdc920a0Smrg      return False;
316cdc920a0Smrg   }
317cdc920a0Smrg   _XReadPad(dpy, *driverName, rep.driverNameLength);
318cdc920a0Smrg   (*driverName)[rep.driverNameLength] = '\0';
319cdc920a0Smrg
320af69d88dSmrg   *deviceName = malloc(rep.deviceNameLength + 1);
321cdc920a0Smrg   if (*deviceName == NULL) {
322af69d88dSmrg      free(*driverName);
323cdc920a0Smrg      _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
324cdc920a0Smrg      UnlockDisplay(dpy);
325cdc920a0Smrg      SyncHandle();
326cdc920a0Smrg      return False;
327cdc920a0Smrg   }
328cdc920a0Smrg   _XReadPad(dpy, *deviceName, rep.deviceNameLength);
329cdc920a0Smrg   (*deviceName)[rep.deviceNameLength] = '\0';
330cdc920a0Smrg
331cdc920a0Smrg   UnlockDisplay(dpy);
332cdc920a0Smrg   SyncHandle();
333cdc920a0Smrg
334cdc920a0Smrg   return True;
335cdc920a0Smrg}
336cdc920a0Smrg
337cdc920a0SmrgBool
338cdc920a0SmrgDRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
339cdc920a0Smrg{
340cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
341cdc920a0Smrg   xDRI2AuthenticateReq *req;
342cdc920a0Smrg   xDRI2AuthenticateReply rep;
343cdc920a0Smrg
344cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
345cdc920a0Smrg
346cdc920a0Smrg   LockDisplay(dpy);
347cdc920a0Smrg   GetReq(DRI2Authenticate, req);
348cdc920a0Smrg   req->reqType = info->codes->major_opcode;
349cdc920a0Smrg   req->dri2ReqType = X_DRI2Authenticate;
350cdc920a0Smrg   req->window = window;
351cdc920a0Smrg   req->magic = magic;
352cdc920a0Smrg
353cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
354cdc920a0Smrg      UnlockDisplay(dpy);
355cdc920a0Smrg      SyncHandle();
356cdc920a0Smrg      return False;
357cdc920a0Smrg   }
358cdc920a0Smrg
359cdc920a0Smrg   UnlockDisplay(dpy);
360cdc920a0Smrg   SyncHandle();
361cdc920a0Smrg
362cdc920a0Smrg   return rep.authenticated;
363cdc920a0Smrg}
364cdc920a0Smrg
365cdc920a0Smrgvoid
366cdc920a0SmrgDRI2CreateDrawable(Display * dpy, XID drawable)
367cdc920a0Smrg{
368cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
369cdc920a0Smrg   xDRI2CreateDrawableReq *req;
370cdc920a0Smrg
371cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
372cdc920a0Smrg
373cdc920a0Smrg   LockDisplay(dpy);
374cdc920a0Smrg   GetReq(DRI2CreateDrawable, req);
375cdc920a0Smrg   req->reqType = info->codes->major_opcode;
376cdc920a0Smrg   req->dri2ReqType = X_DRI2CreateDrawable;
377cdc920a0Smrg   req->drawable = drawable;
378cdc920a0Smrg   UnlockDisplay(dpy);
379cdc920a0Smrg   SyncHandle();
380cdc920a0Smrg}
381cdc920a0Smrg
382cdc920a0Smrgvoid
383cdc920a0SmrgDRI2DestroyDrawable(Display * dpy, XID drawable)
384cdc920a0Smrg{
385cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
386cdc920a0Smrg   xDRI2DestroyDrawableReq *req;
387cdc920a0Smrg
388cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
389cdc920a0Smrg
390cdc920a0Smrg   XSync(dpy, False);
391cdc920a0Smrg
392cdc920a0Smrg   LockDisplay(dpy);
393cdc920a0Smrg   GetReq(DRI2DestroyDrawable, req);
394cdc920a0Smrg   req->reqType = info->codes->major_opcode;
395cdc920a0Smrg   req->dri2ReqType = X_DRI2DestroyDrawable;
396cdc920a0Smrg   req->drawable = drawable;
397cdc920a0Smrg   UnlockDisplay(dpy);
398cdc920a0Smrg   SyncHandle();
399cdc920a0Smrg}
400cdc920a0Smrg
401cdc920a0SmrgDRI2Buffer *
402cdc920a0SmrgDRI2GetBuffers(Display * dpy, XID drawable,
403cdc920a0Smrg               int *width, int *height,
404cdc920a0Smrg               unsigned int *attachments, int count, int *outCount)
405cdc920a0Smrg{
406cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
407cdc920a0Smrg   xDRI2GetBuffersReply rep;
408cdc920a0Smrg   xDRI2GetBuffersReq *req;
409cdc920a0Smrg   DRI2Buffer *buffers;
410cdc920a0Smrg   xDRI2Buffer repBuffer;
411cdc920a0Smrg   CARD32 *p;
412cdc920a0Smrg   int i;
413cdc920a0Smrg
414cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
415cdc920a0Smrg
416cdc920a0Smrg   LockDisplay(dpy);
417cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * 4, req);
418cdc920a0Smrg   req->reqType = info->codes->major_opcode;
419cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffers;
420cdc920a0Smrg   req->drawable = drawable;
421cdc920a0Smrg   req->count = count;
422cdc920a0Smrg   p = (CARD32 *) & req[1];
423cdc920a0Smrg   for (i = 0; i < count; i++)
424cdc920a0Smrg      p[i] = attachments[i];
425cdc920a0Smrg
426cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
427cdc920a0Smrg      UnlockDisplay(dpy);
428cdc920a0Smrg      SyncHandle();
429cdc920a0Smrg      return NULL;
430cdc920a0Smrg   }
431cdc920a0Smrg
432cdc920a0Smrg   *width = rep.width;
433cdc920a0Smrg   *height = rep.height;
434cdc920a0Smrg   *outCount = rep.count;
435cdc920a0Smrg
436af69d88dSmrg   buffers = malloc(rep.count * sizeof buffers[0]);
437cdc920a0Smrg   if (buffers == NULL) {
438cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
439cdc920a0Smrg      UnlockDisplay(dpy);
440cdc920a0Smrg      SyncHandle();
441cdc920a0Smrg      return NULL;
442cdc920a0Smrg   }
443cdc920a0Smrg
444cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
445cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
446cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
447cdc920a0Smrg      buffers[i].name = repBuffer.name;
448cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
449cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
450cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
451cdc920a0Smrg   }
452cdc920a0Smrg
453cdc920a0Smrg   UnlockDisplay(dpy);
454cdc920a0Smrg   SyncHandle();
455cdc920a0Smrg
456cdc920a0Smrg   return buffers;
457cdc920a0Smrg}
458cdc920a0Smrg
459cdc920a0Smrg
460cdc920a0SmrgDRI2Buffer *
461cdc920a0SmrgDRI2GetBuffersWithFormat(Display * dpy, XID drawable,
462cdc920a0Smrg                         int *width, int *height,
463cdc920a0Smrg                         unsigned int *attachments, int count, int *outCount)
464cdc920a0Smrg{
465cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
466cdc920a0Smrg   xDRI2GetBuffersReply rep;
467cdc920a0Smrg   xDRI2GetBuffersReq *req;
468cdc920a0Smrg   DRI2Buffer *buffers;
469cdc920a0Smrg   xDRI2Buffer repBuffer;
470cdc920a0Smrg   CARD32 *p;
471cdc920a0Smrg   int i;
472cdc920a0Smrg
473cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
474cdc920a0Smrg
475cdc920a0Smrg   LockDisplay(dpy);
476cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
477cdc920a0Smrg   req->reqType = info->codes->major_opcode;
478cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
479cdc920a0Smrg   req->drawable = drawable;
480cdc920a0Smrg   req->count = count;
481cdc920a0Smrg   p = (CARD32 *) & req[1];
482cdc920a0Smrg   for (i = 0; i < (count * 2); i++)
483cdc920a0Smrg      p[i] = attachments[i];
484cdc920a0Smrg
485cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
486cdc920a0Smrg      UnlockDisplay(dpy);
487cdc920a0Smrg      SyncHandle();
488cdc920a0Smrg      return NULL;
489cdc920a0Smrg   }
490cdc920a0Smrg
491cdc920a0Smrg   *width = rep.width;
492cdc920a0Smrg   *height = rep.height;
493cdc920a0Smrg   *outCount = rep.count;
494cdc920a0Smrg
495af69d88dSmrg   buffers = malloc(rep.count * sizeof buffers[0]);
496cdc920a0Smrg   if (buffers == NULL) {
497cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
498cdc920a0Smrg      UnlockDisplay(dpy);
499cdc920a0Smrg      SyncHandle();
500cdc920a0Smrg      return NULL;
501cdc920a0Smrg   }
502cdc920a0Smrg
503cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
504cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
505cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
506cdc920a0Smrg      buffers[i].name = repBuffer.name;
507cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
508cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
509cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
510cdc920a0Smrg   }
511cdc920a0Smrg
512cdc920a0Smrg   UnlockDisplay(dpy);
513cdc920a0Smrg   SyncHandle();
514cdc920a0Smrg
515cdc920a0Smrg   return buffers;
516cdc920a0Smrg}
517cdc920a0Smrg
518cdc920a0Smrg
519cdc920a0Smrgvoid
520cdc920a0SmrgDRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
521cdc920a0Smrg               CARD32 dest, CARD32 src)
522cdc920a0Smrg{
523cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
524cdc920a0Smrg   xDRI2CopyRegionReq *req;
525cdc920a0Smrg   xDRI2CopyRegionReply rep;
526cdc920a0Smrg
527cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
528cdc920a0Smrg
529cdc920a0Smrg   LockDisplay(dpy);
530cdc920a0Smrg   GetReq(DRI2CopyRegion, req);
531cdc920a0Smrg   req->reqType = info->codes->major_opcode;
532cdc920a0Smrg   req->dri2ReqType = X_DRI2CopyRegion;
533cdc920a0Smrg   req->drawable = drawable;
534cdc920a0Smrg   req->region = region;
535cdc920a0Smrg   req->dest = dest;
536cdc920a0Smrg   req->src = src;
537cdc920a0Smrg
538cdc920a0Smrg   _XReply(dpy, (xReply *) & rep, 0, xFalse);
539cdc920a0Smrg
540cdc920a0Smrg   UnlockDisplay(dpy);
541cdc920a0Smrg   SyncHandle();
542cdc920a0Smrg}
543cdc920a0Smrg
544cdc920a0Smrg#endif /* GLX_DIRECT_RENDERING */
545