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, &reg, &box, 1);
679     REGION_UNION(pScreen, dst, dst, &reg);
680     REGION_UNINIT(pScreen, &reg);
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