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