diff options
Diffstat (limited to 'src/mesa/drivers/dri/common/dri_util.c')
-rw-r--r-- | src/mesa/drivers/dri/common/dri_util.c | 921 |
1 files changed, 343 insertions, 578 deletions
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index ac6e3cdda8..a2316e2662 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -1,28 +1,4 @@ -/* - * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - +/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */ /** * \file dri_util.c * DRI utility functions. @@ -50,44 +26,24 @@ #define MAP_FAILED ((void *)-1) #endif -#include "imports.h" +#include "main/imports.h" #define None 0 #include "dri_util.h" #include "drm_sarea.h" +#include "utils.h" #ifndef GLX_OML_sync_control -typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRInativeDisplay *dpy, __DRIid drawable, int32_t *numerator, int32_t *denominator); +typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator); #endif -/* This pointer *must* be set by the driver's __driCreateNewScreen funciton! - */ -const __DRIinterfaceMethods * dri_interface = NULL; - -/** - * This is used in a couple of places that call \c driCreateNewDrawable. - */ -static const int empty_attribute_list[1] = { None }; - - /** - * Cached copy of the internal API version used by libGL and the client-side - * DRI driver. + * This is just a token extension used to signal that the driver + * supports setting a read drawable. */ -static int api_ver = 0; - -/* forward declarations */ -static int driQueryFrameTracking( __DRInativeDisplay *dpy, void *priv, - int64_t *sbc, int64_t *missedFrames, - float *lastMissedUsage, float *usage ); - -static void *driCreateNewDrawable(__DRInativeDisplay *dpy, - const __GLcontextModes *modes, - __DRIid draw, __DRIdrawable *pdraw, - int renderType, const int *attrs); - -static void driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate); - +const __DRIextension driReadDrawableExtension = { + __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION +}; /** * Print message to \c stderr if the \c LIBGL_DEBUG environment variable @@ -111,64 +67,19 @@ __driUtilMessage(const char *f, ...) } } - -/*****************************************************************/ -/** \name Drawable list management */ -/*****************************************************************/ -/*@{*/ - -static GLboolean __driAddDrawable(void *drawHash, __DRIdrawable *pdraw) -{ - __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private; - - if (drmHashInsert(drawHash, pdp->draw, pdraw)) - return GL_FALSE; - - return GL_TRUE; -} - -static __DRIdrawable *__driFindDrawable(void *drawHash, __DRIid draw) +GLint +driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) { - int retcode; - __DRIdrawable *pdraw; - - retcode = drmHashLookup(drawHash, draw, (void *)&pdraw); - if (retcode) - return NULL; - - return pdraw; -} - + if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1; + if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2; + if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1; + if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2; -/** - * Find drawables in the local hash that have been destroyed on the - * server. - * - * \param drawHash Hash-table containing all known drawables. - */ -static void __driGarbageCollectDrawables(void *drawHash) -{ - __DRIid draw; - __DRInativeDisplay *dpy; - __DRIdrawable *pdraw; + if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0; - if (drmHashFirst(drawHash, &draw, (void *)&pdraw) == 1) { - do { - __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private; - dpy = pdp->driScreenPriv->display; - if (! (*dri_interface->windowExists)(dpy, draw)) { - /* Destroy the local drawable data, if the drawable no - longer exists in the Xserver */ - (*pdraw->destroyDrawable)(dpy, pdraw->private); - _mesa_free(pdraw); - } - } while (drmHashNext(drawHash, &draw, (void *)&pdraw) == 1); - } + return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1); } -/*@}*/ - - /*****************************************************************/ /** \name Context (un)binding functions */ /*****************************************************************/ @@ -177,10 +88,7 @@ static void __driGarbageCollectDrawables(void *drawHash) /** * Unbind context. * - * \param dpy the display handle. - * \param scrn the screen number. - * \param draw drawable. - * \param read Current reading drawable. + * \param scrn the screen. * \param gc context. * * \return \c GL_TRUE on success, or \c GL_FALSE on failure. @@ -193,56 +101,27 @@ static void __driGarbageCollectDrawables(void *drawHash) * While casting the opaque private pointers associated with the parameters * into their respective real types it also assures they are not \c NULL. */ -static GLboolean driUnbindContext(__DRInativeDisplay *dpy, int scrn, - __DRIid draw, __DRIid read, - __DRIcontext *ctx) +static int driUnbindContext(__DRIcontext *pcp) { - __DRIscreen *pDRIScreen; - __DRIdrawable *pdraw; - __DRIdrawable *pread; - __DRIcontextPrivate *pcp; - __DRIscreenPrivate *psp; - __DRIdrawablePrivate *pdp; - __DRIdrawablePrivate *prp; + __DRIscreen *psp; + __DRIdrawable *pdp; + __DRIdrawable *prp; /* ** Assume error checking is done properly in glXMakeCurrent before ** calling driUnbindContext. */ - if (ctx == NULL || draw == None || read == None) { - /* ERROR!!! */ - return GL_FALSE; - } - - pDRIScreen = (*dri_interface->getScreen)(dpy, scrn); - if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { - /* ERROR!!! */ - return GL_FALSE; - } - - psp = (__DRIscreenPrivate *)pDRIScreen->private; - pcp = (__DRIcontextPrivate *)ctx->private; - - pdraw = __driFindDrawable(psp->drawHash, draw); - if (!pdraw) { - /* ERROR!!! */ - return GL_FALSE; - } - pdp = (__DRIdrawablePrivate *)pdraw->private; - - pread = __driFindDrawable(psp->drawHash, read); - if (!pread) { - /* ERROR!!! */ - return GL_FALSE; - } - prp = (__DRIdrawablePrivate *)pread->private; + if (pcp == NULL) + return GL_FALSE; + psp = pcp->driScreenPriv; + pdp = pcp->driDrawablePriv; + prp = pcp->driReadablePriv; /* Let driver unbind drawable from context */ (*psp->DriverAPI.UnbindContext)(pcp); - if (pdp->refcount == 0) { /* ERROR!!! */ return GL_FALSE; @@ -259,12 +138,6 @@ static GLboolean driUnbindContext(__DRInativeDisplay *dpy, int scrn, prp->refcount--; } - /* destroy the drawables if they no longer exist on the server */ - if ((pdp->refcount == 0) || (prp->refcount == 0)) { - /* probably shouldn't need the collector here, - as we know the affected drawables (or could there be others?) */ - __driGarbageCollectDrawables(pdp->driScreenPriv->drawHash); - } /* XXX this is disabled so that if we call SwapBuffers on an unbound * window we can determine the last context bound to the window and @@ -279,77 +152,24 @@ static GLboolean driUnbindContext(__DRInativeDisplay *dpy, int scrn, return GL_TRUE; } - /** * This function takes both a read buffer and a draw buffer. This is needed * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent * function. - * - * \bug This function calls \c driCreateNewDrawable in two places with the - * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might - * be needed in those places when support for pbuffers and / or pixmaps - * is added. Is it safe to assume that the drawable is a window? */ -static GLboolean DoBindContext(__DRInativeDisplay *dpy, - __DRIid draw, __DRIid read, - __DRIcontext *ctx, const __GLcontextModes * modes, - __DRIscreenPrivate *psp) +static int driBindContext(__DRIcontext *pcp, + __DRIdrawable *pdp, + __DRIdrawable *prp) { - __DRIdrawable *pdraw; - __DRIdrawablePrivate *pdp; - __DRIdrawable *pread; - __DRIdrawablePrivate *prp; - __DRIcontextPrivate * const pcp = ctx->private; - - - /* Find the _DRIdrawable which corresponds to the writing drawable. */ - pdraw = __driFindDrawable(psp->drawHash, draw); - if (!pdraw) { - /* Allocate a new drawable */ - pdraw = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable)); - if (!pdraw) { - /* ERROR!!! */ - return GL_FALSE; - } - - /* Create a new drawable */ - driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT, - empty_attribute_list); - if (!pdraw->private) { - /* ERROR!!! */ - _mesa_free(pdraw); - return GL_FALSE; - } + __DRIscreenPrivate *psp = pcp->driScreenPriv; - } - pdp = (__DRIdrawablePrivate *) pdraw->private; + /* + ** Assume error checking is done properly in glXMakeCurrent before + ** calling driBindContext. + */ - /* Find the _DRIdrawable which corresponds to the reading drawable. */ - if (read == draw) { - /* read buffer == draw buffer */ - prp = pdp; - } - else { - pread = __driFindDrawable(psp->drawHash, read); - if (!pread) { - /* Allocate a new drawable */ - pread = (__DRIdrawable *)_mesa_malloc(sizeof(__DRIdrawable)); - if (!pread) { - /* ERROR!!! */ - return GL_FALSE; - } - - /* Create a new drawable */ - driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT, - empty_attribute_list); - if (!pread->private) { - /* ERROR!!! */ - _mesa_free(pread); - return GL_FALSE; - } - } - prp = (__DRIdrawablePrivate *) pread->private; - } + if (pcp == NULL || pdp == None || prp == None) + return GL_FALSE; /* Bind the drawable to the context */ pcp->driDrawablePriv = pdp; @@ -364,16 +184,19 @@ static GLboolean DoBindContext(__DRInativeDisplay *dpy, ** Now that we have a context associated with this drawable, we can ** initialize the drawable information if has not been done before. */ - if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) { - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - __driUtilUpdateDrawableInfo(pdp); - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - } - if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) { - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - __driUtilUpdateDrawableInfo(prp); - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + if (!psp->dri2.enabled) { + if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) { + DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + __driUtilUpdateDrawableInfo(pdp); + DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + } + + if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) { + DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + __driUtilUpdateDrawableInfo(prp); + DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); + } } /* Call device-specific MakeCurrent */ @@ -382,37 +205,6 @@ static GLboolean DoBindContext(__DRInativeDisplay *dpy, return GL_TRUE; } - -/** - * This function takes both a read buffer and a draw buffer. This is needed - * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent - * function. - */ -static GLboolean driBindContext(__DRInativeDisplay *dpy, int scrn, - __DRIid draw, __DRIid read, - __DRIcontext * ctx) -{ - __DRIscreen *pDRIScreen; - - /* - ** Assume error checking is done properly in glXMakeCurrent before - ** calling driBindContext. - */ - - if (ctx == NULL || draw == None || read == None) { - /* ERROR!!! */ - return GL_FALSE; - } - - pDRIScreen = (*dri_interface->getScreen)(dpy, scrn); - if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { - /* ERROR!!! */ - return GL_FALSE; - } - - return DoBindContext( dpy, draw, read, ctx, ctx->mode, - (__DRIscreenPrivate *)pDRIScreen->private ); -} /*@}*/ @@ -436,7 +228,7 @@ static GLboolean driBindContext(__DRInativeDisplay *dpy, int scrn, void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) { - __DRIscreenPrivate *psp; + __DRIscreenPrivate *psp = pdp->driScreenPriv; __DRIcontextPrivate *pcp = pdp->driContextPriv; if (!pcp @@ -447,15 +239,6 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) */ } - psp = pdp->driScreenPriv; - if (!psp) { - /* ERROR!!! */ - _mesa_problem(NULL, "Warning! Possible infinite loop due to bug " - "in file %s, line %d\n", - __FILE__, __LINE__); - return; - } - if (pdp->pClipRects) { _mesa_free(pdp->pClipRects); pdp->pClipRects = NULL; @@ -468,15 +251,15 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - if (!__driFindDrawable(psp->drawHash, pdp->draw) || - ! (*dri_interface->getDrawableInfo)(pdp->display, pdp->screen, pdp->draw, + if (! (*psp->getDrawableInfo->getDrawableInfo)(pdp, &pdp->index, &pdp->lastStamp, &pdp->x, &pdp->y, &pdp->w, &pdp->h, &pdp->numClipRects, &pdp->pClipRects, &pdp->backX, &pdp->backY, &pdp->numBackClipRects, - &pdp->pBackClipRects )) { + &pdp->pBackClipRects, + pdp->loaderPrivate)) { /* Error -- eg the window may have been destroyed. Keep going * with no cliprects. */ @@ -490,7 +273,6 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp); DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - } /*@}*/ @@ -500,10 +282,28 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) /*****************************************************************/ /*@{*/ +static void driReportDamage(__DRIdrawable *pdp, + struct drm_clip_rect *pClipRects, int numClipRects) +{ + __DRIscreen *psp = pdp->driScreenPriv; + + /* Check that we actually have the new damage report method */ + if (psp->damage) { + /* Report the damage. Currently, all our drivers draw + * directly to the front buffer, so we report the damage there + * rather than to the backing storein (if any). + */ + (*psp->damage->reportDamage)(pdp, + pdp->x, pdp->y, + pClipRects, numClipRects, + GL_TRUE, pdp->loaderPrivate); + } +} + + /** * Swap buffers. * - * \param dpy the display handle. * \param drawablePrivate opaque pointer to the per-drawable private info. * * \internal @@ -511,78 +311,29 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) * * Is called directly from glXSwapBuffers(). */ -static void driSwapBuffers( __DRInativeDisplay *dpy, void *drawablePrivate ) +static void driSwapBuffers(__DRIdrawable *dPriv) { - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; - drm_clip_rect_t rect; + __DRIscreen *psp = dPriv->driScreenPriv; - dPriv->swapBuffers(dPriv); - - /* Check that we actually have the new damage report method */ - if (api_ver < 20070105 || dri_interface->reportDamage == NULL) - return; - - /* Assume it's affecting the whole drawable for now */ - rect.x1 = 0; - rect.y1 = 0; - rect.x2 = rect.x1 + dPriv->w; - rect.y2 = rect.y1 + dPriv->h; - - /* Report the damage. Currently, all our drivers draw directly to the - * front buffer, so we report the damage there rather than to the backing - * store (if any). - */ - (*dri_interface->reportDamage)(dpy, dPriv->screen, dPriv->draw, - dPriv->x, dPriv->y, - &rect, 1, GL_TRUE); -} - -/** - * Called directly from a number of higher-level GLX functions. - */ -static int driGetMSC( void *screenPrivate, int64_t *msc ) -{ - __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate; + psp->DriverAPI.SwapBuffers(dPriv); - return sPriv->DriverAPI.GetMSC( sPriv, msc ); + driReportDamage(dPriv, dPriv->pClipRects, dPriv->numClipRects); } -/** - * Called directly from a number of higher-level GLX functions. - */ -static int driGetSBC( __DRInativeDisplay *dpy, void *drawablePrivate, int64_t *sbc ) +static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv, + int64_t *msc ) { - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; - __DRIswapInfo sInfo; - int status; - - - status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo ); - *sbc = sInfo.swap_count; - - return status; + return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc); } -static int driWaitForSBC( __DRInativeDisplay * dpy, void *drawablePriv, - int64_t target_sbc, - int64_t * msc, int64_t * sbc ) -{ - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv; - - return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc, - msc, sbc ); -} -static int driWaitForMSC( __DRInativeDisplay * dpy, void *drawablePriv, - int64_t target_msc, - int64_t divisor, int64_t remainder, - int64_t * msc, int64_t * sbc ) +static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc, + int64_t divisor, int64_t remainder, + int64_t * msc, int64_t * sbc) { - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv; __DRIswapInfo sInfo; int status; - status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc, divisor, remainder, msc ); @@ -600,63 +351,72 @@ static int driWaitForMSC( __DRInativeDisplay * dpy, void *drawablePriv, return status; } -static int64_t driSwapBuffersMSC( __DRInativeDisplay * dpy, void *drawablePriv, - int64_t target_msc, - int64_t divisor, int64_t remainder ) -{ - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv; - return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc, - divisor, - remainder ); -} +const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = { + { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION }, + driWaitForMSC, + driDrawableGetMSC, +}; + -static void driCopySubBuffer( __DRInativeDisplay *dpy, void *drawablePrivate, +static void driCopySubBuffer(__DRIdrawable *dPriv, int x, int y, int w, int h) { - __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; + drm_clip_rect_t rect; + + rect.x1 = x; + rect.y1 = dPriv->h - y - h; + rect.x2 = x + w; + rect.y2 = rect.y1 + h; + driReportDamage(dPriv, &rect, 1); + dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h); - (void) dpy; } +const __DRIcopySubBufferExtension driCopySubBufferExtension = { + { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION }, + driCopySubBuffer +}; + +static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval) +{ + dPriv->swap_interval = interval; +} + +static unsigned int driGetSwapInterval(__DRIdrawable *dPriv) +{ + return dPriv->swap_interval; +} + +const __DRIswapControlExtension driSwapControlExtension = { + { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION }, + driSetSwapInterval, + driGetSwapInterval +}; + + /** * This is called via __DRIscreenRec's createNewDrawable pointer. */ -static void *driCreateNewDrawable(__DRInativeDisplay *dpy, - const __GLcontextModes *modes, - __DRIid draw, - __DRIdrawable *pdraw, - int renderType, - const int *attrs) +static __DRIdrawable * +driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, + drm_drawable_t hwDrawable, int renderType, + const int *attrs, void *data) { - __DRIscreen * const pDRIScreen = (*dri_interface->getScreen)(dpy, modes->screen); - __DRIscreenPrivate *psp; - __DRIdrawablePrivate *pdp; - - - pdraw->private = NULL; + __DRIdrawable *pdp; /* Since pbuffers are not yet supported, no drawable attributes are * supported either. */ (void) attrs; - if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { - return NULL; - } - - pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate)); + pdp = _mesa_malloc(sizeof *pdp); if (!pdp) { return NULL; } - if (!(*dri_interface->createDrawable)(dpy, modes->screen, draw, &pdp->hHWDrawable)) { - _mesa_free(pdp); - return NULL; - } - - pdp->draw = draw; - pdp->pdraw = pdraw; + pdp->loaderPrivate = data; + pdp->hHWDrawable = hwDrawable; pdp->refcount = 0; pdp->pStamp = NULL; pdp->lastStamp = 0; @@ -669,80 +429,56 @@ static void *driCreateNewDrawable(__DRInativeDisplay *dpy, pdp->numBackClipRects = 0; pdp->pClipRects = NULL; pdp->pBackClipRects = NULL; - pdp->display = dpy; - pdp->screen = modes->screen; + pdp->vblSeq = 0; + pdp->vblFlags = 0; - psp = (__DRIscreenPrivate *)pDRIScreen->private; pdp->driScreenPriv = psp; pdp->driContextPriv = &psp->dummyContextPriv; - if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes, + if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, renderType == GLX_PIXMAP_BIT)) { - (void)(*dri_interface->destroyDrawable)(dpy, modes->screen, pdp->draw); _mesa_free(pdp); return NULL; } - pdraw->private = pdp; - pdraw->destroyDrawable = driDestroyDrawable; - pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */ - - pdraw->getSBC = driGetSBC; - pdraw->waitForSBC = driWaitForSBC; - pdraw->waitForMSC = driWaitForMSC; - pdraw->swapBuffersMSC = driSwapBuffersMSC; - pdraw->frameTracking = NULL; - pdraw->queryFrameTracking = driQueryFrameTracking; - - if (driCompareGLXAPIVersion (20060314) >= 0) - pdraw->copySubBuffer = driCopySubBuffer; + pdp->msc_base = 0; /* This special default value is replaced with the configured * default value when the drawable is first bound to a direct * rendering context. */ - pdraw->swap_interval = (unsigned)-1; - - pdp->swapBuffers = psp->DriverAPI.SwapBuffers; + pdp->swap_interval = (unsigned)-1; - /* Add pdraw to drawable list */ - if (!__driAddDrawable(psp->drawHash, pdraw)) { - /* ERROR!!! */ - (*pdraw->destroyDrawable)(dpy, pdp); - _mesa_free(pdp); - pdp = NULL; - pdraw->private = NULL; - } - - return (void *) pdp; + return pdp; } + static __DRIdrawable * -driGetDrawable(__DRInativeDisplay *dpy, __DRIid draw, void *screenPrivate) +dri2CreateNewDrawable(__DRIscreen *screen, + const __DRIconfig *config, + void *loaderPrivate) { - __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate; + __DRIdrawable *pdraw; - /* - ** Make sure this routine returns NULL if the drawable is not bound - ** to a direct rendering context! - */ - return __driFindDrawable(psp->drawHash, draw); + pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate); + if (!pdraw) + return NULL; + + pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects); + pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects); + + return pdraw; } + static void -driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate) +driDestroyDrawable(__DRIdrawable *pdp) { - __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate; __DRIscreenPrivate *psp; - int scrn; if (pdp) { psp = pdp->driScreenPriv; - scrn = psp->myNum; (*psp->DriverAPI.DestroyBuffer)(pdp); - if ((*dri_interface->windowExists)(dpy, pdp->draw)) - (void)(*dri_interface->destroyDrawable)(dpy, scrn, pdp->draw); - drmHashDelete(psp->drawHash, pdp->draw); if (pdp->pClipRects) { _mesa_free(pdp->pClipRects); pdp->pClipRects = NULL; @@ -766,23 +502,15 @@ driDestroyDrawable(__DRInativeDisplay *dpy, void *drawablePrivate) /** * Destroy the per-context private information. * - * \param dpy the display handle. - * \param scrn the screen number. - * \param contextPrivate opaque pointer to the per-drawable private info. - * * \internal * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls * drmDestroyContext(), and finally frees \p contextPrivate. */ static void -driDestroyContext(__DRInativeDisplay *dpy, int scrn, void *contextPrivate) +driDestroyContext(__DRIcontext *pcp) { - __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate; - if (pcp) { (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp); - __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash); - (void) (*dri_interface->destroyContext)(dpy, scrn, pcp->contextID); _mesa_free(pcp); } } @@ -791,13 +519,9 @@ driDestroyContext(__DRInativeDisplay *dpy, int scrn, void *contextPrivate) /** * Create the per-drawable private driver information. * - * \param dpy The display handle. - * \param modes Mode used to create the new context. * \param render_type Type of rendering target. \c GLX_RGBA is the only * type likely to ever be supported for direct-rendering. - * \param sharedPrivate The shared context dependent methods or \c NULL if - * non-existent. - * \param pctx DRI context to receive the context dependent methods. + * \param shared Context with which to share textures, etc. or NULL * * \returns An opaque pointer to the per-context private information on * success, or \c NULL on failure. @@ -809,36 +533,18 @@ driDestroyContext(__DRInativeDisplay *dpy, int scrn, void *contextPrivate) * context. * */ -static void * -driCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes, - int render_type, void *sharedPrivate, __DRIcontext *pctx) +static __DRIcontext * +driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, + int render_type, __DRIcontext *shared, + drm_context_t hwContext, void *data) { - __DRIscreen *pDRIScreen; - __DRIcontextPrivate *pcp; - __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate; - __DRIscreenPrivate *psp; - void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL; - - pDRIScreen = (*dri_interface->getScreen)(dpy, modes->screen); - if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) { - /* ERROR!!! */ - return NULL; - } - - psp = (__DRIscreenPrivate *)pDRIScreen->private; - - pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate)); - if (!pcp) { - return NULL; - } + __DRIcontext *pcp; + void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; - if (! (*dri_interface->createContext)(dpy, modes->screen, modes->fbconfigID, - &pcp->contextID, &pcp->hHWContext)) { - _mesa_free(pcp); + pcp = _mesa_malloc(sizeof *pcp); + if (!pcp) return NULL; - } - pcp->display = dpy; pcp->driScreenPriv = psp; pcp->driDrawablePriv = NULL; @@ -846,8 +552,7 @@ driCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes, * context. */ - if (!psp->dummyContextPriv.driScreenPriv) { - psp->dummyContextPriv.contextID = 0; + if (!psp->dri2.enabled && !psp->dummyContextPriv.driScreenPriv) { psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context; psp->dummyContextPriv.driScreenPriv = psp; psp->dummyContextPriv.driDrawablePriv = NULL; @@ -855,21 +560,31 @@ driCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes, /* No other fields should be used! */ } - pctx->destroyContext = driDestroyContext; - pctx->bindContext = driBindContext; - pctx->unbindContext = driUnbindContext; + pcp->hHWContext = hwContext; - if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) { - (void) (*dri_interface->destroyContext)(dpy, modes->screen, - pcp->contextID); + if ( !(*psp->DriverAPI.CreateContext)(&config->modes, pcp, shareCtx) ) { _mesa_free(pcp); return NULL; } - __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash); - return pcp; } + + +static __DRIcontext * +dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, + __DRIcontext *shared, void *data) +{ + return driCreateNewContext(screen, config, 0, shared, 0, data); +} + + +static int +driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) +{ + return GL_FALSE; +} + /*@}*/ @@ -881,18 +596,12 @@ driCreateNewContext(__DRInativeDisplay *dpy, const __GLcontextModes *modes, /** * Destroy the per-screen private information. * - * \param dpy the display handle. - * \param scrn the screen number. - * \param screenPrivate opaque pointer to the per-screen private information. - * * \internal * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls * drmClose(), and finally frees \p screenPrivate. */ -static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPrivate) +static void driDestroyScreen(__DRIscreen *psp) { - __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate; - if (psp) { /* No interaction with the X-server is possible at this point. This * routine is called after XCloseDisplay, so there is no protocol @@ -902,34 +611,44 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv if (psp->DriverAPI.DestroyScreen) (*psp->DriverAPI.DestroyScreen)(psp); - (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); - (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); - _mesa_free(psp->pDevPriv); - (void)drmCloseOnce(psp->fd); - if ( psp->modes != NULL ) { - (*dri_interface->destroyContextModes)( psp->modes ); + if (!psp->dri2.enabled) { + (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); + (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); + (void)drmCloseOnce(psp->fd); } - assert(psp->drawHash); - drmHashDestroy(psp->drawHash); - _mesa_free(psp); } } +static void +setupLoaderExtensions(__DRIscreen *psp, + const __DRIextension **extensions) +{ + int i; + + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_GET_DRAWABLE_INFO) == 0) + psp->getDrawableInfo = (__DRIgetDrawableInfoExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_DAMAGE) == 0) + psp->damage = (__DRIdamageExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0) + psp->systemTime = (__DRIsystemTimeExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) + psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; + } +} /** - * Utility function used to create a new driver-private screen structure. + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * For legacy DRI. * - * \param dpy Display pointer * \param scrn Index of the screen - * \param psc DRI screen data (not driver private) - * \param modes Linked list of known display modes. This list is, at a - * minimum, a list of modes based on the current display mode. - * These roughly match the set of available X11 visuals, but it - * need not be limited to X11! The calling libGL should create - * a list that will inform the driver of the current display - * mode (i.e., color buffer depth, depth buffer depth, etc.). * \param ddx_version Version of the 2D DDX. This may not be meaningful for * all drivers. * \param dri_version Version of the "server-side" DRI. @@ -938,48 +657,33 @@ static void driDestroyScreen(__DRInativeDisplay *dpy, int scrn, void *screenPriv * framebuffer. * \param pSAREA Pointer the the SAREA. * \param fd Device handle for the DRM. - * \param internal_api_version Version of the internal interface between the - * driver and libGL. - * \param driverAPI Driver API functions used by other routines in dri_util.c. + * \param extensions ?? + * \param driver_modes Returns modes suppoted by the driver + * \param loaderPrivate ?? * - * \note - * There is no need to check the minimum API version in this function. Since - * the \c __driCreateNewScreen function is versioned, it is impossible for a - * loader that is too old to even load this driver. + * \note There is no need to check the minimum API version in this + * function. Since the name of this function is versioned, it is + * impossible for a loader that is too old to even load this driver. */ -__DRIscreenPrivate * -__driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, - __GLcontextModes * modes, - const __DRIversion * ddx_version, - const __DRIversion * dri_version, - const __DRIversion * drm_version, - const __DRIframebuffer * frame_buffer, - drm_sarea_t *pSAREA, - int fd, - int internal_api_version, - const struct __DriverAPIRec *driverAPI) +static __DRIscreen * +driCreateNewScreen(int scrn, + const __DRIversion *ddx_version, + const __DRIversion *dri_version, + const __DRIversion *drm_version, + const __DRIframebuffer *frame_buffer, + drmAddress pSAREA, int fd, + const __DRIextension **extensions, + const __DRIconfig ***driver_modes, + void *loaderPrivate) { - __DRIscreenPrivate *psp; - - - api_ver = internal_api_version; - - psp = (__DRIscreenPrivate *)_mesa_calloc(sizeof(__DRIscreenPrivate)); - if (!psp) { - return NULL; - } + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; - /* Create the hash table */ - psp->drawHash = drmHashCreate(); - if ( psp->drawHash == NULL ) { - _mesa_free( psp ); + psp = _mesa_calloc(sizeof *psp); + if (!psp) return NULL; - } - psp->display = dpy; - psp->myNum = scrn; - psp->psc = psc; - psp->modes = modes; + setupLoaderExtensions(psp, extensions); /* ** NOT_DONE: This is used by the X server to detect when the client @@ -988,20 +692,12 @@ __driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, */ psp->drawLockID = 1; - psp->drmMajor = drm_version->major; - psp->drmMinor = drm_version->minor; - psp->drmPatch = drm_version->patch; - psp->ddxMajor = ddx_version->major; - psp->ddxMinor = ddx_version->minor; - psp->ddxPatch = ddx_version->patch; - psp->driMajor = dri_version->major; - psp->driMinor = dri_version->minor; - psp->driPatch = dri_version->patch; - - /* install driver's callback functions */ - memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) ); + psp->drm_version = *drm_version; + psp->ddx_version = *ddx_version; + psp->dri_version = *dri_version; psp->pSAREA = pSAREA; + psp->lock = (drmLock *) &psp->pSAREA->lock; psp->pFB = frame_buffer->base; psp->fbSize = frame_buffer->size; @@ -1012,7 +708,10 @@ __driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, psp->pDevPriv = frame_buffer->dev_priv; psp->fbBPP = psp->fbStride * 8 / frame_buffer->width; + psp->extensions = emptyExtensionList; psp->fd = fd; + psp->myNum = scrn; + psp->dri2.enabled = GL_FALSE; /* ** Do not init dummy context here; actual initialization will be @@ -1021,63 +720,125 @@ __driUtilCreateNewScreen(__DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, */ psp->dummyContextPriv.driScreenPriv = NULL; - psc->destroyScreen = driDestroyScreen; - psc->createNewDrawable = driCreateNewDrawable; - psc->getDrawable = driGetDrawable; - psc->getMSC = driGetMSC; - psc->createNewContext = driCreateNewContext; - - if (internal_api_version >= 20070121) - psc->setTexOffset = psp->DriverAPI.setTexOffset; + psp->DriverAPI = driDriverAPI; - if ( (psp->DriverAPI.InitDriver != NULL) - && !(*psp->DriverAPI.InitDriver)(psp) ) { - _mesa_free( psp ); + *driver_modes = driDriverAPI.InitScreen(psp); + if (*driver_modes == NULL) { + _mesa_free(psp); return NULL; } - return psp; } - /** - * Compare the current GLX API version with a driver supplied required version. - * - * The minimum required version is compared with the API version exported by - * the \c __glXGetInternalVersion function (in libGL.so). - * - * \param required_version Minimum required internal GLX API version. - * \return A tri-value return, as from strcmp is returned. A value less - * than, equal to, or greater than zero will be returned if the - * internal GLX API version is less than, equal to, or greater - * than \c required_version. - * - * \sa __glXGetInternalVersion(). + * DRI2 */ -int driCompareGLXAPIVersion( GLint required_version ) +static __DRIscreen * +dri2CreateNewScreen(int scrn, int fd, + const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) { - if ( api_ver > required_version ) { - return 1; - } - else if ( api_ver == required_version ) { - return 0; - } + static const __DRIextension *emptyExtensionList[] = { NULL }; + __DRIscreen *psp; + drmVersionPtr version; + + if (driDriverAPI.InitScreen2 == NULL) + return NULL; + + psp = _mesa_malloc(sizeof(*psp)); + if (!psp) + return NULL; + + setupLoaderExtensions(psp, extensions); + + version = drmGetVersion(fd); + if (version) { + psp->drm_version.major = version->version_major; + psp->drm_version.minor = version->version_minor; + psp->drm_version.patch = version->version_patchlevel; + drmFreeVersion(version); + } + + psp->extensions = emptyExtensionList; + psp->fd = fd; + psp->myNum = scrn; + psp->dri2.enabled = GL_TRUE; - return -1; + psp->DriverAPI = driDriverAPI; + *driver_configs = driDriverAPI.InitScreen2(psp); + if (*driver_configs == NULL) { + _mesa_free(psp); + return NULL; + } + + psp->DriverAPI = driDriverAPI; + + return psp; } +static const __DRIextension **driGetExtensions(__DRIscreen *psp) +{ + return psp->extensions; +} + +/** Core interface */ +const __DRIcoreExtension driCoreExtension = { + { __DRI_CORE, __DRI_CORE_VERSION }, + NULL, + driDestroyScreen, + driGetExtensions, + driGetConfigAttrib, + driIndexConfigAttrib, + NULL, + driDestroyDrawable, + driSwapBuffers, + NULL, + driCopyContext, + driDestroyContext, + driBindContext, + driUnbindContext +}; + +/** Legacy DRI interface */ +const __DRIlegacyExtension driLegacyExtension = { + { __DRI_LEGACY, __DRI_LEGACY_VERSION }, + driCreateNewScreen, + driCreateNewDrawable, + driCreateNewContext, +}; + +/** Legacy DRI interface */ +const __DRIdri2Extension driDRI2Extension = { + { __DRI_DRI2, __DRI_DRI2_VERSION }, + dri2CreateNewScreen, + dri2CreateNewDrawable, + dri2CreateNewContext, +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +PUBLIC const __DRIextension *__driDriverExtensions[] = { + &driCoreExtension.base, + &driLegacyExtension.base, + &driDRI2Extension.base, + NULL +}; static int -driQueryFrameTracking( __DRInativeDisplay * dpy, void * priv, - int64_t * sbc, int64_t * missedFrames, - float * lastMissedUsage, float * usage ) +driFrameTracking(__DRIdrawable *drawable, GLboolean enable) +{ + return GLX_BAD_CONTEXT; +} + +static int +driQueryFrameTracking(__DRIdrawable *dpriv, + int64_t * sbc, int64_t * missedFrames, + float * lastMissedUsage, float * usage) { __DRIswapInfo sInfo; int status; int64_t ust; - __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv; - + __DRIscreenPrivate *psp = dpriv->driScreenPriv; status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo ); if ( status == 0 ) { @@ -1085,13 +846,18 @@ driQueryFrameTracking( __DRInativeDisplay * dpy, void * priv, *missedFrames = sInfo.swap_missed_count; *lastMissedUsage = sInfo.swap_missed_usage; - (*dri_interface->getUST)( & ust ); + (*psp->systemTime->getUST)( & ust ); *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust ); } return status; } +const __DRIframeTrackingExtension driFrameTrackingExtension = { + { __DRI_FRAME_TRACKING, __DRI_FRAME_TRACKING_VERSION }, + driFrameTracking, + driQueryFrameTracking +}; /** * Calculate amount of swap interval used between GLX buffer swaps. @@ -1129,11 +895,10 @@ driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust, int32_t d; int interval; float usage = 1.0; + __DRIscreenPrivate *psp = dPriv->driScreenPriv; - - if ( (*dri_interface->getMSCRate)( dPriv->display, dPriv->draw, &n, &d ) ) { - interval = (dPriv->pdraw->swap_interval != 0) - ? dPriv->pdraw->swap_interval : 1; + if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) { + interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1; /* We want to calculate |