exa_unaccel.c revision 05b261ec
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 "exa_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 exaPrepareAccess with EXA_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 */
39void
40exaPrepareAccessGC(GCPtr pGC)
41{
42    if (pGC->fillStyle == FillTiled)
43	exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
44}
45
46/**
47 * Finishes access to the tile in the GC, if used.
48 */
49void
50exaFinishAccessGC(GCPtr pGC)
51{
52    if (pGC->fillStyle == FillTiled)
53	exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
54}
55
56#if DEBUG_TRACE_FALL
57char
58exaDrawableLocation(DrawablePtr pDrawable)
59{
60    return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm';
61}
62#endif /* DEBUG_TRACE_FALL */
63
64void
65ExaCheckFillSpans (DrawablePtr pDrawable, GCPtr pGC, int nspans,
66		   DDXPointPtr ppt, int *pwidth, int fSorted)
67{
68    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
69    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
70    exaPrepareAccessGC (pGC);
71    fbFillSpans (pDrawable, pGC, nspans, ppt, pwidth, fSorted);
72    exaFinishAccessGC (pGC);
73    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
74}
75
76void
77ExaCheckSetSpans (DrawablePtr pDrawable, GCPtr pGC, char *psrc,
78		 DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
79{
80    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
81    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
82    fbSetSpans (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
83    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
84}
85
86void
87ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
88		 int x, int y, int w, int h, int leftPad, int format,
89		 char *bits)
90{
91    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
92    int xoff, yoff;
93
94    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
95    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
96    fbPutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
97    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
98    exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
99    exaPixmapDirty(pPixmap, x + xoff, y + yoff, x + xoff + w, y + yoff + h);
100}
101
102RegionPtr
103ExaCheckCopyArea (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
104		 int srcx, int srcy, int w, int h, int dstx, int dsty)
105{
106    RegionPtr ret;
107
108    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
109		  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
110    exaPrepareAccess (pDst, EXA_PREPARE_DEST);
111    exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
112    ret = fbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
113    exaFinishAccess (pSrc, EXA_PREPARE_SRC);
114    exaFinishAccess (pDst, EXA_PREPARE_DEST);
115
116    return ret;
117}
118
119RegionPtr
120ExaCheckCopyPlane (DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
121		  int srcx, int srcy, int w, int h, int dstx, int dsty,
122		  unsigned long bitPlane)
123{
124    RegionPtr ret;
125
126    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
127		  exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
128    exaPrepareAccess (pDst, EXA_PREPARE_DEST);
129    exaPrepareAccess (pSrc, EXA_PREPARE_SRC);
130    ret = fbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
131		       bitPlane);
132    exaFinishAccess (pSrc, EXA_PREPARE_SRC);
133    exaFinishAccess (pDst, EXA_PREPARE_DEST);
134
135    return ret;
136}
137
138void
139ExaCheckPolyPoint (DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
140		  DDXPointPtr pptInit)
141{
142    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
143    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
144    fbPolyPoint (pDrawable, pGC, mode, npt, pptInit);
145    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
146}
147
148void
149ExaCheckPolylines (DrawablePtr pDrawable, GCPtr pGC,
150		  int mode, int npt, DDXPointPtr ppt)
151{
152    EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
153		  pDrawable, exaDrawableLocation(pDrawable),
154		  pGC->lineWidth, mode, npt));
155
156    if (pGC->lineWidth == 0) {
157	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
158	exaPrepareAccessGC (pGC);
159	fbPolyLine (pDrawable, pGC, mode, npt, ppt);
160	exaFinishAccessGC (pGC);
161	exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
162	return;
163    }
164    /* fb calls mi functions in the lineWidth != 0 case. */
165    fbPolyLine (pDrawable, pGC, mode, npt, ppt);
166}
167
168void
169ExaCheckPolySegment (DrawablePtr pDrawable, GCPtr pGC,
170		    int nsegInit, xSegment *pSegInit)
171{
172    EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
173		  exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
174    if (pGC->lineWidth == 0) {
175	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
176	exaPrepareAccessGC (pGC);
177	fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
178	exaFinishAccessGC (pGC);
179	exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
180	return;
181    }
182    /* fb calls mi functions in the lineWidth != 0 case. */
183    fbPolySegment (pDrawable, pGC, nsegInit, pSegInit);
184}
185
186void
187ExaCheckPolyArc (DrawablePtr pDrawable, GCPtr pGC,
188		int narcs, xArc *pArcs)
189{
190    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
191    if (pGC->lineWidth == 0)
192    {
193	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
194	exaPrepareAccessGC (pGC);
195	fbPolyArc (pDrawable, pGC, narcs, pArcs);
196	exaFinishAccessGC (pGC);
197	exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
198	return;
199    }
200    miPolyArc (pDrawable, pGC, narcs, pArcs);
201}
202
203void
204ExaCheckPolyFillRect (DrawablePtr pDrawable, GCPtr pGC,
205		     int nrect, xRectangle *prect)
206{
207    EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
208
209    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
210    exaPrepareAccessGC (pGC);
211    fbPolyFillRect (pDrawable, pGC, nrect, prect);
212    exaFinishAccessGC (pGC);
213    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
214}
215
216void
217ExaCheckImageGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
218		      int x, int y, unsigned int nglyph,
219		      CharInfoPtr *ppci, pointer pglyphBase)
220{
221    EXA_FALLBACK(("to %p (%c)\n", pDrawable,
222		  exaDrawableLocation(pDrawable)));
223    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
224    exaPrepareAccessGC (pGC);
225    fbImageGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
226    exaFinishAccessGC (pGC);
227    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
228}
229
230void
231ExaCheckPolyGlyphBlt (DrawablePtr pDrawable, GCPtr pGC,
232		     int x, int y, unsigned int nglyph,
233		     CharInfoPtr *ppci, pointer pglyphBase)
234{
235    EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
236		  exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu));
237    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
238    exaPrepareAccessGC (pGC);
239    fbPolyGlyphBlt (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
240    exaFinishAccessGC (pGC);
241    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
242}
243
244void
245ExaCheckPushPixels (GCPtr pGC, PixmapPtr pBitmap,
246		   DrawablePtr pDrawable,
247		   int w, int h, int x, int y)
248{
249    EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
250		  exaDrawableLocation(&pBitmap->drawable),
251		  exaDrawableLocation(pDrawable)));
252    exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
253    exaPrepareAccessGC (pGC);
254    fbPushPixels (pGC, pBitmap, pDrawable, w, h, x, y);
255    exaFinishAccessGC (pGC);
256    exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
257}
258
259void
260ExaCheckGetImage (DrawablePtr pDrawable,
261		 int x, int y, int w, int h,
262		 unsigned int format, unsigned long planeMask,
263		 char *d)
264{
265    EXA_FALLBACK(("from %p (%c)\n", pDrawable,
266		  exaDrawableLocation(pDrawable)));
267    exaPrepareAccess (pDrawable, EXA_PREPARE_SRC);
268    fbGetImage (pDrawable, x, y, w, h, format, planeMask, d);
269    exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
270}
271
272void
273ExaCheckGetSpans (DrawablePtr pDrawable,
274		 int wMax,
275		 DDXPointPtr ppt,
276		 int *pwidth,
277		 int nspans,
278		 char *pdstStart)
279{
280    EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
281    exaPrepareAccess (pDrawable, EXA_PREPARE_SRC);
282    fbGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
283    exaFinishAccess (pDrawable, EXA_PREPARE_SRC);
284}
285
286void
287ExaCheckSaveAreas (PixmapPtr	pPixmap,
288		  RegionPtr	prgnSave,
289		  int		xorg,
290		  int		yorg,
291		  WindowPtr	pWin)
292{
293    EXA_FALLBACK(("from %p (%c)\n", &pPixmap->drawable,
294		  exaDrawableLocation(&pPixmap->drawable)));
295    exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST);
296    fbSaveAreas (pPixmap, prgnSave, xorg, yorg, pWin);
297    exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST);
298}
299
300void
301ExaCheckRestoreAreas (PixmapPtr	pPixmap,
302		     RegionPtr	prgnSave,
303		     int	xorg,
304		     int    	yorg,
305		     WindowPtr	pWin)
306{
307    EXA_FALLBACK(("to %p (%c)\n", &pPixmap->drawable,
308		  exaDrawableLocation(&pPixmap->drawable)));
309    exaPrepareAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST);
310    fbRestoreAreas (pPixmap, prgnSave, xorg, yorg, pWin);
311    exaFinishAccess ((DrawablePtr)pPixmap, EXA_PREPARE_DEST);
312}
313
314/* XXX: Note the lack of a prepare on the tile, if the window has a tiled
315 * background.  This function happens to only be called if pExaScr->swappedOut,
316 * so we actually end up not having to do it since the tile won't be in fb.
317 * That doesn't make this not dirty, though.
318 */
319void
320ExaCheckPaintWindow (WindowPtr pWin, RegionPtr pRegion, int what)
321{
322    EXA_FALLBACK(("from %p (%c)\n", pWin,
323		  exaDrawableLocation(&pWin->drawable)));
324    exaPrepareAccess (&pWin->drawable, EXA_PREPARE_DEST);
325    fbPaintWindow (pWin, pRegion, what);
326    exaFinishAccess (&pWin->drawable, EXA_PREPARE_DEST);
327}
328
329void
330ExaCheckComposite (CARD8      op,
331                   PicturePtr pSrc,
332                   PicturePtr pMask,
333                   PicturePtr pDst,
334                   INT16      xSrc,
335                   INT16      ySrc,
336                   INT16      xMask,
337                   INT16      yMask,
338                   INT16      xDst,
339                   INT16      yDst,
340                   CARD16     width,
341                   CARD16     height)
342{
343    EXA_FALLBACK(("from picts %p/%p to pict %p\n",
344		 pSrc, pMask, pDst));
345    exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
346    if (pSrc->pDrawable != NULL)
347	exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
348    if (pMask && pMask->pDrawable != NULL)
349	exaPrepareAccess (pMask->pDrawable, EXA_PREPARE_MASK);
350    fbComposite (op,
351                 pSrc,
352                 pMask,
353                 pDst,
354                 xSrc,
355                 ySrc,
356                 xMask,
357                 yMask,
358                 xDst,
359                 yDst,
360                 width,
361                 height);
362    if (pMask && pMask->pDrawable != NULL)
363	exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
364    if (pSrc->pDrawable != NULL)
365	exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
366    exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
367}
368
369/**
370 * Gets the 0,0 pixel of a pixmap.  Used for doing solid fills of tiled pixmaps
371 * that happen to be 1x1.  Pixmap must be at least 8bpp.
372 *
373 * XXX This really belongs in fb, so it can be aware of tiling and etc.
374 */
375CARD32
376exaGetPixmapFirstPixel (PixmapPtr pPixmap)
377{
378    CARD32 pixel;
379    void *fb;
380    Bool need_finish = FALSE;
381    BoxRec box;
382    ExaMigrationRec pixmaps[1];
383    ExaPixmapPriv (pPixmap);
384
385    fb = pExaPixmap->sys_ptr;
386
387    /* Try to avoid framebuffer readbacks */
388    if (exaPixmapIsOffscreen(pPixmap) &&
389        miPointInRegion(DamageRegion(pExaPixmap->pDamage), 0, 0,  &box))
390    {
391	need_finish = TRUE;
392	pixmaps[0].as_dst = FALSE;
393	pixmaps[0].as_src = TRUE;
394	pixmaps[0].pPix = pPixmap;
395	exaDoMigration (pixmaps, 1, FALSE);
396	exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
397	fb = pPixmap->devPrivate.ptr;
398    }
399
400    switch (pPixmap->drawable.bitsPerPixel) {
401    case 32:
402	pixel = *(CARD32 *)fb;
403	break;
404    case 16:
405	pixel = *(CARD16 *)fb;
406	break;
407    default:
408	pixel = *(CARD8 *)fb;
409	break;
410    }
411
412    if (need_finish)
413	exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
414
415    return pixel;
416}
417