⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dri_util.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $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. * * This module acts as glue between GLX and the actual hardware driver.  A DRI * driver doesn't really \e have to use any of this - it's optional.  But, some * useful stuff is done here that otherwise would have to be duplicated in most * drivers. *  * Basically, these utility functions take care of some of the dirty details of * screen initialization, context creation, context binding, DRM setup, etc. * * These functions are compiled into each DRI driver so libGL.so knows nothing * about them. */#include <assert.h>#include <stdarg.h>#include <unistd.h>#include <sys/mman.h>#include <stdio.h>#ifndef MAP_FAILED#define MAP_FAILED ((void *)-1)#endif#include "imports.h"#define None 0#include "dri_util.h"#include "drm_sarea.h"#include "utils.h"#ifndef GLX_OML_sync_controltypedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);#endif/** * 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};/** * Print message to \c stderr if the \c LIBGL_DEBUG environment variable * is set.  *  * Is called from the drivers. *  * \param f \c printf like format string. */void__driUtilMessage(const char *f, ...){    va_list args;    if (getenv("LIBGL_DEBUG")) {        fprintf(stderr, "libGL error: \n");        va_start(args, f);        vfprintf(stderr, f, args);        va_end(args);        fprintf(stderr, "\n");    }}GLintdriIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ){   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;   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);}/*****************************************************************//** \name Context (un)binding functions                          *//*****************************************************************//*@{*//** * 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 * __DRIdrawablePrivateRec::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){    __DRIscreen *psp;    __DRIdrawable *pdp;    __DRIdrawable *prp;    /*    ** Assume error checking is done properly in glXMakeCurrent before    ** calling driUnbindContext.    */    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;    }    pdp->refcount--;    if (prp != pdp) {        if (prp->refcount == 0) {	    /* ERROR!!! */	    return GL_FALSE;	}	prp->refcount--;    }    /* 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)     */#if 0    /* Unbind the drawable */    pcp->driDrawablePriv = NULL;    pdp->driContextPriv = &psp->dummyContextPriv;#endif    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 int driBindContext(__DRIcontext *pcp,			  __DRIdrawable *pdp,			  __DRIdrawable *prp){    __DRIscreenPrivate *psp = pcp->driScreenPriv;    /*    ** Assume error checking is done properly in glXMakeCurrent before    ** calling driBindContext.    */    if (pcp == NULL || pdp == None || prp == None)	return GL_FALSE;    /* Bind the drawable to the context */    pcp->driDrawablePriv = pdp;    pcp->driReadablePriv = prp;    pdp->driContextPriv = pcp;    pdp->refcount++;    if ( pdp != prp ) {	prp->refcount++;    }    /*    ** 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) {       __driParseEvents(pcp, pdp);       __driParseEvents(pcp, prp);    } else {	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 */    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);    return GL_TRUE;}/*@}*//*****************************************************************//** \name Drawable handling functions                            *//*****************************************************************//*@{*//** * Update private drawable information. * * \param pdp pointer to the private drawable information to update. *  * This function basically updates the __DRIdrawablePrivate 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. */void__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp){    __DRIscreenPrivate *psp = pdp->driScreenPriv;    __DRIcontextPrivate *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 (pdp->pClipRects) {	_mesa_free(pdp->pClipRects); 	pdp->pClipRects = NULL;    }    if (pdp->pBackClipRects) {	_mesa_free(pdp->pBackClipRects); 	pdp->pBackClipRects = NULL;    }    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;    }    else       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);}int__driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp){    __DRIscreenPrivate *psp = pdp->driScreenPriv;    __DRIDrawableConfigEvent *dc, *last_dc;    __DRIBufferAttachEvent *ba, *last_ba;    unsigned int tail, mask, *p, end, total, size, changed;    unsigned char *data;    size_t rect_size;    /* Check for wraparound. */    if (pcp && psp->dri2.buffer->prealloc - pdp->dri2.tail > psp->dri2.buffer->size) {       /* If prealloc overlaps into what we just parsed, the	* server overwrote it and we have to reset our tail	* pointer. */	DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext);	(*psp->dri2.loader->reemitDrawableInfo)(pdp, &pdp->dri2.tail,						pdp->loaderPrivate);	DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext);    }    total = psp->dri2.buffer->head - pdp->dri2.tail;    mask = psp->dri2.buffer->size - 1;    end = psp->dri2.buffer->head;    data = psp->dri2.buffer->data;    changed = 0;    last_dc = NULL;    last_ba = NULL;    for (tail = pdp->dri2.tail; tail != end; tail += size) {       p = (unsigned int *) (data + (tail & mask));       size = DRI2_EVENT_SIZE(*p);       if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {	  /* illegal data, bail out. */	  fprintf(stderr, "illegal event size\n");	  break;       }       switch (DRI2_EVENT_TYPE(*p)) {       case DRI2_EVENT_DRAWABLE_CONFIG:	  dc = (__DRIDrawableConfigEvent *) p;	  if (dc->drawable == pdp->dri2.drawable_id)	     last_dc = dc;	  break;       case DRI2_EVENT_BUFFER_ATTACH:	  ba = (__DRIBufferAttachEvent *) p;	  if (ba->drawable == pdp->dri2.drawable_id && 	      ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT)	     last_ba = ba;	  break;       }    }	      if (last_dc) {       if (pdp->w != last_dc->width || pdp->h != last_dc->height)	  changed = 1;       pdp->x = last_dc->x;       pdp->y = last_dc->y;       pdp->w = last_dc->width;       pdp->h = last_dc->height;       pdp->backX = 0;       pdp->backY = 0;       pdp->numBackClipRects = 1;       pdp->pBackClipRects[0].x1 = 0;       pdp->pBackClipRects[0].y1 = 0;       pdp->pBackClipRects[0].x2 = pdp->w;       pdp->pBackClipRects[0].y2 = pdp->h;       pdp->numClipRects = last_dc->num_rects;       _mesa_free(pdp->pClipRects);       rect_size = last_dc->num_rects * sizeof last_dc->rects[0];       pdp->pClipRects = _mesa_malloc(rect_size);       memcpy(pdp->pClipRects, last_dc->rects, rect_size);    }    /* We only care about the most recent drawable config. */    if (last_dc && changed)       (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);    /* Front buffer attachments are special, they typically mean that     * we're rendering to a redirected window (or a child window of a     * redirected window) and that it got resized.  Resizing the root     * window on randr events is a special case of this.  Other causes     * may be a window transitioning between redirected and     * non-redirected, or a window getting reparented between parents     * with different window pixmaps (eg two redirected windows).     * These events are special in that the X server allocates the

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -