diff options
Diffstat (limited to 'saa/saa.c')
-rw-r--r-- | saa/saa.c | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/saa/saa.c b/saa/saa.c new file mode 100644 index 0000000..173c090 --- /dev/null +++ b/saa/saa.c | |||
@@ -0,0 +1,748 @@ | |||
1 | /* | ||
2 | * Copyright © 2001 Keith Packard | ||
3 | * | ||
4 | * Partly based on code that is Copyright © The XFree86 Project Inc. | ||
5 | * | ||
6 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
7 | * documentation for any purpose is hereby granted without fee, provided that | ||
8 | * the above copyright notice appear in all copies and that both that | ||
9 | * copyright notice and this permission notice appear in supporting | ||
10 | * documentation, and that the name of Keith Packard not be used in | ||
11 | * advertising or publicity pertaining to distribution of the software without | ||
12 | * specific, written prior permission. Keith Packard makes no | ||
13 | * representations about the suitability of this software for any purpose. It | ||
14 | * is provided "as is" without express or implied warranty. | ||
15 | * | ||
16 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
17 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
18 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
19 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
20 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
21 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
22 | * PERFORMANCE OF THIS SOFTWARE. | ||
23 | */ | ||
24 | |||
25 | /** @file | ||
26 | * This file covers the initialization and teardown of SAA, and has various | ||
27 | * functions not responsible for performing rendering, pixmap migration, or | ||
28 | * memory management. | ||
29 | */ | ||
30 | |||
31 | #ifdef HAVE_DIX_CONFIG_H | ||
32 | #include <dix-config.h> | ||
33 | #endif | ||
34 | |||
35 | #include <stdlib.h> | ||
36 | |||
37 | #include "saa_priv.h" | ||
38 | #include <X11/fonts/fontstruct.h> | ||
39 | #include "regionstr.h" | ||
40 | #include "saa.h" | ||
41 | #include "saa_priv.h" | ||
42 | |||
43 | #ifdef SAA_DEVPRIVATEKEYREC | ||
44 | DevPrivateKeyRec saa_screen_index; | ||
45 | DevPrivateKeyRec saa_pixmap_index; | ||
46 | DevPrivateKeyRec saa_gc_index; | ||
47 | #else | ||
48 | int saa_screen_index = -1; | ||
49 | int saa_pixmap_index = -1; | ||
50 | int saa_gc_index = -1; | ||
51 | #endif | ||
52 | |||
53 | /** | ||
54 | * saa_get_drawable_pixmap() returns a backing pixmap for a given drawable. | ||
55 | * | ||
56 | * @param pDrawable the drawable being requested. | ||
57 | * | ||
58 | * This function returns the backing pixmap for a drawable, whether it is a | ||
59 | * redirected window, unredirected window, or already a pixmap. Note that | ||
60 | * coordinate translation is needed when drawing to the backing pixmap of a | ||
61 | * redirected window, and the translation coordinates are provided by calling | ||
62 | * saa_get_drawable_pixmap() on the drawable. | ||
63 | */ | ||
64 | PixmapPtr | ||
65 | saa_get_drawable_pixmap(DrawablePtr pDrawable) | ||
66 | { | ||
67 | if (pDrawable->type == DRAWABLE_WINDOW) | ||
68 | return pDrawable->pScreen->GetWindowPixmap((WindowPtr) pDrawable); | ||
69 | else | ||
70 | return (PixmapPtr) pDrawable; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * Sets the offsets to add to coordinates to make them address the same bits in | ||
75 | * the backing drawable. These coordinates are nonzero only for redirected | ||
76 | * windows. | ||
77 | */ | ||
78 | void | ||
79 | saa_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap, | ||
80 | int *xp, int *yp) | ||
81 | { | ||
82 | #ifdef COMPOSITE | ||
83 | if (pDrawable->type == DRAWABLE_WINDOW) { | ||
84 | *xp = -pPixmap->screen_x; | ||
85 | *yp = -pPixmap->screen_y; | ||
86 | return; | ||
87 | } | ||
88 | #endif | ||
89 | |||
90 | *xp = 0; | ||
91 | *yp = 0; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the pixmap which backs a drawable, and the offsets to add to | ||
96 | * coordinates to make them address the same bits in the backing drawable. | ||
97 | */ | ||
98 | PixmapPtr | ||
99 | saa_get_pixmap(DrawablePtr drawable, int *xp, int *yp) | ||
100 | { | ||
101 | PixmapPtr pixmap = saa_get_drawable_pixmap(drawable); | ||
102 | |||
103 | saa_get_drawable_deltas(drawable, pixmap, xp, yp); | ||
104 | |||
105 | return pixmap; | ||
106 | } | ||
107 | |||
108 | static Bool | ||
109 | saa_download_from_hw(PixmapPtr pix, RegionPtr readback) | ||
110 | { | ||
111 | struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); | ||
112 | struct saa_driver *driver = sscreen->driver; | ||
113 | struct saa_pixmap *spix = saa_pixmap(pix); | ||
114 | void *addr; | ||
115 | Bool ret; | ||
116 | |||
117 | if (spix->mapped_access) | ||
118 | driver->release_from_cpu(driver, pix, spix->mapped_access); | ||
119 | |||
120 | ret = driver->download_from_hw(driver, pix, readback); | ||
121 | |||
122 | if (spix->mapped_access) { | ||
123 | addr = driver->sync_for_cpu(driver, pix, spix->mapped_access); | ||
124 | if (addr != NULL) | ||
125 | spix->addr = addr; | ||
126 | } | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | Bool | ||
132 | saa_prepare_access_pixmap(PixmapPtr pix, saa_access_t access, | ||
133 | RegionPtr read_reg) | ||
134 | { | ||
135 | ScreenPtr pScreen = pix->drawable.pScreen; | ||
136 | struct saa_screen_priv *sscreen = saa_screen(pScreen); | ||
137 | struct saa_driver *driver = sscreen->driver; | ||
138 | struct saa_pixmap *spix = saa_pixmap(pix); | ||
139 | saa_access_t map_access = 0; | ||
140 | Bool ret = TRUE; | ||
141 | |||
142 | if (read_reg && REGION_NOTEMPTY(pScreen, read_reg)) | ||
143 | ret = saa_download_from_hw(pix, read_reg); | ||
144 | |||
145 | if (!ret) { | ||
146 | LogMessage(X_ERROR, "Prepare access pixmap failed.\n"); | ||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | if ((access & SAA_ACCESS_R) != 0 && spix->read_access++ == 0) | ||
151 | map_access = SAA_ACCESS_R; | ||
152 | if ((access & SAA_ACCESS_W) != 0 && spix->write_access++ == 0) | ||
153 | map_access |= SAA_ACCESS_W; | ||
154 | |||
155 | if (map_access) { | ||
156 | if (spix->auth_loc != saa_loc_override) { | ||
157 | (void)driver->sync_for_cpu(driver, pix, map_access); | ||
158 | spix->addr = driver->map(driver, pix, map_access); | ||
159 | } else | ||
160 | spix->addr = spix->override; | ||
161 | spix->mapped_access |= map_access; | ||
162 | } | ||
163 | |||
164 | pix->devPrivate.ptr = spix->addr; | ||
165 | return TRUE; | ||
166 | } | ||
167 | |||
168 | void | ||
169 | saa_finish_access_pixmap(PixmapPtr pix, saa_access_t access) | ||
170 | { | ||
171 | struct saa_screen_priv *sscreen = saa_screen(pix->drawable.pScreen); | ||
172 | struct saa_driver *driver = sscreen->driver; | ||
173 | struct saa_pixmap *spix = saa_pixmap(pix); | ||
174 | saa_access_t unmap_access = 0; | ||
175 | |||
176 | if ((access & SAA_ACCESS_R) != 0 && --spix->read_access == 0) | ||
177 | unmap_access = SAA_ACCESS_R; | ||
178 | if ((access & SAA_ACCESS_W) != 0 && --spix->write_access == 0) | ||
179 | unmap_access |= SAA_ACCESS_W; | ||
180 | |||
181 | if (spix->read_access < 0) | ||
182 | LogMessage(X_ERROR, "Incorrect read access.\n"); | ||
183 | if (spix->write_access < 0) | ||
184 | LogMessage(X_ERROR, "Incorrect write access.\n"); | ||
185 | |||
186 | if (unmap_access) { | ||
187 | if (spix->auth_loc != saa_loc_override) { | ||
188 | driver->unmap(driver, pix, unmap_access); | ||
189 | driver->release_from_cpu(driver, pix, unmap_access); | ||
190 | } | ||
191 | spix->mapped_access &= ~unmap_access; | ||
192 | } | ||
193 | if (!spix->mapped_access) { | ||
194 | spix->addr = NULL; | ||
195 | pix->devPrivate.ptr = SAA_INVALID_ADDRESS; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Callback that is called after a rendering operation. We try to | ||
201 | * determine whether it's a shadow damage or a hw damage and call the | ||
202 | * driver callback. | ||
203 | */ | ||
204 | |||
205 | static void | ||
206 | saa_report_damage(DamagePtr damage, RegionPtr reg, void *closure) | ||
207 | { | ||
208 | PixmapPtr pixmap = (PixmapPtr) closure; | ||
209 | struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); | ||
210 | struct saa_driver *driver = saa_screen(pixmap->drawable.pScreen)->driver; | ||
211 | |||
212 | if (spix->read_access || spix->write_access) | ||
213 | LogMessage(X_ERROR, "Damage report inside prepare access.\n"); | ||
214 | |||
215 | driver->operation_complete(driver, pixmap); | ||
216 | DamageEmpty(damage); | ||
217 | } | ||
218 | |||
219 | Bool | ||
220 | saa_add_damage(PixmapPtr pixmap) | ||
221 | { | ||
222 | ScreenPtr pScreen = pixmap->drawable.pScreen; | ||
223 | struct saa_pixmap *spix = saa_get_saa_pixmap(pixmap); | ||
224 | |||
225 | if (spix->damage) | ||
226 | return TRUE; | ||
227 | |||
228 | spix->damage = DamageCreate(saa_report_damage, NULL, | ||
229 | DamageReportRawRegion, TRUE, pScreen, pixmap); | ||
230 | if (!spix->damage) | ||
231 | return FALSE; | ||
232 | |||
233 | DamageRegister(&pixmap->drawable, spix->damage); | ||
234 | DamageSetReportAfterOp(spix->damage, TRUE); | ||
235 | |||
236 | return TRUE; | ||
237 | } | ||
238 | |||
239 | static inline RegionPtr | ||
240 | saa_pix_damage_region(struct saa_pixmap *spix) | ||
241 | { | ||
242 | return (spix->damage ? DamageRegion(spix->damage) : NULL); | ||
243 | } | ||
244 | |||
245 | Bool | ||
246 | saa_pad_read(DrawablePtr draw) | ||
247 | { | ||
248 | ScreenPtr pScreen = draw->pScreen; | ||
249 | PixmapPtr pix; | ||
250 | int xp; | ||
251 | int yp; | ||
252 | BoxRec box; | ||
253 | RegionRec entire; | ||
254 | Bool ret; | ||
255 | |||
256 | (void)pScreen; | ||
257 | pix = saa_get_pixmap(draw, &xp, &yp); | ||
258 | |||
259 | box.x1 = draw->x + xp; | ||
260 | box.y1 = draw->y + yp; | ||
261 | box.x2 = box.x1 + draw->width; | ||
262 | box.y2 = box.y1 + draw->height; | ||
263 | |||
264 | REGION_INIT(pScreen, &entire, &box, 1); | ||
265 | ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); | ||
266 | REGION_UNINIT(pScreen, &entire); | ||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | Bool | ||
271 | saa_pad_read_box(DrawablePtr draw, int x, int y, int w, int h) | ||
272 | { | ||
273 | ScreenPtr pScreen = draw->pScreen; | ||
274 | PixmapPtr pix; | ||
275 | int xp; | ||
276 | int yp; | ||
277 | BoxRec box; | ||
278 | RegionRec entire; | ||
279 | Bool ret; | ||
280 | |||
281 | (void)pScreen; | ||
282 | pix = saa_get_pixmap(draw, &xp, &yp); | ||
283 | |||
284 | box.x1 = x + xp; | ||
285 | box.y1 = y + yp; | ||
286 | box.x2 = box.x1 + w; | ||
287 | box.y2 = box.y1 + h; | ||
288 | |||
289 | REGION_INIT(pScreen, &entire, &box, 1); | ||
290 | ret = saa_prepare_access_pixmap(pix, SAA_ACCESS_R, &entire); | ||
291 | REGION_UNINIT(pScreen, &entire); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * Prepares a drawable destination for access, and maps it read-write. | ||
297 | * If check_read is TRUE, pGC should point to a valid GC. The drawable | ||
298 | * may then be mapped write-only if the pending operation admits. | ||
299 | */ | ||
300 | |||
301 | Bool | ||
302 | saa_pad_write(DrawablePtr draw, GCPtr pGC, Bool check_read, | ||
303 | saa_access_t * access) | ||
304 | { | ||
305 | int xp; | ||
306 | int yp; | ||
307 | PixmapPtr pixmap = saa_get_pixmap(draw, &xp, &yp); | ||
308 | struct saa_pixmap *spix = saa_pixmap(pixmap); | ||
309 | |||
310 | *access = SAA_ACCESS_W; | ||
311 | |||
312 | /* | ||
313 | * If the to-be-damaged area doesn't depend at all on previous | ||
314 | * rendered contents, we don't need to do any readback. | ||
315 | */ | ||
316 | |||
317 | if (check_read && !saa_gc_reads_destination(draw, pGC)) | ||
318 | return saa_prepare_access_pixmap(pixmap, *access, NULL); | ||
319 | |||
320 | *access |= SAA_ACCESS_R; | ||
321 | |||
322 | /* | ||
323 | * Read back the area to be damaged. | ||
324 | */ | ||
325 | |||
326 | return saa_prepare_access_pixmap(pixmap, *access, | ||
327 | saa_pix_damage_pending(spix)); | ||
328 | } | ||
329 | |||
330 | void | ||
331 | saa_fad_read(DrawablePtr draw) | ||
332 | { | ||
333 | saa_finish_access_pixmap(saa_get_drawable_pixmap(draw), SAA_ACCESS_R); | ||
334 | } | ||
335 | |||
336 | void | ||
337 | saa_fad_write(DrawablePtr draw, saa_access_t access) | ||
338 | { | ||
339 | PixmapPtr pix = saa_get_drawable_pixmap(draw); | ||
340 | struct saa_pixmap *spix = saa_pixmap(pix); | ||
341 | |||
342 | saa_finish_access_pixmap(pix, access); | ||
343 | if (spix->damage) | ||
344 | saa_pixmap_dirty(pix, FALSE, saa_pix_damage_pending(spix)); | ||
345 | } | ||
346 | |||
347 | Bool | ||
348 | saa_gc_reads_destination(DrawablePtr pDrawable, GCPtr pGC) | ||
349 | { | ||
350 | return ((pGC->alu != GXcopy && pGC->alu != GXclear && pGC->alu != GXset && | ||
351 | pGC->alu != GXcopyInverted) || pGC->fillStyle == FillStippled || | ||
352 | pGC->clientClipType != CT_NONE || | ||
353 | !SAA_PM_IS_SOLID(pDrawable, pGC->planemask)); | ||
354 | } | ||
355 | |||
356 | Bool | ||
357 | saa_op_reads_destination(CARD8 op) | ||
358 | { | ||
359 | /* FALSE (does not read destination) is the list of ops in the protocol | ||
360 | * document with "0" in the "Fb" column and no "Ab" in the "Fa" column. | ||
361 | * That's just Clear and Src. ReduceCompositeOp() will already have | ||
362 | * converted con/disjoint clear/src to Clear or Src. | ||
363 | */ | ||
364 | switch (op) { | ||
365 | case PictOpClear: | ||
366 | case PictOpSrc: | ||
367 | return FALSE; | ||
368 | default: | ||
369 | return TRUE; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | static void | ||
374 | saa_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) | ||
375 | { | ||
376 | /* fbValidateGC will do direct access to pixmaps if the tiling has changed. | ||
377 | * Do a few smart things so fbValidateGC can do it's work. | ||
378 | */ | ||
379 | |||
380 | ScreenPtr pScreen = pDrawable->pScreen; | ||
381 | struct saa_screen_priv *sscreen = saa_screen(pScreen); | ||
382 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
383 | PixmapPtr pTile = NULL; | ||
384 | Bool finish_current_tile = FALSE; | ||
385 | |||
386 | /* Either of these conditions is enough to trigger access to a tile pixmap. */ | ||
387 | /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */ | ||
388 | if (pGC->fillStyle == FillTiled | ||
389 | || ((changes & GCTile) && !pGC->tileIsPixel)) { | ||
390 | pTile = pGC->tile.pixmap; | ||
391 | |||
392 | /* Sometimes tile pixmaps are swapped, you need access to: | ||
393 | * - The current tile if it depth matches. | ||
394 | * - Or the rotated tile if that one matches depth and !(changes & GCTile). | ||
395 | * - Or the current tile pixmap and a newly created one. | ||
396 | */ | ||
397 | if (pTile && pTile->drawable.depth != pDrawable->depth | ||
398 | && !(changes & GCTile)) { | ||
399 | PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC); | ||
400 | |||
401 | if (pRotatedTile | ||
402 | && pRotatedTile->drawable.depth == pDrawable->depth) | ||
403 | pTile = pRotatedTile; | ||
404 | else | ||
405 | finish_current_tile = TRUE; /* CreatePixmap will be called. */ | ||
406 | } | ||
407 | } | ||
408 | |||
409 | if (pGC->stipple && !saa_pad_read(&pGC->stipple->drawable)) { | ||
410 | LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); | ||
411 | return; | ||
412 | } | ||
413 | |||
414 | if (pTile && !saa_pad_read(&pTile->drawable)) { | ||
415 | LogMessage(X_ERROR, "Failed stipple prepareaccess.\n"); | ||
416 | goto out_no_tile; | ||
417 | } | ||
418 | |||
419 | /* Calls to Create/DestroyPixmap have to be identified as special, so | ||
420 | * up sscreen->fallback_count. | ||
421 | */ | ||
422 | |||
423 | sscreen->fallback_count++; | ||
424 | saa_swap(sgc, pGC, funcs); | ||
425 | (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); | ||
426 | saa_swap(sgc, pGC, funcs); | ||
427 | |||
428 | if (finish_current_tile && pGC->tile.pixmap) | ||
429 | saa_fad_write(&pGC->tile.pixmap->drawable, SAA_ACCESS_W); | ||
430 | sscreen->fallback_count--; | ||
431 | |||
432 | if (pTile) | ||
433 | saa_fad_read(&pTile->drawable); | ||
434 | out_no_tile: | ||
435 | if (pGC->stipple) | ||
436 | saa_fad_read(&pGC->stipple->drawable); | ||
437 | } | ||
438 | |||
439 | static void | ||
440 | saa_destroy_gc(GCPtr pGC) | ||
441 | { | ||
442 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
443 | |||
444 | saa_swap(sgc, pGC, funcs); | ||
445 | (*pGC->funcs->DestroyGC) (pGC); | ||
446 | saa_swap(sgc, pGC, funcs); | ||
447 | } | ||
448 | |||
449 | static void | ||
450 | saa_change_gc(GCPtr pGC, unsigned long mask) | ||
451 | { | ||
452 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
453 | |||
454 | saa_swap(sgc, pGC, funcs); | ||
455 | (*pGC->funcs->ChangeGC) (pGC, mask); | ||
456 | saa_swap(sgc, pGC, funcs); | ||
457 | } | ||
458 | |||
459 | static void | ||
460 | saa_copy_gc(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) | ||
461 | { | ||
462 | struct saa_gc_priv *sgc = saa_gc(pGCDst); | ||
463 | |||
464 | saa_swap(sgc, pGCDst, funcs); | ||
465 | (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); | ||
466 | saa_swap(sgc, pGCDst, funcs); | ||
467 | } | ||
468 | |||
469 | static void | ||
470 | saa_change_clip(GCPtr pGC, int type, pointer pvalue, int nrects) | ||
471 | { | ||
472 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
473 | |||
474 | saa_swap(sgc, pGC, funcs); | ||
475 | (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); | ||
476 | saa_swap(sgc, pGC, funcs); | ||
477 | } | ||
478 | |||
479 | static void | ||
480 | saa_copy_clip(GCPtr pGCDst, GCPtr pGCSrc) | ||
481 | { | ||
482 | struct saa_gc_priv *sgc = saa_gc(pGCDst); | ||
483 | |||
484 | saa_swap(sgc, pGCDst, funcs); | ||
485 | (*pGCDst->funcs->CopyClip) (pGCDst, pGCSrc); | ||
486 | saa_swap(sgc, pGCDst, funcs); | ||
487 | } | ||
488 | |||
489 | static void | ||
490 | saa_destroy_clip(GCPtr pGC) | ||
491 | { | ||
492 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
493 | |||
494 | saa_swap(sgc, pGC, funcs); | ||
495 | (*pGC->funcs->DestroyClip) (pGC); | ||
496 | saa_swap(sgc, pGC, funcs); | ||
497 | } | ||
498 | |||
499 | static GCFuncs saa_gc_funcs = { | ||
500 | saa_validate_gc, | ||
501 | saa_change_gc, | ||
502 | saa_copy_gc, | ||
503 | saa_destroy_gc, | ||
504 | saa_change_clip, | ||
505 | saa_destroy_clip, | ||
506 | saa_copy_clip | ||
507 | }; | ||
508 | |||
509 | /** | ||
510 | * saa_create_gc makes a new GC and hooks up its funcs handler, so that | ||
511 | * saa_validate_gc() will get called. | ||
512 | */ | ||
513 | int | ||
514 | saa_create_gc(GCPtr pGC) | ||
515 | { | ||
516 | ScreenPtr pScreen = pGC->pScreen; | ||
517 | struct saa_screen_priv *sscreen = saa_screen(pScreen); | ||
518 | struct saa_gc_priv *sgc = saa_gc(pGC); | ||
519 | Bool ret; | ||
520 | |||
521 | saa_swap(sscreen, pScreen, CreateGC); | ||
522 | ret = pScreen->CreateGC(pGC); | ||
523 | if (ret) { | ||
524 | saa_wrap(sgc, pGC, funcs, &saa_gc_funcs); | ||
525 | saa_wrap(sgc, pGC, ops, &saa_gc_ops); | ||
526 | } | ||
527 | saa_swap(sscreen, pScreen, CreateGC); | ||
528 | |||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | static Bool | ||
533 | saa_prepare_access_window(WindowPtr pWin) | ||
534 | { | ||
535 | if (pWin->backgroundState == BackgroundPixmap) { | ||
536 | if (!saa_pad_read(&pWin->background.pixmap->drawable)) | ||
537 | return FALSE; | ||
538 | } | ||
539 | |||
540 | if (pWin->borderIsPixel == FALSE) { | ||
541 | if (!saa_pad_read(&pWin->border.pixmap->drawable)) { | ||
542 | if (pWin->backgroundState == BackgroundPixmap) | ||
543 | saa_fad_read(&pWin->background.pixmap->drawable); | ||
544 | return FALSE; | ||
545 | } | ||
546 | } | ||
547 | return TRUE; | ||
548 | } | ||
549 | |||
550 | static void | ||
551 | saa_finish_access_window(WindowPtr pWin) | ||
552 | { | ||
553 | if (pWin->backgroundState == BackgroundPixmap) | ||
554 | saa_fad_read(&pWin->background.pixmap->drawable); | ||
555 | |||
556 | if (pWin->borderIsPixel == FALSE) | ||
557 | saa_fad_read(&pWin->border.pixmap->drawable); | ||
558 | } | ||
559 | |||
560 | static Bool | ||
561 | saa_change_window_attributes(WindowPtr pWin, unsigned long mask) | ||
562 | { | ||
563 | Bool ret; | ||
564 | |||
565 | if (!saa_prepare_access_window(pWin)) | ||
566 | return FALSE; | ||
567 | ret = fbChangeWindowAttributes(pWin, mask); | ||
568 | saa_finish_access_window(pWin); | ||
569 | return ret; | ||
570 | } | ||
571 | |||
572 | RegionPtr | ||
573 | saa_bitmap_to_region(PixmapPtr pPix) | ||
574 | { | ||
575 | RegionPtr ret; | ||
576 | |||
577 | if (!saa_pad_read(&pPix->drawable)) | ||
578 | return NULL; | ||
579 | ret = fbPixmapToRegion(pPix); | ||
580 | saa_fad_read(&pPix->drawable); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
584 | void | ||
585 | saa_set_fallback_debug(ScreenPtr screen, Bool enable) | ||
586 | { | ||
587 | struct saa_screen_priv *sscreen = saa_screen(screen); | ||
588 | |||
589 | sscreen->fallback_debug = enable; | ||
590 | } | ||
591 | |||
592 | /** | ||
593 | * saa_close_screen() unwraps its wrapped screen functions and tears down SAA's | ||
594 | * screen private, before calling down to the next CloseScreen. | ||
595 | */ | ||
596 | Bool | ||
597 | saa_close_screen(int i, ScreenPtr pScreen) | ||
598 | { | ||
599 | struct saa_screen_priv *sscreen = saa_screen(pScreen); | ||
600 | struct saa_driver *driver = sscreen->driver; | ||
601 | |||
602 | if (pScreen->devPrivate) { | ||
603 | /* Destroy the pixmap created by miScreenInit() *before* | ||
604 | * chaining up as we finalize ourselves here and so this | ||
605 | * is the last chance we have of releasing our resources | ||
606 | * associated with the Pixmap. So do it first. | ||
607 | */ | ||
608 | (void)(*pScreen->DestroyPixmap) (pScreen->devPrivate); | ||
609 | pScreen->devPrivate = NULL; | ||
610 | } | ||
611 | |||
612 | saa_unwrap(sscreen, pScreen, CloseScreen); | ||
613 | saa_unwrap(sscreen, pScreen, CreateGC); | ||
614 | saa_unwrap(sscreen, pScreen, ChangeWindowAttributes); | ||
615 | saa_unwrap(sscreen, pScreen, CreatePixmap); | ||
616 | saa_unwrap(sscreen, pScreen, DestroyPixmap); | ||
617 | saa_unwrap(sscreen, pScreen, ModifyPixmapHeader); | ||
618 | saa_unwrap(sscreen, pScreen, BitmapToRegion); | ||
619 | #ifdef RENDER | ||
620 | saa_render_takedown(pScreen); | ||
621 | #endif | ||
622 | saa_unaccel_takedown(pScreen); | ||
623 | driver->takedown(driver); | ||
624 | |||
625 | free(sscreen); | ||
626 | |||
627 | return (*pScreen->CloseScreen) (i, pScreen); | ||
628 | } | ||
629 | |||
630 | struct saa_driver * | ||
631 | saa_get_driver(ScreenPtr pScreen) | ||
632 | { | ||
633 | return saa_screen(pScreen)->driver; | ||
634 | } | ||
635 | |||
636 | /** | ||
637 | * @param pScreen screen being initialized | ||
638 | * @param pScreenInfo SAA driver record | ||
639 | * | ||
640 | * saa_driver_init sets up SAA given a driver record filled in by the driver. | ||
641 | * pScreenInfo should have been allocated by saa_driver_alloc(). See the | ||
642 | * comments in _SaaDriver for what must be filled in and what is optional. | ||
643 | * | ||
644 | * @return TRUE if SAA was successfully initialized. | ||
645 | */ | ||
646 | Bool | ||
647 | saa_driver_init(ScreenPtr screen, struct saa_driver * saa_driver) | ||
648 | { | ||
649 | struct saa_screen_priv *sscreen; | ||
650 | |||
651 | if (!saa_driver) | ||
652 | return FALSE; | ||
653 | |||
654 | if (saa_driver->saa_major != SAA_VERSION_MAJOR || | ||
655 | saa_driver->saa_minor > SAA_VERSION_MINOR) { | ||
656 | LogMessage(X_ERROR, | ||
657 | "SAA(%d): driver's SAA version requirements " | ||
658 | "(%d.%d) are incompatible with SAA version (%d.%d)\n", | ||
659 | screen->myNum, saa_driver->saa_major, | ||
660 | saa_driver->saa_minor, SAA_VERSION_MAJOR, SAA_VERSION_MINOR); | ||
661 | return FALSE; | ||
662 | } | ||
663 | #if 0 | ||
664 | if (!saa_driver->prepare_solid) { | ||
665 | LogMessage(X_ERROR, | ||
666 | "SAA(%d): saa_driver_t::prepare_solid must be " | ||
667 | "non-NULL\n", screen->myNum); | ||
668 | return FALSE; | ||
669 | } | ||
670 | |||
671 | if (!saa_driver->prepare_copy) { | ||
672 | LogMessage(X_ERROR, | ||
673 | "SAA(%d): saa_driver_t::prepare_copy must be " | ||
674 | "non-NULL\n", screen->myNum); | ||
675 | return FALSE; | ||
676 | } | ||
677 | #endif | ||
678 | #ifdef SAA_DEVPRIVATEKEYREC | ||
679 | if (!dixRegisterPrivateKey(&saa_screen_index, PRIVATE_SCREEN, 0)) { | ||
680 | LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); | ||
681 | return FALSE; | ||
682 | } | ||
683 | if (!dixRegisterPrivateKey(&saa_pixmap_index, PRIVATE_PIXMAP, | ||
684 | saa_driver->pixmap_size)) { | ||
685 | LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); | ||
686 | return FALSE; | ||
687 | } | ||
688 | if (!dixRegisterPrivateKey(&saa_gc_index, PRIVATE_GC, | ||
689 | sizeof(struct saa_gc_priv))) { | ||
690 | LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); | ||
691 | return FALSE; | ||
692 | } | ||
693 | #else | ||
694 | if (!dixRequestPrivate(&saa_screen_index, 0)) { | ||
695 | LogMessage(X_ERROR, "Failed to register SAA screen private.\n"); | ||
696 | return FALSE; | ||
697 | } | ||
698 | if (!dixRequestPrivate(&saa_pixmap_index, saa_driver->pixmap_size)) { | ||
699 | LogMessage(X_ERROR, "Failed to register SAA pixmap private.\n"); | ||
700 | return FALSE; | ||
701 | } | ||
702 | if (!dixRequestPrivate(&saa_gc_index, sizeof(struct saa_gc_priv))) { | ||
703 | LogMessage(X_ERROR, "Failed to register SAA gc private.\n"); | ||
704 | return FALSE; | ||
705 | } | ||
706 | #endif | ||
707 | |||
708 | sscreen = calloc(1, sizeof(*sscreen)); | ||
709 | |||
710 | if (!sscreen) { | ||
711 | LogMessage(X_WARNING, | ||
712 | "SAA(%d): Failed to allocate screen private\n", | ||
713 | screen->myNum); | ||
714 | return FALSE; | ||
715 | } | ||
716 | |||
717 | sscreen->driver = saa_driver; | ||
718 | dixSetPrivate(&screen->devPrivates, &saa_screen_index, sscreen); | ||
719 | |||
720 | /* | ||
721 | * Replace various fb screen functions | ||
722 | */ | ||
723 | |||
724 | saa_wrap(sscreen, screen, CloseScreen, saa_close_screen); | ||
725 | saa_wrap(sscreen, screen, CreateGC, saa_create_gc); | ||
726 | saa_wrap(sscreen, screen, ChangeWindowAttributes, | ||
727 | saa_change_window_attributes); | ||
728 | saa_wrap(sscreen, screen, CreatePixmap, saa_create_pixmap); | ||
729 | saa_wrap(sscreen, screen, DestroyPixmap, saa_destroy_pixmap); | ||
730 | saa_wrap(sscreen, screen, ModifyPixmapHeader, saa_modify_pixmap_header); | ||
731 | |||
732 | saa_wrap(sscreen, screen, BitmapToRegion, saa_bitmap_to_region); | ||
733 | saa_unaccel_setup(screen); | ||
734 | #ifdef RENDER | ||
735 | saa_render_setup(screen); | ||
736 | #endif | ||
737 | |||
738 | return TRUE; | ||
739 | } | ||
740 | |||
741 | Bool | ||
742 | saa_resources_init(ScreenPtr screen) | ||
743 | { | ||
744 | /* if (!saa_glyphs_init(screen)) | ||
745 | return FALSE; | ||
746 | */ | ||
747 | return TRUE; | ||
748 | } | ||