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