dri_util.c revision 3528d61820e9ae1aafb12fb90849155f3cab6d2c
1680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
2680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
3680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \file dri_util.c
4680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * DRI utility functions.
5680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
6680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This module acts as glue between GLX and the actual hardware driver.  A DRI
7680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * driver doesn't really \e have to use any of this - it's optional.  But, some
8680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * useful stuff is done here that otherwise would have to be duplicated in most
9680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drivers.
10680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
11680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Basically, these utility functions take care of some of the dirty details of
12680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * screen initialization, context creation, context binding, DRM setup, etc.
13680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
14680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * These functions are compiled into each DRI driver so libGL.so knows nothing
15680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * about them.
16680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
17680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
18680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
19680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#include <assert.h>
20680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#include <stdarg.h>
21680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#include <unistd.h>
22680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#include <sys/mman.h>
23680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#include <stdio.h>
247c46033130b1b4d6098647d85c2710367572e079Ian Romanick
2538b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane#ifndef MAP_FAILED
2638b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane#define MAP_FAILED ((void *)-1)
2738b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane#endif
2838b317d508a2a3a4cc6d700ebca80c3b06c913e2Alan Hourihane
29c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick#include "imports.h"
30c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick#define None 0
317c46033130b1b4d6098647d85c2710367572e079Ian Romanick
327c46033130b1b4d6098647d85c2710367572e079Ian Romanick#include "dri_util.h"
33ffb36d57a5f6359b5b91b73af60482a0016dd431Jon Smirl#include "drm_sarea.h"
34680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
35c604e457d1ebe9a884b0a1fb08af38a0ce486699Ian Romanick#ifndef GLX_OML_sync_control
367c46033130b1b4d6098647d85c2710367572e079Ian Romanicktypedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRInativeDisplay *dpy, __DRIid drawable, int32_t *numerator, int32_t *denominator);
378cdccc82d7948daee256e092a5253d49e277ef75Ian Romanick#endif
388cdccc82d7948daee256e092a5253d49e277ef75Ian Romanick
395f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick/* This pointer *must* be set by the driver's __driCreateNewScreen funciton!
405f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick */
415f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanickconst __DRIinterfaceMethods * dri_interface = NULL;
425f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick
43680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
44680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This is used in a couple of places that call \c driCreateNewDrawable.
45680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
46680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic const int empty_attribute_list[1] = { None };
47680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
48680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
49680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
50680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Cached copy of the internal API version used by libGL and the client-side
51680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * DRI driver.
52680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
53680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic int api_ver = 0;
54680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
55680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/* forward declarations */
56b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic int driQueryFrameTracking( __DRInativeDisplay *dpy, void *priv,
57b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  int64_t *sbc, int64_t *missedFrames,
58b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  float *lastMissedUsage, float *usage );
59680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
60b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void *driCreateNewDrawable(__DRInativeDisplay *dpy,
61b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  const __GLcontextModes *modes,
62b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  __DRIid draw, __DRIdrawable *pdraw,
63b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  int renderType, const int *attrs);
64680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
6560b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic void driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate);
66680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
67680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
68680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
69680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
70680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * is set.
71680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
72680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called from the drivers.
73680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
74680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param f \c printf like format string.
75680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
76680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
77680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilMessage(const char *f, ...)
78680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
79680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    va_list args;
80680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
81680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (getenv("LIBGL_DEBUG")) {
82680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "libGL error: \n");
83680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_start(args, f);
84680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        vfprintf(stderr, f, args);
85680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_end(args);
86680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "\n");
87680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
88680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
89680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
90680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
91680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
92680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Drawable list management */
93680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
94680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
95680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
967c46033130b1b4d6098647d85c2710367572e079Ian Romanickstatic GLboolean __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
97680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
98680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
99680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
100680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (drmHashInsert(drawHash, pdp->draw, pdraw))
101680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
102680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
103680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
104680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
105680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1060521ab46c1340d785ecfe64f4041c86912bc86afIan Romanickstatic __DRIdrawable *__driFindDrawable(void *drawHash, __DRIid draw)
107680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
108680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    int retcode;
1098e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell    __DRIdrawable *pdraw;
110680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1118e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell    retcode = drmHashLookup(drawHash, draw, (void *)&pdraw);
112680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (retcode)
113680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
114680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1158e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell    return pdraw;
116680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
117680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
118680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
119680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
120680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Find drawables in the local hash that have been destroyed on the
121680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * server.
122680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
123680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drawHash  Hash-table containing all know drawables.
124680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
125680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic void __driGarbageCollectDrawables(void *drawHash)
126680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1270521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick    __DRIid draw;
12860b0e12830310e7c05b4043857ed277b28b1c781Ian Romanick    __DRInativeDisplay *dpy;
1298e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell    __DRIdrawable *pdraw;
130680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1318e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell    if (drmHashFirst(drawHash, &draw, (void *)&pdraw) == 1) {
132680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	do {
1338e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell	    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
134680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    dpy = pdp->driScreenPriv->display;
1355f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick	    if (! (*dri_interface->windowExists)(dpy, draw)) {
13696f216565e09032021bafa7a805aa7707777fda1Brian Paul		/* Destroy the local drawable data, if the drawable no
13796f216565e09032021bafa7a805aa7707777fda1Brian Paul		   longer exists in the Xserver */
1388e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell		(*pdraw->destroyDrawable)(dpy, pdraw->private);
1398e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell		_mesa_free(pdraw);
140680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    }
1418e5281fbe1a7b9beea77b93a9cdd1e842a3edfa0Keith Whitwell	} while (drmHashNext(drawHash, &draw, (void *)&pdraw) == 1);
142680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
143680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
144680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
145680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
146680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
147680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
148680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
149680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context (un)binding functions                          */
150680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
151680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
152680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
153680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
154680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Unbind context.
155680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
156680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
157680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn the screen number.
158680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param draw drawable.
159680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param read Current reading drawable.
160680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param gc context.
161680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
162680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
163680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
164680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
165680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::UnbindContext, and then decrements
166680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
167680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * return.
168680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
169680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * While casting the opaque private pointers associated with the parameters
170680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * into their respective real types it also assures they are not \c NULL.
171680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
172c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanickstatic GLboolean driUnbindContext(__DRInativeDisplay *dpy, int scrn,
1730521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick			      __DRIid draw, __DRIid read,
17474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell			      __DRIcontext *ctx)
175680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
176680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreen *pDRIScreen;
177680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawable *pdraw;
178680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawable *pread;
179680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp;
180680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
181680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
182680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *prp;
183680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
184680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
185680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Assume error checking is done properly in glXMakeCurrent before
186c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    ** calling driUnbindContext.
187680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
188680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
18974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    if (ctx == NULL || draw == None || read == None) {
190680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
191680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
192680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
193680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1945f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    pDRIScreen = (*dri_interface->getScreen)(dpy, scrn);
195680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
196680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
197680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
198680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
199680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
200680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp = (__DRIscreenPrivate *)pDRIScreen->private;
20174d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    pcp = (__DRIcontextPrivate *)ctx->private;
202680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
203680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw = __driFindDrawable(psp->drawHash, draw);
204680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdraw) {
205680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
206680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
207680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
208680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp = (__DRIdrawablePrivate *)pdraw->private;
209680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
210680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pread = __driFindDrawable(psp->drawHash, read);
211680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pread) {
212680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
213680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
214680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
215680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    prp = (__DRIdrawablePrivate *)pread->private;
216680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
217680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
218680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Let driver unbind drawable from context */
219680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.UnbindContext)(pcp);
220680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
221680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
222680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->refcount == 0) {
223680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
224680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
225680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
226680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
227680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount--;
228680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
229680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (prp != pdp) {
230680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        if (prp->refcount == 0) {
231680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    /* ERROR!!! */
232680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    return GL_FALSE;
233680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
234680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
235680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount--;
236680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
237680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
238680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
239680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* XXX this is disabled so that if we call SwapBuffers on an unbound
240680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * window we can determine the last context bound to the window and
241680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * use that context's lock. (BrianP, 2-Dec-2000)
242680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
243680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#if 0
244680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Unbind the drawable */
245680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
246680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
247680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#endif
248680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
249680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
250680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
251680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
252680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
253680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
254680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function takes both a read buffer and a draw buffer.  This is needed
255680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
256680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * function.
257680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
258680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \bug This function calls \c driCreateNewDrawable in two places with the
259680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *      \c renderType hard-coded to \c GLX_WINDOW_BIT.  Some checking might
260680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *      be needed in those places when support for pbuffers and / or pixmaps
261680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *      is added.  Is it safe to assume that the drawable is a window?
262680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
2637c46033130b1b4d6098647d85c2710367572e079Ian Romanickstatic GLboolean DoBindContext(__DRInativeDisplay *dpy,
2640521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick			  __DRIid draw, __DRIid read,
26574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell			  __DRIcontext *ctx, const __GLcontextModes * modes,
26674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell			  __DRIscreenPrivate *psp)
267680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
268680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawable *pdraw;
269680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
270680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawable *pread;
271680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *prp;
27274d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    __DRIcontextPrivate * const pcp = ctx->private;
273680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
274680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2750521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick    /* Find the _DRIdrawable which corresponds to the writing drawable. */
276680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw = __driFindDrawable(psp->drawHash, draw);
277680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdraw) {
278680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* Allocate a new drawable */
2797c46033130b1b4d6098647d85c2710367572e079Ian Romanick	pdraw = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable));
280680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (!pdraw) {
281680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    /* ERROR!!! */
282680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    return GL_FALSE;
283680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
284680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
285680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* Create a new drawable */
286680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
287680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			     empty_attribute_list);
288680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (!pdraw->private) {
289680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    /* ERROR!!! */
2907c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdraw);
291680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    return GL_FALSE;
292680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
293680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
294680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
295680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp = (__DRIdrawablePrivate *) pdraw->private;
296680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2970521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick    /* Find the _DRIdrawable which corresponds to the reading drawable. */
298680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (read == draw) {
299680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        /* read buffer == draw buffer */
300680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        prp = pdp;
301680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
302680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    else {
303680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        pread = __driFindDrawable(psp->drawHash, read);
304680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        if (!pread) {
305680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            /* Allocate a new drawable */
3067c46033130b1b4d6098647d85c2710367572e079Ian Romanick            pread = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable));
307680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            if (!pread) {
308680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                /* ERROR!!! */
309680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                return GL_FALSE;
310680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            }
311680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
312680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            /* Create a new drawable */
313680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
314680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				 empty_attribute_list);
315680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            if (!pread->private) {
316680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                /* ERROR!!! */
3177c46033130b1b4d6098647d85c2710367572e079Ian Romanick                _mesa_free(pread);
318680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                return GL_FALSE;
319680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell            }
320680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        }
321680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        prp = (__DRIdrawablePrivate *) pread->private;
322680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
323680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
324680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Bind the drawable to the context */
325680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = pdp;
3267b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    pcp->driReadablePriv = prp;
327680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = pcp;
328680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount++;
329680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( pdp != prp ) {
330680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount++;
331680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
332680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
333680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
334680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Now that we have a context associated with this drawable, we can
335680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** initialize the drawable information if has not been done before.
336680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
337680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
338680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
339680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	__driUtilUpdateDrawableInfo(pdp);
340680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
341680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
342680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
3437b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    if ((pdp != prp) && (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp)) {
3447b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
3457b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	__driUtilUpdateDrawableInfo(prp);
3467b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
3477b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    }
3487b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick
349680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Call device-specific MakeCurrent */
350680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
351680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
352680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
353680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
354680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
355680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
35674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell/**
35774d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * This function takes both a read buffer and a draw buffer.  This is needed
35874d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
35974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * function.
36074d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell */
361c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanickstatic GLboolean driBindContext(__DRInativeDisplay *dpy, int scrn,
3620521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick                            __DRIid draw, __DRIid read,
36374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell                            __DRIcontext * ctx)
36474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell{
36574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    __DRIscreen *pDRIScreen;
36674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
36774d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    /*
36874d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    ** Assume error checking is done properly in glXMakeCurrent before
36974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    ** calling driBindContext.
37074d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    */
37174d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
37274d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    if (ctx == NULL || draw == None || read == None) {
37374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell	/* ERROR!!! */
37474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell	return GL_FALSE;
37574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    }
37674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
3775f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    pDRIScreen = (*dri_interface->getScreen)(dpy, scrn);
37874d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
37974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell	/* ERROR!!! */
38074d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell	return GL_FALSE;
38174d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    }
38274d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
38374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    return DoBindContext( dpy, draw, read, ctx, ctx->mode,
38474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell			  (__DRIscreenPrivate *)pDRIScreen->private );
38574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell}
386680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
387680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
388680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
389680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
390680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Drawable handling functions                            */
391680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
392680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
393680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
394680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
395680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Update private drawable information.
396680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
397680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pdp pointer to the private drawable information to update.
398680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
399680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function basically updates the __DRIdrawablePrivate struct's
4005f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
4015f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
402680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
403680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * the values are different that means we have to update the clipping
404680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * info.
405680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
406680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
407680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
408680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
409680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
410680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp = pdp->driContextPriv;
411680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
4127b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    if (!pcp
4137b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
414682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	/* ERROR!!!
415682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * ...but we must ignore it. There can be many contexts bound to a
416682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * drawable.
417682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 */
418680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
419680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
420680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp = pdp->driScreenPriv;
421680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!psp) {
422680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
4233528d61820e9ae1aafb12fb90849155f3cab6d2cPanagiotis Papadakos       _mesa_problem(NULL, "Warning! Possible infinite loop due to bug "
424682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström		     "in file %s, line %d\n",
425682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström		     __FILE__, __LINE__);
426680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return;
427680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
428680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
429680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pClipRects) {
4307c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pClipRects);
431680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
432680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
433680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pBackClipRects) {
4347c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pBackClipRects);
435680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
436680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
437680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
438680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
439680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
4405f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick	! (*dri_interface->getDrawableInfo)(pdp->display, pdp->screen, pdp->draw,
441680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->index, &pdp->lastStamp,
442680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
443680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numClipRects, &pdp->pClipRects,
444680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backX,
445680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backY,
446680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numBackClipRects,
447680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->pBackClipRects )) {
448680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* Error -- eg the window may have been destroyed.  Keep going
449680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * with no cliprects.
450680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
451680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
452680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numClipRects = 0;
453680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pClipRects = NULL;
454680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numBackClipRects = 0;
455680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pBackClipRects = NULL;
456680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
457680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    else
458680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
459680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
460680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
461680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
462680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
463680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
464680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
465680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
466680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
467680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name GLX callbacks                                          */
468680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
469680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
470680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
471680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
472680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Swap buffers.
473680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
474680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
475680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drawablePrivate opaque pointer to the per-drawable private info.
476680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
477680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
478680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DRIdrawablePrivate::swapBuffers.
479680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
480680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called directly from glXSwapBuffers().
481680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
48260b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic void driSwapBuffers( __DRInativeDisplay *dpy, void *drawablePrivate )
483680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
484680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
485c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    drm_clip_rect_t rect;
486c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
487680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    dPriv->swapBuffers(dPriv);
488c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
489c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Check that we actually have the new damage report method */
490c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    if (api_ver < 20070105 || dri_interface->reportDamage == NULL)
491c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt	return;
492c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
493c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Assume it's affecting the whole drawable for now */
494c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.x1 = 0;
495c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.y1 = 0;
496c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.x2 = rect.x1 + dPriv->w;
497c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.y2 = rect.y1 + dPriv->h;
498c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
499c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Report the damage.  Currently, all our drivers draw directly to the
500c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     * front buffer, so we report the damage there rather than to the backing
501c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     * store (if any).
502c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     */
503c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    (*dri_interface->reportDamage)(dpy, dPriv->screen, dPriv->draw,
504c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt				   dPriv->x, dPriv->y,
505c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt				   &rect, 1, GL_TRUE);
506680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
507680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
508680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
509680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Called directly from a number of higher-level GLX functions.
510680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
511680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic int driGetMSC( void *screenPrivate, int64_t *msc )
512680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
513680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
514680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
515680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return sPriv->DriverAPI.GetMSC( sPriv, msc );
516680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
517680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
518680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
519680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Called directly from a number of higher-level GLX functions.
520680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
52160b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic int driGetSBC( __DRInativeDisplay *dpy, void *drawablePrivate, int64_t *sbc )
522680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
523680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
524680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIswapInfo  sInfo;
525680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int  status;
526680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
527680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
528680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
529680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   *sbc = sInfo.swap_count;
530680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
531680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return status;
532680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
533680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
53460b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic int driWaitForSBC( __DRInativeDisplay * dpy, void *drawablePriv,
535680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  int64_t target_sbc,
536680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  int64_t * msc, int64_t * sbc )
537680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
538680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
539680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
540680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
541680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                       msc, sbc );
542680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
543680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
54460b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic int driWaitForMSC( __DRInativeDisplay * dpy, void *drawablePriv,
545680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  int64_t target_msc,
546680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  int64_t divisor, int64_t remainder,
547680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  int64_t * msc, int64_t * sbc )
548680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
549680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
550680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIswapInfo  sInfo;
551680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    int  status;
552680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
553680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
554680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
555680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         divisor, remainder,
556680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         msc );
557680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
558680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
559680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
560680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * an error value if GetSwapInfo() is not implemented.
561680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
562680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( status == 0
563680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
564680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
565680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        *sbc = sInfo.swap_count;
566680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
567680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
568680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return status;
569680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
570680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
57160b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic int64_t driSwapBuffersMSC( __DRInativeDisplay * dpy, void *drawablePriv,
572680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  int64_t target_msc,
573680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  int64_t divisor, int64_t remainder )
574680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
575680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
576680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
577680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
578680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                           divisor,
579680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                           remainder );
580680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
581680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
582f2ad1b60c0da11283b399008f491792790cea294Brian Paulstatic void driCopySubBuffer( __DRInativeDisplay *dpy, void *drawablePrivate,
583f2ad1b60c0da11283b399008f491792790cea294Brian Paul			      int x, int y, int w, int h)
584f2ad1b60c0da11283b399008f491792790cea294Brian Paul{
585f2ad1b60c0da11283b399008f491792790cea294Brian Paul    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
586f2ad1b60c0da11283b399008f491792790cea294Brian Paul    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
587f2ad1b60c0da11283b399008f491792790cea294Brian Paul    (void) dpy;
588f2ad1b60c0da11283b399008f491792790cea294Brian Paul}
589680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
590680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
591680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This is called via __DRIscreenRec's createNewDrawable pointer.
592680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
59360b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic void *driCreateNewDrawable(__DRInativeDisplay *dpy,
594680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  const __GLcontextModes *modes,
5950521ab46c1340d785ecfe64f4041c86912bc86afIan Romanick				  __DRIid draw,
596680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  __DRIdrawable *pdraw,
597680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  int renderType,
598680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  const int *attrs)
599680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
6005f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    __DRIscreen * const pDRIScreen = (*dri_interface->getScreen)(dpy, modes->screen);
601680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
602680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
603680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
604680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
6051960182ece3f1eca06d2e439f64dd61be8a03ff5Ian Romanick    pdraw->private = NULL;
6061960182ece3f1eca06d2e439f64dd61be8a03ff5Ian Romanick
607680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Since pbuffers are not yet supported, no drawable attributes are
608680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * supported either.
609680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
610680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (void) attrs;
611680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
612680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
613680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
614680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
615680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
6167c46033130b1b4d6098647d85c2710367572e079Ian Romanick    pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
617680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdp) {
618680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
619680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
620680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
6215f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    if (!(*dri_interface->createDrawable)(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
6227c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp);
623680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
624680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
625680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
626680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->draw = draw;
627680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pdraw = pdraw;
628680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount = 0;
629680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pStamp = NULL;
630680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->lastStamp = 0;
631680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->index = 0;
632680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->x = 0;
633680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->y = 0;
634680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->w = 0;
635680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->h = 0;
636680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numClipRects = 0;
637680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numBackClipRects = 0;
638680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pClipRects = NULL;
639680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pBackClipRects = NULL;
640680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->display = dpy;
641680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->screen = modes->screen;
642680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
643680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp = (__DRIscreenPrivate *)pDRIScreen->private;
644680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driScreenPriv = psp;
645680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
646680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
647680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
648680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell					renderType == GLX_PIXMAP_BIT)) {
6495f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick       (void)(*dri_interface->destroyDrawable)(dpy, modes->screen, pdp->draw);
6507c46033130b1b4d6098647d85c2710367572e079Ian Romanick       _mesa_free(pdp);
651680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       return NULL;
652680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
653680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
654680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->private = pdp;
655680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->destroyDrawable = driDestroyDrawable;
656680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
657680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
658c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->getSBC = driGetSBC;
659c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->waitForSBC = driWaitForSBC;
660c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->waitForMSC = driWaitForMSC;
661c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->swapBuffersMSC = driSwapBuffersMSC;
662c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->frameTracking = NULL;
663c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->queryFrameTracking = driQueryFrameTracking;
664c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick
665f2ad1b60c0da11283b399008f491792790cea294Brian Paul    if (driCompareGLXAPIVersion (20060314) >= 0)
666f2ad1b60c0da11283b399008f491792790cea294Brian Paul	pdraw->copySubBuffer = driCopySubBuffer;
667f2ad1b60c0da11283b399008f491792790cea294Brian Paul
668c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    /* This special default value is replaced with the configured
669c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * default value when the drawable is first bound to a direct
670c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * rendering context.
671c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     */
672c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pdraw->swap_interval = (unsigned)-1;
673680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
674680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
675680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
676680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Add pdraw to drawable list */
677680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!__driAddDrawable(psp->drawHash, pdraw)) {
678680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
679680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(*pdraw->destroyDrawable)(dpy, pdp);
6807c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp);
681680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp = NULL;
682680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdraw->private = NULL;
683680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
684680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
685680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return (void *) pdp;
686680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
687680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
688b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic __DRIdrawable *
689b4b040f7d83f5f4917c48bf5833394d550e30421Brian PauldriGetDrawable(__DRInativeDisplay *dpy, __DRIid draw, void *screenPrivate)
690680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
691680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
692680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
693680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
694680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Make sure this routine returns NULL if the drawable is not bound
695680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** to a direct rendering context!
696680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
697680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return __driFindDrawable(psp->drawHash, draw);
698680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
699680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
700b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
701b4b040f7d83f5f4917c48bf5833394d550e30421Brian PauldriDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate)
702680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
703680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
704eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie    __DRIscreenPrivate *psp;
705eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie    int scrn;
706680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
707680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp) {
708eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie	psp = pdp->driScreenPriv;
709eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie	scrn = psp->myNum;
710680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        (*psp->DriverAPI.DestroyBuffer)(pdp);
7115f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick	if ((*dri_interface->windowExists)(dpy, pdp->draw))
7125f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick	    (void)(*dri_interface->destroyDrawable)(dpy, scrn, pdp->draw);
71396f216565e09032021bafa7a805aa7707777fda1Brian Paul	drmHashDelete(psp->drawHash, pdp->draw);
714680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pClipRects) {
7157c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pClipRects);
716680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pClipRects = NULL;
717680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
718680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pBackClipRects) {
7197c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pBackClipRects);
720680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pBackClipRects = NULL;
721680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
7227c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp);
723680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
724680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
725680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
726680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
727680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
728680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
729680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
730680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context handling functions                             */
731680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
732680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
733680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
734680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
735680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-context private information.
736680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
737680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
738680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn the screen number.
739680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param contextPrivate opaque pointer to the per-drawable private info.
740680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
741680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
742680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
743680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmDestroyContext(), and finally frees \p contextPrivate.
744680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
745b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
746b4b040f7d83f5f4917c48bf5833394d550e30421Brian PauldriDestroyContext(__DRInativeDisplay *dpy, int scrn, void *contextPrivate)
747680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
748680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate  *pcp   = (__DRIcontextPrivate *) contextPrivate;
749680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
750680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pcp) {
751680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
752680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	__driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
7535f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick	(void) (*dri_interface->destroyContext)(dpy, scrn, pcp->contextID);
7547c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pcp);
755680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
756680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
757680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
758680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
759680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
760680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Create the per-drawable private driver information.
761680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
762680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy           The display handle.
763680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes         Mode used to create the new context.
764680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
765680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      type likely to ever be supported for direct-rendering.
766680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param sharedPrivate The shared context dependent methods or \c NULL if
767680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      non-existent.
768680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pctx          DRI context to receive the context dependent methods.
769680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
770680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \returns An opaque pointer to the per-context private information on
771680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          success, or \c NULL on failure.
772680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
773680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
774680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function allocates and fills a __DRIcontextPrivateRec structure.  It
775680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * performs some device independent initialization and passes all the
776680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * relevent information to __DriverAPIRec::CreateContext to create the
777680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * context.
778680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
779680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
780680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic void *
78160b0e12830310e7c05b4043857ed277b28b1c781Ian RomanickdriCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes,
782680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		    int render_type, void *sharedPrivate, __DRIcontext *pctx)
783680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
784680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreen *pDRIScreen;
785680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp;
786680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
787680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
788680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
789680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
7905f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    pDRIScreen = (*dri_interface->getScreen)(dpy, modes->screen);
791680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
792680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
793680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
794680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
795680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
796680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp = (__DRIscreenPrivate *)pDRIScreen->private;
797680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
7987c46033130b1b4d6098647d85c2710367572e079Ian Romanick    pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
799680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pcp) {
800680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
801680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
802680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
8035f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick    if (! (*dri_interface->createContext)(dpy, modes->screen, modes->fbconfigID,
804680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell					&pcp->contextID, &pcp->hHWContext)) {
8057c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pcp);
806680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
807680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
808680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
809680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->display = dpy;
810680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driScreenPriv = psp;
811680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
812680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
813680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* When the first context is created for a screen, initialize a "dummy"
814680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * context.
815680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
816680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
817680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!psp->dummyContextPriv.driScreenPriv) {
818680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.contextID = 0;
819680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
820680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driScreenPriv = psp;
821680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driDrawablePriv = NULL;
822680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driverPrivate = NULL;
823680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No other fields should be used! */
824680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
825680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
826680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pctx->destroyContext = driDestroyContext;
827c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pctx->bindContext    = driBindContext;
828c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pctx->unbindContext  = driUnbindContext;
82974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
830680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
8315f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick        (void) (*dri_interface->destroyContext)(dpy, modes->screen,
8325f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick						pcp->contextID);
8337c46033130b1b4d6098647d85c2710367572e079Ian Romanick        _mesa_free(pcp);
834680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        return NULL;
835680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
836680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
837680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
838680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
839680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return pcp;
840680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
841680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
842680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
843680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
844680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
845680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Screen handling functions                              */
846680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
847680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
848680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
849680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
850680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-screen private information.
851680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
852680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
853680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn the screen number.
854680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param screenPrivate opaque pointer to the per-screen private information.
855680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
856680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
857680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
858680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmClose(), and finally frees \p screenPrivate.
859680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
86060b0e12830310e7c05b4043857ed277b28b1c781Ian Romanickstatic void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPrivate)
861680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
862680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
863680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
864680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (psp) {
865680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No interaction with the X-server is possible at this point.  This
866680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * routine is called after XCloseDisplay, so there is no protocol
867680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * stream open to the X-server anymore.
868680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
869680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
870680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (psp->DriverAPI.DestroyScreen)
871680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    (*psp->DriverAPI.DestroyScreen)(psp);
872680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
873680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
874680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
8757c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(psp->pDevPriv);
8765ac93f86210eb5c2a8dee74ec19b0ecd54376863Keith Whitwell	(void)drmCloseOnce(psp->fd);
877680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if ( psp->modes != NULL ) {
87882e3ecf413704440ea64b3b582d68f82f7b83704Ian Romanick	    (*dri_interface->destroyContextModes)( psp->modes );
879680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
880e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck
881e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck	assert(psp->drawHash);
882e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck	drmHashDestroy(psp->drawHash);
883e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck
8847c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(psp);
885680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
886680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
887680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
888680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
889680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
890680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Utility function used to create a new driver-private screen structure.
891680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
892680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy   Display pointer
893680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn  Index of the screen
894680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param psc   DRI screen data (not driver private)
895680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes Linked list of known display modes.  This list is, at a
896680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              minimum, a list of modes based on the current display mode.
897680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              These roughly match the set of available X11 visuals, but it
898680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              need not be limited to X11!  The calling libGL should create
899680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              a list that will inform the driver of the current display
900680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              mode (i.e., color buffer depth, depth buffer depth, etc.).
901680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
902680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                    all drivers.
903680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dri_version Version of the "server-side" DRI.
904680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drm_version Version of the kernel DRM.
905680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param frame_buffer Data describing the location and layout of the
906680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                     framebuffer.
907680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pSAREA       Pointer the the SAREA.
908680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param fd           Device handle for the DRM.
909680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param internal_api_version  Version of the internal interface between the
910680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                              driver and libGL.
911680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param driverAPI Driver API functions used by other routines in dri_util.c.
912c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick *
913c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick * \note
914c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick * There is no need to check the minimum API version in this function.  Since
915c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick * the \c __driCreateNewScreen function is versioned, it is impossible for a
916c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick * loader that is too old to even load this driver.
917680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
918680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__DRIscreenPrivate *
91960b0e12830310e7c05b4043857ed277b28b1c781Ian Romanick__driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
920680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 __GLcontextModes * modes,
921680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 const __DRIversion * ddx_version,
922680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 const __DRIversion * dri_version,
923680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 const __DRIversion * drm_version,
924680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 const __DRIframebuffer * frame_buffer,
925ffb36d57a5f6359b5b91b73af60482a0016dd431Jon Smirl			 drm_sarea_t *pSAREA,
926680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 int fd,
927680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 int internal_api_version,
928680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			 const struct __DriverAPIRec *driverAPI)
929680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
930680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
931680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
932680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
933680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    api_ver = internal_api_version;
934680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
9357c46033130b1b4d6098647d85c2710367572e079Ian Romanick    psp = (__DRIscreenPrivate *)_mesa_malloc(sizeof(__DRIscreenPrivate));
936680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!psp) {
937680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
938680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
939680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
940680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Create the hash table */
941680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drawHash = drmHashCreate();
942680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( psp->drawHash == NULL ) {
9437c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free( psp );
944680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
945680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
946680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
947680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->display = dpy;
948680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->myNum = scrn;
949680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->psc = psc;
950680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->modes = modes;
951680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
952680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
953680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** NOT_DONE: This is used by the X server to detect when the client
954680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** has died while holding the drawable lock.  The client sets the
955680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** drawable lock to this value.
956680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
957680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drawLockID = 1;
958680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
959680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drmMajor = drm_version->major;
960680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drmMinor = drm_version->minor;
961680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drmPatch = drm_version->patch;
962680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->ddxMajor = ddx_version->major;
963680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->ddxMinor = ddx_version->minor;
964680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->ddxPatch = ddx_version->patch;
965680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->driMajor = dri_version->major;
966680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->driMinor = dri_version->minor;
967680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->driPatch = dri_version->patch;
968680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
969680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* install driver's callback functions */
970680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
971680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
972680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pSAREA = pSAREA;
973680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
974680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pFB = frame_buffer->base;
975680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbSize = frame_buffer->size;
976680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbStride = frame_buffer->stride;
977680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbWidth = frame_buffer->width;
978680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbHeight = frame_buffer->height;
979680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->devPrivSize = frame_buffer->dev_priv_size;
980680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pDevPriv = frame_buffer->dev_priv;
981fd4f7064e24654c89248be6d76f39c7baf22fce4Jon Smirl    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
982680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
983680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fd = fd;
984680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
985680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
986680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Do not init dummy context here; actual initialization will be
987680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** done when the first DRI context is created.  Init screen priv ptr
988680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** to NULL to let CreateContext routine that it needs to be inited.
989680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
990680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->dummyContextPriv.driScreenPriv = NULL;
991680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
992680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psc->destroyScreen     = driDestroyScreen;
993680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psc->createNewDrawable = driCreateNewDrawable;
994680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psc->getDrawable       = driGetDrawable;
99574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    psc->getMSC            = driGetMSC;
99674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    psc->createNewContext  = driCreateNewContext;
997680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
998680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( (psp->DriverAPI.InitDriver != NULL)
999680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 && !(*psp->DriverAPI.InitDriver)(psp) ) {
10007c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free( psp );
1001680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
1002680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
1003680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1004680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1005680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return psp;
1006680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1007680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1008680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1009680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
1010680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Compare the current GLX API version with a driver supplied required version.
1011680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1012680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * The minimum required version is compared with the API version exported by
1013680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * the \c __glXGetInternalVersion function (in libGL.so).
1014680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1015680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param   required_version Minimum required internal GLX API version.
1016680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return  A tri-value return, as from strcmp is returned.  A value less
1017680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          than, equal to, or greater than zero will be returned if the
1018680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          internal GLX API version is less than, equal to, or greater
1019680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          than \c required_version.
1020680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1021680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \sa __glXGetInternalVersion().
1022680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
10238d12a6d537ca346291bc3e3bc90cc73509f4b419Dave Airlieint driCompareGLXAPIVersion( GLint required_version )
1024680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1025680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   if ( api_ver > required_version ) {
1026680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      return 1;
1027680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1028680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   else if ( api_ver == required_version ) {
1029680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      return 0;
1030680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1031680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1032680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return -1;
1033680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1034680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1035680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1036680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic int
103760b0e12830310e7c05b4043857ed277b28b1c781Ian RomanickdriQueryFrameTracking( __DRInativeDisplay * dpy, void * priv,
1038680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		       int64_t * sbc, int64_t * missedFrames,
1039680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		       float * lastMissedUsage, float * usage )
1040680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1041680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIswapInfo   sInfo;
1042680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int             status;
1043680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int64_t         ust;
1044680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
1045680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1046680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1047680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
1048680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   if ( status == 0 ) {
1049680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *sbc = sInfo.swap_count;
1050680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *missedFrames = sInfo.swap_missed_count;
1051680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *lastMissedUsage = sInfo.swap_missed_usage;
1052680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
10535f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick      (*dri_interface->getUST)( & ust );
1054680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1055680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1056680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1057680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return status;
1058680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1059680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1060680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1061680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
1062680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Calculate amount of swap interval used between GLX buffer swaps.
1063680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1064680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * The usage value, on the range [0,max], is the fraction of total swap
1065680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * interval time used between GLX buffer swaps is calculated.
1066680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1067680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *            \f$p = t_d / (i * t_r)\f$
1068680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1069680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1070680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1071680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * required for a single vertical refresh period (as returned by \c
1072680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * glXGetMscRateOML).
1073680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1074680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1075680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * details.
1076680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1077680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param   dPriv  Pointer to the private drawable structure.
1078680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return  If less than a single swap interval time period was required
1079680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          between GLX buffer swaps, a number greater than 0 and less than
1080680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          1.0 is returned.  If exactly one swap interval time period is
1081680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          required, 1.0 is returned, and if more than one is required then
1082680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          a number greater than 1.0 will be returned.
1083680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1084680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \sa glXSwapIntervalSGI glXGetMscRateOML
1085680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1086680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1087680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *       be possible to cache the sync rate?
1088680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
1089680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellfloat
1090680ec7f85158eae58fd5ab56da8c66a645883cb0Keith WhitwelldriCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1091680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		       int64_t current_ust )
1092680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1093680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   n;
1094680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   d;
1095680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int       interval;
1096680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   float     usage = 1.0;
1097680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1098680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
10995f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick   if ( (*dri_interface->getMSCRate)( dPriv->display, dPriv->draw, &n, &d ) ) {
1100680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      interval = (dPriv->pdraw->swap_interval != 0)
1101680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	  ? dPriv->pdraw->swap_interval : 1;
1102680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1103680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1104680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      /* We want to calculate
1105680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
1106680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
1107680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * dPriv->swap_ust.  interval has already been calculated.
1108680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       *
1109680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * The only tricky part is us_per_refresh.  us_per_refresh is
1110680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
1111680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
1112680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * the denominator of the final calculation, we calculate
1113680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (interval * 1000000 * d) and move n into the numerator.
1114680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       */
1115680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1116680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage = (current_ust - last_swap_ust);
1117680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage *= n;
1118680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= (interval * d);
1119680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= 1000000.0;
1120680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1121680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1122680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return usage;
1123680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1124680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1125680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
1126