dri_util.c revision c95e66120be049ee51ff84868b1da3379b312fab
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"
34c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis#include "utils.h"
35680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
36c604e457d1ebe9a884b0a1fb08af38a0ce486699Ian Romanick#ifndef GLX_OML_sync_control
37aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsbergtypedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
388cdccc82d7948daee256e092a5253d49e277ef75Ian Romanick#endif
398cdccc82d7948daee256e092a5253d49e277ef75Ian Romanick
40680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
41f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsberg * This is just a token extension used to signal that the driver
42f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsberg * supports setting a read drawable.
43f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsberg */
44f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsbergconst __DRIextension driReadDrawableExtension = {
45ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION
46f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsberg};
47f968f67e6214416f04b8875ce59a94a02f464c81Kristian Høgsberg
48680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
49680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
50680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * is set.
51680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
52680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called from the drivers.
53680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
54680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param f \c printf like format string.
55680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
56680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
57680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilMessage(const char *f, ...)
58680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
59680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    va_list args;
60680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
61680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (getenv("LIBGL_DEBUG")) {
62680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "libGL error: \n");
63680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_start(args, f);
64680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        vfprintf(stderr, f, args);
65680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        va_end(args);
66680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        fprintf(stderr, "\n");
67680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
68680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
69680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
70c95e66120be049ee51ff84868b1da3379b312fabGeorge SapountzisGLint
71c95e66120be049ee51ff84868b1da3379b312fabGeorge SapountzisdriIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
72c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis{
73c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
74c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
75c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
76c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
77c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis
78c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
79c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis
80c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
81c95e66120be049ee51ff84868b1da3379b312fabGeorge Sapountzis}
82680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
83680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
84680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context (un)binding functions                          */
85680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
86680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
87680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
88680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
89680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Unbind context.
90680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
91aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg * \param scrn the screen.
92680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param gc context.
93680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
94680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
95680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
96680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
97680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::UnbindContext, and then decrements
98680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
99680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * return.
100680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
101680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * While casting the opaque private pointers associated with the parameters
102680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * into their respective real types it also assures they are not \c NULL.
103680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
104e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic int driUnbindContext(__DRIcontext *pcp)
105680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
106e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIscreen *psp;
107e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIdrawable *pdp;
108e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIdrawable *prp;
109680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
110680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
111680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Assume error checking is done properly in glXMakeCurrent before
112c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    ** calling driUnbindContext.
113680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
114680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
115e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (pcp == NULL)
116aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg        return GL_FALSE;
117680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
118e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp = pcp->driScreenPriv;
119e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdp = pcp->driDrawablePriv;
120e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    prp = pcp->driReadablePriv;
121680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
122680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Let driver unbind drawable from context */
123680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.UnbindContext)(pcp);
124680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
125680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->refcount == 0) {
126680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* ERROR!!! */
127680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return GL_FALSE;
128680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
129680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
130680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount--;
131680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
132680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (prp != pdp) {
133680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        if (prp->refcount == 0) {
134680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    /* ERROR!!! */
135680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    return GL_FALSE;
136680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
137680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
138680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount--;
139680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
140680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
141680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
142680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* XXX this is disabled so that if we call SwapBuffers on an unbound
143680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * window we can determine the last context bound to the window and
144680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * use that context's lock. (BrianP, 2-Dec-2000)
145680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
146680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#if 0
147680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Unbind the drawable */
148680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
149680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
150680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell#endif
151680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
152680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
153680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
154680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
155680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
156680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
157680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function takes both a read buffer and a draw buffer.  This is needed
158680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
159680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * function.
160680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
161e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic int driBindContext(__DRIcontext *pcp,
162e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg			  __DRIdrawable *pdp,
163e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg			  __DRIdrawable *prp)
164680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
165aceccda56b08338e217991e54607f1c9f18fc3e6Kristian Høgsberg    __DRIscreenPrivate *psp = pcp->driScreenPriv;
166680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
167f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg    /*
168f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg    ** Assume error checking is done properly in glXMakeCurrent before
169f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg    ** calling driBindContext.
170f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg    */
171f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg
172e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (pcp == NULL || pdp == None || prp == None)
173f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg	return GL_FALSE;
174f1139e4c662c47357ee054c2e004b13c9f74ffe1Kristian Høgsberg
175680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Bind the drawable to the context */
176680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = pdp;
1777b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    pcp->driReadablePriv = prp;
178680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = pcp;
179680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount++;
180680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( pdp != prp ) {
181680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	prp->refcount++;
182680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
183680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
184680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
185680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Now that we have a context associated with this drawable, we can
186680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** initialize the drawable information if has not been done before.
187680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
188680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1897da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (psp->dri2.enabled) {
1902d5ea175f7fcd65de71b7589435b9a908f998d51Kristian Høgsberg       __driParseEvents(pcp, pdp);
1912d5ea175f7fcd65de71b7589435b9a908f998d51Kristian Høgsberg       __driParseEvents(pcp, prp);
1927da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    } else {
1937da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
1947da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
1957da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    __driUtilUpdateDrawableInfo(pdp);
1967da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
1977da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	}
1987da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
1997da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
2007da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
2017da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    __driUtilUpdateDrawableInfo(prp);
2027da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
2037da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	}
2047b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    }
2057b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick
206680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Call device-specific MakeCurrent */
207680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
208680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
209680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return GL_TRUE;
210680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
211680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
212680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
213680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
214680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
215680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
216680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Drawable handling functions                            */
217680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
218680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
219680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
220680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
221680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Update private drawable information.
222680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
223680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pdp pointer to the private drawable information to update.
224680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
225680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function basically updates the __DRIdrawablePrivate struct's
2265f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
2275f1ba3e21b62cee1a4f900a2e6964728f3eeea9bIan Romanick * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
228680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
229680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * the values are different that means we have to update the clipping
230680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * info.
231680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
232680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellvoid
233680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
234680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
2356cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    __DRIscreenPrivate *psp = pdp->driScreenPriv;
236680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIcontextPrivate *pcp = pdp->driContextPriv;
237680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2387b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick    if (!pcp
2397b1ff326071658d5bd6e7feb2ad78d0e0209211dIan Romanick	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
240682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	/* ERROR!!!
241682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * ...but we must ignore it. There can be many contexts bound to a
242682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 * drawable.
243682393944c72ecfabe8df674af0b48975e90b98cThomas Hellström	 */
244680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
245680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
246680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pClipRects) {
2477c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pClipRects);
248a903749b246fce26038c66d06fe7eb77daf815abMichel Dänzer	pdp->pClipRects = NULL;
249680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
250680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
251680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp->pBackClipRects) {
2527c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp->pBackClipRects);
253a903749b246fce26038c66d06fe7eb77daf815abMichel Dänzer	pdp->pBackClipRects = NULL;
254680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
255680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
256680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
257680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
258e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp,
259680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->index, &pdp->lastStamp,
260680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
261680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numClipRects, &pdp->pClipRects,
262680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backX,
263680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->backY,
264680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell			  &pdp->numBackClipRects,
265e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg			  &pdp->pBackClipRects,
266e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg			  pdp->loaderPrivate)) {
267680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* Error -- eg the window may have been destroyed.  Keep going
268680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * with no cliprects.
269680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
270680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
271680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numClipRects = 0;
272680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pClipRects = NULL;
273680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->numBackClipRects = 0;
274680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	pdp->pBackClipRects = NULL;
275680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
276680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    else
277680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
278680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
279680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
280680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
281680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
282680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
2837da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsbergint
2842d5ea175f7fcd65de71b7589435b9a908f998d51Kristian Høgsberg__driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp)
2857da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg{
2862d5ea175f7fcd65de71b7589435b9a908f998d51Kristian Høgsberg    __DRIscreenPrivate *psp = pcp->driScreenPriv;
2874f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    __DRIDrawableConfigEvent *dc, *last_dc;
2884f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    __DRIBufferAttachEvent *ba, *last_ba;
2897da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    unsigned int tail, mask, *p, end, total, size, changed;
2907da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    unsigned char *data;
2917da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    size_t rect_size;
2927da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
2937da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    /* Check for wraparound. */
2947da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (psp->dri2.buffer->prealloc - pdp->dri2.tail > psp->dri2.buffer->size) {
2957da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       /* If prealloc overlaps into what we just parsed, the
2967da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	* server overwrote it and we have to reset our tail
2977da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	* pointer. */
2987da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext);
299e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	(*psp->dri2.loader->reemitDrawableInfo)(pdp, &pdp->dri2.tail,
300e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg						pdp->loaderPrivate);
3017da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext);
3027da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
3037da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3047da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    total = psp->dri2.buffer->head - pdp->dri2.tail;
3057da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    mask = psp->dri2.buffer->size - 1;
3067da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    end = psp->dri2.buffer->head;
3077da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    data = psp->dri2.buffer->data;
3084f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3097da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    changed = 0;
3104f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    last_dc = NULL;
3114f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    last_ba = NULL;
3127da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3134f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    for (tail = pdp->dri2.tail; tail != end; tail += size) {
3147da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       p = (unsigned int *) (data + (tail & mask));
3157da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       size = DRI2_EVENT_SIZE(*p);
3167da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {
3177da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  /* illegal data, bail out. */
3187da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  fprintf(stderr, "illegal event size\n");
3197da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  break;
3207da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       }
3217da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3227da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       switch (DRI2_EVENT_TYPE(*p)) {
3237da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       case DRI2_EVENT_DRAWABLE_CONFIG:
3247da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  dc = (__DRIDrawableConfigEvent *) p;
325e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	  if (dc->drawable == pdp->dri2.drawable_id)
3264f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	     last_dc = dc;
3277da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  break;
3287da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3297da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg       case DRI2_EVENT_BUFFER_ATTACH:
3307da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	  ba = (__DRIBufferAttachEvent *) p;
331e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	  if (ba->drawable == pdp->dri2.drawable_id &&
3324f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	      ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT)
3334f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	     last_ba = ba;
3344f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	  break;
3354f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       }
3364f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    }
3374f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3384f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    if (last_dc) {
3394f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       if (pdp->w != last_dc->width || pdp->h != last_dc->height)
3404f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	  changed = 1;
3414f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3424f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->x = last_dc->x;
3434f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->y = last_dc->y;
3444f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->w = last_dc->width;
3454f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->h = last_dc->height;
3464f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3474f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->backX = 0;
3484f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->backY = 0;
3494f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->numBackClipRects = 1;
3504f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->pBackClipRects[0].x1 = 0;
3514f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->pBackClipRects[0].y1 = 0;
3524f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->pBackClipRects[0].x2 = pdp->w;
3534f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->pBackClipRects[0].y2 = pdp->h;
3544f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3554f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->numClipRects = last_dc->num_rects;
3564f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       _mesa_free(pdp->pClipRects);
3574f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       rect_size = last_dc->num_rects * sizeof last_dc->rects[0];
3584f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       pdp->pClipRects = _mesa_malloc(rect_size);
3594f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       memcpy(pdp->pClipRects, last_dc->rects, rect_size);
3604f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    }
3617da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
362e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    /* We only care about the most recent drawable config. */
363e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (last_dc && changed)
364e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg       (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);
365e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
3664f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    /* Front buffer attachments are special, they typically mean that
3674f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * we're rendering to a redirected window (or a child window of a
3684f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * redirected window) and that it got resized.  Resizing the root
3694f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * window on randr events is a special case of this.  Other causes
3704f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * may be a window transitioning between redirected and
3714f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * non-redirected, or a window getting reparented between parents
3724f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * with different window pixmaps (eg two redirected windows).
3734f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * These events are special in that the X server allocates the
3744f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * buffer and that the buffer may be shared by other child
3754f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * windows.  When our window share the window pixmap with its
3764f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * parent, drawable config events doesn't affect the front buffer.
3774f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * We only care about the last such event in the buffer; in fact,
3784f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * older events will refer to invalid buffer objects.*/
3794f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    if (last_ba)
380180b41594c669574355b54ceb2c2ff96889bf336Kristian Høgsberg       (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, last_ba);
3814f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg
3824f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    /* If there was a drawable config event in the buffer and it
3834f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * changed the size of the window, all buffer auxillary buffer
3844f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * attachments prior to that are invalid (as opposed to the front
3854f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * buffer case discussed above).  In that case we can start
3864f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * looking for buffer attachment after the last drawable config
3874f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * event.  If there is no drawable config event in this batch of
3884f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * events, we have to assume that the last batch might have had
3894f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg     * one and process all buffer attach events.*/
3904f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    if (last_dc && changed)
3914f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       tail = (unsigned char *) last_dc - data;
3924f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    else
3934f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       tail = pdp->dri2.tail;
3947da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3954f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg    for ( ; tail != end; tail += size) {
3964f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       ba = (__DRIBufferAttachEvent *) (data + (tail & mask));
3974f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       size = DRI2_EVENT_SIZE(ba->event_header);
3987da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
3994f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH)
4004f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	  continue;
401e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg       if (ba->drawable != pdp->dri2.drawable_id)
4024f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	  continue;
4034f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg       if (last_ba == ba)
4044f7a75cc8a6cee7763b2d92e3d34858c3de7bd4fKristian Høgsberg	  continue;
4057da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
406180b41594c669574355b54ceb2c2ff96889bf336Kristian Høgsberg       (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, ba);
407e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg       changed = 1;
4087da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
4097da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
4107da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    pdp->dri2.tail = tail;
4117da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
412e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return changed || last_ba;
4137da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg}
4147da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
415680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
416680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
417680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
418680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name GLX callbacks                                          */
419680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
420680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
421680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
422e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic void driReportDamage(__DRIdrawable *pdp,
423e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg			    struct drm_clip_rect *pClipRects, int numClipRects)
424e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg{
425e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIscreen *psp = pdp->driScreenPriv;
426e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
427e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    /* Check that we actually have the new damage report method */
428e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (psp->dri2.enabled) {
429e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	(*psp->dri2.loader->postDamage)(pdp,
430e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg					pClipRects,
431e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg					numClipRects,
432e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg					pdp->loaderPrivate);
433e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    } else if (psp->damage) {
434e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	/* Report the damage.  Currently, all our drivers draw
435e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	 * directly to the front buffer, so we report the damage there
436e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	 * rather than to the backing storein (if any).
437e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	 */
438e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	(*psp->damage->reportDamage)(pdp,
439e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg				     pdp->x, pdp->y,
440e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg				     pClipRects, numClipRects,
441e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg				     GL_TRUE, pdp->loaderPrivate);
442e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    }
443e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg}
444e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
445e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
446680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
447680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Swap buffers.
448680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
449680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drawablePrivate opaque pointer to the per-drawable private info.
450680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
451680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
452680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DRIdrawablePrivate::swapBuffers.
453680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
454680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Is called directly from glXSwapBuffers().
455680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
456e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic void driSwapBuffers(__DRIdrawable *dPriv)
457680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
458e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIscreen *psp = dPriv->driScreenPriv;
459c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
4602407e48f2805e27e76e2e1d7083926c4077d9032Xiang, Haihao    if (!dPriv->numClipRects)
4612407e48f2805e27e76e2e1d7083926c4077d9032Xiang, Haihao        return;
4622407e48f2805e27e76e2e1d7083926c4077d9032Xiang, Haihao
463e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp->DriverAPI.SwapBuffers(dPriv);
464c2b185cff82a6cdb723cda4e05ffe1a213a9de3eEric Anholt
465e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driReportDamage(dPriv, dPriv->pClipRects, dPriv->numClipRects);
466680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
467680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
468e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
46938fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes			      int64_t *msc )
47038fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes{
4716e8d21d72f35767e07081a8bee4323aaaf5e2aaeKristian Høgsberg    return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
472680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
473680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
474e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
4755987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			 int64_t divisor, int64_t remainder,
4765987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg			 int64_t * msc, int64_t * sbc)
477680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
478680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    __DRIswapInfo  sInfo;
479680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    int  status;
480680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
481680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
482680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
483680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         divisor, remainder,
484680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell                                                         msc );
485680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
486680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
487680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
488680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * an error value if GetSwapInfo() is not implemented.
489680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
490680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if ( status == 0
491680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
492680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
493680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        *sbc = sInfo.swap_count;
494680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
495680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
496680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return status;
497680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
498680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
499106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsbergconst __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
500ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
501106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg    driWaitForMSC,
50238fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes    driDrawableGetMSC,
503106a6f29bbdc71982afd629bdf89369cefd1459eKristian Høgsberg};
504680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
505e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic void driCopySubBuffer(__DRIdrawable *dPriv,
506f2ad1b60c0da11283b399008f491792790cea294Brian Paul			      int x, int y, int w, int h)
507f2ad1b60c0da11283b399008f491792790cea294Brian Paul{
508e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    drm_clip_rect_t rect;
509e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
510f2ad1b60c0da11283b399008f491792790cea294Brian Paul    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
511e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
512e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    rect.x1 = x;
513e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    rect.y1 = y;
514e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    rect.x2 = x + w;
515e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    rect.y2 = y + w;
516e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driReportDamage(dPriv, &rect, 1);
517f2ad1b60c0da11283b399008f491792790cea294Brian Paul}
518680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
519ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsbergconst __DRIcopySubBufferExtension driCopySubBufferExtension = {
520ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION },
521ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    driCopySubBuffer
522ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg};
523ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg
524e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval)
525efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg{
526e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    dPriv->swap_interval = interval;
527efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg}
528efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
529e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic unsigned int driGetSwapInterval(__DRIdrawable *dPriv)
530efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg{
531e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return dPriv->swap_interval;
532efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg}
533efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
534efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsbergconst __DRIswapControlExtension driSwapControlExtension = {
535ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION },
536efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    driSetSwapInterval,
537efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    driGetSwapInterval
538efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg};
539efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
540efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg
541680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
542680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This is called via __DRIscreenRec's createNewDrawable pointer.
543680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
544e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIdrawable *
545e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
546e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		     drm_drawable_t hwDrawable, int renderType,
547e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		     const int *attrs, void *data)
548680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
549e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIdrawable *pdp;
5501960182ece3f1eca06d2e439f64dd61be8a03ff5Ian Romanick
551680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* Since pbuffers are not yet supported, no drawable attributes are
552680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * supported either.
553680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
554680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    (void) attrs;
555680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
556e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdp = _mesa_malloc(sizeof *pdp);
557680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (!pdp) {
558680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
559680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
560680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
561e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdp->loaderPrivate = data;
5624ff95e78e19e5902352ea3759d32d9f013255f42Kristian Høgsberg    pdp->hHWDrawable = hwDrawable;
563680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->refcount = 0;
564680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pStamp = NULL;
565680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->lastStamp = 0;
566680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->index = 0;
567680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->x = 0;
568680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->y = 0;
569680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->w = 0;
570680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->h = 0;
571680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numClipRects = 0;
572680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->numBackClipRects = 0;
573680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pClipRects = NULL;
574680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->pBackClipRects = NULL;
57538fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes    pdp->vblSeq = 0;
57638fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes    pdp->vblFlags = 0;
577680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
578680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driScreenPriv = psp;
579680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pdp->driContextPriv = &psp->dummyContextPriv;
580680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
581e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
582680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell					renderType == GLX_PIXMAP_BIT)) {
5837c46033130b1b4d6098647d85c2710367572e079Ian Romanick       _mesa_free(pdp);
584680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       return NULL;
585680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
586680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
58738fdb47d26055e19d50cd407266b56ed4317ae0aJesse Barnes    pdp->msc_base = 0;
588680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
589c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick    /* This special default value is replaced with the configured
590c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * default value when the drawable is first bound to a direct
591c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     * rendering context.
592c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick     */
593efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    pdp->swap_interval = (unsigned)-1;
594680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
595e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return pdp;
596e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg}
597680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
598e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIdrawable *
599e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergdri2CreateNewDrawable(__DRIscreen *screen, const __DRIconfig *config,
600e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		      unsigned int drawable_id, unsigned int head, void *data)
601e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg{
602e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIdrawable *pdraw;
6037da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
604e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, data);
605e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
606e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdraw->dri2.drawable_id = drawable_id;
607e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdraw->dri2.tail = head;
608e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
609e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
610e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return pdraw;
611680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
612680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
613e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
614b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
615e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriDestroyDrawable(__DRIdrawable *pdp)
616680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
617eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie    __DRIscreenPrivate *psp;
618680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
619680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pdp) {
620eab896cc213157758d74a2f39b5e3b1e748c071fDave Airlie	psp = pdp->driScreenPriv;
621680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        (*psp->DriverAPI.DestroyBuffer)(pdp);
622680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pClipRects) {
6237c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pClipRects);
624680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pClipRects = NULL;
625680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
626680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (pdp->pBackClipRects) {
6277c46033130b1b4d6098647d85c2710367572e079Ian Romanick	    _mesa_free(pdp->pBackClipRects);
628680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    pdp->pBackClipRects = NULL;
629680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	}
6307c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pdp);
631680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
632680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
633680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
634680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
635680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
636680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
637680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
638680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Context handling functions                             */
639680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
640680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
641680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
642680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
643680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-context private information.
644680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
645680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param contextPrivate opaque pointer to the per-drawable private info.
646680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
647680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
648680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
649680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmDestroyContext(), and finally frees \p contextPrivate.
650680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
651b4b040f7d83f5f4917c48bf5833394d550e30421Brian Paulstatic void
652e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriDestroyContext(__DRIcontext *pcp)
653680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
654680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (pcp) {
655680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
6567c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(pcp);
657680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
658680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
659680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
660680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
661680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
662680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Create the per-drawable private driver information.
663680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
664680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy           The display handle.
665680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes         Mode used to create the new context.
666680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
667680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      type likely to ever be supported for direct-rendering.
668ecdb45cb29e3209287cc297081596126e955ff2bKristian Høgsberg * \param shared        The shared context dependent methods or \c NULL if
669680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                      non-existent.
670680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pctx          DRI context to receive the context dependent methods.
671680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
672680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \returns An opaque pointer to the per-context private information on
673680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          success, or \c NULL on failure.
674680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
675680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
676680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function allocates and fills a __DRIcontextPrivateRec structure.  It
677680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * performs some device independent initialization and passes all the
678680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * relevent information to __DriverAPIRec::CreateContext to create the
679680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * context.
680680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
681680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
682e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIcontext *
683e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
684ecdb45cb29e3209287cc297081596126e955ff2bKristian Høgsberg		    int render_type, __DRIcontext *shared,
685e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		    drm_context_t hwContext, void *data)
686680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
687e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIcontext *pcp;
688e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL;
689680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
690e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pcp = _mesa_malloc(sizeof *pcp);
691e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (!pcp)
692680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
693680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
694680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driScreenPriv = psp;
695680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    pcp->driDrawablePriv = NULL;
696680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
697680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /* When the first context is created for a screen, initialize a "dummy"
698680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     * context.
699680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell     */
700680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
7017da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) {
702680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
703680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driScreenPriv = psp;
704680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driDrawablePriv = NULL;
705680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        psp->dummyContextPriv.driverPrivate = NULL;
706680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No other fields should be used! */
707680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
708680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
709e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    pcp->hHWContext = hwContext;
71074d563cdfbfb07cc666d60dc909e90ddb9949cbbKeith Whitwell
711e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) {
7127c46033130b1b4d6098647d85c2710367572e079Ian Romanick        _mesa_free(pcp);
713680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell        return NULL;
714680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
715680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
716680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return pcp;
717680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
718ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg
719e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIcontext *
720e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergdri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
721e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		      __DRIcontext *shared, void *data)
722f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg{
723e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    drm_context_t hwContext;
724e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    DRM_CAS_RESULT(ret);
725f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg
726e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    /* DRI2 doesn't use kernel with context IDs, we just need an ID that's
727e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg     * different from the kernel context ID to make drmLock() happy. */
728e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
729e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    do {
730e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	hwContext = screen->dri2.lock->next_id;
731e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	DRM_CAS(&screen->dri2.lock->next_id, hwContext, hwContext + 1, ret);
732e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    } while (ret);
733e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
734e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return driCreateNewContext(screen, config, 0, shared, hwContext, data);
735f616a263a25eda135800bea7d3a863c569b93e30Kristian Høgsberg}
736680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
737e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic int
738e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
739e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg{
740e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return GL_FALSE;
741e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg}
742e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
743e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg/*@}*/
744e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
745e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
746680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
747680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/** \name Screen handling functions                              */
748680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*****************************************************************/
749680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@{*/
750680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
751680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
752680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Destroy the per-screen private information.
753680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
754680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dpy the display handle.
755680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn the screen number.
756680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param screenPrivate opaque pointer to the per-screen private information.
757680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
758680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \internal
759680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
760680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * drmClose(), and finally frees \p screenPrivate.
761680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
762e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic void driDestroyScreen(__DRIscreen *psp)
763680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
764680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    if (psp) {
765680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	/* No interaction with the X-server is possible at this point.  This
766680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * routine is called after XCloseDisplay, so there is no protocol
767680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 * stream open to the X-server anymore.
768680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	 */
769680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
770680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	if (psp->DriverAPI.DestroyScreen)
771680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	    (*psp->DriverAPI.DestroyScreen)(psp);
772680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
7737da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	if (psp->dri2.enabled) {
7747da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
7757da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
7767da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	} else {
7777da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	   (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
7787da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	   (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
7797da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	   (void)drmCloseOnce(psp->fd);
7807da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	}
781e5c28321b2047418ba960c5f9c3aa86cf2514bbbTilman Sauerbeck
7827c46033130b1b4d6098647d85c2710367572e079Ian Romanick	_mesa_free(psp);
783680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
784680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
785680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
7866cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsbergstatic void
787e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergsetupLoaderExtensions(__DRIscreen *psp,
7886cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg		      const __DRIextension **extensions)
7896cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg{
7906cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    int i;
7916cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg
7926cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    for (i = 0; extensions[i]; i++) {
7936cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0)
7946cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	    psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i];
7956cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0)
7966cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	    psp->damage = (__DRIdamageExtension *) extensions[i];
7976cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
7986cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg	    psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
799e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	if (strcmp(extensions[i]->name, __DRI_LOADER) == 0)
800e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg	    psp->dri2.loader = (__DRIloaderExtension *) extensions[i];
8016cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    }
8026cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg}
8036cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg
804680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
80564106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * This is the bootstrap function for the driver.  libGL supplies all of the
80664106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * requisite information about the system, and the driver initializes itself.
80764106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * This routine also fills in the linked list pointed to by \c driver_modes
80864106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * with the \c __GLcontextModes that the driver can support for windows or
80964106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * pbuffers.
810680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
811680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param scrn  Index of the screen
812680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param psc   DRI screen data (not driver private)
813680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param modes Linked list of known display modes.  This list is, at a
814680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              minimum, a list of modes based on the current display mode.
815680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              These roughly match the set of available X11 visuals, but it
816680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              need not be limited to X11!  The calling libGL should create
817680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              a list that will inform the driver of the current display
818680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *              mode (i.e., color buffer depth, depth buffer depth, etc.).
819680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
820680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                    all drivers.
821680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param dri_version Version of the "server-side" DRI.
822680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param drm_version Version of the kernel DRM.
823680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param frame_buffer Data describing the location and layout of the
824680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                     framebuffer.
825680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param pSAREA       Pointer the the SAREA.
826680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param fd           Device handle for the DRM.
827680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param internal_api_version  Version of the internal interface between the
828680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *                              driver and libGL.
829680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param driverAPI Driver API functions used by other routines in dri_util.c.
830c39bf5e273a4995a279ae2af59fc29e06ab47e29Ian Romanick *
83164106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * \note There is no need to check the minimum API version in this
83264106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * function.  Since the name of this function is versioned, it is
83364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg * impossible for a loader that is too old to even load this driver.
834680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
835e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIscreen *
836e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriCreateNewScreen(int scrn,
837e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIversion *ddx_version,
838e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIversion *dri_version,
839e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIversion *drm_version,
840e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIframebuffer *frame_buffer,
841e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   drmAddress pSAREA, int fd,
842e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIextension **extensions,
843e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   const __DRIconfig ***driver_modes,
844e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		   void *loaderPrivate)
845680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
846efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg    static const __DRIextension *emptyExtensionList[] = { NULL };
847e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIscreen *psp;
848680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
849e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp = _mesa_malloc(sizeof *psp);
85064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    if (!psp)
851680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
852680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
8536cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    setupLoaderExtensions(psp, extensions);
8546cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg
855680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
856680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** NOT_DONE: This is used by the X server to detect when the client
857680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** has died while holding the drawable lock.  The client sets the
858680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** drawable lock to this value.
859680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
860680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->drawLockID = 1;
861680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
862efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->drm_version = *drm_version;
863efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->ddx_version = *ddx_version;
864efd03a278ae55b454509e9659c42899133983ebdKristian Høgsberg    psp->dri_version = *dri_version;
865680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
866680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pSAREA = pSAREA;
8677da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->lock = (drmLock *) &psp->pSAREA->lock;
868680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
869680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pFB = frame_buffer->base;
870680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbSize = frame_buffer->size;
871680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbStride = frame_buffer->stride;
872680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbWidth = frame_buffer->width;
873680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fbHeight = frame_buffer->height;
874680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->devPrivSize = frame_buffer->dev_priv_size;
875680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->pDevPriv = frame_buffer->dev_priv;
876fd4f7064e24654c89248be6d76f39c7baf22fce4Jon Smirl    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
877680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
878ac3e838fa748c8c8a6ffc04d1ab13da71f75f103Kristian Høgsberg    psp->extensions = emptyExtensionList;
879680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->fd = fd;
88064106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    psp->myNum = scrn;
8817da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->dri2.enabled = GL_FALSE;
882680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
883680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    /*
884680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** Do not init dummy context here; actual initialization will be
885680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** done when the first DRI context is created.  Init screen priv ptr
886680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    ** to NULL to let CreateContext routine that it needs to be inited.
887680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    */
888680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    psp->dummyContextPriv.driScreenPriv = NULL;
889680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
890e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp->DriverAPI = driDriverAPI;
891680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
892e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    *driver_modes = driDriverAPI.InitScreen(psp);
89364106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg    if (*driver_modes == NULL) {
89464106d0d9aeefa6974317042b6bc3e5eaabac5a2Kristian Høgsberg	_mesa_free(psp);
895680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell	return NULL;
896680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    }
897680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
898680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell    return psp;
899680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
900680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
901e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
902e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic __DRIscreen *
903e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergdri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle,
904e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		    const __DRIextension **extensions,
905e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg		    const __DRIconfig ***driver_configs, void *data)
9067da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg{
9077da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    static const __DRIextension *emptyExtensionList[] = { NULL };
908e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    __DRIscreen *psp;
9097da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    unsigned int *p;
91016242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg    drmVersionPtr version;
911129b9ad16f95421d12f77c1bd3eca915d8768b78Kristian Høgsberg
912e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (driDriverAPI.InitScreen2 == NULL)
913129b9ad16f95421d12f77c1bd3eca915d8768b78Kristian Høgsberg        return NULL;
9147da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9157da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp = _mesa_malloc(sizeof(*psp));
9167da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (!psp)
9177da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	return NULL;
9187da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9196cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg    setupLoaderExtensions(psp, extensions);
9206cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg
92116242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg    version = drmGetVersion(fd);
92216242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg    if (version) {
92316242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg	psp->drm_version.major = version->version_major;
92416242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg	psp->drm_version.minor = version->version_minor;
92516242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg	psp->drm_version.patch = version->version_patchlevel;
92616242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg	drmFreeVersion(version);
92716242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg    }
92816242a8007f41ab63f9a28bb9a750857c8cdb8afKristian Høgsberg
9297da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->extensions = emptyExtensionList;
9307da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->fd = fd;
9317da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->myNum = scrn;
9327da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->dri2.enabled = GL_TRUE;
9337da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9347da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) {
9357da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	fprintf(stderr, "Failed to reference DRI2 sarea BO\n");
9367da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	_mesa_free(psp);
9377da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	return NULL;
9387da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
9397da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9407da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    if (drmBOMap(psp->fd, &psp->dri2.sareaBO,
9417da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg		 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &psp->dri2.sarea)) {
9427da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
9437da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	_mesa_free(psp);
9447da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	return NULL;
9457da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
9467da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9477da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    p = psp->dri2.sarea;
9487da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    while (DRI2_SAREA_BLOCK_TYPE(*p)) {
9497da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
9507da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	case DRI2_SAREA_BLOCK_LOCK:
9517da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    psp->dri2.lock = (__DRILock *) p;
9527da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    break;
9537da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	case DRI2_SAREA_BLOCK_EVENT_BUFFER:
9547da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    psp->dri2.buffer = (__DRIEventBuffer *) p;
9557da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	    break;
9567da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	}
9577da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	p = DRI2_SAREA_BLOCK_NEXT(p);
9587da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
9597da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
9607da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    psp->lock = (drmLock *) &psp->dri2.lock->lock;
9617da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
962e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp->DriverAPI = driDriverAPI;
963e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    *driver_configs = driDriverAPI.InitScreen2(psp);
964e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    if (*driver_configs == NULL) {
9657da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
9667da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
9677da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	_mesa_free(psp);
9687da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg	return NULL;
9697da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    }
9707da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
971e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    psp->DriverAPI = driDriverAPI;
972e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
9737da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg    return psp;
9747da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg}
9757da5705b090d9c97a9b765d786c5e89afe9d1f25Kristian Høgsberg
976e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergstatic const __DRIextension **driGetExtensions(__DRIscreen *psp)
977e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg{
978e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    return psp->extensions;
979e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg}
980e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
981e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergconst __DRIlegacyExtension driLegacyExtension = {
982e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    { __DRI_LEGACY, __DRI_LEGACY_VERSION },
983e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driCreateNewScreen,
984e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driCreateNewDrawable,
985e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driCreateNewContext
986e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg};
987e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
988e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsbergconst __DRIcoreExtension driCoreExtension = {
989e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    { __DRI_CORE, __DRI_CORE_VERSION },
990e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    dri2CreateNewScreen,
991e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driDestroyScreen,
992e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driGetExtensions,
993e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driGetConfigAttrib,
994e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driIndexConfigAttrib,
995e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    dri2CreateNewDrawable,
996e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driDestroyDrawable,
997e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driSwapBuffers,
998e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    dri2CreateNewContext,
999e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driCopyContext,
1000e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driDestroyContext,
1001e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driBindContext,
1002e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    driUnbindContext
1003e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg};
1004e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
1005e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg/* This is the table of extensions that the loader will dlsym() for. */
1006e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergPUBLIC const __DRIextension *__driDriverExtensions[] = {
1007e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    &driCoreExtension.base,
1008e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    &driLegacyExtension.base,
1009e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg    NULL
1010e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg};
1011e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg
1012680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellstatic int
1013a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian HøgsbergdriFrameTracking(__DRIdrawable *drawable, GLboolean enable)
1014a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg{
1015a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    return GLX_BAD_CONTEXT;
1016a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg}
1017a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg
1018a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsbergstatic int
1019e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian HøgsbergdriQueryFrameTracking(__DRIdrawable *dpriv,
10205987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg		      int64_t * sbc, int64_t * missedFrames,
10215987a03f994af2bb413d1cf984ab01aa095c0943Kristian Høgsberg		      float * lastMissedUsage, float * usage)
1022680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1023680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   __DRIswapInfo   sInfo;
1024680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int             status;
1025680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int64_t         ust;
10266cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg   __DRIscreenPrivate *psp = dpriv->driScreenPriv;
1027680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1028680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
1029680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   if ( status == 0 ) {
1030680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *sbc = sInfo.swap_count;
1031680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *missedFrames = sInfo.swap_missed_count;
1032680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *lastMissedUsage = sInfo.swap_missed_usage;
1033680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
10346cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg      (*psp->systemTime->getUST)( & ust );
1035680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1036680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1037680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1038680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return status;
1039680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1040680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1041a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsbergconst __DRIframeTrackingExtension driFrameTrackingExtension = {
1042ccff0cb26378ce370fc8697a2a2ada138d2e119eKristian Høgsberg    { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION },
1043a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    driFrameTracking,
1044a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg    driQueryFrameTracking
1045a7a0a2beb54dcb78d7e0ab64cf2f5a6ede8191a4Kristian Høgsberg};
1046680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1047680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/**
1048680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Calculate amount of swap interval used between GLX buffer swaps.
1049680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1050680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * The usage value, on the range [0,max], is the fraction of total swap
1051680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * interval time used between GLX buffer swaps is calculated.
1052680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1053680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *            \f$p = t_d / (i * t_r)\f$
1054680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1055680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1056680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1057680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * required for a single vertical refresh period (as returned by \c
1058680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * glXGetMscRateOML).
1059680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1060680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1061680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * details.
1062680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1063680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \param   dPriv  Pointer to the private drawable structure.
1064680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \return  If less than a single swap interval time period was required
1065680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          between GLX buffer swaps, a number greater than 0 and less than
1066680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          1.0 is returned.  If exactly one swap interval time period is
1067680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          required, 1.0 is returned, and if more than one is required then
1068680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *          a number greater than 1.0 will be returned.
1069680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1070680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \sa glXSwapIntervalSGI glXGetMscRateOML
1071680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *
1072680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1073680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell *       be possible to cache the sync rate?
1074680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell */
1075680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwellfloat
1076680ec7f85158eae58fd5ab56da8c66a645883cb0Keith WhitwelldriCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1077680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell		       int64_t current_ust )
1078680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell{
1079680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   n;
1080680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int32_t   d;
1081680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   int       interval;
1082680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   float     usage = 1.0;
10836cb3f5c4d8618a14bb7ad1d9df10ed7e648a7b2bKristian Høgsberg   __DRIscreenPrivate *psp = dPriv->driScreenPriv;
1084680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1085e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg   if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) {
1086efaf90b03e8b69e04909bce071f8ef6b65cc0e9dKristian Høgsberg      interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1;
1087680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1088680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1089680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      /* We want to calculate
1090680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
1091680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
1092680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * dPriv->swap_ust.  interval has already been calculated.
1093680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       *
1094680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * The only tricky part is us_per_refresh.  us_per_refresh is
1095680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
1096680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
1097680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * the denominator of the final calculation, we calculate
1098680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       * (interval * 1000000 * d) and move n into the numerator.
1099680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell       */
1100680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1101680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage = (current_ust - last_swap_ust);
1102680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage *= n;
1103680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= (interval * d);
1104680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell      usage /= 1000000.0;
1105680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   }
1106680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1107680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell   return usage;
1108680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell}
1109680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell
1110680ec7f85158eae58fd5ab56da8c66a645883cb0Keith Whitwell/*@}*/
1111