Initial commit
[xorg_rtime.git] / xorg-server-1.4 / hw / xgl / xglfill.c
blob64759ab2eeb4a413a0de49aaa141d7144a9a599a
1 /*
2 * Copyright © 2004 David Reveman
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 * David Reveman not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior permission.
11 * David Reveman 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 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17 * NO EVENT SHALL DAVID REVEMAN 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 "fb.h"
30 Bool
31 xglFill (DrawablePtr pDrawable,
32 GCPtr pGC,
33 xglGeometryPtr pGeometry,
34 int x,
35 int y,
36 int width,
37 int height,
38 BoxPtr pBox,
39 int nBox)
41 XGL_GC_PRIV (pGC);
43 switch (pGC->fillStyle) {
44 case FillSolid:
45 if (xglSolid (pDrawable,
46 pGCPriv->op, pGCPriv->fg,
47 pGeometry,
48 x, y,
49 width, height,
50 pBox, nBox))
51 return TRUE;
52 break;
53 case FillStippled:
54 case FillOpaqueStippled:
55 break;
56 case FillTiled:
57 if (xglTile (pDrawable,
58 pGCPriv->op, pGC->tile.pixmap,
59 -(pGC->patOrg.x + pDrawable->x),
60 -(pGC->patOrg.y + pDrawable->y),
61 pGeometry,
62 x, y,
63 width, height,
64 pBox, nBox))
65 return TRUE;
66 break;
69 return FALSE;
72 static void
73 xglFillBox (DrawablePtr pDrawable,
74 GCPtr pGC,
75 int x,
76 int y,
77 int width,
78 int height,
79 BoxPtr pBox,
80 int nBox)
82 if (!nBox)
83 return;
85 if (!xglFill (pDrawable, pGC, NULL, x, y, width, height, pBox, nBox))
87 RegionRec region;
89 XGL_DRAWABLE_PIXMAP (pDrawable);
90 XGL_PIXMAP_PRIV (pPixmap);
92 if (!xglMapPixmapBits (pPixmap))
93 FatalError (XGL_SW_FAILURE_STRING);
95 switch (pGC->fillStyle) {
96 case FillSolid:
97 break;
98 case FillStippled:
99 case FillOpaqueStippled:
100 if (!xglSyncBits (&pGC->stipple->drawable, NullBox))
101 FatalError (XGL_SW_FAILURE_STRING);
102 break;
103 case FillTiled:
104 if (!xglSyncBits (&pGC->tile.pixmap->drawable, NullBox))
105 FatalError (XGL_SW_FAILURE_STRING);
106 break;
109 pPixmapPriv->damageBox = miEmptyBox;
111 while (nBox--)
113 fbFill (pDrawable, pGC,
114 pBox->x1, pBox->y1,
115 pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
117 REGION_INIT (pDrawable->pScreen, &region, pBox, 1);
118 xglAddSurfaceDamage (pDrawable, &region);
119 REGION_UNINIT (pDrawable->pScreen, &region);
121 pBox++;
123 } else
124 xglAddCurrentBitDamage (pDrawable);
127 #define N_STACK_BOX 1024
129 static BoxPtr
130 xglMoreBoxes (BoxPtr stackBox,
131 BoxPtr heapBox,
132 int nBoxes)
134 Bool stack = !heapBox;
136 heapBox = xrealloc (heapBox, sizeof (BoxRec) * nBoxes);
137 if (!heapBox)
138 return NULL;
140 if (stack)
141 memcpy (heapBox, stackBox, sizeof (BoxRec) * N_STACK_BOX);
143 return heapBox;
146 #define ADD_BOX(pBox, nBox, stackBox, heapBox, size, box) \
148 if ((nBox) == (size)) \
150 (size) *= 2; \
151 (heapBox) = xglMoreBoxes (stackBox, heapBox, size); \
152 if (heapBox) \
154 (pBox) = (heapBox) + (nBox); \
155 *(pBox)++ = (box); \
156 (nBox)++; \
159 else \
161 *(pBox)++ = (box); \
162 (nBox)++; \
166 void
167 xglFillRect (DrawablePtr pDrawable,
168 GCPtr pGC,
169 int nrect,
170 xRectangle *prect)
172 RegionPtr pClip = pGC->pCompositeClip;
173 BoxPtr pClipBox;
174 BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip);
175 BoxRec part, full;
176 BoxPtr heapBox = NULL;
177 BoxRec stackBox[N_STACK_BOX];
178 int size = N_STACK_BOX;
179 BoxPtr pBox = stackBox;
180 int nClip, nBox = 0;
182 while (nrect--)
184 full.x1 = prect->x + pDrawable->x;
185 full.y1 = prect->y + pDrawable->y;
186 full.x2 = full.x1 + (int) prect->width;
187 full.y2 = full.y1 + (int) prect->height;
189 prect++;
191 if (full.x1 < pExtent->x1)
192 full.x1 = pExtent->x1;
193 if (full.y1 < pExtent->y1)
194 full.y1 = pExtent->y1;
195 if (full.x2 > pExtent->x2)
196 full.x2 = pExtent->x2;
197 if (full.y2 > pExtent->y2)
198 full.y2 = pExtent->y2;
200 if (full.x1 >= full.x2 || full.y1 >= full.y2)
201 continue;
203 nClip = REGION_NUM_RECTS (pClip);
204 if (nClip == 1)
206 ADD_BOX (pBox, nBox, stackBox, heapBox, size, full);
208 else
210 pClipBox = REGION_RECTS (pClip);
211 while (nClip--)
213 part = *pClipBox++;
215 if (part.x1 < full.x1)
216 part.x1 = full.x1;
217 if (part.y1 < full.y1)
218 part.y1 = full.y1;
219 if (part.x2 > full.x2)
220 part.x2 = full.x2;
221 if (part.y2 > full.y2)
222 part.y2 = full.y2;
224 if (part.x1 < part.x2 && part.y1 < part.y2)
225 ADD_BOX (pBox, nBox, stackBox, heapBox, size, part);
230 xglFillBox (pDrawable, pGC,
231 pExtent->x1, pExtent->y1,
232 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
233 (heapBox) ? heapBox : stackBox, nBox);
235 if (heapBox)
236 xfree (heapBox);
239 void
240 xglFillSpan (DrawablePtr pDrawable,
241 GCPtr pGC,
242 int n,
243 DDXPointPtr ppt,
244 int *pwidth)
246 RegionPtr pClip = pGC->pCompositeClip;
247 BoxPtr pClipBox;
248 BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip);
249 BoxRec part, full;
250 BoxPtr heapBox = NULL;
251 BoxRec stackBox[N_STACK_BOX];
252 int size = N_STACK_BOX;
253 BoxPtr pBox = stackBox;
254 int nClip, nBox = 0;
256 while (n--)
258 full.x1 = ppt->x;
259 full.y1 = ppt->y;
260 full.x2 = full.x1 + *pwidth;
261 full.y2 = full.y1 + 1;
263 pwidth++;
264 ppt++;
266 if (full.x1 < pExtent->x1)
267 full.x1 = pExtent->x1;
268 if (full.y1 < pExtent->y1)
269 full.y1 = pExtent->y1;
270 if (full.x2 > pExtent->x2)
271 full.x2 = pExtent->x2;
272 if (full.y2 > pExtent->y2)
273 full.y2 = pExtent->y2;
275 if (full.x1 >= full.x2 || full.y1 >= full.y2)
276 continue;
278 nClip = REGION_NUM_RECTS (pClip);
279 if (nClip == 1)
281 ADD_BOX (pBox, nBox, stackBox, heapBox, size, full);
283 else
285 pClipBox = REGION_RECTS (pClip);
286 while (nClip--)
288 part = *pClipBox++;
290 if (part.x1 < full.x1)
291 part.x1 = full.x1;
292 if (part.y1 < full.y1)
293 part.y1 = full.y1;
294 if (part.x2 > full.x2)
295 part.x2 = full.x2;
296 if (part.y2 > full.y2)
297 part.y2 = full.y2;
299 if (part.x1 < part.x2 && part.y1 < part.y2)
300 ADD_BOX (pBox, nBox, stackBox, heapBox, size, part);
305 xglFillBox (pDrawable, pGC,
306 pExtent->x1, pExtent->y1,
307 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
308 (heapBox) ? heapBox : stackBox, nBox);
310 if (heapBox)
311 xfree (heapBox);
314 Bool
315 xglFillLine (DrawablePtr pDrawable,
316 GCPtr pGC,
317 int mode,
318 int npt,
319 DDXPointPtr ppt)
321 RegionPtr pClip = pGC->pCompositeClip;
322 BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip);
323 Bool coincidentEndpoints = FALSE;
324 Bool horizontalAndVertical = TRUE;
325 DDXPointPtr pptTmp;
326 int nptTmp;
327 DDXPointRec pt;
328 xglGeometryPtr pGeometry;
330 XGL_SCREEN_PRIV (pGC->pScreen);
332 if (npt < 2)
333 return TRUE;
335 pt = *ppt;
337 nptTmp = npt - 1;
338 pptTmp = ppt + 1;
340 if (mode == CoordModePrevious)
342 while (nptTmp--)
344 if (pptTmp->x && pptTmp->y)
345 horizontalAndVertical = FALSE;
347 pt.x += pptTmp->x;
348 pt.y += pptTmp->y;
350 pptTmp++;
353 if (pt.x == ppt->x && pt.y == ppt->y)
354 coincidentEndpoints = TRUE;
356 else
358 while (nptTmp--)
360 if (pptTmp->x != pt.x && pptTmp->y != pt.y)
362 horizontalAndVertical = FALSE;
363 break;
366 pt = *pptTmp++;
369 if (ppt[npt - 1].x == ppt->x && ppt[npt - 1].y == ppt->y)
370 coincidentEndpoints = TRUE;
373 if (horizontalAndVertical)
375 BoxPtr pClipBox;
376 BoxRec part, full;
377 BoxPtr heapBox = NULL;
378 BoxRec stackBox[N_STACK_BOX];
379 int size = N_STACK_BOX;
380 BoxPtr pBox = stackBox;
381 int nClip, nBox = 0;
382 int dx, dy;
384 pt = *ppt;
386 ppt++;
387 npt--;
389 while (npt--)
391 if (mode == CoordModePrevious)
393 dx = ppt->x;
394 dy = ppt->y;
396 else
398 dx = ppt->x - pt.x;
399 dy = ppt->y - pt.y;
402 if (dx)
404 if (dx > 0)
406 full.x1 = pt.x + pDrawable->x;
408 if (npt || coincidentEndpoints)
409 full.x2 = full.x1 + dx;
410 else
411 full.x2 = full.x1 + dx + 1;
413 else
415 full.x2 = pt.x + pDrawable->x + 1;
417 if (npt || coincidentEndpoints)
418 full.x1 = full.x2 + dx;
419 else
420 full.x1 = full.x2 + dx - 1;
423 full.y1 = pt.y + pDrawable->y;
424 full.y2 = full.y1 + 1;
426 else
428 if (dy > 0)
430 full.y1 = pt.y + pDrawable->y;
432 if (npt || coincidentEndpoints)
433 full.y2 = full.y1 + dy;
434 else
435 full.y2 = full.y1 + dy + 1;
437 else
439 full.y2 = pt.y + pDrawable->y + 1;
441 if (npt || coincidentEndpoints)
442 full.y1 = full.y2 + dy;
443 else
444 full.y1 = full.y2 + dy - 1;
447 full.x1 = pt.x + pDrawable->x;
448 full.x2 = full.x1 + 1;
451 pt.x += dx;
452 pt.y += dy;
454 ppt++;
456 if (full.x1 < pExtent->x1)
457 full.x1 = pExtent->x1;
458 if (full.y1 < pExtent->y1)
459 full.y1 = pExtent->y1;
460 if (full.x2 > pExtent->x2)
461 full.x2 = pExtent->x2;
462 if (full.y2 > pExtent->y2)
463 full.y2 = pExtent->y2;
465 if (full.x1 >= full.x2 || full.y1 >= full.y2)
466 continue;
468 nClip = REGION_NUM_RECTS (pClip);
469 if (nClip == 1)
471 ADD_BOX (pBox, nBox, stackBox, heapBox, size, full);
473 else
475 pClipBox = REGION_RECTS (pClip);
476 while (nClip--)
478 part = *pClipBox++;
480 if (part.x1 < full.x1)
481 part.x1 = full.x1;
482 if (part.y1 < full.y1)
483 part.y1 = full.y1;
484 if (part.x2 > full.x2)
485 part.x2 = full.x2;
486 if (part.y2 > full.y2)
487 part.y2 = full.y2;
489 if (part.x1 < part.x2 && part.y1 < part.y2)
490 ADD_BOX (pBox, nBox, stackBox, heapBox, size, part);
495 xglFillBox (pDrawable, pGC,
496 pExtent->x1, pExtent->y1,
497 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
498 (heapBox) ? heapBox : stackBox, nBox);
500 if (heapBox)
501 xfree (heapBox);
503 return TRUE;
506 if (!pScreenPriv->lines)
507 return FALSE;
509 if (coincidentEndpoints)
510 npt--;
512 pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, npt);
514 GEOMETRY_ADD_LINE (pGC->pScreen, pGeometry,
515 coincidentEndpoints, mode, npt, ppt);
517 if (coincidentEndpoints)
518 GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_LOOP);
519 else
520 GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINE_STRIP);
522 /* Lines need a 0.5 translate */
523 GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15);
525 GEOMETRY_TRANSLATE (pGeometry, pDrawable->x, pDrawable->y);
527 pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip);
529 if (xglFill (pDrawable, pGC, pGeometry,
530 pExtent->x1, pExtent->y1,
531 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
532 REGION_RECTS (pGC->pCompositeClip),
533 REGION_NUM_RECTS (pGC->pCompositeClip)))
535 xglAddCurrentBitDamage (pDrawable);
536 return TRUE;
539 return FALSE;
542 Bool
543 xglFillSegment (DrawablePtr pDrawable,
544 GCPtr pGC,
545 int nSegInit,
546 xSegment *pSegInit)
548 RegionPtr pClip = pGC->pCompositeClip;
549 BoxPtr pExtent = REGION_EXTENTS (pGC->pScreen, pClip);
550 Bool horizontalAndVertical = TRUE;
551 xglGeometryPtr pGeometry;
552 xSegment *pSeg;
553 int nSeg;
555 XGL_SCREEN_PRIV (pGC->pScreen);
557 if (nSegInit < 1)
558 return TRUE;
560 pSeg = pSegInit;
561 nSeg = nSegInit;
562 while (nSeg--)
564 if (pSeg->x1 != pSeg->x2 && pSeg->y1 != pSeg->y2)
565 horizontalAndVertical = FALSE;
567 pSeg++;
570 if (horizontalAndVertical)
572 BoxPtr pClipBox;
573 BoxRec part, full;
574 BoxPtr heapBox = NULL;
575 BoxRec stackBox[N_STACK_BOX];
576 int size = N_STACK_BOX;
577 BoxPtr pBox = stackBox;
578 int nClip, nBox = 0;
580 while (nSegInit--)
582 if (pSegInit->x1 != pSegInit->x2)
584 if (pSegInit->x1 < pSegInit->x2)
586 full.x1 = pSegInit->x1;
587 full.x2 = pSegInit->x2;
589 else
591 full.x1 = pSegInit->x2;
592 full.x2 = pSegInit->x1;
595 full.x1 += pDrawable->x;
596 full.x2 += pDrawable->x + 1;
597 full.y1 = pSegInit->y1 + pDrawable->y;
598 full.y2 = full.y1 + 1;
600 else
602 if (pSegInit->y1 < pSegInit->y2)
604 full.y1 = pSegInit->y1;
605 full.y2 = pSegInit->y2;
607 else
609 full.y1 = pSegInit->y2;
610 full.y2 = pSegInit->y1;
613 full.y1 += pDrawable->y;
614 full.y2 += pDrawable->y + 1;
615 full.x1 = pSegInit->x1 + pDrawable->x;
616 full.x2 = full.x1 + 1;
619 pSegInit++;
621 if (full.x1 < pExtent->x1)
622 full.x1 = pExtent->x1;
623 if (full.y1 < pExtent->y1)
624 full.y1 = pExtent->y1;
625 if (full.x2 > pExtent->x2)
626 full.x2 = pExtent->x2;
627 if (full.y2 > pExtent->y2)
628 full.y2 = pExtent->y2;
630 if (full.x1 >= full.x2 || full.y1 >= full.y2)
631 continue;
633 nClip = REGION_NUM_RECTS (pClip);
634 if (nClip == 1)
636 ADD_BOX (pBox, nBox, stackBox, heapBox, size, full);
638 else
640 pClipBox = REGION_RECTS (pClip);
641 while (nClip--)
643 part = *pClipBox++;
645 if (part.x1 < full.x1)
646 part.x1 = full.x1;
647 if (part.y1 < full.y1)
648 part.y1 = full.y1;
649 if (part.x2 > full.x2)
650 part.x2 = full.x2;
651 if (part.y2 > full.y2)
652 part.y2 = full.y2;
654 if (part.x1 < part.x2 && part.y1 < part.y2)
655 ADD_BOX (pBox, nBox, stackBox, heapBox, size, part);
660 xglFillBox (pDrawable, pGC,
661 pExtent->x1, pExtent->y1,
662 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
663 (heapBox) ? heapBox : stackBox, nBox);
665 if (heapBox)
666 xfree (heapBox);
668 return TRUE;
671 if (!pScreenPriv->lines)
672 return FALSE;
674 pGeometry = xglGetScratchVertexGeometry (pGC->pScreen, 2 * nSegInit);
676 GEOMETRY_ADD_SEGMENT (pGC->pScreen, pGeometry, nSegInit, pSegInit);
678 /* Line segments need 0.5 translate */
679 GEOMETRY_TRANSLATE_FIXED (pGeometry, 1 << 15, 1 << 15);
680 GEOMETRY_SET_VERTEX_PRIMITIVE (pGeometry, GLITZ_PRIMITIVE_LINES);
682 GEOMETRY_TRANSLATE (pGeometry, pDrawable->x, pDrawable->y);
684 if (xglFill (pDrawable, pGC, pGeometry,
685 pExtent->x1, pExtent->y1,
686 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
687 REGION_RECTS (pGC->pCompositeClip),
688 REGION_NUM_RECTS (pGC->pCompositeClip)))
690 xglAddCurrentBitDamage (pDrawable);
691 return TRUE;
694 return FALSE;
697 Bool
698 xglFillGlyph (DrawablePtr pDrawable,
699 GCPtr pGC,
700 int x,
701 int y,
702 unsigned int nGlyph,
703 CharInfoPtr *ppci,
704 pointer pglyphBase)
706 BoxPtr pExtent;
707 xglGeometryRec geometry;
709 if (nGlyph < 1)
710 return TRUE;
712 pExtent = REGION_EXTENTS (pDrawable->pScreen, pGC->pCompositeClip);
714 x += pDrawable->x;
715 y += pDrawable->y;
717 GEOMETRY_INIT (pDrawable->pScreen, &geometry,
718 GLITZ_GEOMETRY_TYPE_BITMAP,
719 GEOMETRY_USAGE_SYSMEM, 0);
721 GEOMETRY_FOR_GLYPH (pDrawable->pScreen,
722 &geometry,
723 nGlyph,
724 ppci,
725 pglyphBase);
727 GEOMETRY_TRANSLATE (&geometry, x, y);
729 if (xglFill (pDrawable, pGC, &geometry,
730 pExtent->x1, pExtent->y1,
731 pExtent->x2 - pExtent->x1, pExtent->y2 - pExtent->y1,
732 REGION_RECTS (pGC->pCompositeClip),
733 REGION_NUM_RECTS (pGC->pCompositeClip)))
735 GEOMETRY_UNINIT (&geometry);
736 xglAddCurrentBitDamage (pDrawable);
737 return TRUE;
740 GEOMETRY_UNINIT (&geometry);
741 return FALSE;