dri_util.c revision 106a6f29bbdc71982afd629bdf89369cefd1459e
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
36aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsbergtypedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *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
55aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsbergstatic void *driCreateNewDrawable(__DRIscreen *screen,
56aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg				  const __GLcontextModes *modes,
574ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg                                  __DRIdrawable *pdraw,
584ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg				  drm_drawable_t hwDrawable,
59b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paul                                  int renderType, const int *attrs);
60680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
615987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic void driDestroyDrawable(__DRIdrawable *drawable);
62680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
63680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
64680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
65680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
66680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * is set.
67680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
68680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called from the drivers.
69680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
70680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param f \c printf like format string.
71680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
72680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
73680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilMessage(const char *f, ...)
74680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
75680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    va_list args;
76680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
77680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (getenv("LIBGL_DEBUG")) {
78680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "libGL error: \n");
79680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_start(args, f);
80680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        vfprintf(stderr, f, args);
81680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_end(args);
82680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "\n");
83680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
84680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
85680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
86680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
87680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
88680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context (un)binding functions                          */
89680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
90680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
91680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
92680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
93680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Unbind context.
94680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
95aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg * \param scrn the screen.
96680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param gc context.
97680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
98680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
99680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
100680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
101680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::UnbindContext, and then decrements
102680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
103680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * return.
104680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
105680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * While casting the opaque private pointers associated with the parameters
106680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * into their respective real types it also assures they are not \c NULL.
107680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
108aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsbergstatic GLboolean driUnbindContext(__DRIcontext *ctx)
109680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
110680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp;
111680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
112680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
113680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *prp;
114680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
115680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
116680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Assume error checking is done properly in glXMakeCurrent before
117c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    ** calling driUnbindContext.
118680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
119680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
120aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    if (ctx == NULL)
121aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg        return GL_FALSE;
122680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
12374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    pcp = (__DRIcontextPrivate *)ctx->private;
124aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    psp = (__DRIscreenPrivate *)pcp->driScreenPriv;
1254a22ae8d446855d839cc199df8eb1b057045cb88Kristian Høgsberg    pdp = (__DRIdrawablePrivate *)pcp->driDrawablePriv;
1264a22ae8d446855d839cc199df8eb1b057045cb88Kristian Høgsberg    prp = (__DRIdrawablePrivate *)pcp->driReadablePriv;
127680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
128680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Let driver unbind drawable from context */
129680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.UnbindContext)(pcp);
130680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
131680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->refcount == 0) {
132680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
133680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
134680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
135680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
136680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount--;
137680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
138680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (prp != pdp) {
139680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        if (prp->refcount == 0) {
140680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    /* ERROR!!! */
141680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    return GL_FALSE;
142680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
143680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
144680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount--;
145680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
146680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
147680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
148680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* XXX this is disabled so that if we call SwapBuffers on an unbound
149680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * window we can determine the last context bound to the window and
150680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * use that context's lock. (BrianP, 2-Dec-2000)
151680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
152680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#if 0
153680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Unbind the drawable */
154680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
155680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
156680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#endif
157680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
158680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
159680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
160680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
161680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
162680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
163680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function takes both a read buffer and a draw buffer.  This is needed
164680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
165680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * function.
166680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
1675987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic GLboolean DoBindContext(__DRIcontext *ctx,
1685987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			       __DRIdrawable *pdraw,
1695987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			       __DRIdrawable *pread)
170680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
171680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
172680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *prp;
17374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    __DRIcontextPrivate * const pcp = ctx->private;
174aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    __DRIscreenPrivate *psp = pcp->driScreenPriv;
175680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
176680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp = (__DRIdrawablePrivate *) pdraw->private;
1774a22ae8d446855d839cc199df8eb1b057045cb88Kristian Høgsberg    prp = (__DRIdrawablePrivate *) pread->private;
178680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
179680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Bind the drawable to the context */
180680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = pdp;
1817b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    pcp->driReadablePriv = prp;
182680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = pcp;
183680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount++;
184680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( pdp != prp ) {
185680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount++;
186680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
187680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
188680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
189680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Now that we have a context associated with this drawable, we can
190680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** initialize the drawable information if has not been done before.
191680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
192680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
193680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
194680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	__driUtilUpdateDrawableInfo(pdp);
195680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
196680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
197680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1981a72c8ed3ff6ffc4a301f3c4a107d2693719edb8Panagiotis Papadakos    if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
1997b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
2007b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	__driUtilUpdateDrawableInfo(prp);
2017b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
2027b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    }
2037b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick
204680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Call device-specific MakeCurrent */
205680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
206680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
207680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
208680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
209680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
210680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
21174d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell/**
21274d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * This function takes both a read buffer and a draw buffer.  This is needed
21374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
21474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell * function.
21574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell */
2165987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic GLboolean driBindContext(__DRIcontext * ctx,
2175987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg				__DRIdrawable *pdraw,
2185987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg				__DRIdrawable *pread)
21974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell{
22074d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    /*
22174d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    ** Assume error checking is done properly in glXMakeCurrent before
22274d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    ** calling driBindContext.
22374d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    */
22474d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
225aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    if (ctx == NULL || pdraw == None || pread == None)
22674d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell	return GL_FALSE;
22774d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
2285987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    return DoBindContext( ctx, pdraw, pread );
22974d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell}
230680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
231680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
232680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
233680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
234680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Drawable handling functions                            */
235680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
236680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
237680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
238680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
239680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Update private drawable information.
240680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
241680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pdp pointer to the private drawable information to update.
242680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
243680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function basically updates the __DRIdrawablePrivate struct's
2445f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
2455f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
246680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
247680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * the values are different that means we have to update the clipping
248680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * info.
249680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
250680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
251680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
252680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
253680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
254680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp = pdp->driContextPriv;
255680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2567b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    if (!pcp
2577b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
258682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	/* ERROR!!!
259682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * ...but we must ignore it. There can be many contexts bound to a
260682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * drawable.
261682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 */
262680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
263680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
264680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp = pdp->driScreenPriv;
265680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!psp) {
266680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
2673528d61820e9ae1aafb12fb90849155f3cab6d2cPanagiotis Papadakos       _mesa_problem(NULL, "Warning! Possible infinite loop due to bug "
268682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström		     "in file %s, line %d\n",
269682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström		     __FILE__, __LINE__);
270680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return;
271680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
272680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
273680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pClipRects) {
2747c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pClipRects);
275a903749b246fce26038c66d06fe7eb77daf815abMichel Dänzer	pdp->pClipRects = NULL;
276680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
277680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
278680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pBackClipRects) {
2797c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pBackClipRects);
280a903749b246fce26038c66d06fe7eb77daf815abMichel Dänzer	pdp->pBackClipRects = NULL;
281680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
282680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
283680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
284680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2854ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg    if (! (*dri_interface->getDrawableInfo)(pdp->pdraw,
286680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->index, &pdp->lastStamp,
287680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
288680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numClipRects, &pdp->pClipRects,
289680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backX,
290680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backY,
291680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numBackClipRects,
292680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->pBackClipRects )) {
293680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* Error -- eg the window may have been destroyed.  Keep going
294680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * with no cliprects.
295680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
296680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
297680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numClipRects = 0;
298680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pClipRects = NULL;
299680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numBackClipRects = 0;
300680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pBackClipRects = NULL;
301680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
302680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    else
303680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
304680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
305680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
306680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
307680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
308680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
309680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
310680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
311680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
312680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name GLX callbacks                                          */
313680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
314680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
315680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
316680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
317680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Swap buffers.
318680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
319680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drawablePrivate opaque pointer to the per-drawable private info.
320680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
321680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
322680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DRIdrawablePrivate::swapBuffers.
323680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
324680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called directly from glXSwapBuffers().
325680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
3265987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic void driSwapBuffers(__DRIdrawable *drawable)
327680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
3285987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIdrawablePrivate *dPriv = drawable->private;
329c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    drm_clip_rect_t rect;
330c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
331680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    dPriv->swapBuffers(dPriv);
332c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
333c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Check that we actually have the new damage report method */
334c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    if (api_ver < 20070105 || dri_interface->reportDamage == NULL)
335c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt	return;
336c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
337c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Assume it's affecting the whole drawable for now */
338c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.x1 = 0;
339c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.y1 = 0;
340c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.x2 = rect.x1 + dPriv->w;
341c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    rect.y2 = rect.y1 + dPriv->h;
342c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
343c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt    /* Report the damage.  Currently, all our drivers draw directly to the
344c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     * front buffer, so we report the damage there rather than to the backing
345c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     * store (if any).
346c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt     */
347aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    (*dri_interface->reportDamage)(dPriv->pdraw, dPriv->x, dPriv->y,
348c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt				   &rect, 1, GL_TRUE);
349680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
350680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
351680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
352680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Called directly from a number of higher-level GLX functions.
353680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
3545987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic int driGetMSC( __DRIscreen *screen, int64_t *msc )
355680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
3565987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIscreenPrivate *sPriv = screen->private;
357680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
358680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return sPriv->DriverAPI.GetMSC( sPriv, msc );
359680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
360680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
3615987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic int driWaitForMSC(__DRIdrawable *drawable, int64_t target_msc,
3625987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			 int64_t divisor, int64_t remainder,
3635987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			 int64_t * msc, int64_t * sbc)
364680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
3655987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIdrawablePrivate *dPriv = drawable->private;
366680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIswapInfo  sInfo;
367680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    int  status;
368680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
369680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
370680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
371680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         divisor, remainder,
372680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         msc );
373680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
374680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
375680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
376680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * an error value if GetSwapInfo() is not implemented.
377680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
378680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( status == 0
379680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
380680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
381680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        *sbc = sInfo.swap_count;
382680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
383680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
384680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return status;
385680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
386680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
387106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsbergconst __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
388106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg    { __DRI_MEDIA_STREAM_COUNTER },
389106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg    driGetMSC,
390106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg    driWaitForMSC,
391106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg};
392680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
3935987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic void driCopySubBuffer(__DRIdrawable *drawable,
394f2ad1b60c0da11283b399008f491792790cea294Brian Paul			      int x, int y, int w, int h)
395f2ad1b60c0da11283b399008f491792790cea294Brian Paul{
3965987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIdrawablePrivate *dPriv = drawable->private;
397f2ad1b60c0da11283b399008f491792790cea294Brian Paul    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
398f2ad1b60c0da11283b399008f491792790cea294Brian Paul}
399680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
400ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsbergconst __DRIcopySubBufferExtension driCopySubBufferExtension = {
401ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg    { __DRI_COPY_SUB_BUFFER }, driCopySubBuffer
402ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg};
403ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg
404efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsbergstatic void driSetSwapInterval(__DRIdrawable *drawable, unsigned int interval)
405efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg{
406efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    __DRIdrawablePrivate *dpriv = drawable->private;
407efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
408efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    dpriv->swap_interval = interval;
409efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg}
410efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
411efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsbergstatic unsigned int driGetSwapInterval(__DRIdrawable *drawable)
412efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg{
413efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    __DRIdrawablePrivate *dpriv = drawable->private;
414efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
415efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    return dpriv->swap_interval;
416efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg}
417efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
418efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsbergconst __DRIswapControlExtension driSwapControlExtension = {
419efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    { __DRI_SWAP_CONTROL },
420efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    driSetSwapInterval,
421efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    driGetSwapInterval
422efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg};
423efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
424efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
425680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
426680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This is called via __DRIscreenRec's createNewDrawable pointer.
427680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
428aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsbergstatic void *driCreateNewDrawable(__DRIscreen *screen,
429680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  const __GLcontextModes *modes,
430680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  __DRIdrawable *pdraw,
4314ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg				  drm_drawable_t hwDrawable,
432680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  int renderType,
433680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell				  const int *attrs)
434680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
435680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
436680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIdrawablePrivate *pdp;
437680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
438680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
4391960182ece3f1eca06d2e439f64dd61be8a03ff5Ian Romanick    pdraw->private = NULL;
4401960182ece3f1eca06d2e439f64dd61be8a03ff5Ian Romanick
441680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Since pbuffers are not yet supported, no drawable attributes are
442680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * supported either.
443680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
444680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (void) attrs;
445680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
4467c46033130b1b4d6098647d85c2710367572e079Ian Romanick    pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
447680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdp) {
448680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
449680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
450680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
4514ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg    pdp->hHWDrawable = hwDrawable;
452680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pdraw = pdraw;
453680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount = 0;
454680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pStamp = NULL;
455680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->lastStamp = 0;
456680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->index = 0;
457680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->x = 0;
458680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->y = 0;
459680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->w = 0;
460680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->h = 0;
461680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numClipRects = 0;
462680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numBackClipRects = 0;
463680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pClipRects = NULL;
464680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pBackClipRects = NULL;
465680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
466aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    psp = (__DRIscreenPrivate *)screen->private;
467680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driScreenPriv = psp;
468680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
469680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
470680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
471680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell					renderType == GLX_PIXMAP_BIT)) {
4727c46033130b1b4d6098647d85c2710367572e079Ian Romanick       _mesa_free(pdp);
473680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       return NULL;
474680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
475680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
476680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->private = pdp;
477680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->destroyDrawable = driDestroyDrawable;
478680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
479680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
480c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    /* This special default value is replaced with the configured
481c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * default value when the drawable is first bound to a direct
482c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * rendering context.
483c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     */
484efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    pdp->swap_interval = (unsigned)-1;
485680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
486680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
487680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
488680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return (void *) pdp;
489680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
490680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
491b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
4925987a03f994af2bb413d1cf984ab01aa095c0943Kristian HøgsbergdriDestroyDrawable(__DRIdrawable *drawable)
493680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
4945987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIdrawablePrivate *pdp = drawable->private;
495eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie    __DRIscreenPrivate *psp;
496680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
497680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp) {
498eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie	psp = pdp->driScreenPriv;
499680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        (*psp->DriverAPI.DestroyBuffer)(pdp);
500680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pClipRects) {
5017c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pClipRects);
502680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pClipRects = NULL;
503680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
504680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pBackClipRects) {
5057c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pBackClipRects);
506680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pBackClipRects = NULL;
507680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
5087c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp);
509680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
510680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
511680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
512680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
513680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
514680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
515680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
516680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context handling functions                             */
517680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
518680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
519680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
520680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
521680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-context private information.
522680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
523680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param contextPrivate opaque pointer to the per-drawable private info.
524680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
525680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
526680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
527680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmDestroyContext(), and finally frees \p contextPrivate.
528680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
529b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
5305987a03f994af2bb413d1cf984ab01aa095c0943Kristian HøgsbergdriDestroyContext(__DRIcontext *context)
531680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
5325987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIcontextPrivate  *pcp   = context->private;
533680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
534680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pcp) {
535680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
5367c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pcp);
537680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
538680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
539680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
540680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
541680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
542680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Create the per-drawable private driver information.
543680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
544680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy           The display handle.
545680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes         Mode used to create the new context.
546680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
547680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      type likely to ever be supported for direct-rendering.
548680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param sharedPrivate The shared context dependent methods or \c NULL if
549680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      non-existent.
550680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pctx          DRI context to receive the context dependent methods.
551680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
552680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \returns An opaque pointer to the per-context private information on
553680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          success, or \c NULL on failure.
554680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
555680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
556680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function allocates and fills a __DRIcontextPrivateRec structure.  It
557680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * performs some device independent initialization and passes all the
558680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * relevent information to __DriverAPIRec::CreateContext to create the
559680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * context.
560680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
561680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
562680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic void *
563aceccda56b08338e217991e54607f1c9f18fc3e6Kristian HøgsbergdriCreateNewContext(__DRIscreen *screen, const __GLcontextModes *modes,
5648ed5c7ca0572a09375bdfd411c3804456dac78d6Kristian Høgsberg		    int render_type, void *sharedPrivate,
5658ed5c7ca0572a09375bdfd411c3804456dac78d6Kristian Høgsberg		    drm_context_t hwContext, __DRIcontext *pctx)
566680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
567680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp;
568680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
569680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
570680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
571680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
572aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    psp = (__DRIscreenPrivate *)screen->private;
573680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
5747c46033130b1b4d6098647d85c2710367572e079Ian Romanick    pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
575680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pcp) {
576680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
577680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
578680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
5798ed5c7ca0572a09375bdfd411c3804456dac78d6Kristian Høgsberg    pcp->hHWContext = hwContext;
580680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driScreenPriv = psp;
581680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
582680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
583680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* When the first context is created for a screen, initialize a "dummy"
584680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * context.
585680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
586680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
587680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!psp->dummyContextPriv.driScreenPriv) {
588680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
589680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driScreenPriv = psp;
590680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driDrawablePriv = NULL;
591680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driverPrivate = NULL;
592680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No other fields should be used! */
593680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
594680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
595680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pctx->destroyContext = driDestroyContext;
596c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pctx->bindContext    = driBindContext;
597c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    pctx->unbindContext  = driUnbindContext;
59874d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
599680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
6007c46033130b1b4d6098647d85c2710367572e079Ian Romanick        _mesa_free(pcp);
601680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        return NULL;
602680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
603680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
604680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return pcp;
605680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
606680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
607680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
608ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg
609f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsbergstatic const __DRIextension **
610f616a263a25eda135800bea7d3a863c569b93e30Kristian HøgsbergdriGetExtensions(__DRIscreen *screen)
611f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg{
612f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg    __DRIscreenPrivate *psp = screen->private;
613f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg
614ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg    return psp->extensions;
615f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg}
616680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
617680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
618680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Screen handling functions                              */
619680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
620680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
621680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
622680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
623680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-screen private information.
624680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
625680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
626680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn the screen number.
627680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param screenPrivate opaque pointer to the per-screen private information.
628680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
629680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
630680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
631680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmClose(), and finally frees \p screenPrivate.
632680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
6335987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsbergstatic void driDestroyScreen(__DRIscreen *screen)
634680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
6355987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg    __DRIscreenPrivate *psp = screen->private;
636680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
637680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (psp) {
638680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No interaction with the X-server is possible at this point.  This
639680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * routine is called after XCloseDisplay, so there is no protocol
640680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * stream open to the X-server anymore.
641680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
642680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
643680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (psp->DriverAPI.DestroyScreen)
644680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    (*psp->DriverAPI.DestroyScreen)(psp);
645680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
646680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
647680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
6485ac93f86210eb5c2a8dee74ec19b0ecd54376863Keith Whitwell	(void)drmCloseOnce(psp->fd);
649e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck
6507c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(psp);
651680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
652680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
653680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
654680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
655680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
65664106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * This is the bootstrap function for the driver.  libGL supplies all of the
65764106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * requisite information about the system, and the driver initializes itself.
65864106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * This routine also fills in the linked list pointed to by \c driver_modes
65964106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * with the \c __GLcontextModes that the driver can support for windows or
66064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * pbuffers.
661680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
662680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn  Index of the screen
663680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param psc   DRI screen data (not driver private)
664680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes Linked list of known display modes.  This list is, at a
665680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              minimum, a list of modes based on the current display mode.
666680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              These roughly match the set of available X11 visuals, but it
667680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              need not be limited to X11!  The calling libGL should create
668680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              a list that will inform the driver of the current display
669680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              mode (i.e., color buffer depth, depth buffer depth, etc.).
670680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
671680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                    all drivers.
672680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dri_version Version of the "server-side" DRI.
673680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drm_version Version of the kernel DRM.
674680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param frame_buffer Data describing the location and layout of the
675680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                     framebuffer.
676680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pSAREA       Pointer the the SAREA.
677680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param fd           Device handle for the DRM.
678680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param internal_api_version  Version of the internal interface between the
679680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                              driver and libGL.
680680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param driverAPI Driver API functions used by other routines in dri_util.c.
681c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick *
68264106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * \note There is no need to check the minimum API version in this
68364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * function.  Since the name of this function is versioned, it is
68464106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * impossible for a loader that is too old to even load this driver.
685680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
68664106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian HøgsbergPUBLIC
68764106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsbergvoid * __DRI_CREATE_NEW_SCREEN( int scrn, __DRIscreen *psc,
68864106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				const __DRIversion * ddx_version,
68964106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				const __DRIversion * dri_version,
69064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				const __DRIversion * drm_version,
69164106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				const __DRIframebuffer * frame_buffer,
69264106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				drmAddress pSAREA, int fd,
69364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				int internal_api_version,
69464106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				const __DRIinterfaceMethods * interface,
69564106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg				__GLcontextModes ** driver_modes )
69664106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg
697680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
698680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIscreenPrivate *psp;
699efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    static const __DRIextension *emptyExtensionList[] = { NULL };
70064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    dri_interface = interface;
701680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    api_ver = internal_api_version;
702680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
70364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    psp = _mesa_malloc(sizeof(*psp));
70464106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    if (!psp)
705680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
706680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
707680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->psc = psc;
708680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
709680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
710680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** NOT_DONE: This is used by the X server to detect when the client
711680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** has died while holding the drawable lock.  The client sets the
712680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** drawable lock to this value.
713680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
714680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drawLockID = 1;
715680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
716efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->drm_version = *drm_version;
717efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->ddx_version = *ddx_version;
718efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->dri_version = *dri_version;
719680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
720680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pSAREA = pSAREA;
721680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
722680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pFB = frame_buffer->base;
723680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbSize = frame_buffer->size;
724680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbStride = frame_buffer->stride;
725680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbWidth = frame_buffer->width;
726680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbHeight = frame_buffer->height;
727680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->devPrivSize = frame_buffer->dev_priv_size;
728680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pDevPriv = frame_buffer->dev_priv;
729fd4f7064e24654c89248be6d76f39c7baf22fce4Jon Smirl    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
730680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
731ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg    psp->extensions = emptyExtensionList;
732680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fd = fd;
73364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    psp->myNum = scrn;
734680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
735680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
736680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Do not init dummy context here; actual initialization will be
737680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** done when the first DRI context is created.  Init screen priv ptr
738680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** to NULL to let CreateContext routine that it needs to be inited.
739680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
740680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->dummyContextPriv.driScreenPriv = NULL;
741680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
742680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psc->destroyScreen     = driDestroyScreen;
743f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg    psc->getExtensions     = driGetExtensions;
744680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psc->createNewDrawable = driCreateNewDrawable;
74574d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell    psc->createNewContext  = driCreateNewContext;
746680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
747043d219b6da0636886f739613380cf44e334f268Michel Dänzer    if (internal_api_version >= 20070121)
748043d219b6da0636886f739613380cf44e334f268Michel Dänzer	psc->setTexOffset  = psp->DriverAPI.setTexOffset;
749043d219b6da0636886f739613380cf44e334f268Michel Dänzer
75064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    *driver_modes = __driDriverInitScreen(psp);
75164106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    if (*driver_modes == NULL) {
75264106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg	_mesa_free(psp);
753680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
754680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
755680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
756680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return psp;
757680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
758680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
759680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
760680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Compare the current GLX API version with a driver supplied required version.
761680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
762680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * The minimum required version is compared with the API version exported by
763680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * the \c __glXGetInternalVersion function (in libGL.so).
764680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
765680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param   required_version Minimum required internal GLX API version.
766680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return  A tri-value return, as from strcmp is returned.  A value less
767680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          than, equal to, or greater than zero will be returned if the
768680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          internal GLX API version is less than, equal to, or greater
769680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          than \c required_version.
770680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
771680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \sa __glXGetInternalVersion().
772680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
7738d12a6d537ca346291bc3e3bc90cc73509f4b419Dave Airlieint driCompareGLXAPIVersion( GLint required_version )
774680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
775680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   if ( api_ver > required_version ) {
776680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      return 1;
777680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
778680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   else if ( api_ver == required_version ) {
779680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      return 0;
780680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
781680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
782680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return -1;
783680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
784680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
785680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
786680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic int
787a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian HøgsbergdriFrameTracking(__DRIdrawable *drawable, GLboolean enable)
788a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg{
789a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    return GLX_BAD_CONTEXT;
790a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg}
791a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg
792a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsbergstatic int
7935987a03f994af2bb413d1cf984ab01aa095c0943Kristian HøgsbergdriQueryFrameTracking(__DRIdrawable *drawable,
7945987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg		      int64_t * sbc, int64_t * missedFrames,
7955987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg		      float * lastMissedUsage, float * usage)
796680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
797680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIswapInfo   sInfo;
798680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int             status;
799680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int64_t         ust;
8005987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg   __DRIdrawablePrivate * dpriv = drawable->private;
801680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
802680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
803680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
804680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   if ( status == 0 ) {
805680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *sbc = sInfo.swap_count;
806680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *missedFrames = sInfo.swap_missed_count;
807680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *lastMissedUsage = sInfo.swap_missed_usage;
808680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
8095f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick      (*dri_interface->getUST)( & ust );
810680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
811680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
812680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
813680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return status;
814680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
815680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
816a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsbergconst __DRIframeTrackingExtension driFrameTrackingExtension = {
817a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    { __DRI_FRAME_TRACKING },
818a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    driFrameTracking,
819a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    driQueryFrameTracking
820a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg};
821680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
822680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
823680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Calculate amount of swap interval used between GLX buffer swaps.
824680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
825680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * The usage value, on the range [0,max], is the fraction of total swap
826680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * interval time used between GLX buffer swaps is calculated.
827680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
828680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *            \f$p = t_d / (i * t_r)\f$
829680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
830680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
831680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
832680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * required for a single vertical refresh period (as returned by \c
833680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * glXGetMscRateOML).
834680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
835680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * See the documentation for the GLX_MESA_swap_frame_usage extension for more
836680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * details.
837680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
838680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param   dPriv  Pointer to the private drawable structure.
839680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return  If less than a single swap interval time period was required
840680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          between GLX buffer swaps, a number greater than 0 and less than
841680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          1.0 is returned.  If exactly one swap interval time period is
842680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          required, 1.0 is returned, and if more than one is required then
843680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          a number greater than 1.0 will be returned.
844680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
845680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \sa glXSwapIntervalSGI glXGetMscRateOML
846680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
847680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
848680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *       be possible to cache the sync rate?
849680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
850680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellfloat
851680ec7f85158eae58fd5ab56da8c66a645883cb0Keith WhitwelldriCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
852680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		       int64_t current_ust )
853680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
854680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   n;
855680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   d;
856680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int       interval;
857680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   float     usage = 1.0;
858680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
859680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
860aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg   if ( (*dri_interface->getMSCRate)(dPriv->pdraw, &n, &d) ) {
861efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg      interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
862680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
863680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
864680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      /* We want to calculate
865680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
866680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
867680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * dPriv->swap_ust.  interval has already been calculated.
868680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       *
869680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * The only tricky part is us_per_refresh.  us_per_refresh is
870680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
871680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
872680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * the denominator of the final calculation, we calculate
873680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (interval * 1000000 * d) and move n into the numerator.
874680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       */
875680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
876680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage = (current_ust - last_swap_ust);
877680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage *= n;
878680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= (interval * d);
879680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= 1000000.0;
880680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
881680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
882680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return usage;
883680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
884680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
885680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
886