Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | ||
3 | Copyright 1993, 1998 The Open Group | |
4 | ||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |
6 | documentation for any purpose is hereby granted without fee, provided that | |
7 | the above copyright notice appear in all copies and that both that | |
8 | copyright notice and this permission notice appear in supporting | |
9 | documentation. | |
10 | ||
11 | The above copyright notice and this permission notice shall be included | |
12 | in all copies or substantial portions of the Software. | |
13 | ||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
17 | IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
20 | OTHER DEALINGS IN THE SOFTWARE. | |
21 | ||
22 | Except as contained in this notice, the name of The Open Group shall | |
23 | not be used in advertising or otherwise to promote the sale, use or | |
24 | other dealings in this Software without prior written authorization | |
25 | from The Open Group. | |
26 | ||
27 | */ | |
28 | ||
29 | #ifdef HAVE_DIX_CONFIG_H | |
30 | #include <dix-config.h> | |
31 | #endif | |
32 | ||
33 | #include <X11/X.h> | |
34 | #include "scrnintstr.h" | |
35 | #include "misc.h" | |
36 | #include "os.h" | |
37 | #include "windowstr.h" | |
38 | #include "resource.h" | |
39 | #include "dixstruct.h" | |
40 | #include "gcstruct.h" | |
41 | #include "servermd.h" | |
42 | #include "site.h" | |
43 | ||
44 | /* | |
45 | * Scratch pixmap management and device independent pixmap allocation | |
46 | * function. | |
47 | */ | |
48 | ||
49 | /* callable by ddx */ | |
50 | PixmapPtr | |
51 | GetScratchPixmapHeader(ScreenPtr pScreen, int width, int height, int depth, | |
52 | int bitsPerPixel, int devKind, pointer pPixData) | |
53 | { | |
54 | PixmapPtr pPixmap = pScreen->pScratchPixmap; | |
55 | ||
56 | if (pPixmap) | |
57 | pScreen->pScratchPixmap = NULL; | |
58 | else | |
59 | /* width and height of 0 means don't allocate any pixmap data */ | |
60 | pPixmap = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, 0); | |
61 | ||
62 | if (pPixmap) { | |
63 | if ((*pScreen->ModifyPixmapHeader) (pPixmap, width, height, depth, | |
64 | bitsPerPixel, devKind, pPixData)) | |
65 | return pPixmap; | |
66 | (*pScreen->DestroyPixmap) (pPixmap); | |
67 | } | |
68 | return NullPixmap; | |
69 | } | |
70 | ||
71 | /* callable by ddx */ | |
72 | void | |
73 | FreeScratchPixmapHeader(PixmapPtr pPixmap) | |
74 | { | |
75 | if (pPixmap) { | |
76 | ScreenPtr pScreen = pPixmap->drawable.pScreen; | |
77 | ||
78 | pPixmap->devPrivate.ptr = NULL; /* lest ddx chases bad ptr */ | |
79 | if (pScreen->pScratchPixmap) | |
80 | (*pScreen->DestroyPixmap) (pPixmap); | |
81 | else | |
82 | pScreen->pScratchPixmap = pPixmap; | |
83 | } | |
84 | } | |
85 | ||
86 | Bool | |
87 | CreateScratchPixmapsForScreen(ScreenPtr pScreen) | |
88 | { | |
89 | unsigned int pixmap_size; | |
90 | ||
91 | pixmap_size = sizeof(PixmapRec) + dixScreenSpecificPrivatesSize(pScreen, PRIVATE_PIXMAP); | |
92 | pScreen->totalPixmapSize = | |
93 | BitmapBytePad(pixmap_size * 8); | |
94 | ||
95 | /* let it be created on first use */ | |
96 | pScreen->pScratchPixmap = NULL; | |
97 | return TRUE; | |
98 | } | |
99 | ||
100 | void | |
101 | FreeScratchPixmapsForScreen(ScreenPtr pScreen) | |
102 | { | |
103 | FreeScratchPixmapHeader(pScreen->pScratchPixmap); | |
104 | } | |
105 | ||
106 | /* callable by ddx */ | |
107 | PixmapPtr | |
108 | AllocatePixmap(ScreenPtr pScreen, int pixDataSize) | |
109 | { | |
110 | PixmapPtr pPixmap; | |
111 | ||
112 | assert(pScreen->totalPixmapSize > 0); | |
113 | ||
114 | if (pScreen->totalPixmapSize > ((size_t) - 1) - pixDataSize) | |
115 | return NullPixmap; | |
116 | ||
117 | pPixmap = malloc(pScreen->totalPixmapSize + pixDataSize); | |
118 | if (!pPixmap) | |
119 | return NullPixmap; | |
120 | ||
121 | dixInitScreenPrivates(pScreen, pPixmap, pPixmap + 1, PRIVATE_PIXMAP); | |
122 | return pPixmap; | |
123 | } | |
124 | ||
125 | /* callable by ddx */ | |
126 | void | |
127 | FreePixmap(PixmapPtr pPixmap) | |
128 | { | |
129 | dixFiniPrivates(pPixmap, PRIVATE_PIXMAP); | |
130 | free(pPixmap); | |
131 | } | |
132 | ||
133 | PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave) | |
134 | { | |
135 | PixmapPtr spix; | |
136 | int ret; | |
137 | void *handle; | |
138 | ScreenPtr master = pixmap->drawable.pScreen; | |
139 | int depth = pixmap->drawable.depth; | |
140 | ||
141 | ret = master->SharePixmapBacking(pixmap, slave, &handle); | |
142 | if (ret == FALSE) | |
143 | return NULL; | |
144 | ||
145 | spix = slave->CreatePixmap(slave, 0, 0, depth, | |
146 | CREATE_PIXMAP_USAGE_SHARED); | |
147 | slave->ModifyPixmapHeader(spix, pixmap->drawable.width, | |
148 | pixmap->drawable.height, depth, 0, | |
149 | pixmap->devKind, NULL); | |
150 | ||
151 | /* have the slave pixmap take a reference on the master pixmap | |
152 | later we destroy them both at the same time */ | |
153 | pixmap->refcnt++; | |
154 | ||
155 | spix->master_pixmap = pixmap; | |
156 | ||
157 | ret = slave->SetSharedPixmapBacking(spix, handle); | |
158 | if (ret == FALSE) { | |
159 | slave->DestroyPixmap(spix); | |
160 | return NULL; | |
161 | } | |
162 | ||
163 | return spix; | |
164 | } | |
165 | ||
166 | Bool | |
167 | PixmapStartDirtyTracking(PixmapPtr src, | |
168 | PixmapPtr slave_dst, | |
169 | int x, int y) | |
170 | { | |
171 | ScreenPtr screen = src->drawable.pScreen; | |
172 | PixmapDirtyUpdatePtr dirty_update; | |
173 | ||
174 | dirty_update = calloc(1, sizeof(PixmapDirtyUpdateRec)); | |
175 | if (!dirty_update) | |
176 | return FALSE; | |
177 | ||
178 | dirty_update->src = src; | |
179 | dirty_update->slave_dst = slave_dst; | |
180 | dirty_update->x = x; | |
181 | dirty_update->y = y; | |
182 | ||
183 | dirty_update->damage = DamageCreate(NULL, NULL, | |
184 | DamageReportNone, | |
185 | TRUE, src->drawable.pScreen, | |
186 | src->drawable.pScreen); | |
187 | if (!dirty_update->damage) { | |
188 | free(dirty_update); | |
189 | return FALSE; | |
190 | } | |
191 | ||
192 | DamageRegister(&src->drawable, dirty_update->damage); | |
193 | xorg_list_add(&dirty_update->ent, &screen->pixmap_dirty_list); | |
194 | return TRUE; | |
195 | } | |
196 | ||
197 | Bool | |
198 | PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst) | |
199 | { | |
200 | ScreenPtr screen = src->drawable.pScreen; | |
201 | PixmapDirtyUpdatePtr ent, safe; | |
202 | ||
203 | xorg_list_for_each_entry_safe(ent, safe, &screen->pixmap_dirty_list, ent) { | |
204 | if (ent->src == src && ent->slave_dst == slave_dst) { | |
205 | DamageDestroy(ent->damage); | |
206 | xorg_list_del(&ent->ent); | |
207 | free(ent); | |
208 | } | |
209 | } | |
210 | return TRUE; | |
211 | } | |
212 | ||
213 | /* | |
214 | * this function can possibly be improved and optimised, by clipping | |
215 | * instead of iterating | |
216 | */ | |
217 | Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region) | |
218 | { | |
219 | ScreenPtr pScreen = dirty->src->drawable.pScreen; | |
220 | int n; | |
221 | BoxPtr b; | |
222 | RegionPtr region = DamageRegion(dirty->damage); | |
223 | GCPtr pGC; | |
224 | PixmapPtr dst; | |
225 | SourceValidateProcPtr SourceValidate; | |
226 | ||
227 | /* | |
228 | * SourceValidate is used by the software cursor code | |
229 | * to pull the cursor off of the screen when reading | |
230 | * bits from the frame buffer. Bypassing this function | |
231 | * leaves the software cursor in place | |
232 | */ | |
233 | SourceValidate = pScreen->SourceValidate; | |
234 | pScreen->SourceValidate = NULL; | |
235 | ||
236 | RegionTranslate(dirty_region, dirty->x, dirty->y); | |
237 | RegionIntersect(dirty_region, dirty_region, region); | |
238 | ||
239 | if (RegionNil(dirty_region)) { | |
240 | RegionUninit(dirty_region); | |
241 | return FALSE; | |
242 | } | |
243 | ||
244 | dst = dirty->slave_dst->master_pixmap; | |
245 | if (!dst) | |
246 | dst = dirty->slave_dst; | |
247 | ||
248 | RegionTranslate(dirty_region, -dirty->x, -dirty->y); | |
249 | n = RegionNumRects(dirty_region); | |
250 | b = RegionRects(dirty_region); | |
251 | ||
252 | pGC = GetScratchGC(dirty->src->drawable.depth, pScreen); | |
253 | ValidateGC(&dst->drawable, pGC); | |
254 | ||
255 | while (n--) { | |
256 | BoxRec dst_box; | |
257 | int w, h; | |
258 | ||
259 | dst_box = *b; | |
260 | w = dst_box.x2 - dst_box.x1; | |
261 | h = dst_box.y2 - dst_box.y1; | |
262 | ||
263 | pGC->ops->CopyArea(&dirty->src->drawable, &dst->drawable, pGC, | |
264 | dirty->x + dst_box.x1, dirty->y + dst_box.y1, w, h, dst_box.x1, dst_box.y1); | |
265 | b++; | |
266 | } | |
267 | FreeScratchGC(pGC); | |
268 | ||
269 | pScreen->SourceValidate = SourceValidate; | |
270 | return TRUE; | |
271 | } |