2 * Copyright © 2005 Novell, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Novell, Inc. not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * Novell, Inc. makes no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
15 * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: David Reveman <davidr@novell.com>
32 #define XGL_TRAP_FALLBACK_PROLOGUE(pPicture, func) \
33 xglSyncDamageBoxBits (pPicture->pDrawable); \
34 XGL_PICTURE_SCREEN_UNWRAP (func)
36 #define XGL_TRAP_FALLBACK_EPILOGUE(pPicture, func, xglfunc) \
37 XGL_PICTURE_SCREEN_WRAP (func, xglfunc); \
38 xglAddCurrentSurfaceDamage (pPicture->pDrawable)
41 #define SMOOTH_TRAPS_ESTIMATE_RECTS(nTrap) (30 * nTrap)
43 #define LINE_FIXED_X(l, _y, v) \
44 dx = (l)->p2.x - (l)->p1.x; \
45 ex = (xFixed_32_32) ((_y) - (l)->p1.y) * dx; \
46 dy = (l)->p2.y - (l)->p1.y; \
47 (v) = (l)->p1.x + (xFixed) (ex / dy)
49 #define LINE_FIXED_X_CEIL(l, _y, v) \
50 dx = (l)->p2.x - (l)->p1.x; \
51 ex = (xFixed_32_32) ((_y) - (l)->p1.y) * dx; \
52 dy = (l)->p2.y - (l)->p1.y; \
53 (v) = (l)->p1.x + (xFixed) ((ex + (dy - 1)) / dy)
56 xglTrapezoidExtents (PicturePtr pDst
,
61 Bool x_overlap
, overlap
= FALSE
;
62 xFixed dx
, dy
, top
, bottom
;
67 extents
->x1
= MAXSHORT
;
68 extents
->x2
= MINSHORT
;
69 extents
->y1
= MAXSHORT
;
70 extents
->y2
= MINSHORT
;
75 extents
->y1
= xFixedToInt (traps
->top
);
76 extents
->y2
= xFixedToInt (xFixedCeil (traps
->bottom
));
78 LINE_FIXED_X (&traps
->left
, traps
->top
, top
);
79 LINE_FIXED_X (&traps
->left
, traps
->bottom
, bottom
);
80 extents
->x1
= xFixedToInt (MIN (top
, bottom
));
82 LINE_FIXED_X_CEIL (&traps
->right
, traps
->top
, top
);
83 LINE_FIXED_X_CEIL (&traps
->right
, traps
->bottom
, bottom
);
84 extents
->x2
= xFixedToInt (xFixedCeil (MAX (top
, bottom
)));
89 for (; ntrap
; ntrap
--, traps
++)
93 if (!xTrapezoidValid (traps
))
96 y1
= xFixedToInt (traps
->top
);
97 y2
= xFixedToInt (xFixedCeil (traps
->bottom
));
99 LINE_FIXED_X (&traps
->left
, traps
->top
, top
);
100 LINE_FIXED_X (&traps
->left
, traps
->bottom
, bottom
);
101 x1
= xFixedToInt (MIN (top
, bottom
));
103 LINE_FIXED_X_CEIL (&traps
->right
, traps
->top
, top
);
104 LINE_FIXED_X_CEIL (&traps
->right
, traps
->bottom
, bottom
);
105 x2
= xFixedToInt (xFixedCeil (MAX (top
, bottom
)));
108 if (x1
>= extents
->x2
)
110 else if (x2
<= extents
->x1
)
115 if (x1
< extents
->x1
)
117 if (x2
> extents
->x2
)
121 if (y1
>= extents
->y2
)
123 else if (y2
<= extents
->y1
)
127 if (y1
< extents
->y1
)
129 if (y2
> extents
->y2
)
137 xglPictureClipExtents (pDst
, extents
);
143 xglTrapezoids (CARD8 op
,
146 PictFormatPtr maskFormat
,
152 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
153 PicturePtr pMask
= NULL
, pSrcPicture
, pDstPicture
;
154 PicturePtr pMaskPicture
= NULL
;
155 xglGeometryPtr pGeometry
= NULL
;
156 unsigned int polyEdge
= pDst
->polyEdge
;
163 XGL_SCREEN_PRIV (pScreen
);
165 xDst
= traps
[0].left
.p1
.x
>> 16;
166 yDst
= traps
[0].left
.p1
.y
>> 16;
168 overlap
= xglTrapezoidExtents (pDst
, nTrap
, traps
, &extents
);
169 if (extents
.y1
>= extents
.y2
|| extents
.x1
>= extents
.x2
)
172 target
= xglPrepareTarget (pDst
->pDrawable
);
174 if (nTrap
> 1 && op
!= PictOpAdd
&& maskFormat
&&
175 (!target
|| overlap
|| op
!= PictOpOver
))
183 if (!pScreenPriv
->pSolidAlpha
)
185 xglCreateSolidAlphaPicture (pScreen
);
186 if (!pScreenPriv
->pSolidAlpha
)
192 rect
.width
= extents
.x2
- extents
.x1
;
193 rect
.height
= extents
.y2
- extents
.y1
;
195 pPixmap
= (*pScreen
->CreatePixmap
) (pScreen
,
196 rect
.width
, rect
.height
,
201 pMask
= CreatePicture (0, &pPixmap
->drawable
, maskFormat
,
202 0, 0, serverClient
, &error
);
205 (*pScreen
->DestroyPixmap
) (pPixmap
);
211 /* make sure we don't do accelerated drawing to mask */
212 xglSetPixmapVisual (pPixmap
, NULL
);
215 area
= rect
.width
* rect
.height
;
216 if ((SMOOTH_TRAPS_ESTIMATE_RECTS (nTrap
) * 4) > area
)
217 XGL_GET_PIXMAP_PRIV (pPixmap
)->target
= xglPixmapTargetNo
;
219 ValidatePicture (pMask
);
220 pGC
= GetScratchGC (pPixmap
->drawable
.depth
, pScreen
);
221 ValidateGC (&pPixmap
->drawable
, pGC
);
222 (*pGC
->ops
->PolyFillRect
) (&pPixmap
->drawable
, pGC
, 1, &rect
);
225 (*pScreen
->DestroyPixmap
) (pPixmap
);
227 target
= xglPrepareTarget (pMask
->pDrawable
);
231 pSrcPicture
= pScreenPriv
->pSolidAlpha
;
238 if (maskFormat
->depth
== 1)
239 polyEdge
= PolyEdgeSharp
;
241 polyEdge
= PolyEdgeSmooth
;
252 if (maskFormat
|| polyEdge
== PolyEdgeSmooth
)
254 glitz_vertex_format_t
*format
;
255 glitz_surface_t
*mask
;
256 xTrapezoid
*pTrap
= traps
;
257 int nAddedTrap
, n
= nTrap
;
259 int size
= SMOOTH_TRAPS_ESTIMATE_RECTS (n
);
261 pMaskPicture
= pScreenPriv
->trapInfo
.pMask
;
262 format
= &pScreenPriv
->trapInfo
.format
.vertex
;
263 mask
= pMaskPicture
->pSourcePict
->source
.devPrivate
.ptr
;
265 size
*= format
->bytes_per_vertex
;
266 pGeometry
= xglGetScratchGeometryWithSize (pScreen
, size
);
270 if (pGeometry
->size
< size
)
271 GEOMETRY_RESIZE (pScreen
, pGeometry
, size
);
273 if (!pGeometry
->buffer
)
276 FreePicture (pMask
, 0);
282 glitz_add_trapezoids (pGeometry
->buffer
,
283 offset
, size
- offset
, format
->type
,
284 mask
, (glitz_trapezoid_t
*) pTrap
, n
,
292 pGeometry
->f
= pScreenPriv
->trapInfo
.format
;
293 pGeometry
->count
= offset
/ format
->bytes_per_vertex
;
298 xglGetScratchVertexGeometryWithType (pScreen
,
299 GEOMETRY_DATA_TYPE_FLOAT
,
301 if (!pGeometry
->buffer
)
304 FreePicture (pMask
, 0);
309 GEOMETRY_ADD_TRAPEZOID (pScreen
, pGeometry
, traps
, nTrap
);
312 GEOMETRY_TRANSLATE (pGeometry
,
313 pDstPicture
->pDrawable
->x
+ xOff
,
314 pDstPicture
->pDrawable
->y
+ yOff
);
318 xglCompositeGeneral (pMask
? PictOpAdd
: op
,
323 extents
.x1
+ xOff
+ xSrc
- xDst
,
324 extents
.y1
+ yOff
+ ySrc
- yDst
,
326 pDstPicture
->pDrawable
->x
+ extents
.x1
+ xOff
,
327 pDstPicture
->pDrawable
->y
+ extents
.y1
+ yOff
,
328 extents
.x2
- extents
.x1
,
329 extents
.y2
- extents
.y1
))
331 /* no intermediate mask? we need to register damage from here as
332 CompositePicture will never be called. */
337 REGION_INIT (pScreen
, ®ion
, &extents
, 1);
338 REGION_TRANSLATE (pScreen
, ®ion
,
339 pDst
->pDrawable
->x
, pDst
->pDrawable
->y
);
341 DamageDamageRegion (pDst
->pDrawable
, ®ion
);
343 REGION_UNINIT (pScreen
, ®ion
);
346 xglAddCurrentBitDamage (pDstPicture
->pDrawable
);
350 XGL_DRAWABLE_PIXMAP_PRIV (pDstPicture
->pDrawable
);
352 pPixmapPriv
->damageBox
.x1
= extents
.x1
+ xOff
;
353 pPixmapPriv
->damageBox
.y1
= extents
.y1
+ yOff
;
354 pPixmapPriv
->damageBox
.x2
= extents
.x2
+ xOff
;
355 pPixmapPriv
->damageBox
.y2
= extents
.y2
+ yOff
;
357 xglSyncDamageBoxBits (pDstPicture
->pDrawable
);
359 if (pMask
|| (polyEdge
== PolyEdgeSmooth
&&
360 op
== PictOpAdd
&& miIsSolidAlpha (pSrc
)))
362 PictureScreenPtr ps
= GetPictureScreen (pScreen
);
364 for (; nTrap
; nTrap
--, traps
++)
365 (*ps
->RasterizeTrapezoid
) (pDstPicture
, traps
, xOff
, yOff
);
367 xglAddCurrentSurfaceDamage (pDstPicture
->pDrawable
);
370 miTrapezoids (op
, pSrc
, pDstPicture
, maskFormat
,
371 xSrc
, ySrc
, nTrap
, traps
);
376 CompositePicture (op
, pSrc
, pMask
, pDst
,
377 extents
.x1
+ xSrc
- xDst
,
378 extents
.y1
+ ySrc
- yDst
,
380 extents
.x1
, extents
.y1
,
381 extents
.x2
- extents
.x1
,
382 extents
.y2
- extents
.y1
);
384 FreePicture (pMask
, 0);
389 xglAddTraps (PicturePtr pDst
,
395 PictureScreenPtr pPictureScreen
;
396 ScreenPtr pScreen
= pDst
->pDrawable
->pScreen
;
398 XGL_SCREEN_PRIV (pScreen
);
399 XGL_DRAWABLE_PIXMAP_PRIV (pDst
->pDrawable
);
401 if (!pScreenPriv
->pSolidAlpha
)
403 xglCreateSolidAlphaPicture (pScreen
);
404 if (!pScreenPriv
->pSolidAlpha
)
408 pPixmapPriv
->damageBox
.x1
= 0;
409 pPixmapPriv
->damageBox
.y1
= 0;
410 pPixmapPriv
->damageBox
.x2
= pDst
->pDrawable
->width
;
411 pPixmapPriv
->damageBox
.y2
= pDst
->pDrawable
->height
;
413 if (xglPrepareTarget (pDst
->pDrawable
))
416 glitz_vertex_format_t
*format
;
417 glitz_surface_t
*mask
;
418 xglGeometryPtr pGeometry
;
419 xTrap
*pTrap
= traps
;
420 int nAddedTrap
, n
= nTrap
;
422 int size
= SMOOTH_TRAPS_ESTIMATE_RECTS (n
);
424 pMask
= pScreenPriv
->trapInfo
.pMask
;
425 format
= &pScreenPriv
->trapInfo
.format
.vertex
;
426 mask
= pMask
->pSourcePict
->source
.devPrivate
.ptr
;
428 size
*= format
->bytes_per_vertex
;
429 pGeometry
= xglGetScratchGeometryWithSize (pScreen
, size
);
433 if (pGeometry
->size
< size
)
434 GEOMETRY_RESIZE (pScreen
, pGeometry
, size
);
436 if (!pGeometry
->buffer
)
440 glitz_add_traps (pGeometry
->buffer
,
441 offset
, size
- offset
, format
->type
, mask
,
442 (glitz_trap_t
*) pTrap
, n
,
450 pGeometry
->f
= pScreenPriv
->trapInfo
.format
;
451 pGeometry
->count
= offset
/ format
->bytes_per_vertex
;
453 GEOMETRY_TRANSLATE (pGeometry
,
454 pDst
->pDrawable
->x
+ xOff
,
455 pDst
->pDrawable
->y
+ yOff
);
457 if (xglCompositeGeneral (PictOpAdd
,
458 pScreenPriv
->pSolidAlpha
,
464 pDst
->pDrawable
->x
, pDst
->pDrawable
->y
,
465 pDst
->pDrawable
->width
,
466 pDst
->pDrawable
->height
))
468 xglAddCurrentBitDamage (pDst
->pDrawable
);
473 pPictureScreen
= GetPictureScreen (pScreen
);
475 XGL_TRAP_FALLBACK_PROLOGUE (pDst
, AddTraps
);
476 (*pPictureScreen
->AddTraps
) (pDst
, xOff
, yOff
, nTrap
, traps
);
477 XGL_TRAP_FALLBACK_EPILOGUE (pDst
, AddTraps
, xglAddTraps
);