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