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
33 static unsigned
drawStamp(volatile drm_sarea_t * pSarea,int index)34 drawStamp(volatile drm_sarea_t * pSarea, int index)
35 {
36 return pSarea->drawableTable[index].stamp;
37 }
38
39 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)40 getDRIDrawableInfoLocked(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
148 void
driDestroyHashContents(void * drawHash)149 driDestroyHashContents(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