1/*
2 *
3 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
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#ifdef HAVE_DIX_CONFIG_H
25#include <dix-config.h>
26#endif
27
28#include "scrnintstr.h"
29#include "gcstruct.h"
30#include "pixmapstr.h"
31#include "windowstr.h"
32#include "mi.h"
33#include "picturestr.h"
34#include "mipict.h"
35
36static void
37miColorRects (PicturePtr    pDst,
38	      PicturePtr    pClipPict,
39	      xRenderColor  *color,
40	      int	    nRect,
41	      xRectangle    *rects,
42	      int	    xoff,
43	      int	    yoff)
44{
45    CARD32		pixel;
46    GCPtr		pGC;
47    ChangeGCVal		tmpval[5];
48    RegionPtr		pClip;
49    unsigned long	mask;
50
51    miRenderColorToPixel (pDst->pFormat, color, &pixel);
52
53    pGC = GetScratchGC (pDst->pDrawable->depth, pDst->pDrawable->pScreen);
54    if (!pGC)
55	return;
56    tmpval[0].val = GXcopy;
57    tmpval[1].val = pixel;
58    tmpval[2].val = pDst->subWindowMode;
59    mask = GCFunction | GCForeground | GCSubwindowMode;
60    if (pClipPict->clientClipType == CT_REGION)
61    {
62	tmpval[3].val = pDst->clipOrigin.x - xoff;
63	tmpval[4].val = pDst->clipOrigin.y - yoff;
64	mask |= GCClipXOrigin|GCClipYOrigin;
65
66	pClip = RegionCreate(NULL, 1);
67	RegionCopy(pClip,
68		     (RegionPtr) pClipPict->clientClip);
69	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0);
70    }
71
72    ChangeGC (NullClient, pGC, mask, tmpval);
73    ValidateGC (pDst->pDrawable, pGC);
74    if (xoff || yoff)
75    {
76	int	i;
77	for (i = 0; i < nRect; i++)
78	{
79	    rects[i].x -= xoff;
80	    rects[i].y -= yoff;
81	}
82    }
83    (*pGC->ops->PolyFillRect) (pDst->pDrawable, pGC, nRect, rects);
84    if (xoff || yoff)
85    {
86	int	i;
87	for (i = 0; i < nRect; i++)
88	{
89	    rects[i].x += xoff;
90	    rects[i].y += yoff;
91	}
92    }
93    FreeScratchGC (pGC);
94}
95
96void
97miCompositeRects (CARD8		op,
98		  PicturePtr	pDst,
99		  xRenderColor  *color,
100		  int		nRect,
101		  xRectangle    *rects)
102{
103    ScreenPtr		pScreen = pDst->pDrawable->pScreen;
104
105    if (color->alpha == 0xffff)
106    {
107	if (op == PictOpOver)
108	    op = PictOpSrc;
109    }
110    if (op == PictOpClear)
111	color->red = color->green = color->blue = color->alpha = 0;
112
113    if (op == PictOpSrc || op == PictOpClear)
114    {
115	miColorRects (pDst, pDst, color, nRect, rects, 0, 0);
116	if (pDst->alphaMap)
117	    miColorRects (pDst->alphaMap, pDst,
118			  color, nRect, rects,
119			  pDst->alphaOrigin.x,
120			  pDst->alphaOrigin.y);
121    }
122    else
123    {
124	PictFormatPtr	rgbaFormat;
125	PixmapPtr	pPixmap;
126	PicturePtr	pSrc;
127	xRectangle	one;
128	int		error;
129	Pixel		pixel;
130	GCPtr		pGC;
131	ChangeGCVal	gcvals[2];
132	XID		tmpval[1];
133
134	rgbaFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
135	if (!rgbaFormat)
136	    goto bail1;
137
138	pPixmap = (*pScreen->CreatePixmap) (pScreen, 1, 1, rgbaFormat->depth,
139					    CREATE_PIXMAP_USAGE_SCRATCH);
140	if (!pPixmap)
141	    goto bail2;
142
143	miRenderColorToPixel (rgbaFormat, color, &pixel);
144
145	pGC = GetScratchGC (rgbaFormat->depth, pScreen);
146	if (!pGC)
147	    goto bail3;
148	gcvals[0].val = GXcopy;
149	gcvals[1].val = pixel;
150
151	ChangeGC (NullClient, pGC, GCFunction | GCForeground, gcvals);
152	ValidateGC (&pPixmap->drawable, pGC);
153	one.x = 0;
154	one.y = 0;
155	one.width = 1;
156	one.height = 1;
157	(*pGC->ops->PolyFillRect) (&pPixmap->drawable, pGC, 1, &one);
158
159	tmpval[0] = xTrue;
160	pSrc = CreatePicture (0, &pPixmap->drawable, rgbaFormat,
161			      CPRepeat, tmpval, serverClient, &error);
162
163	if (!pSrc)
164	    goto bail4;
165
166	while (nRect--)
167	{
168	    CompositePicture (op, pSrc, 0, pDst, 0, 0, 0, 0,
169			      rects->x,
170			      rects->y,
171			      rects->width,
172			      rects->height);
173	    rects++;
174	}
175
176	FreePicture ((pointer) pSrc, 0);
177bail4:
178	FreeScratchGC (pGC);
179bail3:
180	(*pScreen->DestroyPixmap) (pPixmap);
181bail2:
182bail1:
183	;
184    }
185}
186