First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xgl / xgltrap.c
blob26e2bc451eee54a72024477b8a3eeefb841cae56
1 /*
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
13 * implied warranty.
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>
26 #include "xgl.h"
27 #include "gcstruct.h"
28 #include "damage.h"
30 #ifdef RENDER
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)
40 /* just a guess */
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)
55 static Bool
56 xglTrapezoidExtents (PicturePtr pDst,
57 int ntrap,
58 xTrapezoid *traps,
59 BoxPtr extents)
61 Bool x_overlap, overlap = FALSE;
62 xFixed dx, dy, top, bottom;
63 xFixed_32_32 ex;
65 if (!ntrap)
67 extents->x1 = MAXSHORT;
68 extents->x2 = MINSHORT;
69 extents->y1 = MAXSHORT;
70 extents->y2 = MINSHORT;
72 return FALSE;
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)));
86 ntrap--;
87 traps++;
89 for (; ntrap; ntrap--, traps++)
91 INT16 x1, y1, x2, y2;
93 if (!xTrapezoidValid (traps))
94 continue;
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)));
107 x_overlap = FALSE;
108 if (x1 >= extents->x2)
109 extents->x2 = x2;
110 else if (x2 <= extents->x1)
111 extents->x1 = x1;
112 else
114 x_overlap = TRUE;
115 if (x1 < extents->x1)
116 extents->x1 = x1;
117 if (x2 > extents->x2)
118 extents->x2 = x2;
121 if (y1 >= extents->y2)
122 extents->y2 = y2;
123 else if (y2 <= extents->y1)
124 extents->y1 = y1;
125 else
127 if (y1 < extents->y1)
128 extents->y1 = y1;
129 if (y2 > extents->y2)
130 extents->y2 = y2;
132 if (x_overlap)
133 overlap = TRUE;
137 xglPictureClipExtents (pDst, extents);
139 return overlap;
142 void
143 xglTrapezoids (CARD8 op,
144 PicturePtr pSrc,
145 PicturePtr pDst,
146 PictFormatPtr maskFormat,
147 INT16 xSrc,
148 INT16 ySrc,
149 int nTrap,
150 xTrapezoid *traps)
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;
157 INT16 xDst, yDst;
158 INT16 xOff, yOff;
159 BoxRec extents;
160 Bool overlap;
161 Bool target;
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)
170 return;
172 target = xglPrepareTarget (pDst->pDrawable);
174 if (nTrap > 1 && op != PictOpAdd && maskFormat &&
175 (!target || overlap || op != PictOpOver))
177 PixmapPtr pPixmap;
178 GCPtr pGC;
179 xRectangle rect;
180 int error;
181 int area;
183 if (!pScreenPriv->pSolidAlpha)
185 xglCreateSolidAlphaPicture (pScreen);
186 if (!pScreenPriv->pSolidAlpha)
187 return;
190 rect.x = 0;
191 rect.y = 0;
192 rect.width = extents.x2 - extents.x1;
193 rect.height = extents.y2 - extents.y1;
195 pPixmap = (*pScreen->CreatePixmap) (pScreen,
196 rect.width, rect.height,
197 maskFormat->depth);
198 if (!pPixmap)
199 return;
201 pMask = CreatePicture (0, &pPixmap->drawable, maskFormat,
202 0, 0, serverClient, &error);
203 if (!pMask)
205 (*pScreen->DestroyPixmap) (pPixmap);
206 return;
209 if (!target)
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);
223 FreeScratchGC (pGC);
225 (*pScreen->DestroyPixmap) (pPixmap);
227 target = xglPrepareTarget (pMask->pDrawable);
229 xOff = -extents.x1;
230 yOff = -extents.y1;
231 pSrcPicture = pScreenPriv->pSolidAlpha;
232 pDstPicture = pMask;
234 else
236 if (maskFormat)
238 if (maskFormat->depth == 1)
239 polyEdge = PolyEdgeSharp;
240 else
241 polyEdge = PolyEdgeSmooth;
244 xOff = 0;
245 yOff = 0;
246 pSrcPicture = pSrc;
247 pDstPicture = pDst;
250 if (target)
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;
258 int offset = 0;
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);
268 while (n)
270 if (pGeometry->size < size)
271 GEOMETRY_RESIZE (pScreen, pGeometry, size);
273 if (!pGeometry->buffer)
275 if (pMask)
276 FreePicture (pMask, 0);
278 return;
281 offset +=
282 glitz_add_trapezoids (pGeometry->buffer,
283 offset, size - offset, format->type,
284 mask, (glitz_trapezoid_t *) pTrap, n,
285 &nAddedTrap);
287 n -= nAddedTrap;
288 pTrap += nAddedTrap;
289 size *= 2;
292 pGeometry->f = pScreenPriv->trapInfo.format;
293 pGeometry->count = offset / format->bytes_per_vertex;
295 else
297 pGeometry =
298 xglGetScratchVertexGeometryWithType (pScreen,
299 GEOMETRY_DATA_TYPE_FLOAT,
300 4 * nTrap);
301 if (!pGeometry->buffer)
303 if (pMask)
304 FreePicture (pMask, 0);
306 return;
309 GEOMETRY_ADD_TRAPEZOID (pScreen, pGeometry, traps, nTrap);
312 GEOMETRY_TRANSLATE (pGeometry,
313 pDstPicture->pDrawable->x + xOff,
314 pDstPicture->pDrawable->y + yOff);
317 if (pGeometry &&
318 xglCompositeGeneral (pMask ? PictOpAdd : op,
319 pSrcPicture,
320 pMaskPicture,
321 pDstPicture,
322 pGeometry,
323 extents.x1 + xOff + xSrc - xDst,
324 extents.y1 + yOff + ySrc - yDst,
325 0, 0,
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. */
333 if (!pMask)
335 RegionRec region;
337 REGION_INIT (pScreen, &region, &extents, 1);
338 REGION_TRANSLATE (pScreen, &region,
339 pDst->pDrawable->x, pDst->pDrawable->y);
341 DamageDamageRegion (pDst->pDrawable, &region);
343 REGION_UNINIT (pScreen, &region);
346 xglAddCurrentBitDamage (pDstPicture->pDrawable);
348 else
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);
369 else
370 miTrapezoids (op, pSrc, pDstPicture, maskFormat,
371 xSrc, ySrc, nTrap, traps);
374 if (pMask)
376 CompositePicture (op, pSrc, pMask, pDst,
377 extents.x1 + xSrc - xDst,
378 extents.y1 + ySrc - yDst,
379 0, 0,
380 extents.x1, extents.y1,
381 extents.x2 - extents.x1,
382 extents.y2 - extents.y1);
384 FreePicture (pMask, 0);
388 void
389 xglAddTraps (PicturePtr pDst,
390 INT16 xOff,
391 INT16 yOff,
392 int nTrap,
393 xTrap *traps)
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)
405 return;
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))
415 PicturePtr pMask;
416 glitz_vertex_format_t *format;
417 glitz_surface_t *mask;
418 xglGeometryPtr pGeometry;
419 xTrap *pTrap = traps;
420 int nAddedTrap, n = nTrap;
421 int offset = 0;
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);
431 while (n)
433 if (pGeometry->size < size)
434 GEOMETRY_RESIZE (pScreen, pGeometry, size);
436 if (!pGeometry->buffer)
437 return;
439 offset +=
440 glitz_add_traps (pGeometry->buffer,
441 offset, size - offset, format->type, mask,
442 (glitz_trap_t *) pTrap, n,
443 &nAddedTrap);
445 n -= nAddedTrap;
446 pTrap += nAddedTrap;
447 size *= 2;
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,
459 pMask,
460 pDst,
461 pGeometry,
462 0, 0,
463 0, 0,
464 pDst->pDrawable->x, pDst->pDrawable->y,
465 pDst->pDrawable->width,
466 pDst->pDrawable->height))
468 xglAddCurrentBitDamage (pDst->pDrawable);
469 return;
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);
480 #endif