/***************************************************************************** * driDrawable.c: Lean Version of DRI utilities. * * Copyright (c) 2005 Thomas Hellstrom. 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, sublicense, * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHOR(S) OR COPYRIGHT HOLDER(S) 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. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "xf86drm.h" #include "drm.h" #include "xf86dri.h" #include "drm_sarea.h" #include "driDrawable.h" static unsigned drawStamp(volatile drm_sarea_t *pSarea, int index) { return pSarea->drawableTable[index].stamp; } int getDRIDrawableInfoLocked(void *drawHash, Display *display, int screen, Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext, drmAddress sarea, Bool updateInfo, drawableInfo **info, unsigned long infoSize) { drawableInfo *drawInfo; void *res; drm_drawable_t drmDraw=0; volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea; drm_clip_rect_t *clipFront, *clipBack; int ret; if (drmHashLookup(drawHash, (unsigned long) draw, &res)) { /* * The drawable is unknown to us. Create it and put it in the * hash table. */ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) { DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); return 1; } DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); drawInfo = (drawableInfo *) malloc(infoSize); if (!drawInfo) return 1; drawInfo->drmDraw = drmDraw; drawInfo->stamp = 0; drawInfo->clipFront = 0; drawInfo->clipBack = 0; drmHashInsert( drawHash, (unsigned long) draw, drawInfo); } else { drawInfo = res; } drawInfo->touched = FALSE; while (!drawInfo->clipFront || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { /* * The drawable has been touched since we last got info about it. * obtain new info from the X server. */ drawInfo->touched = TRUE; if (updateInfo || !drawInfo->clipFront) { DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); ret = uniDRIGetDrawableInfo(display, screen, draw, &drawInfo->index, &drawInfo->stamp, &drawInfo->x, &drawInfo->y, &drawInfo->w, &drawInfo->h, &drawInfo->numClipFront, &clipFront, &drawInfo->backX, &drawInfo->backY, &drawInfo->numClipBack, &clipBack); DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext); /* * Error. Probably the drawable is destroyed. Return error and old values. */ if (!ret) { free(drawInfo); drawInfo = NULL; drmHashDelete(drawHash, (unsigned long) draw); DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); uniDRIDestroyDrawable( display, screen, draw); DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); return 1; } if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { /* * The info is already outdated. Sigh. Have another go. */ XFree(clipFront); XFree(clipBack); continue; } if (drawInfo->clipFront) XFree(drawInfo->clipFront); drawInfo->clipFront = clipFront; if (drawInfo->clipBack) XFree(drawInfo->clipBack); drawInfo->clipBack = clipBack; } else { if (!drawInfo->clipFront) drawInfo->clipFront = (drm_clip_rect_t *) ~0UL; drawInfo->stamp = drawStamp(pSarea, drawInfo->index); } } *info = drawInfo; return 0; } void driDestroyHashContents(void *drawHash) { unsigned long key; void *content; drawableInfo *drawInfo; if (drmHashFirst(drawHash, &key, &content) < 1) return; drawInfo = (drawableInfo *) content; if (drawInfo->clipBack) XFree(drawInfo->clipBack); if (drawInfo->clipFront) XFree(drawInfo->clipFront); free(drawInfo); while(drmHashNext(drawHash, &key, &content) == 1) { drawInfo = (drawableInfo *) content; if (drawInfo->clipBack) XFree(drawInfo->clipBack); if (drawInfo->clipFront) XFree(drawInfo->clipFront); free(drawInfo); } return ; }