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