dri2_glx.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#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
34cdc920a0Smrg
35cdc920a0Smrg#include <X11/Xlib.h>
36cdc920a0Smrg#include <X11/extensions/Xfixes.h>
37cdc920a0Smrg#include <X11/extensions/Xdamage.h>
38cdc920a0Smrg#include "glapi.h"
39cdc920a0Smrg#include "glxclient.h"
40cdc920a0Smrg#include <X11/extensions/dri2proto.h>
41cdc920a0Smrg#include "xf86dri.h"
42cdc920a0Smrg#include <dlfcn.h>
43cdc920a0Smrg#include <fcntl.h>
44cdc920a0Smrg#include <unistd.h>
45cdc920a0Smrg#include <sys/types.h>
46cdc920a0Smrg#include <sys/mman.h>
47cdc920a0Smrg#include "xf86drm.h"
48cdc920a0Smrg#include "dri2.h"
49cdc920a0Smrg#include "dri_common.h"
50cdc920a0Smrg#include "../../mesa/drivers/dri/common/dri_util.h"
51cdc920a0Smrg
52cdc920a0Smrg#undef DRI2_MINOR
53cdc920a0Smrg#define DRI2_MINOR 1
54cdc920a0Smrg
55cdc920a0Smrgtypedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
56cdc920a0Smrgtypedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
57cdc920a0Smrgtypedef struct __GLXDRIdrawablePrivateRec __GLXDRIdrawablePrivate;
58cdc920a0Smrg
59cdc920a0Smrgstruct __GLXDRIdisplayPrivateRec
60cdc920a0Smrg{
61cdc920a0Smrg   __GLXDRIdisplay base;
62cdc920a0Smrg
63cdc920a0Smrg   /*
64cdc920a0Smrg    ** XFree86-DRI version information
65cdc920a0Smrg    */
66cdc920a0Smrg   int driMajor;
67cdc920a0Smrg   int driMinor;
68cdc920a0Smrg   int driPatch;
69cdc920a0Smrg   int swapAvailable;
70cdc920a0Smrg   int invalidateAvailable;
71cdc920a0Smrg};
72cdc920a0Smrg
73cdc920a0Smrgstruct __GLXDRIcontextPrivateRec
74cdc920a0Smrg{
75cdc920a0Smrg   __GLXDRIcontext base;
76cdc920a0Smrg   __DRIcontext *driContext;
77cdc920a0Smrg   __GLXscreenConfigs *psc;
78cdc920a0Smrg};
79cdc920a0Smrg
80cdc920a0Smrgstruct __GLXDRIdrawablePrivateRec
81cdc920a0Smrg{
82cdc920a0Smrg   __GLXDRIdrawable base;
83cdc920a0Smrg   __DRIbuffer buffers[5];
84cdc920a0Smrg   int bufferCount;
85cdc920a0Smrg   int width, height;
86cdc920a0Smrg   int have_back;
87cdc920a0Smrg   int have_fake_front;
88cdc920a0Smrg   int swap_interval;
89cdc920a0Smrg};
90cdc920a0Smrg
91cdc920a0Smrgstatic void dri2WaitX(__GLXDRIdrawable * pdraw);
92cdc920a0Smrg
93cdc920a0Smrgstatic void
94cdc920a0Smrgdri2DestroyContext(__GLXDRIcontext * context,
95cdc920a0Smrg                   __GLXscreenConfigs * psc, Display * dpy)
96cdc920a0Smrg{
97cdc920a0Smrg   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
98cdc920a0Smrg   const __DRIcoreExtension *core = pcp->psc->core;
99cdc920a0Smrg
100cdc920a0Smrg   (*core->destroyContext) (pcp->driContext);
101cdc920a0Smrg
102cdc920a0Smrg   Xfree(pcp);
103cdc920a0Smrg}
104cdc920a0Smrg
105cdc920a0Smrgstatic Bool
106cdc920a0Smrgdri2BindContext(__GLXDRIcontext * context,
107cdc920a0Smrg                __GLXDRIdrawable * draw, __GLXDRIdrawable * read)
108cdc920a0Smrg{
109cdc920a0Smrg   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
110cdc920a0Smrg   const __DRIcoreExtension *core = pcp->psc->core;
111cdc920a0Smrg
112cdc920a0Smrg   return (*core->bindContext) (pcp->driContext,
113cdc920a0Smrg                                draw->driDrawable, read->driDrawable);
114cdc920a0Smrg}
115cdc920a0Smrg
116cdc920a0Smrgstatic void
117cdc920a0Smrgdri2UnbindContext(__GLXDRIcontext * context)
118cdc920a0Smrg{
119cdc920a0Smrg   __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
120cdc920a0Smrg   const __DRIcoreExtension *core = pcp->psc->core;
121cdc920a0Smrg
122cdc920a0Smrg   (*core->unbindContext) (pcp->driContext);
123cdc920a0Smrg}
124cdc920a0Smrg
125cdc920a0Smrgstatic __GLXDRIcontext *
126cdc920a0Smrgdri2CreateContext(__GLXscreenConfigs * psc,
127cdc920a0Smrg                  const __GLcontextModes * mode,
128cdc920a0Smrg                  GLXContext gc, GLXContext shareList, int renderType)
129cdc920a0Smrg{
130cdc920a0Smrg   __GLXDRIcontextPrivate *pcp, *pcp_shared;
131cdc920a0Smrg   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
132cdc920a0Smrg   __DRIcontext *shared = NULL;
133cdc920a0Smrg
134cdc920a0Smrg   if (shareList) {
135cdc920a0Smrg      pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
136cdc920a0Smrg      shared = pcp_shared->driContext;
137cdc920a0Smrg   }
138cdc920a0Smrg
139cdc920a0Smrg   pcp = Xmalloc(sizeof *pcp);
140cdc920a0Smrg   if (pcp == NULL)
141cdc920a0Smrg      return NULL;
142cdc920a0Smrg
143cdc920a0Smrg   pcp->psc = psc;
144cdc920a0Smrg   pcp->driContext =
145cdc920a0Smrg      (*psc->dri2->createNewContext) (psc->__driScreen,
146cdc920a0Smrg                                      config->driConfig, shared, pcp);
147cdc920a0Smrg   gc->__driContext = pcp->driContext;
148cdc920a0Smrg
149cdc920a0Smrg   if (pcp->driContext == NULL) {
150cdc920a0Smrg      Xfree(pcp);
151cdc920a0Smrg      return NULL;
152cdc920a0Smrg   }
153cdc920a0Smrg
154cdc920a0Smrg   pcp->base.destroyContext = dri2DestroyContext;
155cdc920a0Smrg   pcp->base.bindContext = dri2BindContext;
156cdc920a0Smrg   pcp->base.unbindContext = dri2UnbindContext;
157cdc920a0Smrg
158cdc920a0Smrg   return &pcp->base;
159cdc920a0Smrg}
160cdc920a0Smrg
161cdc920a0Smrgstatic void
162cdc920a0Smrgdri2DestroyDrawable(__GLXDRIdrawable * pdraw)
163cdc920a0Smrg{
164cdc920a0Smrg   const __DRIcoreExtension *core = pdraw->psc->core;
165cdc920a0Smrg
166cdc920a0Smrg   (*core->destroyDrawable) (pdraw->driDrawable);
167cdc920a0Smrg   DRI2DestroyDrawable(pdraw->psc->dpy, pdraw->xDrawable);
168cdc920a0Smrg   Xfree(pdraw);
169cdc920a0Smrg}
170cdc920a0Smrg
171cdc920a0Smrgstatic __GLXDRIdrawable *
172cdc920a0Smrgdri2CreateDrawable(__GLXscreenConfigs * psc,
173cdc920a0Smrg                   XID xDrawable,
174cdc920a0Smrg                   GLXDrawable drawable, const __GLcontextModes * modes)
175cdc920a0Smrg{
176cdc920a0Smrg   __GLXDRIdrawablePrivate *pdraw;
177cdc920a0Smrg   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
178cdc920a0Smrg   __GLXdisplayPrivate *dpyPriv;
179cdc920a0Smrg   __GLXDRIdisplayPrivate *pdp;
180cdc920a0Smrg
181cdc920a0Smrg   pdraw = Xmalloc(sizeof(*pdraw));
182cdc920a0Smrg   if (!pdraw)
183cdc920a0Smrg      return NULL;
184cdc920a0Smrg
185cdc920a0Smrg   pdraw->base.destroyDrawable = dri2DestroyDrawable;
186cdc920a0Smrg   pdraw->base.xDrawable = xDrawable;
187cdc920a0Smrg   pdraw->base.drawable = drawable;
188cdc920a0Smrg   pdraw->base.psc = psc;
189cdc920a0Smrg   pdraw->bufferCount = 0;
190cdc920a0Smrg   pdraw->swap_interval = 1;
191cdc920a0Smrg   pdraw->have_back = 0;
192cdc920a0Smrg
193cdc920a0Smrg   DRI2CreateDrawable(psc->dpy, xDrawable);
194cdc920a0Smrg
195cdc920a0Smrg   dpyPriv = __glXInitialize(psc->dpy);
196cdc920a0Smrg   pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;;
197cdc920a0Smrg   /* Create a new drawable */
198cdc920a0Smrg   pdraw->base.driDrawable =
199cdc920a0Smrg      (*psc->dri2->createNewDrawable) (psc->__driScreen,
200cdc920a0Smrg                                       config->driConfig, pdraw);
201cdc920a0Smrg
202cdc920a0Smrg   if (!pdraw->base.driDrawable) {
203cdc920a0Smrg      DRI2DestroyDrawable(psc->dpy, xDrawable);
204cdc920a0Smrg      Xfree(pdraw);
205cdc920a0Smrg      return NULL;
206cdc920a0Smrg   }
207cdc920a0Smrg
208cdc920a0Smrg#ifdef X_DRI2SwapInterval
209cdc920a0Smrg   /*
210cdc920a0Smrg    * Make sure server has the same swap interval we do for the new
211cdc920a0Smrg    * drawable.
212cdc920a0Smrg    */
213cdc920a0Smrg   if (pdp->swapAvailable)
214cdc920a0Smrg      DRI2SwapInterval(psc->dpy, xDrawable, pdraw->swap_interval);
215cdc920a0Smrg#endif
216cdc920a0Smrg
217cdc920a0Smrg   return &pdraw->base;
218cdc920a0Smrg}
219cdc920a0Smrg
220cdc920a0Smrg#ifdef X_DRI2GetMSC
221cdc920a0Smrg
222cdc920a0Smrgstatic int
223cdc920a0Smrgdri2DrawableGetMSC(__GLXscreenConfigs *psc, __GLXDRIdrawable *pdraw,
224cdc920a0Smrg		   int64_t *ust, int64_t *msc, int64_t *sbc)
225cdc920a0Smrg{
226cdc920a0Smrg   return DRI2GetMSC(psc->dpy, pdraw->xDrawable, ust, msc, sbc);
227cdc920a0Smrg}
228cdc920a0Smrg
229cdc920a0Smrg#endif
230cdc920a0Smrg
231cdc920a0Smrg
232cdc920a0Smrg#ifdef X_DRI2WaitMSC
233cdc920a0Smrg
234cdc920a0Smrgstatic int
235cdc920a0Smrgdri2WaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
236cdc920a0Smrg	       int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
237cdc920a0Smrg{
238cdc920a0Smrg   return DRI2WaitMSC(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
239cdc920a0Smrg		      remainder, ust, msc, sbc);
240cdc920a0Smrg}
241cdc920a0Smrg
242cdc920a0Smrgstatic int
243cdc920a0Smrgdri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
244cdc920a0Smrg	       int64_t *msc, int64_t *sbc)
245cdc920a0Smrg{
246cdc920a0Smrg   return DRI2WaitSBC(pdraw->psc->dpy, pdraw->xDrawable, target_sbc, ust, msc,
247cdc920a0Smrg		      sbc);
248cdc920a0Smrg}
249cdc920a0Smrg
250cdc920a0Smrg#endif /* X_DRI2WaitMSC */
251cdc920a0Smrg
252cdc920a0Smrgstatic void
253cdc920a0Smrgdri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
254cdc920a0Smrg{
255cdc920a0Smrg   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
256cdc920a0Smrg   XRectangle xrect;
257cdc920a0Smrg   XserverRegion region;
258cdc920a0Smrg
259cdc920a0Smrg   /* Check we have the right attachments */
260cdc920a0Smrg   if (!priv->have_back)
261cdc920a0Smrg      return;
262cdc920a0Smrg
263cdc920a0Smrg   xrect.x = x;
264cdc920a0Smrg   xrect.y = priv->height - y - height;
265cdc920a0Smrg   xrect.width = width;
266cdc920a0Smrg   xrect.height = height;
267cdc920a0Smrg
268cdc920a0Smrg#ifdef __DRI2_FLUSH
269cdc920a0Smrg   if (pdraw->psc->f)
270cdc920a0Smrg      (*pdraw->psc->f->flush) (pdraw->driDrawable);
271cdc920a0Smrg#endif
272cdc920a0Smrg
273cdc920a0Smrg   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
274cdc920a0Smrg   /* should get a fence ID back from here at some point */
275cdc920a0Smrg   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
276cdc920a0Smrg                  DRI2BufferFrontLeft, DRI2BufferBackLeft);
277cdc920a0Smrg   XFixesDestroyRegion(pdraw->psc->dpy, region);
278cdc920a0Smrg
279cdc920a0Smrg   /* Refresh the fake front (if present) after we just damaged the real
280cdc920a0Smrg    * front.
281cdc920a0Smrg    */
282cdc920a0Smrg   dri2WaitX(pdraw);
283cdc920a0Smrg}
284cdc920a0Smrg
285cdc920a0Smrgstatic void
286cdc920a0Smrgdri2WaitX(__GLXDRIdrawable *pdraw)
287cdc920a0Smrg{
288cdc920a0Smrg   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
289cdc920a0Smrg   XRectangle xrect;
290cdc920a0Smrg   XserverRegion region;
291cdc920a0Smrg
292cdc920a0Smrg   /* Check we have the right attachments */
293cdc920a0Smrg   if (!priv->have_fake_front)
294cdc920a0Smrg      return;
295cdc920a0Smrg
296cdc920a0Smrg   xrect.x = 0;
297cdc920a0Smrg   xrect.y = 0;
298cdc920a0Smrg   xrect.width = priv->width;
299cdc920a0Smrg   xrect.height = priv->height;
300cdc920a0Smrg
301cdc920a0Smrg#ifdef __DRI2_FLUSH
302cdc920a0Smrg   if (pdraw->psc->f)
303cdc920a0Smrg      (*pdraw->psc->f->flush) (pdraw->driDrawable);
304cdc920a0Smrg#endif
305cdc920a0Smrg
306cdc920a0Smrg   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
307cdc920a0Smrg   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
308cdc920a0Smrg                  DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
309cdc920a0Smrg   XFixesDestroyRegion(pdraw->psc->dpy, region);
310cdc920a0Smrg}
311cdc920a0Smrg
312cdc920a0Smrgstatic void
313cdc920a0Smrgdri2WaitGL(__GLXDRIdrawable * pdraw)
314cdc920a0Smrg{
315cdc920a0Smrg   __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
316cdc920a0Smrg   XRectangle xrect;
317cdc920a0Smrg   XserverRegion region;
318cdc920a0Smrg
319cdc920a0Smrg   if (!priv->have_fake_front)
320cdc920a0Smrg      return;
321cdc920a0Smrg
322cdc920a0Smrg   xrect.x = 0;
323cdc920a0Smrg   xrect.y = 0;
324cdc920a0Smrg   xrect.width = priv->width;
325cdc920a0Smrg   xrect.height = priv->height;
326cdc920a0Smrg
327cdc920a0Smrg#ifdef __DRI2_FLUSH
328cdc920a0Smrg   if (pdraw->psc->f)
329cdc920a0Smrg      (*pdraw->psc->f->flush) (pdraw->driDrawable);
330cdc920a0Smrg#endif
331cdc920a0Smrg
332cdc920a0Smrg   region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
333cdc920a0Smrg   DRI2CopyRegion(pdraw->psc->dpy, pdraw->xDrawable, region,
334cdc920a0Smrg                  DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
335cdc920a0Smrg   XFixesDestroyRegion(pdraw->psc->dpy, region);
336cdc920a0Smrg}
337cdc920a0Smrg
338cdc920a0Smrgstatic void
339cdc920a0Smrgdri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
340cdc920a0Smrg{
341cdc920a0Smrg   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
342cdc920a0Smrg   __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
343cdc920a0Smrg   __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
344cdc920a0Smrg
345cdc920a0Smrg   /* Old servers don't send invalidate events */
346cdc920a0Smrg   if (!pdp->invalidateAvailable)
347cdc920a0Smrg       dri2InvalidateBuffers(priv->dpy, pdraw->base.drawable);
348cdc920a0Smrg
349cdc920a0Smrg   dri2WaitGL(loaderPrivate);
350cdc920a0Smrg}
351cdc920a0Smrg
352cdc920a0Smrg
353cdc920a0Smrgstatic void
354cdc920a0Smrgdri2DestroyScreen(__GLXscreenConfigs * psc)
355cdc920a0Smrg{
356cdc920a0Smrg   /* Free the direct rendering per screen data */
357cdc920a0Smrg   (*psc->core->destroyScreen) (psc->__driScreen);
358cdc920a0Smrg   close(psc->fd);
359cdc920a0Smrg   psc->__driScreen = NULL;
360cdc920a0Smrg}
361cdc920a0Smrg
362cdc920a0Smrg/**
363cdc920a0Smrg * Process list of buffer received from the server
364cdc920a0Smrg *
365cdc920a0Smrg * Processes the list of buffers received in a reply from the server to either
366cdc920a0Smrg * \c DRI2GetBuffers or \c DRI2GetBuffersWithFormat.
367cdc920a0Smrg */
368cdc920a0Smrgstatic void
369cdc920a0Smrgprocess_buffers(__GLXDRIdrawablePrivate * pdraw, DRI2Buffer * buffers,
370cdc920a0Smrg                unsigned count)
371cdc920a0Smrg{
372cdc920a0Smrg   int i;
373cdc920a0Smrg
374cdc920a0Smrg   pdraw->bufferCount = count;
375cdc920a0Smrg   pdraw->have_fake_front = 0;
376cdc920a0Smrg   pdraw->have_back = 0;
377cdc920a0Smrg
378cdc920a0Smrg   /* This assumes the DRI2 buffer attachment tokens matches the
379cdc920a0Smrg    * __DRIbuffer tokens. */
380cdc920a0Smrg   for (i = 0; i < count; i++) {
381cdc920a0Smrg      pdraw->buffers[i].attachment = buffers[i].attachment;
382cdc920a0Smrg      pdraw->buffers[i].name = buffers[i].name;
383cdc920a0Smrg      pdraw->buffers[i].pitch = buffers[i].pitch;
384cdc920a0Smrg      pdraw->buffers[i].cpp = buffers[i].cpp;
385cdc920a0Smrg      pdraw->buffers[i].flags = buffers[i].flags;
386cdc920a0Smrg      if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
387cdc920a0Smrg         pdraw->have_fake_front = 1;
388cdc920a0Smrg      if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
389cdc920a0Smrg         pdraw->have_back = 1;
390cdc920a0Smrg   }
391cdc920a0Smrg
392cdc920a0Smrg}
393cdc920a0Smrg
394cdc920a0Smrgstatic int64_t
395cdc920a0Smrgdri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
396cdc920a0Smrg		int64_t remainder)
397cdc920a0Smrg{
398cdc920a0Smrg    __GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
399cdc920a0Smrg    __GLXdisplayPrivate *dpyPriv = __glXInitialize(priv->base.psc->dpy);
400cdc920a0Smrg    __GLXDRIdisplayPrivate *pdp =
401cdc920a0Smrg	(__GLXDRIdisplayPrivate *)dpyPriv->dri2Display;
402cdc920a0Smrg    int64_t ret;
403cdc920a0Smrg
404cdc920a0Smrg#ifdef __DRI2_FLUSH
405cdc920a0Smrg    if (pdraw->psc->f)
406cdc920a0Smrg    	(*pdraw->psc->f->flush)(pdraw->driDrawable);
407cdc920a0Smrg#endif
408cdc920a0Smrg
409cdc920a0Smrg    /* Old servers don't send invalidate events */
410cdc920a0Smrg    if (!pdp->invalidateAvailable)
411cdc920a0Smrg       dri2InvalidateBuffers(dpyPriv->dpy, pdraw->drawable);
412cdc920a0Smrg
413cdc920a0Smrg    /* Old servers can't handle swapbuffers */
414cdc920a0Smrg    if (!pdp->swapAvailable) {
415cdc920a0Smrg       dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
416cdc920a0Smrg       return 0;
417cdc920a0Smrg    }
418cdc920a0Smrg
419cdc920a0Smrg#ifdef X_DRI2SwapBuffers
420cdc920a0Smrg    DRI2SwapBuffers(pdraw->psc->dpy, pdraw->xDrawable, target_msc, divisor,
421cdc920a0Smrg		    remainder, &ret);
422cdc920a0Smrg#endif
423cdc920a0Smrg
424cdc920a0Smrg    return ret;
425cdc920a0Smrg}
426cdc920a0Smrg
427cdc920a0Smrgstatic __DRIbuffer *
428cdc920a0Smrgdri2GetBuffers(__DRIdrawable * driDrawable,
429cdc920a0Smrg               int *width, int *height,
430cdc920a0Smrg               unsigned int *attachments, int count,
431cdc920a0Smrg               int *out_count, void *loaderPrivate)
432cdc920a0Smrg{
433cdc920a0Smrg   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
434cdc920a0Smrg   DRI2Buffer *buffers;
435cdc920a0Smrg
436cdc920a0Smrg   buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable,
437cdc920a0Smrg                            width, height, attachments, count, out_count);
438cdc920a0Smrg   if (buffers == NULL)
439cdc920a0Smrg      return NULL;
440cdc920a0Smrg
441cdc920a0Smrg   pdraw->width = *width;
442cdc920a0Smrg   pdraw->height = *height;
443cdc920a0Smrg   process_buffers(pdraw, buffers, *out_count);
444cdc920a0Smrg
445cdc920a0Smrg   Xfree(buffers);
446cdc920a0Smrg
447cdc920a0Smrg   return pdraw->buffers;
448cdc920a0Smrg}
449cdc920a0Smrg
450cdc920a0Smrgstatic __DRIbuffer *
451cdc920a0Smrgdri2GetBuffersWithFormat(__DRIdrawable * driDrawable,
452cdc920a0Smrg                         int *width, int *height,
453cdc920a0Smrg                         unsigned int *attachments, int count,
454cdc920a0Smrg                         int *out_count, void *loaderPrivate)
455cdc920a0Smrg{
456cdc920a0Smrg   __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
457cdc920a0Smrg   DRI2Buffer *buffers;
458cdc920a0Smrg
459cdc920a0Smrg   buffers = DRI2GetBuffersWithFormat(pdraw->base.psc->dpy,
460cdc920a0Smrg                                      pdraw->base.xDrawable,
461cdc920a0Smrg                                      width, height, attachments,
462cdc920a0Smrg                                      count, out_count);
463cdc920a0Smrg   if (buffers == NULL)
464cdc920a0Smrg      return NULL;
465cdc920a0Smrg
466cdc920a0Smrg   pdraw->width = *width;
467cdc920a0Smrg   pdraw->height = *height;
468cdc920a0Smrg   process_buffers(pdraw, buffers, *out_count);
469cdc920a0Smrg
470cdc920a0Smrg   Xfree(buffers);
471cdc920a0Smrg
472cdc920a0Smrg   return pdraw->buffers;
473cdc920a0Smrg}
474cdc920a0Smrg
475cdc920a0Smrg#ifdef X_DRI2SwapInterval
476cdc920a0Smrg
477cdc920a0Smrgstatic void
478cdc920a0Smrgdri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
479cdc920a0Smrg{
480cdc920a0Smrg   __GLXDRIdrawablePrivate *priv =  (__GLXDRIdrawablePrivate *) pdraw;
481cdc920a0Smrg
482cdc920a0Smrg   DRI2SwapInterval(priv->base.psc->dpy, pdraw->xDrawable, interval);
483cdc920a0Smrg   priv->swap_interval = interval;
484cdc920a0Smrg}
485cdc920a0Smrg
486cdc920a0Smrgstatic unsigned int
487cdc920a0Smrgdri2GetSwapInterval(__GLXDRIdrawable *pdraw)
488cdc920a0Smrg{
489cdc920a0Smrg   __GLXDRIdrawablePrivate *priv =  (__GLXDRIdrawablePrivate *) pdraw;
490cdc920a0Smrg
491cdc920a0Smrg  return priv->swap_interval;
492cdc920a0Smrg}
493cdc920a0Smrg
494cdc920a0Smrg#endif /* X_DRI2SwapInterval */
495cdc920a0Smrg
496cdc920a0Smrgstatic const __DRIdri2LoaderExtension dri2LoaderExtension = {
497cdc920a0Smrg   {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
498cdc920a0Smrg   dri2GetBuffers,
499cdc920a0Smrg   dri2FlushFrontBuffer,
500cdc920a0Smrg   dri2GetBuffersWithFormat,
501cdc920a0Smrg};
502cdc920a0Smrg
503cdc920a0Smrgstatic const __DRIdri2LoaderExtension dri2LoaderExtension_old = {
504cdc920a0Smrg   {__DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION},
505cdc920a0Smrg   dri2GetBuffers,
506cdc920a0Smrg   dri2FlushFrontBuffer,
507cdc920a0Smrg   NULL,
508cdc920a0Smrg};
509cdc920a0Smrg
510cdc920a0Smrgstatic const __DRIextension *loader_extensions[] = {
511cdc920a0Smrg   &dri2LoaderExtension.base,
512cdc920a0Smrg   &systemTimeExtension.base,
513cdc920a0Smrg   NULL
514cdc920a0Smrg};
515cdc920a0Smrg
516cdc920a0Smrgstatic const __DRIextension *loader_extensions_old[] = {
517cdc920a0Smrg   &dri2LoaderExtension_old.base,
518cdc920a0Smrg   &systemTimeExtension.base,
519cdc920a0Smrg   NULL
520cdc920a0Smrg};
521cdc920a0Smrg
522cdc920a0Smrg_X_HIDDEN void
523cdc920a0Smrgdri2InvalidateBuffers(Display *dpy, XID drawable)
524cdc920a0Smrg{
525cdc920a0Smrg   __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
526cdc920a0Smrg
527cdc920a0Smrg#if __DRI2_FLUSH_VERSION >= 3
528cdc920a0Smrg   if (pdraw && pdraw->psc->f)
529cdc920a0Smrg       pdraw->psc->f->invalidate(pdraw->driDrawable);
530cdc920a0Smrg#endif
531cdc920a0Smrg}
532cdc920a0Smrg
533cdc920a0Smrgstatic __GLXDRIscreen *
534cdc920a0Smrgdri2CreateScreen(__GLXscreenConfigs * psc, int screen,
535cdc920a0Smrg                 __GLXdisplayPrivate * priv)
536cdc920a0Smrg{
537cdc920a0Smrg   const __DRIconfig **driver_configs;
538cdc920a0Smrg   const __DRIextension **extensions;
539cdc920a0Smrg   const __GLXDRIdisplayPrivate *const pdp = (__GLXDRIdisplayPrivate *)
540cdc920a0Smrg      priv->dri2Display;
541cdc920a0Smrg   __GLXDRIscreen *psp;
542cdc920a0Smrg   char *driverName, *deviceName;
543cdc920a0Smrg   drm_magic_t magic;
544cdc920a0Smrg   int i;
545cdc920a0Smrg
546cdc920a0Smrg   psp = Xmalloc(sizeof *psp);
547cdc920a0Smrg   if (psp == NULL)
548cdc920a0Smrg      return NULL;
549cdc920a0Smrg
550cdc920a0Smrg   if (!DRI2Connect(psc->dpy, RootWindow(psc->dpy, screen),
551cdc920a0Smrg		    &driverName, &deviceName)) {
552cdc920a0Smrg      XFree(psp);
553cdc920a0Smrg      return NULL;
554cdc920a0Smrg   }
555cdc920a0Smrg
556cdc920a0Smrg   psc->driver = driOpenDriver(driverName);
557cdc920a0Smrg   if (psc->driver == NULL) {
558cdc920a0Smrg      ErrorMessageF("driver pointer missing\n");
559cdc920a0Smrg      goto handle_error;
560cdc920a0Smrg   }
561cdc920a0Smrg
562cdc920a0Smrg   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
563cdc920a0Smrg   if (extensions == NULL) {
564cdc920a0Smrg      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
565cdc920a0Smrg      goto handle_error;
566cdc920a0Smrg   }
567cdc920a0Smrg
568cdc920a0Smrg   for (i = 0; extensions[i]; i++) {
569cdc920a0Smrg      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
570cdc920a0Smrg	 psc->core = (__DRIcoreExtension *) extensions[i];
571cdc920a0Smrg      if (strcmp(extensions[i]->name, __DRI_DRI2) == 0)
572cdc920a0Smrg	 psc->dri2 = (__DRIdri2Extension *) extensions[i];
573cdc920a0Smrg   }
574cdc920a0Smrg
575cdc920a0Smrg   if (psc->core == NULL || psc->dri2 == NULL) {
576cdc920a0Smrg      ErrorMessageF("core dri or dri2 extension not found\n");
577cdc920a0Smrg      goto handle_error;
578cdc920a0Smrg   }
579cdc920a0Smrg
580cdc920a0Smrg   psc->fd = open(deviceName, O_RDWR);
581cdc920a0Smrg   if (psc->fd < 0) {
582cdc920a0Smrg      ErrorMessageF("failed to open drm device: %s\n", strerror(errno));
583cdc920a0Smrg      goto handle_error;
584cdc920a0Smrg   }
585cdc920a0Smrg
586cdc920a0Smrg   if (drmGetMagic(psc->fd, &magic)) {
587cdc920a0Smrg      ErrorMessageF("failed to get magic\n");
588cdc920a0Smrg      goto handle_error;
589cdc920a0Smrg   }
590cdc920a0Smrg
591cdc920a0Smrg   if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) {
592cdc920a0Smrg      ErrorMessageF("failed to authenticate magic %d\n", magic);
593cdc920a0Smrg      goto handle_error;
594cdc920a0Smrg   }
595cdc920a0Smrg
596cdc920a0Smrg   /* If the server does not support the protocol for
597cdc920a0Smrg    * DRI2GetBuffersWithFormat, don't supply that interface to the driver.
598cdc920a0Smrg    */
599cdc920a0Smrg   psc->__driScreen =
600cdc920a0Smrg      psc->dri2->createNewScreen(screen, psc->fd, ((pdp->driMinor < 1)
601cdc920a0Smrg						   ? loader_extensions_old
602cdc920a0Smrg						   : loader_extensions),
603cdc920a0Smrg				 &driver_configs, psc);
604cdc920a0Smrg
605cdc920a0Smrg   if (psc->__driScreen == NULL) {
606cdc920a0Smrg      ErrorMessageF("failed to create dri screen\n");
607cdc920a0Smrg      goto handle_error;
608cdc920a0Smrg   }
609cdc920a0Smrg
610cdc920a0Smrg   driBindCommonExtensions(psc);
611cdc920a0Smrg   dri2BindExtensions(psc);
612cdc920a0Smrg
613cdc920a0Smrg   psc->configs = driConvertConfigs(psc->core, psc->configs, driver_configs);
614cdc920a0Smrg   psc->visuals = driConvertConfigs(psc->core, psc->visuals, driver_configs);
615cdc920a0Smrg
616cdc920a0Smrg   psc->driver_configs = driver_configs;
617cdc920a0Smrg
618cdc920a0Smrg   psp->destroyScreen = dri2DestroyScreen;
619cdc920a0Smrg   psp->createContext = dri2CreateContext;
620cdc920a0Smrg   psp->createDrawable = dri2CreateDrawable;
621cdc920a0Smrg   psp->swapBuffers = dri2SwapBuffers;
622cdc920a0Smrg   psp->waitGL = dri2WaitGL;
623cdc920a0Smrg   psp->waitX = dri2WaitX;
624cdc920a0Smrg   psp->getDrawableMSC = NULL;
625cdc920a0Smrg   psp->waitForMSC = NULL;
626cdc920a0Smrg   psp->waitForSBC = NULL;
627cdc920a0Smrg   psp->setSwapInterval = NULL;
628cdc920a0Smrg   psp->getSwapInterval = NULL;
629cdc920a0Smrg
630cdc920a0Smrg   if (pdp->driMinor >= 2) {
631cdc920a0Smrg#ifdef X_DRI2GetMSC
632cdc920a0Smrg      psp->getDrawableMSC = dri2DrawableGetMSC;
633cdc920a0Smrg#endif
634cdc920a0Smrg#ifdef X_DRI2WaitMSC
635cdc920a0Smrg      psp->waitForMSC = dri2WaitForMSC;
636cdc920a0Smrg      psp->waitForSBC = dri2WaitForSBC;
637cdc920a0Smrg#endif
638cdc920a0Smrg#ifdef X_DRI2SwapInterval
639cdc920a0Smrg      psp->setSwapInterval = dri2SetSwapInterval;
640cdc920a0Smrg      psp->getSwapInterval = dri2GetSwapInterval;
641cdc920a0Smrg#endif
642cdc920a0Smrg#if defined(X_DRI2GetMSC) && defined(X_DRI2WaitMSC) && defined(X_DRI2SwapInterval)
643cdc920a0Smrg      __glXEnableDirectExtension(psc, "GLX_OML_sync_control");
644cdc920a0Smrg#endif
645cdc920a0Smrg   }
646cdc920a0Smrg
647cdc920a0Smrg   /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
648cdc920a0Smrg    * available.*/
649cdc920a0Smrg   psp->copySubBuffer = dri2CopySubBuffer;
650cdc920a0Smrg   __glXEnableDirectExtension(psc, "GLX_MESA_copy_sub_buffer");
651cdc920a0Smrg
652cdc920a0Smrg   Xfree(driverName);
653cdc920a0Smrg   Xfree(deviceName);
654cdc920a0Smrg
655cdc920a0Smrg   return psp;
656cdc920a0Smrg
657cdc920a0Smrghandle_error:
658cdc920a0Smrg   Xfree(driverName);
659cdc920a0Smrg   Xfree(deviceName);
660cdc920a0Smrg   XFree(psp);
661cdc920a0Smrg
662cdc920a0Smrg   /* FIXME: clean up here */
663cdc920a0Smrg
664cdc920a0Smrg   return NULL;
665cdc920a0Smrg}
666cdc920a0Smrg
667cdc920a0Smrg/* Called from __glXFreeDisplayPrivate.
668cdc920a0Smrg */
669cdc920a0Smrgstatic void
670cdc920a0Smrgdri2DestroyDisplay(__GLXDRIdisplay * dpy)
671cdc920a0Smrg{
672cdc920a0Smrg   Xfree(dpy);
673cdc920a0Smrg}
674cdc920a0Smrg
675cdc920a0Smrg/*
676cdc920a0Smrg * Allocate, initialize and return a __DRIdisplayPrivate object.
677cdc920a0Smrg * This is called from __glXInitialize() when we are given a new
678cdc920a0Smrg * display pointer.
679cdc920a0Smrg */
680cdc920a0Smrg_X_HIDDEN __GLXDRIdisplay *
681cdc920a0Smrgdri2CreateDisplay(Display * dpy)
682cdc920a0Smrg{
683cdc920a0Smrg   __GLXDRIdisplayPrivate *pdp;
684cdc920a0Smrg   int eventBase, errorBase;
685cdc920a0Smrg
686cdc920a0Smrg   if (!DRI2QueryExtension(dpy, &eventBase, &errorBase))
687cdc920a0Smrg      return NULL;
688cdc920a0Smrg
689cdc920a0Smrg   pdp = Xmalloc(sizeof *pdp);
690cdc920a0Smrg   if (pdp == NULL)
691cdc920a0Smrg      return NULL;
692cdc920a0Smrg
693cdc920a0Smrg   if (!DRI2QueryVersion(dpy, &pdp->driMajor, &pdp->driMinor)) {
694cdc920a0Smrg      Xfree(pdp);
695cdc920a0Smrg      return NULL;
696cdc920a0Smrg   }
697cdc920a0Smrg
698cdc920a0Smrg   pdp->driPatch = 0;
699cdc920a0Smrg   pdp->swapAvailable = (pdp->driMinor >= 2);
700cdc920a0Smrg   pdp->invalidateAvailable = (pdp->driMinor >= 3);
701cdc920a0Smrg
702cdc920a0Smrg   pdp->base.destroyDisplay = dri2DestroyDisplay;
703cdc920a0Smrg   pdp->base.createScreen = dri2CreateScreen;
704cdc920a0Smrg
705cdc920a0Smrg   return &pdp->base;
706cdc920a0Smrg}
707cdc920a0Smrg
708cdc920a0Smrg#endif /* GLX_DIRECT_RENDERING */
709