driDrawable.c revision 90b17f1b
1/*****************************************************************************
2 * driDrawable.c: Lean Version of DRI utilities.
3 *
4 * Copyright (c) 2005 Thomas Hellstrom. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHOR(S) OR COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <X11/Xlibint.h>
26#include <X11/Xutil.h>
27#include "xf86drm.h"
28#include "drm.h"
29#include "xf86dri.h"
30#include "drm_sarea.h"
31#include "driDrawable.h"
32
33static unsigned
34drawStamp(volatile drm_sarea_t * pSarea, int index)
35{
36    return pSarea->drawableTable[index].stamp;
37}
38
39int
40getDRIDrawableInfoLocked(void *drawHash, Display * display, int screen,
41    Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext,
42    drmAddress sarea, Bool updateInfo, drawableInfo ** info,
43    unsigned long infoSize)
44{
45    drawableInfo *drawInfo;
46    void *res;
47    drm_drawable_t drmDraw = 0;
48    volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea;
49    drm_clip_rect_t *clipFront, *clipBack;
50
51    int ret;
52
53    if (drmHashLookup(drawHash, (unsigned long)draw, &res)) {
54
55	/*
56	 * The drawable is unknown to us. Create it and put it in the
57	 * hash table.
58	 */
59
60	DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
61	if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) {
62	    DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
63	    return 1;
64	}
65	DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
66
67	drawInfo = (drawableInfo *) malloc(infoSize);
68	if (!drawInfo)
69	    return 1;
70
71	drawInfo->drmDraw = drmDraw;
72	drawInfo->stamp = 0;
73	drawInfo->clipFront = 0;
74	drawInfo->clipBack = 0;
75
76	drmHashInsert(drawHash, (unsigned long)draw, drawInfo);
77
78    } else {
79	drawInfo = res;
80    }
81
82    drawInfo->touched = FALSE;
83    while (!drawInfo->clipFront
84	|| drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
85
86	/*
87	 * The drawable has been touched since we last got info about it.
88	 * obtain new info from the X server.
89	 */
90
91	drawInfo->touched = TRUE;
92
93	if (updateInfo || !drawInfo->clipFront) {
94	    DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
95
96	    ret = uniDRIGetDrawableInfo(display, screen, draw,
97		&drawInfo->index, &drawInfo->stamp, &drawInfo->x,
98		&drawInfo->y, &drawInfo->w, &drawInfo->h,
99		&drawInfo->numClipFront, &clipFront,
100		&drawInfo->backX, &drawInfo->backY,
101		&drawInfo->numClipBack, &clipBack);
102
103	    DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext);
104
105	    /*
106	     * Error. Probably the drawable is destroyed. Return error and old values.
107	     */
108
109	    if (!ret) {
110		free(drawInfo);
111		drawInfo = NULL;
112		drmHashDelete(drawHash, (unsigned long)draw);
113
114		DRM_UNLOCK(drmFD, &pSarea->lock, drmContext);
115		uniDRIDestroyDrawable(display, screen, draw);
116		DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags);
117
118		return 1;
119	    }
120
121	    if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) {
122
123		/*
124		 * The info is already outdated. Sigh. Have another go.
125		 */
126
127		XFree(clipFront);
128		XFree(clipBack);
129		continue;
130	    }
131
132	    if (drawInfo->clipFront)
133		XFree(drawInfo->clipFront);
134	    drawInfo->clipFront = clipFront;
135	    if (drawInfo->clipBack)
136		XFree(drawInfo->clipBack);
137	    drawInfo->clipBack = clipBack;
138	} else {
139	    if (!drawInfo->clipFront)
140		drawInfo->clipFront = (drm_clip_rect_t *) ~ 0UL;
141	    drawInfo->stamp = drawStamp(pSarea, drawInfo->index);
142	}
143    }
144    *info = drawInfo;
145    return 0;
146}
147
148void
149driDestroyHashContents(void *drawHash)
150{
151    unsigned long key;
152    void *content;
153    drawableInfo *drawInfo;
154
155    if (drmHashFirst(drawHash, &key, &content) < 1)
156	return;
157    drawInfo = (drawableInfo *) content;
158    if (drawInfo->clipBack)
159	XFree(drawInfo->clipBack);
160    if (drawInfo->clipFront)
161	XFree(drawInfo->clipFront);
162    free(drawInfo);
163    while (drmHashNext(drawHash, &key, &content) == 1) {
164	drawInfo = (drawableInfo *) content;
165	if (drawInfo->clipBack)
166	    XFree(drawInfo->clipBack);
167	if (drawInfo->clipFront)
168	    XFree(drawInfo->clipFront);
169	free(drawInfo);
170    }
171
172    return;
173}
174