dri2.c revision cdc920a0
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#define NEED_REPLIES
37cdc920a0Smrg#include <stdio.h>
38cdc920a0Smrg#include <X11/Xlibint.h>
39cdc920a0Smrg#include <X11/extensions/Xext.h>
40cdc920a0Smrg#include <X11/extensions/extutil.h>
41cdc920a0Smrg#include <X11/extensions/dri2proto.h>
42cdc920a0Smrg#include "xf86drm.h"
43cdc920a0Smrg#include "dri2.h"
44cdc920a0Smrg#include "glxclient.h"
45cdc920a0Smrg#include "GL/glxext.h"
46cdc920a0Smrg
47cdc920a0Smrg/* Allow the build to work with an older versions of dri2proto.h and
48cdc920a0Smrg * dri2tokens.h.
49cdc920a0Smrg */
50cdc920a0Smrg#if DRI2_MINOR < 1
51cdc920a0Smrg#undef DRI2_MINOR
52cdc920a0Smrg#define DRI2_MINOR 1
53cdc920a0Smrg#define X_DRI2GetBuffersWithFormat 7
54cdc920a0Smrg#endif
55cdc920a0Smrg
56cdc920a0Smrg
57cdc920a0Smrgstatic char dri2ExtensionName[] = DRI2_NAME;
58cdc920a0Smrgstatic XExtensionInfo *dri2Info;
59cdc920a0Smrgstatic XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
60cdc920a0Smrg
61cdc920a0Smrgstatic Bool
62cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
63cdc920a0Smrgstatic Status
64cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
65cdc920a0Smrgstatic int
66cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
67cdc920a0Smrg
68cdc920a0Smrgstatic /* const */ XExtensionHooks dri2ExtensionHooks = {
69cdc920a0Smrg  NULL,                   /* create_gc */
70cdc920a0Smrg  NULL,                   /* copy_gc */
71cdc920a0Smrg  NULL,                   /* flush_gc */
72cdc920a0Smrg  NULL,                   /* free_gc */
73cdc920a0Smrg  NULL,                   /* create_font */
74cdc920a0Smrg  NULL,                   /* free_font */
75cdc920a0Smrg  DRI2CloseDisplay,       /* close_display */
76cdc920a0Smrg  DRI2WireToEvent,        /* wire_to_event */
77cdc920a0Smrg  DRI2EventToWire,        /* event_to_wire */
78cdc920a0Smrg  DRI2Error,              /* error */
79cdc920a0Smrg  NULL,                   /* error_string */
80cdc920a0Smrg};
81cdc920a0Smrg
82cdc920a0Smrgstatic XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
83cdc920a0Smrg                                   dri2Info,
84cdc920a0Smrg                                   dri2ExtensionName,
85cdc920a0Smrg                                   &dri2ExtensionHooks,
86cdc920a0Smrg                                   0, NULL)
87cdc920a0Smrg
88cdc920a0Smrgstatic Bool
89cdc920a0SmrgDRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
90cdc920a0Smrg{
91cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
92cdc920a0Smrg   XExtDisplayInfo *glx_info = __glXFindDisplay(dpy);
93cdc920a0Smrg
94cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
95cdc920a0Smrg
96cdc920a0Smrg   switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
97cdc920a0Smrg
98cdc920a0Smrg#ifdef X_DRI2SwapBuffers
99cdc920a0Smrg   case DRI2_BufferSwapComplete:
100cdc920a0Smrg   {
101cdc920a0Smrg      GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
102cdc920a0Smrg      xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
103cdc920a0Smrg      aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire);
104cdc920a0Smrg      aevent->type = glx_info->codes->first_event + GLX_BufferSwapComplete;
105cdc920a0Smrg      aevent->send_event = (awire->type & 0x80) != 0;
106cdc920a0Smrg      aevent->display = dpy;
107cdc920a0Smrg      aevent->drawable = awire->drawable;
108cdc920a0Smrg      switch (awire->event_type) {
109cdc920a0Smrg      case DRI2_EXCHANGE_COMPLETE:
110cdc920a0Smrg	 aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL;
111cdc920a0Smrg	 break;
112cdc920a0Smrg      case DRI2_BLIT_COMPLETE:
113cdc920a0Smrg	 aevent->event_type = GLX_COPY_COMPLETE_INTEL;
114cdc920a0Smrg	 break;
115cdc920a0Smrg      case DRI2_FLIP_COMPLETE:
116cdc920a0Smrg	 aevent->event_type = GLX_FLIP_COMPLETE_INTEL;
117cdc920a0Smrg	 break;
118cdc920a0Smrg      default:
119cdc920a0Smrg	 /* unknown swap completion type */
120cdc920a0Smrg	 return False;
121cdc920a0Smrg      }
122cdc920a0Smrg      aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo;
123cdc920a0Smrg      aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo;
124cdc920a0Smrg      aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
125cdc920a0Smrg      return True;
126cdc920a0Smrg   }
127cdc920a0Smrg#endif
128cdc920a0Smrg#ifdef DRI2_InvalidateBuffers
129cdc920a0Smrg   case DRI2_InvalidateBuffers:
130cdc920a0Smrg   {
131cdc920a0Smrg      xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
132cdc920a0Smrg
133cdc920a0Smrg      dri2InvalidateBuffers(dpy, awire->drawable);
134cdc920a0Smrg      return False;
135cdc920a0Smrg   }
136cdc920a0Smrg#endif
137cdc920a0Smrg   default:
138cdc920a0Smrg      /* client doesn't support server event */
139cdc920a0Smrg      break;
140cdc920a0Smrg   }
141cdc920a0Smrg
142cdc920a0Smrg   return False;
143cdc920a0Smrg}
144cdc920a0Smrg
145cdc920a0Smrg/* We don't actually support this.  It doesn't make sense for clients to
146cdc920a0Smrg * send each other DRI2 events.
147cdc920a0Smrg */
148cdc920a0Smrgstatic Status
149cdc920a0SmrgDRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
150cdc920a0Smrg{
151cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
152cdc920a0Smrg
153cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
154cdc920a0Smrg
155cdc920a0Smrg   switch (event->type) {
156cdc920a0Smrg   default:
157cdc920a0Smrg      /* client doesn't support server event */
158cdc920a0Smrg      break;
159cdc920a0Smrg   }
160cdc920a0Smrg
161cdc920a0Smrg   return Success;
162cdc920a0Smrg}
163cdc920a0Smrg
164cdc920a0Smrgstatic int
165cdc920a0SmrgDRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
166cdc920a0Smrg{
167cdc920a0Smrg    if (err->majorCode == codes->major_opcode &&
168cdc920a0Smrg	err->errorCode == BadDrawable &&
169cdc920a0Smrg	err->minorCode == X_DRI2CopyRegion)
170cdc920a0Smrg	return True;
171cdc920a0Smrg
172cdc920a0Smrg    return False;
173cdc920a0Smrg}
174cdc920a0Smrg
175cdc920a0SmrgBool
176cdc920a0SmrgDRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
177cdc920a0Smrg{
178cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
179cdc920a0Smrg
180cdc920a0Smrg   if (XextHasExtension(info)) {
181cdc920a0Smrg      *eventBase = info->codes->first_event;
182cdc920a0Smrg      *errorBase = info->codes->first_error;
183cdc920a0Smrg      return True;
184cdc920a0Smrg   }
185cdc920a0Smrg
186cdc920a0Smrg   return False;
187cdc920a0Smrg}
188cdc920a0Smrg
189cdc920a0SmrgBool
190cdc920a0SmrgDRI2QueryVersion(Display * dpy, int *major, int *minor)
191cdc920a0Smrg{
192cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
193cdc920a0Smrg   xDRI2QueryVersionReply rep;
194cdc920a0Smrg   xDRI2QueryVersionReq *req;
195cdc920a0Smrg   int i, nevents;
196cdc920a0Smrg
197cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
198cdc920a0Smrg
199cdc920a0Smrg   LockDisplay(dpy);
200cdc920a0Smrg   GetReq(DRI2QueryVersion, req);
201cdc920a0Smrg   req->reqType = info->codes->major_opcode;
202cdc920a0Smrg   req->dri2ReqType = X_DRI2QueryVersion;
203cdc920a0Smrg   req->majorVersion = DRI2_MAJOR;
204cdc920a0Smrg   req->minorVersion = DRI2_MINOR;
205cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
206cdc920a0Smrg      UnlockDisplay(dpy);
207cdc920a0Smrg      SyncHandle();
208cdc920a0Smrg      return False;
209cdc920a0Smrg   }
210cdc920a0Smrg   *major = rep.majorVersion;
211cdc920a0Smrg   *minor = rep.minorVersion;
212cdc920a0Smrg   UnlockDisplay(dpy);
213cdc920a0Smrg   SyncHandle();
214cdc920a0Smrg
215cdc920a0Smrg   switch (rep.minorVersion) {
216cdc920a0Smrg   case 1:
217cdc920a0Smrg	   nevents = 0;
218cdc920a0Smrg	   break;
219cdc920a0Smrg   case 2:
220cdc920a0Smrg	   nevents = 1;
221cdc920a0Smrg	   break;
222cdc920a0Smrg   case 3:
223cdc920a0Smrg   default:
224cdc920a0Smrg	   nevents = 2;
225cdc920a0Smrg	   break;
226cdc920a0Smrg   }
227cdc920a0Smrg
228cdc920a0Smrg   for (i = 0; i < nevents; i++) {
229cdc920a0Smrg       XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
230cdc920a0Smrg       XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
231cdc920a0Smrg   }
232cdc920a0Smrg
233cdc920a0Smrg   return True;
234cdc920a0Smrg}
235cdc920a0Smrg
236cdc920a0SmrgBool
237cdc920a0SmrgDRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
238cdc920a0Smrg{
239cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
240cdc920a0Smrg   xDRI2ConnectReply rep;
241cdc920a0Smrg   xDRI2ConnectReq *req;
242cdc920a0Smrg
243cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
244cdc920a0Smrg
245cdc920a0Smrg   LockDisplay(dpy);
246cdc920a0Smrg   GetReq(DRI2Connect, req);
247cdc920a0Smrg   req->reqType = info->codes->major_opcode;
248cdc920a0Smrg   req->dri2ReqType = X_DRI2Connect;
249cdc920a0Smrg   req->window = window;
250cdc920a0Smrg   req->driverType = DRI2DriverDRI;
251cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
252cdc920a0Smrg      UnlockDisplay(dpy);
253cdc920a0Smrg      SyncHandle();
254cdc920a0Smrg      return False;
255cdc920a0Smrg   }
256cdc920a0Smrg
257cdc920a0Smrg   if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
258cdc920a0Smrg      UnlockDisplay(dpy);
259cdc920a0Smrg      SyncHandle();
260cdc920a0Smrg      return False;
261cdc920a0Smrg   }
262cdc920a0Smrg
263cdc920a0Smrg   *driverName = Xmalloc(rep.driverNameLength + 1);
264cdc920a0Smrg   if (*driverName == NULL) {
265cdc920a0Smrg      _XEatData(dpy,
266cdc920a0Smrg                ((rep.driverNameLength + 3) & ~3) +
267cdc920a0Smrg                ((rep.deviceNameLength + 3) & ~3));
268cdc920a0Smrg      UnlockDisplay(dpy);
269cdc920a0Smrg      SyncHandle();
270cdc920a0Smrg      return False;
271cdc920a0Smrg   }
272cdc920a0Smrg   _XReadPad(dpy, *driverName, rep.driverNameLength);
273cdc920a0Smrg   (*driverName)[rep.driverNameLength] = '\0';
274cdc920a0Smrg
275cdc920a0Smrg   *deviceName = Xmalloc(rep.deviceNameLength + 1);
276cdc920a0Smrg   if (*deviceName == NULL) {
277cdc920a0Smrg      Xfree(*driverName);
278cdc920a0Smrg      _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
279cdc920a0Smrg      UnlockDisplay(dpy);
280cdc920a0Smrg      SyncHandle();
281cdc920a0Smrg      return False;
282cdc920a0Smrg   }
283cdc920a0Smrg   _XReadPad(dpy, *deviceName, rep.deviceNameLength);
284cdc920a0Smrg   (*deviceName)[rep.deviceNameLength] = '\0';
285cdc920a0Smrg
286cdc920a0Smrg   UnlockDisplay(dpy);
287cdc920a0Smrg   SyncHandle();
288cdc920a0Smrg
289cdc920a0Smrg   return True;
290cdc920a0Smrg}
291cdc920a0Smrg
292cdc920a0SmrgBool
293cdc920a0SmrgDRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
294cdc920a0Smrg{
295cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
296cdc920a0Smrg   xDRI2AuthenticateReq *req;
297cdc920a0Smrg   xDRI2AuthenticateReply rep;
298cdc920a0Smrg
299cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
300cdc920a0Smrg
301cdc920a0Smrg   LockDisplay(dpy);
302cdc920a0Smrg   GetReq(DRI2Authenticate, req);
303cdc920a0Smrg   req->reqType = info->codes->major_opcode;
304cdc920a0Smrg   req->dri2ReqType = X_DRI2Authenticate;
305cdc920a0Smrg   req->window = window;
306cdc920a0Smrg   req->magic = magic;
307cdc920a0Smrg
308cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
309cdc920a0Smrg      UnlockDisplay(dpy);
310cdc920a0Smrg      SyncHandle();
311cdc920a0Smrg      return False;
312cdc920a0Smrg   }
313cdc920a0Smrg
314cdc920a0Smrg   UnlockDisplay(dpy);
315cdc920a0Smrg   SyncHandle();
316cdc920a0Smrg
317cdc920a0Smrg   return rep.authenticated;
318cdc920a0Smrg}
319cdc920a0Smrg
320cdc920a0Smrgvoid
321cdc920a0SmrgDRI2CreateDrawable(Display * dpy, XID drawable)
322cdc920a0Smrg{
323cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
324cdc920a0Smrg   xDRI2CreateDrawableReq *req;
325cdc920a0Smrg
326cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
327cdc920a0Smrg
328cdc920a0Smrg   LockDisplay(dpy);
329cdc920a0Smrg   GetReq(DRI2CreateDrawable, req);
330cdc920a0Smrg   req->reqType = info->codes->major_opcode;
331cdc920a0Smrg   req->dri2ReqType = X_DRI2CreateDrawable;
332cdc920a0Smrg   req->drawable = drawable;
333cdc920a0Smrg   UnlockDisplay(dpy);
334cdc920a0Smrg   SyncHandle();
335cdc920a0Smrg}
336cdc920a0Smrg
337cdc920a0Smrgvoid
338cdc920a0SmrgDRI2DestroyDrawable(Display * dpy, XID drawable)
339cdc920a0Smrg{
340cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
341cdc920a0Smrg   xDRI2DestroyDrawableReq *req;
342cdc920a0Smrg
343cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
344cdc920a0Smrg
345cdc920a0Smrg   XSync(dpy, False);
346cdc920a0Smrg
347cdc920a0Smrg   LockDisplay(dpy);
348cdc920a0Smrg   GetReq(DRI2DestroyDrawable, req);
349cdc920a0Smrg   req->reqType = info->codes->major_opcode;
350cdc920a0Smrg   req->dri2ReqType = X_DRI2DestroyDrawable;
351cdc920a0Smrg   req->drawable = drawable;
352cdc920a0Smrg   UnlockDisplay(dpy);
353cdc920a0Smrg   SyncHandle();
354cdc920a0Smrg}
355cdc920a0Smrg
356cdc920a0SmrgDRI2Buffer *
357cdc920a0SmrgDRI2GetBuffers(Display * dpy, XID drawable,
358cdc920a0Smrg               int *width, int *height,
359cdc920a0Smrg               unsigned int *attachments, int count, int *outCount)
360cdc920a0Smrg{
361cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
362cdc920a0Smrg   xDRI2GetBuffersReply rep;
363cdc920a0Smrg   xDRI2GetBuffersReq *req;
364cdc920a0Smrg   DRI2Buffer *buffers;
365cdc920a0Smrg   xDRI2Buffer repBuffer;
366cdc920a0Smrg   CARD32 *p;
367cdc920a0Smrg   int i;
368cdc920a0Smrg
369cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
370cdc920a0Smrg
371cdc920a0Smrg   LockDisplay(dpy);
372cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * 4, req);
373cdc920a0Smrg   req->reqType = info->codes->major_opcode;
374cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffers;
375cdc920a0Smrg   req->drawable = drawable;
376cdc920a0Smrg   req->count = count;
377cdc920a0Smrg   p = (CARD32 *) & req[1];
378cdc920a0Smrg   for (i = 0; i < count; i++)
379cdc920a0Smrg      p[i] = attachments[i];
380cdc920a0Smrg
381cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
382cdc920a0Smrg      UnlockDisplay(dpy);
383cdc920a0Smrg      SyncHandle();
384cdc920a0Smrg      return NULL;
385cdc920a0Smrg   }
386cdc920a0Smrg
387cdc920a0Smrg   *width = rep.width;
388cdc920a0Smrg   *height = rep.height;
389cdc920a0Smrg   *outCount = rep.count;
390cdc920a0Smrg
391cdc920a0Smrg   buffers = Xmalloc(rep.count * sizeof buffers[0]);
392cdc920a0Smrg   if (buffers == NULL) {
393cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
394cdc920a0Smrg      UnlockDisplay(dpy);
395cdc920a0Smrg      SyncHandle();
396cdc920a0Smrg      return NULL;
397cdc920a0Smrg   }
398cdc920a0Smrg
399cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
400cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
401cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
402cdc920a0Smrg      buffers[i].name = repBuffer.name;
403cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
404cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
405cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
406cdc920a0Smrg   }
407cdc920a0Smrg
408cdc920a0Smrg   UnlockDisplay(dpy);
409cdc920a0Smrg   SyncHandle();
410cdc920a0Smrg
411cdc920a0Smrg   return buffers;
412cdc920a0Smrg}
413cdc920a0Smrg
414cdc920a0Smrg
415cdc920a0SmrgDRI2Buffer *
416cdc920a0SmrgDRI2GetBuffersWithFormat(Display * dpy, XID drawable,
417cdc920a0Smrg                         int *width, int *height,
418cdc920a0Smrg                         unsigned int *attachments, int count, int *outCount)
419cdc920a0Smrg{
420cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
421cdc920a0Smrg   xDRI2GetBuffersReply rep;
422cdc920a0Smrg   xDRI2GetBuffersReq *req;
423cdc920a0Smrg   DRI2Buffer *buffers;
424cdc920a0Smrg   xDRI2Buffer repBuffer;
425cdc920a0Smrg   CARD32 *p;
426cdc920a0Smrg   int i;
427cdc920a0Smrg
428cdc920a0Smrg   XextCheckExtension(dpy, info, dri2ExtensionName, False);
429cdc920a0Smrg
430cdc920a0Smrg   LockDisplay(dpy);
431cdc920a0Smrg   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
432cdc920a0Smrg   req->reqType = info->codes->major_opcode;
433cdc920a0Smrg   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
434cdc920a0Smrg   req->drawable = drawable;
435cdc920a0Smrg   req->count = count;
436cdc920a0Smrg   p = (CARD32 *) & req[1];
437cdc920a0Smrg   for (i = 0; i < (count * 2); i++)
438cdc920a0Smrg      p[i] = attachments[i];
439cdc920a0Smrg
440cdc920a0Smrg   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
441cdc920a0Smrg      UnlockDisplay(dpy);
442cdc920a0Smrg      SyncHandle();
443cdc920a0Smrg      return NULL;
444cdc920a0Smrg   }
445cdc920a0Smrg
446cdc920a0Smrg   *width = rep.width;
447cdc920a0Smrg   *height = rep.height;
448cdc920a0Smrg   *outCount = rep.count;
449cdc920a0Smrg
450cdc920a0Smrg   buffers = Xmalloc(rep.count * sizeof buffers[0]);
451cdc920a0Smrg   if (buffers == NULL) {
452cdc920a0Smrg      _XEatData(dpy, rep.count * sizeof repBuffer);
453cdc920a0Smrg      UnlockDisplay(dpy);
454cdc920a0Smrg      SyncHandle();
455cdc920a0Smrg      return NULL;
456cdc920a0Smrg   }
457cdc920a0Smrg
458cdc920a0Smrg   for (i = 0; i < rep.count; i++) {
459cdc920a0Smrg      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
460cdc920a0Smrg      buffers[i].attachment = repBuffer.attachment;
461cdc920a0Smrg      buffers[i].name = repBuffer.name;
462cdc920a0Smrg      buffers[i].pitch = repBuffer.pitch;
463cdc920a0Smrg      buffers[i].cpp = repBuffer.cpp;
464cdc920a0Smrg      buffers[i].flags = repBuffer.flags;
465cdc920a0Smrg   }
466cdc920a0Smrg
467cdc920a0Smrg   UnlockDisplay(dpy);
468cdc920a0Smrg   SyncHandle();
469cdc920a0Smrg
470cdc920a0Smrg   return buffers;
471cdc920a0Smrg}
472cdc920a0Smrg
473cdc920a0Smrg
474cdc920a0Smrgvoid
475cdc920a0SmrgDRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
476cdc920a0Smrg               CARD32 dest, CARD32 src)
477cdc920a0Smrg{
478cdc920a0Smrg   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
479cdc920a0Smrg   xDRI2CopyRegionReq *req;
480cdc920a0Smrg   xDRI2CopyRegionReply rep;
481cdc920a0Smrg
482cdc920a0Smrg   XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
483cdc920a0Smrg
484cdc920a0Smrg   LockDisplay(dpy);
485cdc920a0Smrg   GetReq(DRI2CopyRegion, req);
486cdc920a0Smrg   req->reqType = info->codes->major_opcode;
487cdc920a0Smrg   req->dri2ReqType = X_DRI2CopyRegion;
488cdc920a0Smrg   req->drawable = drawable;
489cdc920a0Smrg   req->region = region;
490cdc920a0Smrg   req->dest = dest;
491cdc920a0Smrg   req->src = src;
492cdc920a0Smrg
493cdc920a0Smrg   _XReply(dpy, (xReply *) & rep, 0, xFalse);
494cdc920a0Smrg
495cdc920a0Smrg   UnlockDisplay(dpy);
496cdc920a0Smrg   SyncHandle();
497cdc920a0Smrg}
498cdc920a0Smrg
499cdc920a0Smrg#ifdef X_DRI2SwapBuffers
500cdc920a0Smrgstatic void
501cdc920a0Smrgload_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
502cdc920a0Smrg	     CARD64 remainder)
503cdc920a0Smrg{
504cdc920a0Smrg    req->target_msc_hi = target >> 32;
505cdc920a0Smrg    req->target_msc_lo = target & 0xffffffff;
506cdc920a0Smrg    req->divisor_hi = divisor >> 32;
507cdc920a0Smrg    req->divisor_lo = divisor & 0xffffffff;
508cdc920a0Smrg    req->remainder_hi = remainder >> 32;
509cdc920a0Smrg    req->remainder_lo = remainder & 0xffffffff;
510cdc920a0Smrg}
511cdc920a0Smrg
512cdc920a0Smrgstatic CARD64
513cdc920a0Smrgvals_to_card64(CARD32 lo, CARD32 hi)
514cdc920a0Smrg{
515cdc920a0Smrg    return (CARD64)hi << 32 | lo;
516cdc920a0Smrg}
517cdc920a0Smrg
518cdc920a0Smrgvoid DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
519cdc920a0Smrg		     CARD64 divisor, CARD64 remainder, CARD64 *count)
520cdc920a0Smrg{
521cdc920a0Smrg    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
522cdc920a0Smrg    xDRI2SwapBuffersReq *req;
523cdc920a0Smrg    xDRI2SwapBuffersReply rep;
524cdc920a0Smrg
525cdc920a0Smrg    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
526cdc920a0Smrg
527cdc920a0Smrg    LockDisplay(dpy);
528cdc920a0Smrg    GetReq(DRI2SwapBuffers, req);
529cdc920a0Smrg    req->reqType = info->codes->major_opcode;
530cdc920a0Smrg    req->dri2ReqType = X_DRI2SwapBuffers;
531cdc920a0Smrg    req->drawable = drawable;
532cdc920a0Smrg    load_swap_req(req, target_msc, divisor, remainder);
533cdc920a0Smrg
534cdc920a0Smrg    _XReply(dpy, (xReply *)&rep, 0, xFalse);
535cdc920a0Smrg
536cdc920a0Smrg    *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
537cdc920a0Smrg
538cdc920a0Smrg    UnlockDisplay(dpy);
539cdc920a0Smrg    SyncHandle();
540cdc920a0Smrg}
541cdc920a0Smrg#endif
542cdc920a0Smrg
543cdc920a0Smrg#ifdef X_DRI2GetMSC
544cdc920a0SmrgBool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
545cdc920a0Smrg		CARD64 *sbc)
546cdc920a0Smrg{
547cdc920a0Smrg    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
548cdc920a0Smrg    xDRI2GetMSCReq *req;
549cdc920a0Smrg    xDRI2MSCReply rep;
550cdc920a0Smrg
551cdc920a0Smrg    XextCheckExtension (dpy, info, dri2ExtensionName, False);
552cdc920a0Smrg
553cdc920a0Smrg    LockDisplay(dpy);
554cdc920a0Smrg    GetReq(DRI2GetMSC, req);
555cdc920a0Smrg    req->reqType = info->codes->major_opcode;
556cdc920a0Smrg    req->dri2ReqType = X_DRI2GetMSC;
557cdc920a0Smrg    req->drawable = drawable;
558cdc920a0Smrg
559cdc920a0Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
560cdc920a0Smrg	UnlockDisplay(dpy);
561cdc920a0Smrg	SyncHandle();
562cdc920a0Smrg	return False;
563cdc920a0Smrg    }
564cdc920a0Smrg
565cdc920a0Smrg    *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
566cdc920a0Smrg    *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
567cdc920a0Smrg    *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
568cdc920a0Smrg
569cdc920a0Smrg    UnlockDisplay(dpy);
570cdc920a0Smrg    SyncHandle();
571cdc920a0Smrg
572cdc920a0Smrg    return True;
573cdc920a0Smrg}
574cdc920a0Smrg#endif
575cdc920a0Smrg
576cdc920a0Smrg#ifdef X_DRI2WaitMSC
577cdc920a0Smrgstatic void
578cdc920a0Smrgload_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
579cdc920a0Smrg	     CARD64 remainder)
580cdc920a0Smrg{
581cdc920a0Smrg    req->target_msc_hi = target >> 32;
582cdc920a0Smrg    req->target_msc_lo = target & 0xffffffff;
583cdc920a0Smrg    req->divisor_hi = divisor >> 32;
584cdc920a0Smrg    req->divisor_lo = divisor & 0xffffffff;
585cdc920a0Smrg    req->remainder_hi = remainder >> 32;
586cdc920a0Smrg    req->remainder_lo = remainder & 0xffffffff;
587cdc920a0Smrg}
588cdc920a0Smrg
589cdc920a0SmrgBool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
590cdc920a0Smrg		 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
591cdc920a0Smrg{
592cdc920a0Smrg    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
593cdc920a0Smrg    xDRI2WaitMSCReq *req;
594cdc920a0Smrg    xDRI2MSCReply rep;
595cdc920a0Smrg
596cdc920a0Smrg    XextCheckExtension (dpy, info, dri2ExtensionName, False);
597cdc920a0Smrg
598cdc920a0Smrg    LockDisplay(dpy);
599cdc920a0Smrg    GetReq(DRI2WaitMSC, req);
600cdc920a0Smrg    req->reqType = info->codes->major_opcode;
601cdc920a0Smrg    req->dri2ReqType = X_DRI2WaitMSC;
602cdc920a0Smrg    req->drawable = drawable;
603cdc920a0Smrg    load_msc_req(req, target_msc, divisor, remainder);
604cdc920a0Smrg
605cdc920a0Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
606cdc920a0Smrg	UnlockDisplay(dpy);
607cdc920a0Smrg	SyncHandle();
608cdc920a0Smrg	return False;
609cdc920a0Smrg    }
610cdc920a0Smrg
611cdc920a0Smrg    *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
612cdc920a0Smrg    *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
613cdc920a0Smrg    *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
614cdc920a0Smrg
615cdc920a0Smrg    UnlockDisplay(dpy);
616cdc920a0Smrg    SyncHandle();
617cdc920a0Smrg
618cdc920a0Smrg    return True;
619cdc920a0Smrg}
620cdc920a0Smrg#endif
621cdc920a0Smrg
622cdc920a0Smrg#ifdef X_DRI2WaitSBC
623cdc920a0Smrgstatic void
624cdc920a0Smrgload_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
625cdc920a0Smrg{
626cdc920a0Smrg    req->target_sbc_hi = target >> 32;
627cdc920a0Smrg    req->target_sbc_lo = target & 0xffffffff;
628cdc920a0Smrg}
629cdc920a0Smrg
630cdc920a0SmrgBool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
631cdc920a0Smrg		 CARD64 *msc, CARD64 *sbc)
632cdc920a0Smrg{
633cdc920a0Smrg    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
634cdc920a0Smrg    xDRI2WaitSBCReq *req;
635cdc920a0Smrg    xDRI2MSCReply rep;
636cdc920a0Smrg
637cdc920a0Smrg    XextCheckExtension (dpy, info, dri2ExtensionName, False);
638cdc920a0Smrg
639cdc920a0Smrg    LockDisplay(dpy);
640cdc920a0Smrg    GetReq(DRI2WaitSBC, req);
641cdc920a0Smrg    req->reqType = info->codes->major_opcode;
642cdc920a0Smrg    req->dri2ReqType = X_DRI2WaitSBC;
643cdc920a0Smrg    req->drawable = drawable;
644cdc920a0Smrg    load_sbc_req(req, target_sbc);
645cdc920a0Smrg
646cdc920a0Smrg    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
647cdc920a0Smrg	UnlockDisplay(dpy);
648cdc920a0Smrg	SyncHandle();
649cdc920a0Smrg	return False;
650cdc920a0Smrg    }
651cdc920a0Smrg
652cdc920a0Smrg    *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
653cdc920a0Smrg    *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
654cdc920a0Smrg    *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
655cdc920a0Smrg
656cdc920a0Smrg    UnlockDisplay(dpy);
657cdc920a0Smrg    SyncHandle();
658cdc920a0Smrg
659cdc920a0Smrg    return True;
660cdc920a0Smrg}
661cdc920a0Smrg#endif
662cdc920a0Smrg
663cdc920a0Smrg#ifdef X_DRI2SwapInterval
664cdc920a0Smrgvoid DRI2SwapInterval(Display *dpy, XID drawable, int interval)
665cdc920a0Smrg{
666cdc920a0Smrg    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
667cdc920a0Smrg    xDRI2SwapIntervalReq *req;
668cdc920a0Smrg
669cdc920a0Smrg    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
670cdc920a0Smrg
671cdc920a0Smrg    LockDisplay(dpy);
672cdc920a0Smrg    GetReq(DRI2SwapInterval, req);
673cdc920a0Smrg    req->reqType = info->codes->major_opcode;
674cdc920a0Smrg    req->dri2ReqType = X_DRI2SwapInterval;
675cdc920a0Smrg    req->drawable = drawable;
676cdc920a0Smrg    req->interval = interval;
677cdc920a0Smrg    UnlockDisplay(dpy);
678cdc920a0Smrg    SyncHandle();
679cdc920a0Smrg}
680cdc920a0Smrg#endif
681cdc920a0Smrg
682cdc920a0Smrg#endif /* GLX_DIRECT_RENDERING */
683