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