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