190b17f1bSmrg/***************************************************************************** 290b17f1bSmrg * driDrawable.c: Lean Version of DRI utilities. 390b17f1bSmrg * 490b17f1bSmrg * Copyright (c) 2005 Thomas Hellstrom. All rights reserved. 590b17f1bSmrg * 690b17f1bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 790b17f1bSmrg * copy of this software and associated documentation files (the "Software"), 890b17f1bSmrg * to deal in the Software without restriction, including without limitation 990b17f1bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1090b17f1bSmrg * and/or sell copies of the Software, and to permit persons to whom the 1190b17f1bSmrg * Software is furnished to do so, subject to the following conditions: 1290b17f1bSmrg * 1390b17f1bSmrg * The above copyright notice and this permission notice shall be included in 1490b17f1bSmrg * all copies or substantial portions of the Software. 1590b17f1bSmrg * 1690b17f1bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1790b17f1bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1890b17f1bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1990b17f1bSmrg * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2090b17f1bSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2190b17f1bSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2290b17f1bSmrg * DEALINGS IN THE SOFTWARE. 2390b17f1bSmrg */ 2490b17f1bSmrg 2590b17f1bSmrg#include <X11/Xlibint.h> 2690b17f1bSmrg#include <X11/Xutil.h> 2790b17f1bSmrg#include "xf86drm.h" 2890b17f1bSmrg#include "drm.h" 2990b17f1bSmrg#include "xf86dri.h" 3090b17f1bSmrg#include "drm_sarea.h" 3190b17f1bSmrg#include "driDrawable.h" 3290b17f1bSmrg 3390b17f1bSmrgstatic unsigned 3490b17f1bSmrgdrawStamp(volatile drm_sarea_t * pSarea, int index) 3590b17f1bSmrg{ 3690b17f1bSmrg return pSarea->drawableTable[index].stamp; 3790b17f1bSmrg} 3890b17f1bSmrg 3990b17f1bSmrgint 4090b17f1bSmrggetDRIDrawableInfoLocked(void *drawHash, Display * display, int screen, 4190b17f1bSmrg Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext, 4290b17f1bSmrg drmAddress sarea, Bool updateInfo, drawableInfo ** info, 4390b17f1bSmrg unsigned long infoSize) 4490b17f1bSmrg{ 4590b17f1bSmrg drawableInfo *drawInfo; 4690b17f1bSmrg void *res; 4790b17f1bSmrg drm_drawable_t drmDraw = 0; 4890b17f1bSmrg volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea; 4990b17f1bSmrg drm_clip_rect_t *clipFront, *clipBack; 5090b17f1bSmrg 5190b17f1bSmrg int ret; 5290b17f1bSmrg 5390b17f1bSmrg if (drmHashLookup(drawHash, (unsigned long)draw, &res)) { 5490b17f1bSmrg 5590b17f1bSmrg /* 5690b17f1bSmrg * The drawable is unknown to us. Create it and put it in the 5790b17f1bSmrg * hash table. 5890b17f1bSmrg */ 5990b17f1bSmrg 6090b17f1bSmrg DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); 6190b17f1bSmrg if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) { 6290b17f1bSmrg DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); 6390b17f1bSmrg return 1; 6490b17f1bSmrg } 6590b17f1bSmrg DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); 6690b17f1bSmrg 6790b17f1bSmrg drawInfo = (drawableInfo *) malloc(infoSize); 6890b17f1bSmrg if (!drawInfo) 6990b17f1bSmrg return 1; 7090b17f1bSmrg 7190b17f1bSmrg drawInfo->drmDraw = drmDraw; 7290b17f1bSmrg drawInfo->stamp = 0; 7390b17f1bSmrg drawInfo->clipFront = 0; 7490b17f1bSmrg drawInfo->clipBack = 0; 7590b17f1bSmrg 7690b17f1bSmrg drmHashInsert(drawHash, (unsigned long)draw, drawInfo); 7790b17f1bSmrg 7890b17f1bSmrg } else { 7990b17f1bSmrg drawInfo = res; 8090b17f1bSmrg } 8190b17f1bSmrg 8290b17f1bSmrg drawInfo->touched = FALSE; 8390b17f1bSmrg while (!drawInfo->clipFront 8490b17f1bSmrg || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { 8590b17f1bSmrg 8690b17f1bSmrg /* 8790b17f1bSmrg * The drawable has been touched since we last got info about it. 8890b17f1bSmrg * obtain new info from the X server. 8990b17f1bSmrg */ 9090b17f1bSmrg 9190b17f1bSmrg drawInfo->touched = TRUE; 9290b17f1bSmrg 9390b17f1bSmrg if (updateInfo || !drawInfo->clipFront) { 9490b17f1bSmrg DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); 9590b17f1bSmrg 9690b17f1bSmrg ret = uniDRIGetDrawableInfo(display, screen, draw, 9790b17f1bSmrg &drawInfo->index, &drawInfo->stamp, &drawInfo->x, 9890b17f1bSmrg &drawInfo->y, &drawInfo->w, &drawInfo->h, 9990b17f1bSmrg &drawInfo->numClipFront, &clipFront, 10090b17f1bSmrg &drawInfo->backX, &drawInfo->backY, 10190b17f1bSmrg &drawInfo->numClipBack, &clipBack); 10290b17f1bSmrg 10390b17f1bSmrg DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext); 10490b17f1bSmrg 10590b17f1bSmrg /* 10690b17f1bSmrg * Error. Probably the drawable is destroyed. Return error and old values. 10790b17f1bSmrg */ 10890b17f1bSmrg 10990b17f1bSmrg if (!ret) { 11090b17f1bSmrg free(drawInfo); 11190b17f1bSmrg drawInfo = NULL; 11290b17f1bSmrg drmHashDelete(drawHash, (unsigned long)draw); 11390b17f1bSmrg 11490b17f1bSmrg DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); 11590b17f1bSmrg uniDRIDestroyDrawable(display, screen, draw); 11690b17f1bSmrg DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); 11790b17f1bSmrg 11890b17f1bSmrg return 1; 11990b17f1bSmrg } 12090b17f1bSmrg 12190b17f1bSmrg if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { 12290b17f1bSmrg 12390b17f1bSmrg /* 12490b17f1bSmrg * The info is already outdated. Sigh. Have another go. 12590b17f1bSmrg */ 12690b17f1bSmrg 12790b17f1bSmrg XFree(clipFront); 12890b17f1bSmrg XFree(clipBack); 12990b17f1bSmrg continue; 13090b17f1bSmrg } 13190b17f1bSmrg 13290b17f1bSmrg if (drawInfo->clipFront) 13390b17f1bSmrg XFree(drawInfo->clipFront); 13490b17f1bSmrg drawInfo->clipFront = clipFront; 13590b17f1bSmrg if (drawInfo->clipBack) 13690b17f1bSmrg XFree(drawInfo->clipBack); 13790b17f1bSmrg drawInfo->clipBack = clipBack; 13890b17f1bSmrg } else { 13990b17f1bSmrg if (!drawInfo->clipFront) 14090b17f1bSmrg drawInfo->clipFront = (drm_clip_rect_t *) ~ 0UL; 14190b17f1bSmrg drawInfo->stamp = drawStamp(pSarea, drawInfo->index); 14290b17f1bSmrg } 14390b17f1bSmrg } 14490b17f1bSmrg *info = drawInfo; 14590b17f1bSmrg return 0; 14690b17f1bSmrg} 14790b17f1bSmrg 14890b17f1bSmrgvoid 14990b17f1bSmrgdriDestroyHashContents(void *drawHash) 15090b17f1bSmrg{ 15190b17f1bSmrg unsigned long key; 15290b17f1bSmrg void *content; 15390b17f1bSmrg drawableInfo *drawInfo; 15490b17f1bSmrg 15590b17f1bSmrg if (drmHashFirst(drawHash, &key, &content) < 1) 15690b17f1bSmrg return; 15790b17f1bSmrg drawInfo = (drawableInfo *) content; 15890b17f1bSmrg if (drawInfo->clipBack) 15990b17f1bSmrg XFree(drawInfo->clipBack); 16090b17f1bSmrg if (drawInfo->clipFront) 16190b17f1bSmrg XFree(drawInfo->clipFront); 16290b17f1bSmrg free(drawInfo); 16390b17f1bSmrg while (drmHashNext(drawHash, &key, &content) == 1) { 16490b17f1bSmrg drawInfo = (drawableInfo *) content; 16590b17f1bSmrg if (drawInfo->clipBack) 16690b17f1bSmrg XFree(drawInfo->clipBack); 16790b17f1bSmrg if (drawInfo->clipFront) 16890b17f1bSmrg XFree(drawInfo->clipFront); 16990b17f1bSmrg free(drawInfo); 17090b17f1bSmrg } 17190b17f1bSmrg 17290b17f1bSmrg return; 17390b17f1bSmrg} 174