1 /*
2 * Copyright © 1999 Keith Packard
3 * Copyright 2011 VMWare, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Author: Based on "exa_unaccel.c"
26 * Author: Thomas Hellstrom <thellstrom@vmware.com>
27 */
28
29 #include "saa_priv.h"
30 #include "saa.h"
31 #include "mipict.h"
32
33 /**
34 * Calls saa_prepare_access with SAA_ACCESS_R for the tile, if that is the
35 * current fill style.
36 *
37 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
38 * 1bpp and never in fb, so we don't worry about them.
39 * We should worry about them for completeness sake and going forward.
40 */
41 static Bool
saa_prepare_access_gc(GCPtr pGC)42 saa_prepare_access_gc(GCPtr pGC)
43 {
44 if (pGC->stipple)
45 if (!saa_pad_read(&pGC->stipple->drawable))
46 return FALSE;
47 if (pGC->fillStyle == FillTiled)
48 if (!saa_pad_read(&pGC->tile.pixmap->drawable)) {
49 if (pGC->stipple)
50 saa_fad_read(&pGC->stipple->drawable);
51 return FALSE;
52 }
53 return TRUE;
54 }
55
56 /**
57 * Finishes access to the tile in the GC, if used.
58 */
59 static void
saa_finish_access_gc(GCPtr pGC)60 saa_finish_access_gc(GCPtr pGC)
61 {
62 if (pGC->fillStyle == FillTiled)
63 saa_fad_read(&pGC->tile.pixmap->drawable);
64 if (pGC->stipple)
65 saa_fad_read(&pGC->stipple->drawable);
66 }
67
68 void
saa_check_fill_spans(DrawablePtr pDrawable,GCPtr pGC,int nspans,DDXPointPtr ppt,int * pwidth,int fSorted)69 saa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
70 DDXPointPtr ppt, int *pwidth, int fSorted)
71 {
72 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
73 struct saa_gc_priv *sgc = saa_gc(pGC);
74 saa_access_t access;
75
76 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_location(pDrawable)));
77
78 sscreen->fallback_count++;
79 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
80 if (saa_prepare_access_gc(pGC)) {
81 saa_swap(sgc, pGC, ops);
82 pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted);
83 saa_swap(sgc, pGC, ops);
84 saa_finish_access_gc(pGC);
85 }
86 saa_fad_write(pDrawable, access);
87 }
88 sscreen->fallback_count--;
89 }
90
91 static void
saa_check_set_spans(DrawablePtr pDrawable,GCPtr pGC,char * psrc,DDXPointPtr ppt,int * pwidth,int nspans,int fSorted)92 saa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
93 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
94 {
95 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
96 struct saa_gc_priv *sgc = saa_gc(pGC);
97 saa_access_t access
98 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
99
100 sscreen->fallback_count++;
101 if (saa_pad_write(pDrawable, NULL, FALSE, &access)) {
102 saa_swap(sgc, pGC, ops);
103 pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
104 saa_swap(sgc, pGC, ops);
105 saa_fad_write(pDrawable, access);
106 }
107 sscreen->fallback_count--;
108 }
109
110 static void
saa_check_put_image(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * bits)111 saa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
112 int x, int y, int w, int h, int leftPad, int format,
113 char *bits)
114 {
115 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
116 struct saa_gc_priv *sgc = saa_gc(pGC);
117 saa_access_t access;
118
119 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
120 sscreen->fallback_count++;
121 if (saa_pad_write(pDrawable, pGC, TRUE, &access)) {
122 saa_swap(sgc, pGC, ops);
123 pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad,
124 format, bits);
125 saa_swap(sgc, pGC, ops);
126 saa_fad_write(pDrawable, access);
127 }
128 sscreen->fallback_count--;
129 }
130
131 RegionPtr
saa_boxes_to_region(ScreenPtr pScreen,int nbox,BoxPtr pbox,int ordering)132 saa_boxes_to_region(ScreenPtr pScreen, int nbox, BoxPtr pbox, int ordering)
133 {
134 xRectangle *rects = malloc(nbox * sizeof(*rects));
135 int i;
136 RegionPtr reg;
137
138 if (!rects)
139 return NULL;
140
141 for (i = 0; i < nbox; i++) {
142 rects[i].x = pbox[i].x1;
143 rects[i].y = pbox[i].y1;
144 rects[i].width = pbox[i].x2 - pbox[i].x1;
145 rects[i].height = pbox[i].y2 - pbox[i].y1;
146 }
147
148 reg = RECTS_TO_REGION(pScreen, nbox, rects, ordering);
149 free(rects);
150 return reg;
151 }
152
153 void
saa_check_copy_nton(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,BoxPtr pbox,int nbox,int dx,int dy,Bool reverse,Bool upsidedown,Pixel bitplane,void * closure)154 saa_check_copy_nton(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
155 BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
156 Bool upsidedown, Pixel bitplane, void *closure)
157 {
158 ScreenPtr pScreen = pSrc->pScreen;
159 struct saa_screen_priv *sscreen = saa_screen(pScreen);
160 RegionPtr reg, readback;
161 int src_xoff, src_yoff, dst_xoff, dst_yoff;
162 struct saa_gc_priv *sgc = saa_gc(pGC);
163 PixmapPtr src_pixmap;
164 PixmapPtr dst_pixmap;
165 saa_access_t access = SAA_ACCESS_R;
166 int ordering;
167
168 sscreen->fallback_count++;
169 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
170 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
171
172 src_pixmap = saa_get_pixmap(pSrc, &src_xoff, &src_yoff);
173 dst_pixmap = saa_get_pixmap(pDst, &dst_xoff, &dst_yoff);
174
175 ordering = (nbox == 1 || (dx > 0 && dy > 0) ||
176 (pDst != pSrc &&
177 (pDst->type != DRAWABLE_WINDOW ||
178 pSrc->type != DRAWABLE_WINDOW))) ? CT_YXBANDED : CT_UNSORTED;
179
180 reg = saa_boxes_to_region(pScreen, nbox, pbox, ordering);
181 if (!reg)
182 return;
183
184 REGION_TRANSLATE(pScreen, reg, src_xoff + dx, src_yoff + dy);
185 if (!saa_prepare_access_pixmap(src_pixmap, SAA_ACCESS_R, reg))
186 goto out_no_access;
187
188 REGION_TRANSLATE(pScreen, reg, dst_xoff - dx - src_xoff,
189 dst_yoff - dy - src_yoff);
190
191 if (saa_gc_reads_destination(pDst, pGC)) {
192 readback = reg;
193 access = SAA_ACCESS_RW;
194 } else {
195 readback = NULL;
196 access = SAA_ACCESS_W;
197 }
198
199 if (!saa_prepare_access_pixmap(dst_pixmap, access, readback))
200 goto out_no_dst;
201
202 saa_swap(sgc, pGC, ops);
203 while (nbox--) {
204 pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
205 pbox->y1 - pSrc->y + dy,
206 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
207 pbox->x1 - pDst->x, pbox->y1 - pDst->y);
208 pbox++;
209 }
210
211 saa_swap(sgc, pGC, ops);
212 saa_finish_access_pixmap(dst_pixmap, access);
213 saa_pixmap_dirty(dst_pixmap, FALSE, reg);
214 out_no_dst:
215 saa_fad_read(pSrc);
216 out_no_access:
217 sscreen->fallback_count--;
218 REGION_DESTROY(pScreen, reg);
219 }
220
221 RegionPtr
saa_check_copy_area(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)222 saa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
223 int srcx, int srcy, int w, int h, int dstx, int dsty)
224 {
225 RegionPtr ret = NULL;
226 struct saa_gc_priv *sgc = saa_gc(pGC);
227 saa_access_t access;
228 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
229
230 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
231 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
232 sscreen->fallback_count++;
233 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
234 goto out_no_access;
235 if (!saa_pad_write(pDst, pGC, TRUE, &access))
236 goto out_no_dst;
237
238 saa_swap(sgc, pGC, ops);
239 ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
240 saa_swap(sgc, pGC, ops);
241
242 saa_fad_write(pDst, access);
243 out_no_dst:
244 saa_fad_read(pSrc);
245 out_no_access:
246 sscreen->fallback_count--;
247
248 return ret;
249 }
250
251 static RegionPtr
saa_check_copy_plane(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long bitplane)252 saa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
253 int srcx, int srcy, int w, int h, int dstx, int dsty,
254 unsigned long bitplane)
255 {
256 RegionPtr ret = NULL;
257 struct saa_gc_priv *sgc = saa_gc(pGC);
258 saa_access_t access;
259 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
260
261 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
262 saa_drawable_loc(pSrc), saa_drawable_loc(pDst)));
263 sscreen->fallback_count++;
264 if (!saa_pad_read_box(pSrc, srcx, srcy, w, h))
265 goto out_no_src;
266 if (!saa_pad_write(pDst, pGC, TRUE, &access))
267 goto out_no_dst;
268
269 saa_swap(sgc, pGC, ops);
270 ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
271 bitplane);
272 saa_swap(sgc, pGC, ops);
273
274 saa_fad_write(pDst, access);
275 out_no_dst:
276 saa_fad_read(pSrc);
277 out_no_src:
278 sscreen->fallback_count--;
279
280 return ret;
281 }
282
283 static void
saa_check_poly_point(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)284 saa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
285 DDXPointPtr pptInit)
286 {
287 struct saa_gc_priv *sgc = saa_gc(pGC);
288 saa_access_t access;
289 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
290
291 sscreen->fallback_count++;
292 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
293 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
294 goto out_no_access;
295 saa_swap(sgc, pGC, ops);
296 pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
297 saa_swap(sgc, pGC, ops);
298 saa_fad_write(pDrawable, access);
299
300 out_no_access:
301 sscreen->fallback_count--;
302 }
303
304 static void
saa_check_poly_lines(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr ppt)305 saa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
306 int mode, int npt, DDXPointPtr ppt)
307 {
308 struct saa_gc_priv *sgc = saa_gc(pGC);
309 saa_access_t access;
310 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
311
312 SAA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
313 pDrawable, saa_drawable_loc(pDrawable),
314 pGC->lineWidth, mode, npt));
315
316 sscreen->fallback_count++;
317 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
318 goto out_no_access;
319 if (!saa_prepare_access_gc(pGC))
320 goto out_no_gc;
321 saa_swap(sgc, pGC, ops);
322 pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
323 saa_swap(sgc, pGC, ops);
324 saa_finish_access_gc(pGC);
325 out_no_gc:
326 saa_fad_write(pDrawable, access);
327 out_no_access:
328 sscreen->fallback_count--;
329 }
330
331 static void
saa_check_poly_segment(DrawablePtr pDrawable,GCPtr pGC,int nsegInit,xSegment * pSegInit)332 saa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
333 int nsegInit, xSegment * pSegInit)
334 {
335 struct saa_gc_priv *sgc = saa_gc(pGC);
336 saa_access_t access;
337 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
338
339 SAA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
340 saa_drawable_loc(pDrawable), pGC->lineWidth, nsegInit));
341
342 sscreen->fallback_count++;
343 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
344 goto out_no_access;;
345 if (!saa_prepare_access_gc(pGC))
346 goto out_no_gc;
347 saa_swap(sgc, pGC, ops);
348 pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
349 saa_swap(sgc, pGC, ops);
350 saa_finish_access_gc(pGC);
351 out_no_gc:
352 saa_fad_write(pDrawable, access);
353 out_no_access:
354 sscreen->fallback_count--;
355 }
356
357 static void
saa_check_poly_arc(DrawablePtr pDrawable,GCPtr pGC,int narcs,xArc * pArcs)358 saa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
359 {
360 struct saa_gc_priv *sgc = saa_gc(pGC);
361 saa_access_t access;
362 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
363
364 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
365
366 sscreen->fallback_count++;
367 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
368 goto out_no_access;;
369 if (!saa_prepare_access_gc(pGC))
370 goto out_no_gc;
371 saa_swap(sgc, pGC, ops);
372 pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
373 saa_swap(sgc, pGC, ops);
374 saa_finish_access_gc(pGC);
375 out_no_gc:
376 saa_fad_write(pDrawable, access);
377 out_no_access:
378 sscreen->fallback_count--;
379 }
380
381
382 /**
383 * saa_check_poly_fill_rect_noreadback - PolyFillRect avoiding unnecessary readbacks.
384 *
385 * @pDrawable: The drawable on which to fill.
386 * @pGC: Pointer to the GC to use.
387 * @nrect: Number of rectangles to fill.
388 * @xRectangle: Pointer to rectangles to fill.
389 *
390 * During a standard saa polyFillRect, the damage region is usually the bounding
391 * box of all rectangles. Since we mark the software pixmap dirty based on that
392 * damage region, we need to read all of it back first, even if the fill operation
393 * itself doesn't read anything. This version of polyFillRect improves on that by
394 * only damaging the area we actually fill. If it's a non-reading fill we thus don't
395 * need to read back anything, but this may come at the cost of increased dirty
396 * region fragmentation. In any case, this greatly improves on the performance of
397 * shaped windows on top of accelerated contents, for example unscaled OSD in xine.
398 */
399 static Bool
saa_check_poly_fill_rect_noreadback(DrawablePtr pDrawable,GCPtr pGC,int nrect,xRectangle * prect)400 saa_check_poly_fill_rect_noreadback(DrawablePtr pDrawable, GCPtr pGC,
401 int nrect, xRectangle *prect)
402 {
403 struct saa_gc_priv *sgc = saa_gc(pGC);
404 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
405 RegionPtr region;
406 saa_access_t access;
407 Bool ret;
408 PixmapPtr pPixmap;
409 xRectangle *prect_save = prect;
410 int xoff, yoff;
411 struct saa_pixmap *spix;
412
413 if (!nrect)
414 return TRUE;
415
416 sscreen->fallback_count++;
417
418 pPixmap = saa_get_pixmap(pDrawable, &xoff, &yoff);
419 spix = saa_get_saa_pixmap(pPixmap);
420 region = RECTS_TO_REGION(pGC->pScreen, nrect, prect, CT_UNSORTED);
421 if (!region)
422 goto out_no_region;
423
424 REGION_TRANSLATE(pGC->pScreen, region, pDrawable->x, pDrawable->y);
425 REGION_INTERSECT(pGC->pScreen, region, fbGetCompositeClip(pGC), region);
426 REGION_TRANSLATE(pGC->pScreen, region, xoff, yoff);
427
428 access = SAA_ACCESS_W;
429 if (saa_gc_reads_destination(pDrawable, pGC)) {
430 /*
431 * We need to do a readback anyway. In case of more than an
432 * ad hoc number of say 4 rectangles, we might as well do a
433 * readback of the whole damage area to avoid fragmentation.
434 */
435 if (REGION_NUM_RECTS(region) > 4)
436 goto out_no_access;
437
438 access |= SAA_ACCESS_R;
439 ret = saa_prepare_access_pixmap(pPixmap, access, region);
440 } else
441 ret = saa_prepare_access_pixmap(pPixmap, access, NULL);
442
443 if (!ret)
444 goto out_no_access;
445
446 if (!saa_prepare_access_gc(pGC))
447 goto out_no_gc;
448
449 saa_swap(sgc, pGC, ops);
450 pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect_save);
451 saa_swap(sgc, pGC, ops);
452
453 saa_finish_access_gc(pGC);
454 saa_finish_access_pixmap(pPixmap, access);
455
456 if (spix->damage) {
457 REGION_INTERSECT(pGC->pScreen, region, region,
458 saa_pix_damage_pending(spix));
459 saa_pixmap_dirty(pPixmap, FALSE, region);
460 }
461
462 REGION_DESTROY(pGC->pScreen, region);
463
464 sscreen->fallback_count--;
465
466 return TRUE;
467
468 out_no_gc:
469 saa_finish_access_pixmap(pPixmap, access);
470 out_no_access:
471 REGION_DESTROY(pGC->pScreen, region);
472 out_no_region:
473 sscreen->fallback_count--;
474
475 return FALSE;
476 }
477
478 void
saa_check_poly_fill_rect(DrawablePtr pDrawable,GCPtr pGC,int nrect,xRectangle * prect)479 saa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
480 int nrect, xRectangle * prect)
481 {
482 struct saa_gc_priv *sgc = saa_gc(pGC);
483 saa_access_t access;
484 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
485
486 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
487
488 if (saa_check_poly_fill_rect_noreadback(pDrawable, pGC, nrect, prect))
489 return;
490
491 sscreen->fallback_count++;
492
493 /*
494 * TODO: Use @prect for readback / damaging instead of
495 * the damage region. This may fragment the dirty regions more
496 * but should avoid unnecessary readbacks.
497 */
498 if (!saa_pad_write(pDrawable, pGC, FALSE, &access))
499 goto out_no_access;;
500 if (!saa_prepare_access_gc(pGC))
501 goto out_no_gc;
502 saa_swap(sgc, pGC, ops);
503 pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
504 saa_swap(sgc, pGC, ops);
505 saa_finish_access_gc(pGC);
506 out_no_gc:
507 saa_fad_write(pDrawable, access);
508 out_no_access:
509 sscreen->fallback_count--;
510 }
511
512 static void
saa_check_image_glyph_blt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,pointer pglyphBase)513 saa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
514 int x, int y, unsigned int nglyph,
515 CharInfoPtr * ppci, pointer pglyphBase)
516 {
517 struct saa_gc_priv *sgc = saa_gc(pGC);
518 saa_access_t access;
519 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
520
521 SAA_FALLBACK(("to %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
522
523 sscreen->fallback_count++;
524 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
525 goto out_no_access;;
526 if (!saa_prepare_access_gc(pGC))
527 goto out_no_gc;
528 saa_swap(sgc, pGC, ops);
529 pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
530 saa_swap(sgc, pGC, ops);
531 saa_finish_access_gc(pGC);
532 out_no_gc:
533 saa_fad_write(pDrawable, access);
534 out_no_access:
535 sscreen->fallback_count--;
536 }
537
538 static void
saa_check_poly_glyph_blt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,pointer pglyphBase)539 saa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
540 int x, int y, unsigned int nglyph,
541 CharInfoPtr * ppci, pointer pglyphBase)
542 {
543 struct saa_gc_priv *sgc = saa_gc(pGC);
544 saa_access_t access;
545 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
546
547 SAA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
548 saa_drawable_loc(pDrawable), pGC->fillStyle, pGC->alu));
549
550 sscreen->fallback_count++;
551 if (!saa_pad_write(pDrawable, NULL, FALSE, &access))
552 goto out_no_access;;
553 if (!saa_prepare_access_gc(pGC))
554 goto out_no_gc;
555 saa_swap(sgc, pGC, ops);
556 pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
557 saa_swap(sgc, pGC, ops);
558 saa_finish_access_gc(pGC);
559 out_no_gc:
560 saa_fad_write(pDrawable, access);
561 out_no_access:
562 sscreen->fallback_count--;
563 }
564
565 static void
saa_check_push_pixels(GCPtr pGC,PixmapPtr pBitmap,DrawablePtr pDrawable,int w,int h,int x,int y)566 saa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
567 DrawablePtr pDrawable, int w, int h, int x, int y)
568 {
569 struct saa_gc_priv *sgc = saa_gc(pGC);
570 saa_access_t access;
571 struct saa_screen_priv *sscreen = saa_screen(pGC->pScreen);
572
573 SAA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
574 saa_drawable_loc(&pBitmap->drawable),
575 saa_drawable_loc(pDrawable)));
576
577 sscreen->fallback_count++;
578 if (!saa_pad_write(pDrawable, pGC, TRUE, &access))
579 goto out_no_access;;
580 if (!saa_pad_read_box(&pBitmap->drawable, 0, 0, w, h))
581 goto out_no_src;
582 if (!saa_prepare_access_gc(pGC))
583 goto out_no_gc;
584 saa_swap(sgc, pGC, ops);
585 pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
586 saa_swap(sgc, pGC, ops);
587 saa_finish_access_gc(pGC);
588 out_no_gc:
589 saa_fad_read(&pBitmap->drawable);
590 out_no_src:
591 saa_fad_write(pDrawable, access);
592 out_no_access:
593 sscreen->fallback_count--;
594 }
595
596 static void
saa_check_copy_window(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc)597 saa_check_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
598 {
599 DrawablePtr pDrawable = &pWin->drawable;
600 ScreenPtr pScreen = pDrawable->pScreen;
601 struct saa_screen_priv *sscreen = saa_screen(pScreen);
602 int xoff, yoff;
603 PixmapPtr pPixmap = saa_get_pixmap(&pWin->drawable, &xoff, &yoff);
604 Bool ret;
605
606 SAA_FALLBACK(("from %p\n", pWin));
607
608 /* Only need the source bits, the destination region will be overwritten */
609
610 sscreen->fallback_count++;
611 REGION_TRANSLATE(pScreen, prgnSrc, xoff, yoff);
612 ret = saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_R, prgnSrc);
613 REGION_TRANSLATE(pScreen, prgnSrc, -xoff, -yoff);
614 if (!ret)
615 goto out_no_access;;
616
617 if (saa_prepare_access_pixmap(pPixmap, SAA_ACCESS_W, NULL)) {
618 struct saa_pixmap *spix;
619 RegionRec rgnDst;
620
621 REGION_NULL(pScreen, &rgnDst);
622 REGION_COPY(pScreen, &rgnDst, prgnSrc);
623
624 saa_swap(sscreen, pScreen, CopyWindow);
625 pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
626 saa_swap(sscreen, pScreen, CopyWindow);
627 saa_finish_access_pixmap(pPixmap, SAA_ACCESS_W);
628
629 spix = saa_get_saa_pixmap(pPixmap);
630 if (spix->damage) {
631 int dx, dy;
632
633 dx = ptOldOrg.x - pWin->drawable.x;
634 dy = ptOldOrg.y - pWin->drawable.y;
635 REGION_TRANSLATE(pScreen, &rgnDst, -dx, -dy);
636 REGION_INTERSECT(pSreen, &rgnDst, &pWin->borderClip, &rgnDst);
637 REGION_TRANSLATE(pScreen, &rgnDst, xoff, yoff);
638
639 REGION_INTERSECT(pScreen, &rgnDst, &rgnDst,
640 saa_pix_damage_pending(spix));
641 saa_pixmap_dirty(pPixmap, FALSE, &rgnDst);
642 }
643 REGION_UNINIT(pScreen, &rgnDst);
644 }
645 saa_fad_read(pDrawable);
646 out_no_access:
647 sscreen->fallback_count--;
648 }
649
650 #ifdef RENDER
651
652 #if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
653 static void
saa_src_validate(DrawablePtr pDrawable,int x,int y,int width,int height,unsigned int subWindowMode)654 saa_src_validate(DrawablePtr pDrawable,
655 int x,
656 int y, int width, int height, unsigned int subWindowMode)
657 #else
658 static void
659 saa_src_validate(DrawablePtr pDrawable, int x, int y, int width, int height)
660 #endif
661 {
662 ScreenPtr pScreen = pDrawable->pScreen;
663 struct saa_screen_priv *sscreen = saa_screen(pScreen);
664 int xoff, yoff;
665 BoxRec box;
666 RegionRec reg;
667 RegionPtr dst;
668
669 (void) saa_get_pixmap(pDrawable, &xoff, &yoff);
670 box.x1 = x + xoff;
671 box.y1 = y + yoff;
672 box.x2 = box.x1 + width;
673 box.y2 = box.y1 + height;
674
675 dst = (sscreen->srcDraw == pDrawable) ?
676 &sscreen->srcReg : &sscreen->maskReg;
677
678 REGION_INIT(pScreen, ®, &box, 1);
679 REGION_UNION(pScreen, dst, dst, ®);
680 REGION_UNINIT(pScreen, ®);
681
682 if (sscreen->saved_SourceValidate) {
683 saa_swap(sscreen, pScreen, SourceValidate);
684 pScreen->SourceValidate(pDrawable, x, y, width, height
685 #if (GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10)
686 , subWindowMode
687 #endif
688 );
689 saa_swap(sscreen, pScreen, SourceValidate);
690 }
691 }
692
693 static void
saa_check_get_image(DrawablePtr pDrawable,int x,int y,int w,int h,unsigned int format,unsigned long planeMask,char * d)694 saa_check_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
695 unsigned int format, unsigned long planeMask, char *d)
696 {
697 ScreenPtr pScreen = pDrawable->pScreen;
698 struct saa_screen_priv *sscreen = saa_screen(pScreen);
699
700 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
701
702 sscreen->fallback_count++;
703 if (!saa_pad_read_box(pDrawable, x, y, w, h))
704 goto out_no_access;;
705 saa_swap(sscreen, pScreen, GetImage);
706 pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
707 saa_swap(sscreen, pScreen, GetImage);
708 saa_fad_read(pDrawable);
709 out_no_access:
710 sscreen->fallback_count--;
711 }
712
713 static void
saa_check_get_spans(DrawablePtr pDrawable,int wMax,DDXPointPtr ppt,int * pwidth,int nspans,char * pdstStart)714 saa_check_get_spans(DrawablePtr pDrawable,
715 int wMax,
716 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
717 {
718 ScreenPtr pScreen = pDrawable->pScreen;
719 struct saa_screen_priv *sscreen = saa_screen(pScreen);
720
721 SAA_FALLBACK(("from %p (%c)\n", pDrawable, saa_drawable_loc(pDrawable)));
722
723 sscreen->fallback_count++;
724 if (!saa_pad_read(pDrawable))
725 goto out_no_access;;
726 saa_swap(sscreen, pScreen, GetSpans);
727 pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
728 saa_swap(sscreen, pScreen, GetSpans);
729 saa_fad_read(pDrawable);
730 out_no_access:
731 sscreen->fallback_count--;
732 }
733
734 /*
735 * Compute composite regions taking transforms into account.
736 * The caller must provide a pointer to an initialized dst_reg,
737 * and the function returns pointers to set up source- and mask regions.
738 * The source and mask regions must be uninitialized after use.
739 */
740
741 Bool
saa_compute_composite_regions(ScreenPtr pScreen,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,INT16 width,INT16 height,RegionPtr dst_reg,RegionPtr * src_reg,RegionPtr * mask_reg)742 saa_compute_composite_regions(ScreenPtr pScreen,
743 PicturePtr pSrc,
744 PicturePtr pMask,
745 PicturePtr pDst,
746 INT16 xSrc, INT16 ySrc, INT16 xMask,
747 INT16 yMask, INT16 xDst,
748 INT16 yDst, INT16 width, INT16 height,
749 RegionPtr dst_reg,
750 RegionPtr *src_reg,
751 RegionPtr *mask_reg)
752 {
753 struct saa_screen_priv *sscreen = saa_screen(pScreen);
754 RegionPtr srcReg = NULL;
755 RegionPtr maskReg = NULL;
756 Bool ret;
757 int xoff, yoff;
758
759 *src_reg = NULL;
760 *mask_reg = NULL;
761
762 if (pSrc->pDrawable) {
763 REGION_NULL(pScreen, &sscreen->srcReg);
764 srcReg = &sscreen->srcReg;
765 sscreen->srcDraw = pSrc->pDrawable;
766 if (pSrc != pDst)
767 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
768 -pSrc->pDrawable->x, -pSrc->pDrawable->y);
769 }
770
771 if (pMask && pMask->pDrawable) {
772 REGION_NULL(pScreen, &sscreen->maskReg);
773 maskReg = &sscreen->maskReg;
774 if (pMask != pDst && pMask != pSrc)
775 REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
776 -pMask->pDrawable->x, -pMask->pDrawable->y);
777 }
778
779 REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
780 -pDst->pDrawable->x, -pDst->pDrawable->y);
781
782 sscreen->saved_SourceValidate = saa_src_validate;
783 saa_swap(sscreen, pScreen, SourceValidate);
784 ret = miComputeCompositeRegion(dst_reg, pSrc, pMask, pDst,
785 xSrc, ySrc, xMask, yMask,
786 xDst, yDst, width, height);
787 saa_swap(sscreen, pScreen, SourceValidate);
788
789 REGION_TRANSLATE(pScreen, pDst->pCompositeClip,
790 pDst->pDrawable->x, pDst->pDrawable->y);
791 if (pSrc->pDrawable && pSrc != pDst)
792 REGION_TRANSLATE(pScreen, pSrc->pCompositeClip,
793 pSrc->pDrawable->x, pSrc->pDrawable->y);
794 if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
795 REGION_TRANSLATE(pScreen, pMask->pCompositeClip,
796 pMask->pDrawable->x, pMask->pDrawable->y);
797
798 if (!ret) {
799 if (srcReg)
800 REGION_UNINIT(pScreen, srcReg);
801 if (maskReg)
802 REGION_UNINIT(pScreen, maskReg);
803
804 return FALSE;
805 }
806
807 *src_reg = srcReg;
808 *mask_reg = maskReg;
809
810 /*
811 * Translate dst region to pixmap space.
812 */
813 (void) saa_get_pixmap(pDst->pDrawable, &xoff, &yoff);
814 REGION_TRANSLATE(pScreen, dst_reg, pDst->pDrawable->x + xoff,
815 pDst->pDrawable->y + yoff);
816
817
818 return TRUE;
819 }
820
821 static Bool
saa_prepare_composite_reg(ScreenPtr pScreen,CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height,RegionPtr src_region,RegionPtr mask_region,RegionPtr dst_region,saa_access_t * access)822 saa_prepare_composite_reg(ScreenPtr pScreen,
823 CARD8 op,
824 PicturePtr pSrc,
825 PicturePtr pMask,
826 PicturePtr pDst,
827 INT16 xSrc,
828 INT16 ySrc,
829 INT16 xMask,
830 INT16 yMask,
831 INT16 xDst,
832 INT16 yDst,
833 CARD16 width,
834 CARD16 height,
835 RegionPtr src_region,
836 RegionPtr mask_region,
837 RegionPtr dst_region,
838 saa_access_t * access)
839 {
840 RegionPtr dstReg = NULL;
841 PixmapPtr pSrcPix = NULL;
842 PixmapPtr pMaskPix = NULL;
843 PixmapPtr pDstPix;
844 struct saa_pixmap *dst_spix;
845
846 *access = SAA_ACCESS_W;
847
848 if (pSrc->pDrawable)
849 pSrcPix = saa_get_drawable_pixmap(pSrc->pDrawable);
850 if (pMask && pMask->pDrawable)
851 pMaskPix = saa_get_drawable_pixmap(pMask->pDrawable);
852
853 /*
854 * Don't limit alphamaps readbacks for now until we've figured out how that
855 * should be done.
856 */
857
858 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
859 if (!saa_pad_read(pSrc->alphaMap->pDrawable))
860 goto out_no_src_alpha;
861 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
862 if (!saa_pad_read(pMask->alphaMap->pDrawable))
863 goto out_no_mask_alpha;
864 if (pSrcPix)
865 if (!saa_prepare_access_pixmap(pSrcPix, SAA_ACCESS_R, src_region))
866 goto out_no_src;
867 if (pMaskPix)
868 if (!saa_prepare_access_pixmap(pMaskPix, SAA_ACCESS_R, mask_region))
869 goto out_no_mask;
870
871 pDstPix = saa_get_drawable_pixmap(pDst->pDrawable);
872 dst_spix = saa_get_saa_pixmap(pDstPix);
873
874 if (dst_spix->damage && saa_op_reads_destination(op)) {
875 dstReg = dst_region;
876 *access |= SAA_ACCESS_R;
877 }
878
879 if (pDst->alphaMap && pDst->alphaMap->pDrawable)
880 if (!saa_prepare_access_pixmap
881 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable),
882 *access, dstReg))
883 goto out_no_dst_alpha;
884
885 if (!saa_prepare_access_pixmap(pDstPix, *access, dstReg))
886 goto out_no_dst;
887
888 return TRUE;
889
890 out_no_dst:
891 LogMessage(X_ERROR, "No dst\n");
892 saa_finish_access_pixmap
893 (saa_get_drawable_pixmap(pDst->alphaMap->pDrawable), *access);
894 out_no_dst_alpha:
895 LogMessage(X_ERROR, "No dst alpha\n");
896 if (pMaskPix)
897 saa_finish_access_pixmap(pMaskPix, SAA_ACCESS_R);
898 out_no_mask:
899 LogMessage(X_ERROR, "No mask\n");
900 if (pSrcPix)
901 saa_finish_access_pixmap(pSrcPix, SAA_ACCESS_R);
902 out_no_src:
903 LogMessage(X_ERROR, "No src\n");
904 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
905 saa_fad_read(pMask->alphaMap->pDrawable);
906 out_no_mask_alpha:
907 LogMessage(X_ERROR, "No mask alpha\n");
908 if (pSrc && pSrc->alphaMap && pSrc->alphaMap->pDrawable)
909 saa_fad_read(pSrc->alphaMap->pDrawable);
910 out_no_src_alpha:
911 LogMessage(X_ERROR, "No src alpha\n");
912 return FALSE;
913
914 }
915
916 void
saa_check_composite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height,RegionPtr src_region,RegionPtr mask_region,RegionPtr dst_region)917 saa_check_composite(CARD8 op,
918 PicturePtr pSrc,
919 PicturePtr pMask,
920 PicturePtr pDst,
921 INT16 xSrc,
922 INT16 ySrc,
923 INT16 xMask,
924 INT16 yMask,
925 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height,
926 RegionPtr src_region,
927 RegionPtr mask_region,
928 RegionPtr dst_region)
929 {
930 ScreenPtr pScreen = pDst->pDrawable->pScreen;
931 PictureScreenPtr ps = GetPictureScreen(pScreen);
932 struct saa_screen_priv *sscreen = saa_screen(pScreen);
933 saa_access_t access;
934 PixmapPtr pixmap;
935
936 sscreen->fallback_count++;
937 if (!saa_prepare_composite_reg(pScreen, op, pSrc, pMask, pDst, xSrc,
938 ySrc, xMask, yMask, xDst, yDst, width,
939 height,
940 src_region,
941 mask_region,
942 dst_region,
943 &access)) {
944 goto out_no_access;;
945 }
946
947 saa_swap(sscreen, ps, Composite);
948 ps->Composite(op,
949 pSrc,
950 pMask,
951 pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
952 saa_swap(sscreen, ps, Composite);
953 if (pMask && pMask->pDrawable != NULL)
954 saa_fad_read(pMask->pDrawable);
955 if (pSrc->pDrawable != NULL)
956 saa_fad_read(pSrc->pDrawable);
957 pixmap = saa_get_drawable_pixmap(pDst->pDrawable);
958 saa_finish_access_pixmap(pixmap, access);
959 saa_pixmap_dirty(pixmap, FALSE, dst_region);
960 if (pDst->alphaMap && pDst->alphaMap->pDrawable) {
961 pixmap = saa_get_drawable_pixmap(pDst->alphaMap->pDrawable);
962 saa_finish_access_pixmap(pixmap, access);
963 saa_pixmap_dirty(pixmap, FALSE, dst_region);
964 }
965 if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
966 saa_fad_read(pSrc->alphaMap->pDrawable);
967 if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
968 saa_fad_read(pMask->alphaMap->pDrawable);
969 out_no_access:
970 sscreen->fallback_count--;
971 }
972
973 static void
saa_check_add_traps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)974 saa_check_add_traps(PicturePtr pPicture,
975 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
976 {
977 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
978 PictureScreenPtr ps = GetPictureScreen(pScreen);
979 struct saa_screen_priv *sscreen = saa_screen(pScreen);
980 saa_access_t access;
981
982 SAA_FALLBACK(("to pict %p (%c)\n", saa_drawable_loc(pPicture->pDrawable)));
983
984 sscreen->fallback_count++;
985 if (!saa_pad_write(pPicture->pDrawable, NULL, FALSE, &access))
986 goto out_no_access;
987 saa_swap(sscreen, ps, AddTraps);
988 ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
989 saa_swap(sscreen, ps, AddTraps);
990 saa_fad_write(pPicture->pDrawable, access);
991 out_no_access:
992 sscreen->fallback_count--;
993 }
994
995 #endif
996
997 void
saa_unaccel_setup(ScreenPtr pScreen)998 saa_unaccel_setup(ScreenPtr pScreen)
999 {
1000 #ifdef RENDER
1001 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
1002 #endif
1003 struct saa_screen_priv *sscreen = saa_screen(pScreen);
1004
1005 saa_wrap(sscreen, pScreen, GetImage, saa_check_get_image);
1006 saa_wrap(sscreen, pScreen, GetSpans, saa_check_get_spans);
1007 saa_wrap(sscreen, pScreen, CopyWindow, saa_check_copy_window);
1008
1009 #ifdef RENDER
1010 if (ps) {
1011 saa_wrap(sscreen, ps, AddTraps, saa_check_add_traps);
1012 }
1013 #endif
1014 }
1015
1016 void
saa_unaccel_takedown(ScreenPtr pScreen)1017 saa_unaccel_takedown(ScreenPtr pScreen)
1018 {
1019 #ifdef RENDER
1020 PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
1021 #endif
1022 struct saa_screen_priv *sscreen = saa_screen(pScreen);
1023
1024 saa_unwrap(sscreen, pScreen, GetImage);
1025 saa_unwrap(sscreen, pScreen, GetSpans);
1026 saa_unwrap(sscreen, pScreen, CopyWindow);
1027
1028 #ifdef RENDER
1029 if (ps) {
1030 saa_unwrap(sscreen, ps, AddTraps);
1031 }
1032 #endif
1033 }
1034
1035 GCOps saa_gc_ops = {
1036 saa_check_fill_spans,
1037 saa_check_set_spans,
1038 saa_check_put_image,
1039 saa_copy_area,
1040 saa_check_copy_plane,
1041 saa_check_poly_point,
1042 saa_check_poly_lines,
1043 saa_check_poly_segment,
1044 miPolyRectangle,
1045 saa_check_poly_arc,
1046 miFillPolygon,
1047 saa_check_poly_fill_rect,
1048 miPolyFillArc,
1049 miPolyText8,
1050 miPolyText16,
1051 miImageText8,
1052 miImageText16,
1053 saa_check_image_glyph_blt,
1054 saa_check_poly_glyph_blt,
1055 saa_check_push_pixels,
1056 };
1057