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