1 /*
2 *
3 * Copyright � 1999 Keith Packard
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of Keith Packard not be used in
10 * advertising or publicity pertaining to distribution of the software without
11 * specific, written prior permission. Keith Packard makes no
12 * representations about the suitability of this software for any purpose. It
13 * is provided "as is" without express or implied warranty.
14 *
15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21 * PERFORMANCE OF THIS SOFTWARE.
22 */
23
24 #include "uxa-priv.h"
25
26 /*
27 * These functions wrap the low-level fb rendering functions and
28 * synchronize framebuffer/accelerated drawing by stalling until
29 * the accelerator is idle
30 */
31
32 /**
33 * Calls uxa_prepare_access with UXA_PREPARE_SRC for the tile, if that is the
34 * current fill style.
35 *
36 * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
37 * 1bpp and never in fb, so we don't worry about them.
38 * We should worry about them for completeness sake and going forward.
39 */
uxa_prepare_access_gc(GCPtr pGC)40 Bool uxa_prepare_access_gc(GCPtr pGC)
41 {
42 if (pGC->stipple)
43 if (!uxa_prepare_access(&pGC->stipple->drawable, UXA_ACCESS_RO))
44 return FALSE;
45 if (pGC->fillStyle == FillTiled)
46 if (!uxa_prepare_access
47 (&pGC->tile.pixmap->drawable, UXA_ACCESS_RO)) {
48 if (pGC->stipple)
49 uxa_finish_access(&pGC->stipple->drawable, UXA_ACCESS_RO);
50 return FALSE;
51 }
52 return TRUE;
53 }
54
55 /**
56 * Finishes access to the tile in the GC, if used.
57 */
uxa_finish_access_gc(GCPtr pGC)58 void uxa_finish_access_gc(GCPtr pGC)
59 {
60 if (pGC->fillStyle == FillTiled)
61 uxa_finish_access(&pGC->tile.pixmap->drawable, UXA_ACCESS_RO);
62 if (pGC->stipple)
63 uxa_finish_access(&pGC->stipple->drawable, UXA_ACCESS_RO);
64 }
65
uxa_picture_prepare_access(PicturePtr picture,int mode)66 Bool uxa_picture_prepare_access(PicturePtr picture, int mode)
67 {
68 if (picture->pDrawable == NULL)
69 return TRUE;
70
71 if (!uxa_prepare_access(picture->pDrawable, mode))
72 return FALSE;
73
74 if (picture->alphaMap &&
75 !uxa_prepare_access(picture->alphaMap->pDrawable, mode)) {
76 uxa_finish_access(picture->pDrawable, mode);
77 return FALSE;
78 }
79
80 return TRUE;
81 }
82
uxa_picture_finish_access(PicturePtr picture,int mode)83 void uxa_picture_finish_access(PicturePtr picture, int mode)
84 {
85 if (picture->pDrawable == NULL)
86 return;
87
88 uxa_finish_access(picture->pDrawable, mode);
89 if (picture->alphaMap)
90 uxa_finish_access(picture->alphaMap->pDrawable, mode);
91 }
92
93
uxa_drawable_location(DrawablePtr pDrawable)94 char uxa_drawable_location(DrawablePtr pDrawable)
95 {
96 return uxa_drawable_is_offscreen(pDrawable) ? 's' : 'm';
97 }
98
99 void
uxa_check_fill_spans(DrawablePtr pDrawable,GCPtr pGC,int nspans,DDXPointPtr ppt,int * pwidth,int fSorted)100 uxa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
101 DDXPointPtr ppt, int *pwidth, int fSorted)
102 {
103 ScreenPtr screen = pDrawable->pScreen;
104
105 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
106 uxa_drawable_location(pDrawable)));
107 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
108 if (uxa_prepare_access_gc(pGC)) {
109 fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
110 fSorted);
111 uxa_finish_access_gc(pGC);
112 }
113 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
114 }
115 }
116
117 void
uxa_check_set_spans(DrawablePtr pDrawable,GCPtr pGC,char * psrc,DDXPointPtr ppt,int * pwidth,int nspans,int fSorted)118 uxa_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
119 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
120 {
121 ScreenPtr screen = pDrawable->pScreen;
122
123 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
124 uxa_drawable_location(pDrawable)));
125 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
126 fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
127 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
128 }
129 }
130
131 void
uxa_check_put_image(DrawablePtr pDrawable,GCPtr pGC,int depth,int x,int y,int w,int h,int leftPad,int format,char * bits)132 uxa_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
133 int x, int y, int w, int h, int leftPad, int format,
134 char *bits)
135 {
136 ScreenPtr screen = pDrawable->pScreen;
137
138 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
139 uxa_drawable_location(pDrawable)));
140 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
141 fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
142 bits);
143 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
144 }
145 }
146
147 RegionPtr
uxa_check_copy_area(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty)148 uxa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
149 int srcx, int srcy, int w, int h, int dstx, int dsty)
150 {
151 ScreenPtr screen = pSrc->pScreen;
152 RegionPtr ret = NULL;
153
154 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
155 uxa_drawable_location(pSrc),
156 uxa_drawable_location(pDst)));
157 if (uxa_prepare_access(pDst, UXA_ACCESS_RW)) {
158 if (uxa_prepare_access(pSrc, UXA_ACCESS_RO)) {
159 ret =
160 fbCopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
161 dsty);
162 uxa_finish_access(pSrc, UXA_ACCESS_RO);
163 }
164 uxa_finish_access(pDst, UXA_ACCESS_RW);
165 }
166 return ret;
167 }
168
169 RegionPtr
uxa_check_copy_plane(DrawablePtr pSrc,DrawablePtr pDst,GCPtr pGC,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long bitPlane)170 uxa_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
171 int srcx, int srcy, int w, int h, int dstx, int dsty,
172 unsigned long bitPlane)
173 {
174 ScreenPtr screen = pSrc->pScreen;
175 RegionPtr ret = NULL;
176
177 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
178 uxa_drawable_location(pSrc),
179 uxa_drawable_location(pDst)));
180 if (uxa_prepare_access(pDst, UXA_ACCESS_RW)) {
181 if (uxa_prepare_access(pSrc, UXA_ACCESS_RO)) {
182 ret =
183 fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
184 dsty, bitPlane);
185 uxa_finish_access(pSrc, UXA_ACCESS_RO);
186 }
187 uxa_finish_access(pDst, UXA_ACCESS_RW);
188 }
189 return ret;
190 }
191
192 void
uxa_check_poly_point(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr pptInit)193 uxa_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
194 DDXPointPtr pptInit)
195 {
196 ScreenPtr screen = pDrawable->pScreen;
197
198 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
199 uxa_drawable_location(pDrawable)));
200 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
201 fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
202 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
203 }
204 }
205
206 void
uxa_check_poly_lines(DrawablePtr pDrawable,GCPtr pGC,int mode,int npt,DDXPointPtr ppt)207 uxa_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
208 int mode, int npt, DDXPointPtr ppt)
209 {
210 ScreenPtr screen = pDrawable->pScreen;
211
212 UXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
213 pDrawable, uxa_drawable_location(pDrawable),
214 pGC->lineWidth, mode, npt));
215
216 if (pGC->lineWidth == 0) {
217 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
218 if (uxa_prepare_access_gc(pGC)) {
219 fbPolyLine(pDrawable, pGC, mode, npt, ppt);
220 uxa_finish_access_gc(pGC);
221 }
222 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
223 }
224 return;
225 }
226 /* fb calls mi functions in the lineWidth != 0 case. */
227 fbPolyLine(pDrawable, pGC, mode, npt, ppt);
228 }
229
230 void
uxa_check_poly_segment(DrawablePtr pDrawable,GCPtr pGC,int nsegInit,xSegment * pSegInit)231 uxa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
232 int nsegInit, xSegment * pSegInit)
233 {
234 ScreenPtr screen = pDrawable->pScreen;
235
236 UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
237 uxa_drawable_location(pDrawable), pGC->lineWidth,
238 nsegInit));
239 if (pGC->lineWidth == 0) {
240 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
241 if (uxa_prepare_access_gc(pGC)) {
242 fbPolySegment(pDrawable, pGC, nsegInit,
243 pSegInit);
244 uxa_finish_access_gc(pGC);
245 }
246 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
247 }
248 return;
249 }
250 /* fb calls mi functions in the lineWidth != 0 case. */
251 fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
252 }
253
254 void
uxa_check_poly_arc(DrawablePtr pDrawable,GCPtr pGC,int narcs,xArc * pArcs)255 uxa_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
256 {
257 ScreenPtr screen = pDrawable->pScreen;
258
259 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
260 uxa_drawable_location(pDrawable)));
261
262 /* Disable this as fbPolyArc can call miZeroPolyArc which in turn
263 * can call accelerated functions, that as yet, haven't been notified
264 * with uxa_finish_access().
265 */
266 #if 0
267 if (pGC->lineWidth == 0) {
268 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
269 if (uxa_prepare_access_gc(pGC)) {
270 fbPolyArc(pDrawable, pGC, narcs, pArcs);
271 uxa_finish_access_gc(pGC);
272 }
273 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
274 }
275 return;
276 }
277 #endif
278 miPolyArc(pDrawable, pGC, narcs, pArcs);
279 }
280
281 void
uxa_check_poly_fill_rect(DrawablePtr pDrawable,GCPtr pGC,int nrect,xRectangle * prect)282 uxa_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
283 int nrect, xRectangle * prect)
284 {
285 ScreenPtr screen = pDrawable->pScreen;
286
287 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
288 uxa_drawable_location(pDrawable)));
289
290 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
291 if (uxa_prepare_access_gc(pGC)) {
292 fbPolyFillRect(pDrawable, pGC, nrect, prect);
293 uxa_finish_access_gc(pGC);
294 }
295 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
296 }
297 }
298
299 void
uxa_check_image_glyph_blt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,pointer pglyphBase)300 uxa_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
301 int x, int y, unsigned int nglyph,
302 CharInfoPtr * ppci, pointer pglyphBase)
303 {
304 ScreenPtr screen = pDrawable->pScreen;
305
306 UXA_FALLBACK(("to %p (%c)\n", pDrawable,
307 uxa_drawable_location(pDrawable)));
308 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
309 if (uxa_prepare_access_gc(pGC)) {
310 fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
311 pglyphBase);
312 uxa_finish_access_gc(pGC);
313 }
314 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
315 }
316 }
317
318 void
uxa_check_poly_glyph_blt(DrawablePtr pDrawable,GCPtr pGC,int x,int y,unsigned int nglyph,CharInfoPtr * ppci,pointer pglyphBase)319 uxa_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
320 int x, int y, unsigned int nglyph,
321 CharInfoPtr * ppci, pointer pglyphBase)
322 {
323 ScreenPtr screen = pDrawable->pScreen;
324
325 UXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
326 uxa_drawable_location(pDrawable), pGC->fillStyle,
327 pGC->alu));
328 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
329 if (uxa_prepare_access_gc(pGC)) {
330 fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
331 pglyphBase);
332 uxa_finish_access_gc(pGC);
333 }
334 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
335 }
336 }
337
338 void
uxa_check_push_pixels(GCPtr pGC,PixmapPtr pBitmap,DrawablePtr pDrawable,int w,int h,int x,int y)339 uxa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
340 DrawablePtr pDrawable, int w, int h, int x, int y)
341 {
342 ScreenPtr screen = pDrawable->pScreen;
343
344 UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
345 uxa_drawable_location(&pBitmap->drawable),
346 uxa_drawable_location(pDrawable)));
347 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RW)) {
348 if (uxa_prepare_access(&pBitmap->drawable, UXA_ACCESS_RO)) {
349 if (uxa_prepare_access_gc(pGC)) {
350 fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
351 y);
352 uxa_finish_access_gc(pGC);
353 }
354 uxa_finish_access(&pBitmap->drawable, UXA_ACCESS_RO);
355 }
356 uxa_finish_access(pDrawable, UXA_ACCESS_RW);
357 }
358 }
359
360 void
uxa_check_get_spans(DrawablePtr pDrawable,int wMax,DDXPointPtr ppt,int * pwidth,int nspans,char * pdstStart)361 uxa_check_get_spans(DrawablePtr pDrawable,
362 int wMax,
363 DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
364 {
365 ScreenPtr screen = pDrawable->pScreen;
366
367 UXA_FALLBACK(("from %p (%c)\n", pDrawable,
368 uxa_drawable_location(pDrawable)));
369 if (uxa_prepare_access(pDrawable, UXA_ACCESS_RO)) {
370 fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
371 uxa_finish_access(pDrawable, UXA_ACCESS_RO);
372 }
373 }
374
375 void
uxa_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)376 uxa_check_composite(CARD8 op,
377 PicturePtr pSrc,
378 PicturePtr pMask,
379 PicturePtr pDst,
380 INT16 xSrc, INT16 ySrc,
381 INT16 xMask, INT16 yMask,
382 INT16 xDst, INT16 yDst,
383 CARD16 width, CARD16 height)
384 {
385 ScreenPtr screen = pDst->pDrawable->pScreen;
386
387 UXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
388
389 if (uxa_picture_prepare_access(pDst, UXA_ACCESS_RW)) {
390 if (uxa_picture_prepare_access(pSrc, UXA_ACCESS_RO)) {
391 if (!pMask || uxa_picture_prepare_access(pMask, UXA_ACCESS_RO)) {
392 fbComposite(op, pSrc, pMask, pDst,
393 xSrc, ySrc,
394 xMask, yMask,
395 xDst, yDst,
396 width, height);
397 if (pMask)
398 uxa_picture_finish_access(pMask, UXA_ACCESS_RO);
399 }
400 uxa_picture_finish_access(pSrc, UXA_ACCESS_RO);
401 }
402 uxa_picture_finish_access(pDst, UXA_ACCESS_RW);
403 }
404 }
405
406 void
uxa_check_add_traps(PicturePtr pPicture,INT16 x_off,INT16 y_off,int ntrap,xTrap * traps)407 uxa_check_add_traps(PicturePtr pPicture,
408 INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
409 {
410 ScreenPtr screen = pPicture->pDrawable->pScreen;
411
412 UXA_FALLBACK(("to pict %p (%c)\n", pPicture,
413 uxa_drawable_location(pPicture->pDrawable)));
414 if (uxa_picture_prepare_access(pPicture, UXA_ACCESS_RW)) {
415 fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
416 uxa_picture_finish_access(pPicture, UXA_ACCESS_RW);
417 }
418 }
419
420 /**
421 * Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
422 * that happen to be 1x1. Pixmap must be at least 8bpp.
423 *
424 * XXX This really belongs in fb, so it can be aware of tiling and etc.
425 */
uxa_get_pixmap_first_pixel(PixmapPtr pPixmap)426 CARD32 uxa_get_pixmap_first_pixel(PixmapPtr pPixmap)
427 {
428 CARD32 pixel;
429 void *fb;
430
431 if (!uxa_prepare_access(&pPixmap->drawable, UXA_ACCESS_RO))
432 return 0;
433
434 fb = pPixmap->devPrivate.ptr;
435
436 switch (pPixmap->drawable.bitsPerPixel) {
437 case 32:
438 pixel = *(CARD32 *) fb;
439 break;
440 case 16:
441 pixel = *(CARD16 *) fb;
442 break;
443 default:
444 pixel = *(CARD8 *) fb;
445 break;
446 }
447 uxa_finish_access(&pPixmap->drawable, UXA_ACCESS_RO);
448
449 return pixel;
450 }
451