X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fcommon%2Fdri_util.c;h=d35ac263a454005981f535820cc02236dd052418;hb=094877f9d23169b1d209fb0c97f9b6d4679842d9;hp=82638fa72079a06f0990f9d017448cc652248e00;hpb=b922a0ce12916a91cfc3e56714913fcf63279ff2;p=mesa.git diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c index 82638fa7207..d35ac263a45 100644 --- a/src/mesa/drivers/dri/common/dri_util.c +++ b/src/mesa/drivers/dri/common/dri_util.c @@ -1,3 +1,27 @@ +/* + * (C) Copyright IBM Corporation 2002, 2004 + * 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 + * on 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 + * THE AUTHORS AND/OR THEIR 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. + */ + /** * \file dri_util.c * DRI utility functions. @@ -15,1016 +39,852 @@ */ -#include -#include -#include -#include -#include - -#ifndef MAP_FAILED -#define MAP_FAILED ((void *)-1) -#endif - -#include "main/imports.h" -#define None 0 - +#include #include "dri_util.h" -#include "drm_sarea.h" #include "utils.h" #include "xmlpool.h" -#include "../glsl/glsl_parser_extras.h" +#include "main/mtypes.h" +#include "main/version.h" +#include "main/errors.h" +#include "main/macros.h" -PUBLIC const char __dri2ConfigOptions[] = +const char __dri2ConfigOptions[] = DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1) DRI_CONF_SECTION_END DRI_CONF_END; -static const uint __dri2NConfigOptions = 1; - -#ifndef GLX_OML_sync_control -typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator); -#endif - -static void dri_get_drawable(__DRIdrawable *pdp); -static void dri_put_drawable(__DRIdrawable *pdp); - -/** - * This is just a token extension used to signal that the driver - * supports setting a read drawable. - */ -const __DRIextension driReadDrawableExtension = { - __DRI_READ_DRAWABLE, __DRI_READ_DRAWABLE_VERSION -}; +/*****************************************************************/ +/** \name Screen handling functions */ +/*****************************************************************/ +/*@{*/ -GLint -driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) +static void +setupLoaderExtensions(__DRIscreen *psp, + const __DRIextension **extensions) { - 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; - - if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0; + int i; - return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1); + for (i = 0; extensions[i]; i++) { + if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0) + psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) + psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) + psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) + psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0) + psp->image.loader = (__DRIimageLoaderExtension *) extensions[i]; + } } -/*****************************************************************/ -/** \name Context (un)binding functions */ -/*****************************************************************/ -/*@{*/ +/** + * This pointer determines which driver API we'll use in the case of the + * loader not passing us an explicit driver extensions list (that would, + * itself, contain a pointer to a driver API.) + * + * A driver's driDriverGetExtensions_drivername() can update this pointer to + * what it's returning, and a loader that is ignorant of createNewScreen2() + * will get the correct driver screen created, as long as no other + * driDriverGetExtensions() happened in between the first one and the + * createNewScreen(). + * + * This allows the X Server to not require the significant dri_interface.h + * updates for doing createNewScreen2(), which would discourage backporting of + * the X Server patches to support the new loader interface. + */ +const struct __DriverAPIRec *globalDriverAPI = &driDriverAPI; /** - * Unbind context. - * - * \param scrn the screen. - * \param gc context. + * This is the first entrypoint in the driver called by the DRI driver loader + * after dlopen()ing it. * - * \return \c GL_TRUE on success, or \c GL_FALSE on failure. - * - * \internal - * This function calls __DriverAPIRec::UnbindContext, and then decrements - * __DRIdrawableRec::refcount which must be non-zero for a successful - * return. - * - * While casting the opaque private pointers associated with the parameters - * into their respective real types it also assures they are not \c NULL. + * It's used to create global state for the driver across contexts on the same + * Display. */ -static int driUnbindContext(__DRIcontext *pcp) +static __DRIscreen * +driCreateNewScreen2(int scrn, int fd, + const __DRIextension **extensions, + const __DRIextension **driver_extensions, + const __DRIconfig ***driver_configs, void *data) { + static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; - __DRIdrawable *pdp; - __DRIdrawable *prp; - /* - ** Assume error checking is done properly in glXMakeCurrent before - ** calling driUnbindContext. - */ + psp = calloc(1, sizeof(*psp)); + if (!psp) + return NULL; - if (pcp == NULL) - return GL_FALSE; + /* By default, use the global driDriverAPI symbol (non-megadrivers). */ + psp->driver = globalDriverAPI; - psp = pcp->driScreenPriv; - pdp = pcp->driDrawablePriv; - prp = pcp->driReadablePriv; + /* If the driver exposes its vtable through its extensions list + * (megadrivers), use that instead. + */ + if (driver_extensions) { + for (int i = 0; driver_extensions[i]; i++) { + if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) { + psp->driver = + ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; + } + } + } - /* already unbound */ - if (!pdp && !prp) - return GL_TRUE; - /* Let driver unbind drawable from context */ - (*psp->DriverAPI.UnbindContext)(pcp); + setupLoaderExtensions(psp, extensions); - assert(pdp); - if (pdp->refcount == 0) { - /* ERROR!!! */ - return GL_FALSE; - } + psp->loaderPrivate = data; - dri_put_drawable(pdp); + psp->extensions = emptyExtensionList; + psp->fd = fd; + psp->myNum = scrn; - if (prp != pdp) { - if (prp->refcount == 0) { - /* ERROR!!! */ - return GL_FALSE; - } + *driver_configs = psp->driver->InitScreen(psp); + if (*driver_configs == NULL) { + free(psp); + return NULL; + } - dri_put_drawable(prp); + struct gl_constants consts = { 0 }; + gl_api api; + unsigned version; + + api = API_OPENGLES2; + if (_mesa_override_gl_version_contextless(&consts, &api, &version)) + psp->max_gl_es2_version = version; + + api = API_OPENGL_COMPAT; + if (_mesa_override_gl_version_contextless(&consts, &api, &version)) { + if (api == API_OPENGL_CORE) { + psp->max_gl_core_version = version; + } else { + psp->max_gl_compat_version = version; + } } + psp->api_mask = 0; + if (psp->max_gl_compat_version > 0) + psp->api_mask |= (1 << __DRI_API_OPENGL); + if (psp->max_gl_core_version > 0) + psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); + if (psp->max_gl_es1_version > 0) + psp->api_mask |= (1 << __DRI_API_GLES); + if (psp->max_gl_es2_version > 0) + psp->api_mask |= (1 << __DRI_API_GLES2); + if (psp->max_gl_es2_version >= 30) + psp->api_mask |= (1 << __DRI_API_GLES3); - /* 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 - * use that context's lock. (BrianP, 2-Dec-2000) - */ - pcp->driDrawablePriv = pcp->driReadablePriv = NULL; + driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions); + driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); - return GL_TRUE; + + return psp; } -/** - * 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 int driBindContext(__DRIcontext *pcp, - __DRIdrawable *pdp, - __DRIdrawable *prp) +static __DRIscreen * +dri2CreateNewScreen(int scrn, int fd, + const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) { - __DRIscreen *psp = NULL; - - /* - ** Assume error checking is done properly in glXMakeCurrent before - ** calling driUnbindContext. - */ - - if (!pcp) - return GL_FALSE; - - /* Bind the drawable to the context */ - psp = pcp->driScreenPriv; - pcp->driDrawablePriv = pdp; - pcp->driReadablePriv = prp; - if (pdp) { - pdp->driContextPriv = pcp; - dri_get_drawable(pdp); - } - if (prp && pdp != prp) { - dri_get_drawable(prp); - } - - /* - ** Now that we have a context associated with this drawable, we can - ** initialize the drawable information if has not been done before. - */ - - if (!psp->dri2.enabled) { - if (pdp && !pdp->pStamp) { - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - __driUtilUpdateDrawableInfo(pdp); - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - } - if (prp && pdp != prp && !prp->pStamp) { - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - __driUtilUpdateDrawableInfo(prp); - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - } - } - - /* Call device-specific MakeCurrent */ - return (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp); + return driCreateNewScreen2(scrn, fd, extensions, NULL, + driver_configs, data); } -/*@}*/ - +/** swrast driver createNewScreen entrypoint. */ +static __DRIscreen * +driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions, + const __DRIconfig ***driver_configs, void *data) +{ + return driCreateNewScreen2(scrn, -1, extensions, NULL, + driver_configs, data); +} -/*****************************************************************/ -/** \name Drawable handling functions */ -/*****************************************************************/ -/*@{*/ +static __DRIscreen * +driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions, + const __DRIextension **driver_extensions, + const __DRIconfig ***driver_configs, void *data) +{ + return driCreateNewScreen2(scrn, -1, extensions, driver_extensions, + driver_configs, data); +} /** - * Update private drawable information. - * - * \param pdp pointer to the private drawable information to update. + * Destroy the per-screen private information. * - * This function basically updates the __DRIdrawable struct's - * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo. - * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which - * compares the __DRIdrwablePrivate pStamp and lastStamp values. If - * the values are different that means we have to update the clipping - * info. + * \internal + * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls + * drmClose(), and finally frees \p screenPrivate. */ -void -__driUtilUpdateDrawableInfo(__DRIdrawable *pdp) +static void driDestroyScreen(__DRIscreen *psp) { - __DRIscreen *psp = pdp->driScreenPriv; - __DRIcontext *pcp = pdp->driContextPriv; - - if (!pcp - || ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) { - /* ERROR!!! - * ...but we must ignore it. There can be many contexts bound to a - * drawable. + if (psp) { + /* No interaction with the X-server is possible at this point. This + * routine is called after XCloseDisplay, so there is no protocol + * stream open to the X-server anymore. */ - } - if (pdp->pClipRects) { - free(pdp->pClipRects); - pdp->pClipRects = NULL; - } + psp->driver->DestroyScreen(psp); - if (pdp->pBackClipRects) { - free(pdp->pBackClipRects); - pdp->pBackClipRects = NULL; - } + driDestroyOptionCache(&psp->optionCache); + driDestroyOptionInfo(&psp->optionInfo); - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); - - 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->loaderPrivate)) { - /* Error -- eg the window may have been destroyed. Keep going - * with no cliprects. - */ - pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */ - pdp->numClipRects = 0; - pdp->pClipRects = NULL; - pdp->numBackClipRects = 0; - pdp->pBackClipRects = NULL; + free(psp); } - else - pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp); +} - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); +static const __DRIextension **driGetExtensions(__DRIscreen *psp) +{ + return psp->extensions; } /*@}*/ + +static bool +validate_context_version(__DRIscreen *screen, + int mesa_api, + unsigned major_version, + unsigned minor_version, + unsigned *dri_ctx_error) +{ + unsigned req_version = 10 * major_version + minor_version; + unsigned max_version = 0; + + switch (mesa_api) { + case API_OPENGL_COMPAT: + max_version = screen->max_gl_compat_version; + break; + case API_OPENGL_CORE: + max_version = screen->max_gl_core_version; + break; + case API_OPENGLES: + max_version = screen->max_gl_es1_version; + break; + case API_OPENGLES2: + max_version = screen->max_gl_es2_version; + break; + default: + max_version = 0; + break; + } + + if (max_version == 0) { + *dri_ctx_error = __DRI_CTX_ERROR_BAD_API; + return false; + } else if (req_version > max_version) { + *dri_ctx_error = __DRI_CTX_ERROR_BAD_VERSION; + return false; + } + + return true; +} + /*****************************************************************/ -/** \name GLX callbacks */ +/** \name Context handling functions */ /*****************************************************************/ /*@{*/ -static void driReportDamage(__DRIdrawable *pdp, - struct drm_clip_rect *pClipRects, int numClipRects) +static __DRIcontext * +driCreateContextAttribs(__DRIscreen *screen, int api, + const __DRIconfig *config, + __DRIcontext *shared, + unsigned num_attribs, + const uint32_t *attribs, + unsigned *error, + void *data) { - __DRIscreen *psp = pdp->driScreenPriv; + __DRIcontext *context; + const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; + void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + gl_api mesa_api; + unsigned major_version = 1; + unsigned minor_version = 0; + uint32_t flags = 0; + bool notify_reset = false; - /* 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); - } -} + assert((num_attribs == 0) || (attribs != NULL)); + if (!(screen->api_mask & (1 << api))) { + *error = __DRI_CTX_ERROR_BAD_API; + return NULL; + } -/** - * Swap buffers. - * - * \param drawablePrivate opaque pointer to the per-drawable private info. - * - * \internal - * This function calls __DRIdrawable::swapBuffers. - * - * Is called directly from glXSwapBuffers(). - */ -static void driSwapBuffers(__DRIdrawable *dPriv) -{ - __DRIscreen *psp = dPriv->driScreenPriv; - drm_clip_rect_t *rects; - int i; + switch (api) { + case __DRI_API_OPENGL: + mesa_api = API_OPENGL_COMPAT; + break; + case __DRI_API_GLES: + mesa_api = API_OPENGLES; + break; + case __DRI_API_GLES2: + case __DRI_API_GLES3: + mesa_api = API_OPENGLES2; + break; + case __DRI_API_OPENGL_CORE: + mesa_api = API_OPENGL_CORE; + break; + default: + *error = __DRI_CTX_ERROR_BAD_API; + return NULL; + } - psp->DriverAPI.SwapBuffers(dPriv); + for (unsigned i = 0; i < num_attribs; i++) { + switch (attribs[i * 2]) { + case __DRI_CTX_ATTRIB_MAJOR_VERSION: + major_version = attribs[i * 2 + 1]; + break; + case __DRI_CTX_ATTRIB_MINOR_VERSION: + minor_version = attribs[i * 2 + 1]; + break; + case __DRI_CTX_ATTRIB_FLAGS: + flags = attribs[i * 2 + 1]; + break; + case __DRI_CTX_ATTRIB_RESET_STRATEGY: + notify_reset = (attribs[i * 2 + 1] + != __DRI_CTX_RESET_NO_NOTIFICATION); + break; + default: + /* We can't create a context that satisfies the requirements of an + * attribute that we don't understand. Return failure. + */ + assert(!"Should not get here."); + *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; + return NULL; + } + } - if (!dPriv->numClipRects) - return; + /* Mesa does not support the GL_ARB_compatibilty extension or the + * compatibility profile. This means that we treat a API_OPENGL_COMPAT 3.1 as + * API_OPENGL_CORE and reject API_OPENGL_COMPAT 3.2+. + */ + if (mesa_api == API_OPENGL_COMPAT && major_version == 3 && minor_version == 1) + mesa_api = API_OPENGL_CORE; - rects = malloc(sizeof(*rects) * dPriv->numClipRects); + if (mesa_api == API_OPENGL_COMPAT + && ((major_version > 3) + || (major_version == 3 && minor_version >= 2))) { + *error = __DRI_CTX_ERROR_BAD_API; + return NULL; + } - if (!rects) - return; + /* The latest version of EGL_KHR_create_context spec says: + * + * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in + * EGL_CONTEXT_FLAGS_KHR, then a will be created. + * [...] This bit is supported for OpenGL and OpenGL ES contexts. + * + * None of the other flags have any meaning in an ES context, so this seems safe. + */ + if (mesa_api != API_OPENGL_COMPAT + && mesa_api != API_OPENGL_CORE + && (flags & ~__DRI_CTX_FLAG_DEBUG)) { + *error = __DRI_CTX_ERROR_BAD_FLAG; + return NULL; + } - for (i = 0; i < dPriv->numClipRects; i++) { - rects[i].x1 = dPriv->pClipRects[i].x1 - dPriv->x; - rects[i].y1 = dPriv->pClipRects[i].y1 - dPriv->y; - rects[i].x2 = dPriv->pClipRects[i].x2 - dPriv->x; - rects[i].y2 = dPriv->pClipRects[i].y2 - dPriv->y; + /* There are no forward-compatible contexts before OpenGL 3.0. The + * GLX_ARB_create_context spec says: + * + * "Forward-compatible contexts are defined only for OpenGL versions + * 3.0 and later." + * + * Forward-looking contexts are supported by silently converting the + * requested API to API_OPENGL_CORE. + * + * In Mesa, a debug context is the same as a regular context. + */ + if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) { + mesa_api = API_OPENGL_CORE; } - driReportDamage(dPriv, rects, dPriv->numClipRects); - free(rects); -} + const uint32_t allowed_flags = (__DRI_CTX_FLAG_DEBUG + | __DRI_CTX_FLAG_FORWARD_COMPATIBLE + | __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS); + if (flags & ~allowed_flags) { + *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; + return NULL; + } -static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv, - int64_t *msc ) -{ - return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc); -} + if (!validate_context_version(screen, mesa_api, + major_version, minor_version, error)) + return NULL; + context = calloc(1, sizeof *context); + if (!context) { + *error = __DRI_CTX_ERROR_NO_MEMORY; + return NULL; + } -static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc, - int64_t divisor, int64_t remainder, - int64_t * msc, int64_t * sbc) -{ - __DRIswapInfo sInfo; - int status; + context->loaderPrivate = data; - status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc, - divisor, remainder, - msc ); + context->driScreenPriv = screen; + context->driDrawablePriv = NULL; + context->driReadablePriv = NULL; - /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync - * is supported but GLX_OML_sync_control is not. Therefore, don't return - * an error value if GetSwapInfo() is not implemented. - */ - if ( status == 0 - && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) { - status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo ); - *sbc = sInfo.swap_count; + if (!screen->driver->CreateContext(mesa_api, modes, context, + major_version, minor_version, + flags, notify_reset, error, shareCtx)) { + free(context); + return NULL; } - return status; + *error = __DRI_CTX_ERROR_SUCCESS; + return context; } - -const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = { - { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION }, - driWaitForMSC, - driDrawableGetMSC, -}; - - -static void driCopySubBuffer(__DRIdrawable *dPriv, - int x, int y, int w, int h) +void +driContextSetFlags(struct gl_context *ctx, uint32_t flags) { - 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); + if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) + ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) { + _mesa_set_debug_state_int(ctx, GL_DEBUG_OUTPUT, GL_TRUE); + ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT; + } } -const __DRIcopySubBufferExtension driCopySubBufferExtension = { - { __DRI_COPY_SUB_BUFFER, __DRI_COPY_SUB_BUFFER_VERSION }, - driCopySubBuffer -}; - -static void driSetSwapInterval(__DRIdrawable *dPriv, unsigned int interval) +static __DRIcontext * +driCreateNewContextForAPI(__DRIscreen *screen, int api, + const __DRIconfig *config, + __DRIcontext *shared, void *data) { - dPriv->swap_interval = interval; + unsigned error; + + return driCreateContextAttribs(screen, api, config, shared, 0, NULL, + &error, data); } -static unsigned int driGetSwapInterval(__DRIdrawable *dPriv) +static __DRIcontext * +driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, + __DRIcontext *shared, void *data) { - return dPriv->swap_interval; + return driCreateNewContextForAPI(screen, __DRI_API_OPENGL, + config, shared, data); } -const __DRIswapControlExtension driSwapControlExtension = { - { __DRI_SWAP_CONTROL, __DRI_SWAP_CONTROL_VERSION }, - driSetSwapInterval, - driGetSwapInterval -}; - - /** - * This is called via __DRIscreenRec's createNewDrawable pointer. + * Destroy the per-context private information. + * + * \internal + * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls + * drmDestroyContext(), and finally frees \p contextPrivate. */ -static __DRIdrawable * -driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config, - drm_drawable_t hwDrawable, int renderType, - const int *attrs, void *data) +static void +driDestroyContext(__DRIcontext *pcp) { - __DRIdrawable *pdp; - - /* Since pbuffers are not yet supported, no drawable attributes are - * supported either. - */ - (void) attrs; - - pdp = malloc(sizeof *pdp); - if (!pdp) { - return NULL; + if (pcp) { + pcp->driScreenPriv->driver->DestroyContext(pcp); + free(pcp); } +} - pdp->driContextPriv = NULL; - pdp->loaderPrivate = data; - pdp->hHWDrawable = hwDrawable; - pdp->refcount = 1; - pdp->pStamp = NULL; - pdp->lastStamp = 0; - pdp->index = 0; - pdp->x = 0; - pdp->y = 0; - pdp->w = 0; - pdp->h = 0; - pdp->numClipRects = 0; - pdp->numBackClipRects = 0; - pdp->pClipRects = NULL; - pdp->pBackClipRects = NULL; - pdp->vblSeq = 0; - pdp->vblFlags = 0; - - pdp->driScreenPriv = psp; - - if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, 0)) { - free(pdp); - return NULL; - } +static int +driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) +{ + (void) dest; + (void) src; + (void) mask; + return GL_FALSE; +} - 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. - */ - pdp->swap_interval = (unsigned)-1; - return pdp; -} +/*****************************************************************/ +/** \name Context (un)binding functions */ +/*****************************************************************/ +/*@{*/ +static void dri_get_drawable(__DRIdrawable *pdp); +static void dri_put_drawable(__DRIdrawable *pdp); -static __DRIdrawable * -dri2CreateNewDrawable(__DRIscreen *screen, - const __DRIconfig *config, - void *loaderPrivate) +/** + * 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 int driBindContext(__DRIcontext *pcp, + __DRIdrawable *pdp, + __DRIdrawable *prp) { - __DRIdrawable *pdraw; - - pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate); - if (!pdraw) - return NULL; + /* + ** Assume error checking is done properly in glXMakeCurrent before + ** calling driUnbindContext. + */ - pdraw->pClipRects = &pdraw->dri2.clipRect; - pdraw->pBackClipRects = &pdraw->dri2.clipRect; + if (!pcp) + return GL_FALSE; - pdraw->pStamp = &pdraw->dri2.stamp; - *pdraw->pStamp = pdraw->lastStamp + 1; + /* Bind the drawable to the context */ + pcp->driDrawablePriv = pdp; + pcp->driReadablePriv = prp; + if (pdp) { + pdp->driContextPriv = pcp; + dri_get_drawable(pdp); + } + if (prp && pdp != prp) { + dri_get_drawable(prp); + } - return pdraw; + return pcp->driScreenPriv->driver->MakeCurrent(pcp, pdp, prp); } -static __DRIbuffer * -dri2AllocateBuffer(__DRIscreen *screen, - unsigned int attachment, unsigned int format, - int width, int height) +/** + * Unbind context. + * + * \param scrn the screen. + * \param gc context. + * + * \return \c GL_TRUE on success, or \c GL_FALSE on failure. + * + * \internal + * This function calls __DriverAPIRec::UnbindContext, and then decrements + * __DRIdrawableRec::refcount which must be non-zero for a successful + * return. + * + * While casting the opaque private pointers associated with the parameters + * into their respective real types it also assures they are not \c NULL. + */ +static int driUnbindContext(__DRIcontext *pcp) { - return (*screen->DriverAPI.AllocateBuffer)(screen, attachment, format, - width, height); -} + __DRIdrawable *pdp; + __DRIdrawable *prp; -static void -dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) -{ - (*screen->DriverAPI.ReleaseBuffer)(screen, buffer); -} + /* + ** Assume error checking is done properly in glXMakeCurrent before + ** calling driUnbindContext. + */ + if (pcp == NULL) + return GL_FALSE; -static int -dri2ConfigQueryb(__DRIscreen *screen, const char *var, GLboolean *val) -{ - if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) - return -1; + /* + ** Call driUnbindContext before checking for valid drawables + ** to handle surfaceless contexts properly. + */ + pcp->driScreenPriv->driver->UnbindContext(pcp); - *val = driQueryOptionb(&screen->optionCache, var); + pdp = pcp->driDrawablePriv; + prp = pcp->driReadablePriv; - return 0; -} + /* already unbound */ + if (!pdp && !prp) + return GL_TRUE; -static int -dri2ConfigQueryi(__DRIscreen *screen, const char *var, GLint *val) -{ - if (!driCheckOption(&screen->optionCache, var, DRI_INT) && - !driCheckOption(&screen->optionCache, var, DRI_ENUM)) - return -1; + assert(pdp); + if (pdp->refcount == 0) { + /* ERROR!!! */ + return GL_FALSE; + } - *val = driQueryOptioni(&screen->optionCache, var); + dri_put_drawable(pdp); - return 0; -} + if (prp != pdp) { + if (prp->refcount == 0) { + /* ERROR!!! */ + return GL_FALSE; + } -static int -dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) -{ - if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) - return -1; + dri_put_drawable(prp); + } - *val = driQueryOptionf(&screen->optionCache, var); + pcp->driDrawablePriv = NULL; + pcp->driReadablePriv = NULL; - return 0; + return GL_TRUE; } +/*@}*/ + static void dri_get_drawable(__DRIdrawable *pdp) { pdp->refcount++; } - + static void dri_put_drawable(__DRIdrawable *pdp) { - __DRIscreen *psp; - if (pdp) { pdp->refcount--; if (pdp->refcount) return; - psp = pdp->driScreenPriv; - (*psp->DriverAPI.DestroyBuffer)(pdp); - if (pdp->pClipRects && pdp->pClipRects != &pdp->dri2.clipRect) { - free(pdp->pClipRects); - pdp->pClipRects = NULL; - } - if (pdp->pBackClipRects && pdp->pClipRects != &pdp->dri2.clipRect) { - free(pdp->pBackClipRects); - pdp->pBackClipRects = NULL; - } + pdp->driScreenPriv->driver->DestroyBuffer(pdp); free(pdp); } } -static void -driDestroyDrawable(__DRIdrawable *pdp) -{ - dri_put_drawable(pdp); -} - -/*@}*/ - - -/*****************************************************************/ -/** \name Context handling functions */ -/*****************************************************************/ -/*@{*/ - -/** - * Destroy the per-context private information. - * - * \internal - * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls - * drmDestroyContext(), and finally frees \p contextPrivate. - */ -static void -driDestroyContext(__DRIcontext *pcp) -{ - if (pcp) { - (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp); - free(pcp); - } -} - - -/** - * Create the per-drawable private driver information. - * - * \param render_type Type of rendering target. \c GLX_RGBA is the only - * type likely to ever be supported for direct-rendering. - * \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. - * - * \internal - * This function allocates and fills a __DRIcontextRec structure. It - * performs some device independent initialization and passes all the - * relevent information to __DriverAPIRec::CreateContext to create the - * context. - * - */ -static __DRIcontext * -driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config, - int render_type, __DRIcontext *shared, - drm_context_t hwContext, void *data) +static __DRIdrawable * +driCreateNewDrawable(__DRIscreen *screen, + const __DRIconfig *config, + void *data) { - __DRIcontext *pcp; - void * const shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; + __DRIdrawable *pdraw; - pcp = malloc(sizeof *pcp); - if (!pcp) + pdraw = malloc(sizeof *pdraw); + if (!pdraw) return NULL; - pcp->driScreenPriv = psp; - pcp->driDrawablePriv = NULL; - pcp->loaderPrivate = data; - - pcp->dri2.draw_stamp = 0; - pcp->dri2.read_stamp = 0; + pdraw->loaderPrivate = data; - pcp->hHWContext = hwContext; + pdraw->driScreenPriv = screen; + pdraw->driContextPriv = NULL; + pdraw->refcount = 0; + pdraw->lastStamp = 0; + pdraw->w = 0; + pdraw->h = 0; - if ( !(*psp->DriverAPI.CreateContext)(API_OPENGL, - &config->modes, pcp, shareCtx) ) { - free(pcp); - return NULL; + dri_get_drawable(pdraw); + + if (!screen->driver->CreateBuffer(screen, pdraw, &config->modes, + GL_FALSE)) { + free(pdraw); + return NULL; } - return pcp; + pdraw->dri2.stamp = pdraw->lastStamp + 1; + + return pdraw; } -static unsigned int -dri2GetAPIMask(__DRIscreen *screen) +static void +driDestroyDrawable(__DRIdrawable *pdp) { - return screen->api_mask; + dri_put_drawable(pdp); } -static __DRIcontext * -dri2CreateNewContextForAPI(__DRIscreen *screen, int api, - const __DRIconfig *config, - __DRIcontext *shared, void *data) +static __DRIbuffer * +dri2AllocateBuffer(__DRIscreen *screen, + unsigned int attachment, unsigned int format, + int width, int height) { - __DRIcontext *context; - const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; - void *shareCtx = (shared != NULL) ? shared->driverPrivate : NULL; - gl_api mesa_api; - - if (!(screen->api_mask & (1 << api))) - return NULL; - - switch (api) { - case __DRI_API_OPENGL: - mesa_api = API_OPENGL; - break; - case __DRI_API_GLES: - mesa_api = API_OPENGLES; - break; - case __DRI_API_GLES2: - mesa_api = API_OPENGLES2; - break; - default: - return NULL; - } - - context = malloc(sizeof *context); - if (!context) - return NULL; - - context->driScreenPriv = screen; - context->driDrawablePriv = NULL; - context->loaderPrivate = data; - - if (!(*screen->DriverAPI.CreateContext)(mesa_api, modes, - context, shareCtx) ) { - free(context); - return NULL; - } - - return context; + return screen->driver->AllocateBuffer(screen, attachment, format, + width, height); } - -static __DRIcontext * -dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, - __DRIcontext *shared, void *data) +static void +dri2ReleaseBuffer(__DRIscreen *screen, __DRIbuffer *buffer) { - return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL, - config, shared, data); + screen->driver->ReleaseBuffer(screen, buffer); } + static int -driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask) +dri2ConfigQueryb(__DRIscreen *screen, const char *var, unsigned char *val) { - return GL_FALSE; -} - -/*@}*/ + if (!driCheckOption(&screen->optionCache, var, DRI_BOOL)) + return -1; + *val = driQueryOptionb(&screen->optionCache, var); -/*****************************************************************/ -/** \name Screen handling functions */ -/*****************************************************************/ -/*@{*/ + return 0; +} -/** - * Destroy the per-screen private information. - * - * \internal - * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls - * drmClose(), and finally frees \p screenPrivate. - */ -static void driDestroyScreen(__DRIscreen *psp) +static int +dri2ConfigQueryi(__DRIscreen *screen, const char *var, int *val) { - if (psp) { - /* No interaction with the X-server is possible at this point. This - * routine is called after XCloseDisplay, so there is no protocol - * stream open to the X-server anymore. - */ + if (!driCheckOption(&screen->optionCache, var, DRI_INT) && + !driCheckOption(&screen->optionCache, var, DRI_ENUM)) + return -1; - _mesa_destroy_shader_compiler(); + *val = driQueryOptioni(&screen->optionCache, var); - if (psp->DriverAPI.DestroyScreen) - (*psp->DriverAPI.DestroyScreen)(psp); + return 0; +} - if (!psp->dri2.enabled) { - (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX); - (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize); - (void)drmCloseOnce(psp->fd); - } else { - driDestroyOptionCache(&psp->optionCache); - driDestroyOptionInfo(&psp->optionInfo); - } +static int +dri2ConfigQueryf(__DRIscreen *screen, const char *var, float *val) +{ + if (!driCheckOption(&screen->optionCache, var, DRI_FLOAT)) + return -1; - free(psp); - } + *val = driQueryOptionf(&screen->optionCache, var); + + return 0; } -static void -setupLoaderExtensions(__DRIscreen *psp, - const __DRIextension **extensions) +static unsigned int +driGetAPIMask(__DRIscreen *screen) { - 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]; - if (strcmp(extensions[i]->name, __DRI_IMAGE_LOOKUP) == 0) - psp->dri2.image = (__DRIimageLookupExtension *) extensions[i]; - if (strcmp(extensions[i]->name, __DRI_USE_INVALIDATE) == 0) - psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; - } + return screen->api_mask; } /** - * 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 struct gl_config that the driver can support for windows or - * pbuffers. + * swrast swapbuffers entrypoint. * - * For legacy DRI. - * - * \param scrn Index of the screen - * \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. - * \param drm_version Version of the kernel DRM. - * \param frame_buffer Data describing the location and layout of the - * framebuffer. - * \param pSAREA Pointer to the SAREA. - * \param fd Device handle for the DRM. - * \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 name of this function is versioned, it is - * impossible for a loader that is too old to even load this driver. + * DRI2 implements this inside the loader with only flushes handled by the + * driver. */ -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) +static void +driSwapBuffers(__DRIdrawable *pdp) { - static const __DRIextension *emptyExtensionList[] = { NULL }; - __DRIscreen *psp; - - if (driDriverAPI.InitScreen == NULL) - return NULL; + assert(pdp->driScreenPriv->swrast_loader); - psp = calloc(1, sizeof *psp); - if (!psp) - return NULL; - - setupLoaderExtensions(psp, extensions); - - /* - ** NOT_DONE: This is used by the X server to detect when the client - ** has died while holding the drawable lock. The client sets the - ** drawable lock to this value. - */ - psp->drawLockID = 1; + pdp->driScreenPriv->driver->SwapBuffers(pdp); +} - psp->drm_version = *drm_version; - psp->ddx_version = *ddx_version; - psp->dri_version = *dri_version; +/** Core interface */ +const __DRIcoreExtension driCoreExtension = { + .base = { __DRI_CORE, 1 }, + + .createNewScreen = NULL, + .destroyScreen = driDestroyScreen, + .getExtensions = driGetExtensions, + .getConfigAttrib = driGetConfigAttrib, + .indexConfigAttrib = driIndexConfigAttrib, + .createNewDrawable = NULL, + .destroyDrawable = driDestroyDrawable, + .swapBuffers = driSwapBuffers, /* swrast */ + .createNewContext = driCreateNewContext, /* swrast */ + .copyContext = driCopyContext, + .destroyContext = driDestroyContext, + .bindContext = driBindContext, + .unbindContext = driUnbindContext +}; - psp->pSAREA = pSAREA; - psp->lock = (drmLock *) &psp->pSAREA->lock; +/** DRI2 interface */ +const __DRIdri2Extension driDRI2Extension = { + .base = { __DRI_DRI2, 4 }, + + .createNewScreen = dri2CreateNewScreen, + .createNewDrawable = driCreateNewDrawable, + .createNewContext = driCreateNewContext, + .getAPIMask = driGetAPIMask, + .createNewContextForAPI = driCreateNewContextForAPI, + .allocateBuffer = dri2AllocateBuffer, + .releaseBuffer = dri2ReleaseBuffer, + .createContextAttribs = driCreateContextAttribs, + .createNewScreen2 = driCreateNewScreen2, +}; - psp->pFB = frame_buffer->base; - psp->fbSize = frame_buffer->size; - psp->fbStride = frame_buffer->stride; - psp->fbWidth = frame_buffer->width; - psp->fbHeight = frame_buffer->height; - psp->devPrivSize = frame_buffer->dev_priv_size; - psp->pDevPriv = frame_buffer->dev_priv; - psp->fbBPP = psp->fbStride * 8 / frame_buffer->width; +const __DRIswrastExtension driSWRastExtension = { + .base = { __DRI_SWRAST, 4 }, - psp->extensions = emptyExtensionList; - psp->fd = fd; - psp->myNum = scrn; - psp->dri2.enabled = GL_FALSE; + .createNewScreen = driSWRastCreateNewScreen, + .createNewDrawable = driCreateNewDrawable, + .createNewContextForAPI = driCreateNewContextForAPI, + .createContextAttribs = driCreateContextAttribs, + .createNewScreen2 = driSWRastCreateNewScreen2, +}; - psp->DriverAPI = driDriverAPI; - psp->api_mask = (1 << __DRI_API_OPENGL); +const __DRI2configQueryExtension dri2ConfigQueryExtension = { + .base = { __DRI2_CONFIG_QUERY, 1 }, - *driver_modes = driDriverAPI.InitScreen(psp); - if (*driver_modes == NULL) { - free(psp); - return NULL; - } + .configQueryb = dri2ConfigQueryb, + .configQueryi = dri2ConfigQueryi, + .configQueryf = dri2ConfigQueryf, +}; - return psp; +void +dri2InvalidateDrawable(__DRIdrawable *drawable) +{ + drawable->dri2.stamp++; } /** - * DRI2 + * Check that the gl_framebuffer associated with dPriv is the right size. + * Resize the gl_framebuffer if needed. + * It's expected that the dPriv->driverPrivate member points to a + * gl_framebuffer object. */ -static __DRIscreen * -dri2CreateNewScreen(int scrn, int fd, - const __DRIextension **extensions, - const __DRIconfig ***driver_configs, void *data) -{ - static const __DRIextension *emptyExtensionList[] = { NULL }; - __DRIscreen *psp; - drmVersionPtr version; - - if (driDriverAPI.InitScreen2 == NULL) - return NULL; - - psp = calloc(1, 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; - - psp->DriverAPI = driDriverAPI; - psp->api_mask = (1 << __DRI_API_OPENGL); - *driver_configs = driDriverAPI.InitScreen2(psp); - if (*driver_configs == NULL) { - free(psp); - return NULL; - } - - psp->DriverAPI = driDriverAPI; - psp->loaderPrivate = data; - - driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, - __dri2NConfigOptions); - driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, - "dri2"); +void +driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) +{ + struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; + if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { + ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); + /* if the driver needs the hw lock for ResizeBuffers, the drawable + might have changed again by now */ + assert(fb->Width == dPriv->w); + assert(fb->Height == dPriv->h); + } +} - return psp; +uint32_t +driGLFormatToImageFormat(mesa_format format) +{ + switch (format) { + case MESA_FORMAT_B5G6R5_UNORM: + return __DRI_IMAGE_FORMAT_RGB565; + case MESA_FORMAT_B8G8R8X8_UNORM: + return __DRI_IMAGE_FORMAT_XRGB8888; + case MESA_FORMAT_B10G10R10A2_UNORM: + return __DRI_IMAGE_FORMAT_ARGB2101010; + case MESA_FORMAT_B10G10R10X2_UNORM: + return __DRI_IMAGE_FORMAT_XRGB2101010; + case MESA_FORMAT_B8G8R8A8_UNORM: + return __DRI_IMAGE_FORMAT_ARGB8888; + case MESA_FORMAT_R8G8B8A8_UNORM: + return __DRI_IMAGE_FORMAT_ABGR8888; + case MESA_FORMAT_R8G8B8X8_UNORM: + return __DRI_IMAGE_FORMAT_XBGR8888; + case MESA_FORMAT_R_UNORM8: + return __DRI_IMAGE_FORMAT_R8; + case MESA_FORMAT_R8G8_UNORM: + return __DRI_IMAGE_FORMAT_GR88; + case MESA_FORMAT_NONE: + return __DRI_IMAGE_FORMAT_NONE; + case MESA_FORMAT_B8G8R8A8_SRGB: + return __DRI_IMAGE_FORMAT_SARGB8; + default: + return 0; + } } -static const __DRIextension **driGetExtensions(__DRIscreen *psp) -{ - return psp->extensions; +mesa_format +driImageFormatToGLFormat(uint32_t image_format) +{ + switch (image_format) { + case __DRI_IMAGE_FORMAT_RGB565: + return MESA_FORMAT_B5G6R5_UNORM; + case __DRI_IMAGE_FORMAT_XRGB8888: + return MESA_FORMAT_B8G8R8X8_UNORM; + case __DRI_IMAGE_FORMAT_ARGB2101010: + return MESA_FORMAT_B10G10R10A2_UNORM; + case __DRI_IMAGE_FORMAT_XRGB2101010: + return MESA_FORMAT_B10G10R10X2_UNORM; + case __DRI_IMAGE_FORMAT_ARGB8888: + return MESA_FORMAT_B8G8R8A8_UNORM; + case __DRI_IMAGE_FORMAT_ABGR8888: + return MESA_FORMAT_R8G8B8A8_UNORM; + case __DRI_IMAGE_FORMAT_XBGR8888: + return MESA_FORMAT_R8G8B8X8_UNORM; + case __DRI_IMAGE_FORMAT_R8: + return MESA_FORMAT_R_UNORM8; + case __DRI_IMAGE_FORMAT_GR88: + return MESA_FORMAT_R8G8_UNORM; + case __DRI_IMAGE_FORMAT_SARGB8: + return MESA_FORMAT_B8G8R8A8_SRGB; + case __DRI_IMAGE_FORMAT_NONE: + return MESA_FORMAT_NONE; + default: + return MESA_FORMAT_NONE; + } } -/** Core interface */ -const __DRIcoreExtension driCoreExtension = { - { __DRI_CORE, __DRI_CORE_VERSION }, - NULL, - driDestroyScreen, - driGetExtensions, - driGetConfigAttrib, - driIndexConfigAttrib, - NULL, - driDestroyDrawable, - driSwapBuffers, - NULL, - driCopyContext, - driDestroyContext, - driBindContext, - driUnbindContext -}; +/** Image driver interface */ +const __DRIimageDriverExtension driImageDriverExtension = { + .base = { __DRI_IMAGE_DRIVER, 1 }, -/** Legacy DRI interface */ -const __DRIlegacyExtension driLegacyExtension = { - { __DRI_LEGACY, __DRI_LEGACY_VERSION }, - driCreateNewScreen, - driCreateNewDrawable, - driCreateNewContext, + .createNewScreen2 = driCreateNewScreen2, + .createNewDrawable = driCreateNewDrawable, + .getAPIMask = driGetAPIMask, + .createContextAttribs = driCreateContextAttribs, }; -/** DRI2 interface */ -const __DRIdri2Extension driDRI2Extension = { - { __DRI_DRI2, __DRI_DRI2_VERSION }, - dri2CreateNewScreen, - dri2CreateNewDrawable, - dri2CreateNewContext, - dri2GetAPIMask, - dri2CreateNewContextForAPI, - dri2AllocateBuffer, - dri2ReleaseBuffer -}; - -const __DRI2configQueryExtension dri2ConfigQueryExtension = { - { __DRI2_CONFIG_QUERY, __DRI2_CONFIG_QUERY_VERSION }, - dri2ConfigQueryb, - dri2ConfigQueryi, - dri2ConfigQueryf, -}; - -/** - * Calculate amount of swap interval used between GLX buffer swaps. - * - * The usage value, on the range [0,max], is the fraction of total swap - * interval time used between GLX buffer swaps is calculated. - * - * \f$p = t_d / (i * t_r)\f$ - * - * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the - * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time - * required for a single vertical refresh period (as returned by \c - * glXGetMscRateOML). - * - * See the documentation for the GLX_MESA_swap_frame_usage extension for more - * details. - * - * \param dPriv Pointer to the private drawable structure. - * \return If less than a single swap interval time period was required - * between GLX buffer swaps, a number greater than 0 and less than - * 1.0 is returned. If exactly one swap interval time period is - * required, 1.0 is returned, and if more than one is required then - * a number greater than 1.0 will be returned. - * - * \sa glXSwapIntervalSGI glXGetMscRateOML - * - * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it - * be possible to cache the sync rate? - */ -float -driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust, - int64_t current_ust ) +/* swrast copy sub buffer entrypoint. */ +static void driCopySubBuffer(__DRIdrawable *pdp, int x, int y, + int w, int h) { - int32_t n; - int32_t d; - int interval; - float usage = 1.0; - __DRIscreen *psp = dPriv->driScreenPriv; - - if ( (*psp->systemTime->getMSCRate)(dPriv, &n, &d, dPriv->loaderPrivate) ) { - interval = (dPriv->swap_interval != 0) ? dPriv->swap_interval : 1; - - - /* We want to calculate - * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get - * current_UST by calling __glXGetUST. last_swap_UST is stored in - * dPriv->swap_ust. interval has already been calculated. - * - * The only tricky part is us_per_refresh. us_per_refresh is - * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it - * around and say us_per_refresh = 1000000 * d / n. Since this goes in - * the denominator of the final calculation, we calculate - * (interval * 1000000 * d) and move n into the numerator. - */ - - usage = (current_ust - last_swap_ust); - usage *= n; - usage /= (interval * d); - usage /= 1000000.0; - } - - return usage; -} + assert(pdp->driScreenPriv->swrast_loader); -void -dri2InvalidateDrawable(__DRIdrawable *drawable) -{ - drawable->dri2.stamp++; + pdp->driScreenPriv->driver->CopySubBuffer(pdp, x, y, w, h); } -/*@}*/ +/* for swrast only */ +const __DRIcopySubBufferExtension driCopySubBufferExtension = { + .base = { __DRI_COPY_SUB_BUFFER, 1 }, + + .copySubBuffer = driCopySubBuffer, +};