1706f2543Smrg/*
2706f2543Smrg *
3706f2543Smrg * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
4706f2543Smrg *
5706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
7706f2543Smrg * the above copyright notice appear in all copies and that both that
8706f2543Smrg * copyright notice and this permission notice appear in supporting
9706f2543Smrg * documentation, and that the name of Keith Packard not be used in
10706f2543Smrg * advertising or publicity pertaining to distribution of the software without
11706f2543Smrg * specific, written prior permission.  Keith Packard makes no
12706f2543Smrg * representations about the suitability of this software for any purpose.  It
13706f2543Smrg * is provided "as is" without express or implied warranty.
14706f2543Smrg *
15706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
22706f2543Smrg */
23706f2543Smrg
24706f2543Smrg#ifdef HAVE_XORG_CONFIG_H
25706f2543Smrg#include <xorg-config.h>
26706f2543Smrg#endif
27706f2543Smrg
28706f2543Smrg#include <string.h>
29706f2543Smrg
30706f2543Smrg#include "misc.h"
31706f2543Smrg#include "xf86.h"
32706f2543Smrg#include "xf86_OSproc.h"
33706f2543Smrg
34706f2543Smrg#include <X11/X.h>
35706f2543Smrg#include "scrnintstr.h"
36706f2543Smrg#include "pixmapstr.h"
37706f2543Smrg#include "windowstr.h"
38706f2543Smrg#include "xf86str.h"
39706f2543Smrg#include "mi.h"
40706f2543Smrg#include "picturestr.h"
41706f2543Smrg#include "glyphstr.h"
42706f2543Smrg#include "picture.h"
43706f2543Smrg#include "mipict.h"
44706f2543Smrg#include "xaa.h"
45706f2543Smrg#include "xaalocal.h"
46706f2543Smrg#include "xaawrap.h"
47706f2543Smrg#include "xaacexp.h"
48706f2543Smrg#include "xf86fbman.h"
49706f2543Smrg#include "servermd.h"
50706f2543Smrg
51706f2543SmrgBool
52706f2543SmrgXAAGetPixelFromRGBA (
53706f2543Smrg    CARD32 *pixel,
54706f2543Smrg    CARD16 red,
55706f2543Smrg    CARD16 green,
56706f2543Smrg    CARD16 blue,
57706f2543Smrg    CARD16 alpha,
58706f2543Smrg    CARD32 format
59706f2543Smrg){
60706f2543Smrg    int rbits, bbits, gbits, abits;
61706f2543Smrg    int rshift, bshift, gshift, ashift;
62706f2543Smrg
63706f2543Smrg    *pixel = 0;
64706f2543Smrg
65706f2543Smrg    if(!PICT_FORMAT_COLOR(format))
66706f2543Smrg    	return FALSE;
67706f2543Smrg
68706f2543Smrg    rbits = PICT_FORMAT_R(format);
69706f2543Smrg    gbits = PICT_FORMAT_G(format);
70706f2543Smrg    bbits = PICT_FORMAT_B(format);
71706f2543Smrg    abits = PICT_FORMAT_A(format);
72706f2543Smrg
73706f2543Smrg    if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
74706f2543Smrg        bshift = 0;
75706f2543Smrg        gshift = bbits;
76706f2543Smrg	rshift = gshift + gbits;
77706f2543Smrg	ashift = rshift + rbits;
78706f2543Smrg    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
79706f2543Smrg        rshift = 0;
80706f2543Smrg	gshift = rbits;
81706f2543Smrg	bshift = gshift + gbits;
82706f2543Smrg	ashift = bshift + bbits;
83706f2543Smrg    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
84706f2543Smrg	bshift = PICT_FORMAT_BPP(format) - bbits;
85706f2543Smrg	gshift = bshift - gbits;
86706f2543Smrg	rshift = gshift - rbits;
87706f2543Smrg	ashift = 0;
88706f2543Smrg    } else
89706f2543Smrg	return FALSE;
90706f2543Smrg
91706f2543Smrg    *pixel |=  ( blue >> (16 - bbits)) << bshift;
92706f2543Smrg    *pixel |=  (  red >> (16 - rbits)) << rshift;
93706f2543Smrg    *pixel |=  (green >> (16 - gbits)) << gshift;
94706f2543Smrg    *pixel |=  (alpha >> (16 - abits)) << ashift;
95706f2543Smrg
96706f2543Smrg    return TRUE;
97706f2543Smrg}
98706f2543Smrg
99706f2543Smrg
100706f2543SmrgBool
101706f2543SmrgXAAGetRGBAFromPixel(
102706f2543Smrg    CARD32 pixel,
103706f2543Smrg    CARD16 *red,
104706f2543Smrg    CARD16 *green,
105706f2543Smrg    CARD16 *blue,
106706f2543Smrg    CARD16 *alpha,
107706f2543Smrg    CARD32 format
108706f2543Smrg){
109706f2543Smrg    int rbits, bbits, gbits, abits;
110706f2543Smrg    int rshift, bshift, gshift, ashift;
111706f2543Smrg
112706f2543Smrg    if(!PICT_FORMAT_COLOR(format))
113706f2543Smrg    	return FALSE;
114706f2543Smrg
115706f2543Smrg    rbits = PICT_FORMAT_R(format);
116706f2543Smrg    gbits = PICT_FORMAT_G(format);
117706f2543Smrg    bbits = PICT_FORMAT_B(format);
118706f2543Smrg    abits = PICT_FORMAT_A(format);
119706f2543Smrg
120706f2543Smrg    if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
121706f2543Smrg        bshift = 0;
122706f2543Smrg        gshift = bbits;
123706f2543Smrg	rshift = gshift + gbits;
124706f2543Smrg	ashift = rshift + rbits;
125706f2543Smrg    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
126706f2543Smrg        rshift = 0;
127706f2543Smrg	gshift = rbits;
128706f2543Smrg	bshift = gshift + gbits;
129706f2543Smrg	ashift = bshift + bbits;
130706f2543Smrg    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
131706f2543Smrg	bshift = PICT_FORMAT_BPP(format) - bbits;
132706f2543Smrg	gshift = bshift - gbits;
133706f2543Smrg	rshift = gshift - rbits;
134706f2543Smrg	ashift = 0;
135706f2543Smrg    } else
136706f2543Smrg	return FALSE;
137706f2543Smrg
138706f2543Smrg    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
139706f2543Smrg    while(rbits < 16) {
140706f2543Smrg       *red |= *red >> rbits;
141706f2543Smrg       rbits <<= 1;
142706f2543Smrg    }
143706f2543Smrg
144706f2543Smrg    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
145706f2543Smrg    while(gbits < 16) {
146706f2543Smrg       *green |= *green >> gbits;
147706f2543Smrg       gbits <<= 1;
148706f2543Smrg    }
149706f2543Smrg
150706f2543Smrg    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
151706f2543Smrg    while(bbits < 16) {
152706f2543Smrg       *blue |= *blue >> bbits;
153706f2543Smrg       bbits <<= 1;
154706f2543Smrg    }
155706f2543Smrg
156706f2543Smrg    if(abits) {
157706f2543Smrg       *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
158706f2543Smrg       while(abits < 16) {
159706f2543Smrg          *alpha |= *alpha >> abits;
160706f2543Smrg          abits <<= 1;
161706f2543Smrg       }
162706f2543Smrg    } else *alpha = 0xffff;
163706f2543Smrg
164706f2543Smrg    return TRUE;
165706f2543Smrg}
166706f2543Smrg
167706f2543Smrg/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */
168706f2543Smrg
169706f2543Smrgvoid
170706f2543SmrgXAA_888_plus_PICT_a8_to_8888 (
171706f2543Smrg    CARD32 color,
172706f2543Smrg    CARD8  *alphaPtr,   /* in bytes */
173706f2543Smrg    int    alphaPitch,
174706f2543Smrg    CARD32  *dstPtr,
175706f2543Smrg    int    dstPitch,	/* in dwords */
176706f2543Smrg    int    width,
177706f2543Smrg    int    height
178706f2543Smrg){
179706f2543Smrg    int x;
180706f2543Smrg
181706f2543Smrg    color &= 0x00ffffff;
182706f2543Smrg
183706f2543Smrg    while(height--) {
184706f2543Smrg	for(x = 0; x < width; x++)
185706f2543Smrg	   dstPtr[x] = color | (alphaPtr[x] << 24);
186706f2543Smrg	dstPtr += dstPitch;
187706f2543Smrg	alphaPtr += alphaPitch;
188706f2543Smrg    }
189706f2543Smrg}
190706f2543Smrg
191706f2543Smrg#define DRAWABLE_IS_ON_CARD(pDraw) \
192706f2543Smrg    (pDraw->type == DRAWABLE_WINDOW || \
193706f2543Smrg     (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw)))
194706f2543Smrg
195706f2543SmrgBool
196706f2543SmrgXAADoComposite (
197706f2543Smrg    CARD8      op,
198706f2543Smrg    PicturePtr pSrc,
199706f2543Smrg    PicturePtr pMask,
200706f2543Smrg    PicturePtr pDst,
201706f2543Smrg    INT16      xSrc,
202706f2543Smrg    INT16      ySrc,
203706f2543Smrg    INT16      xMask,
204706f2543Smrg    INT16      yMask,
205706f2543Smrg    INT16      xDst,
206706f2543Smrg    INT16      yDst,
207706f2543Smrg    CARD16     width,
208706f2543Smrg    CARD16     height
209706f2543Smrg){
210706f2543Smrg    ScreenPtr pScreen = pDst->pDrawable->pScreen;
211706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
212706f2543Smrg    RegionRec region;
213706f2543Smrg    CARD32 *formats, *dstformats;
214706f2543Smrg    int flags = 0;
215706f2543Smrg    BoxPtr pbox;
216706f2543Smrg    int nbox, w, h;
217706f2543Smrg
218706f2543Smrg    if(!RegionNumRects(pDst->pCompositeClip))
219706f2543Smrg        return TRUE;
220706f2543Smrg
221706f2543Smrg    if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable))
222706f2543Smrg	return FALSE;
223706f2543Smrg
224706f2543Smrg    if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable))
225706f2543Smrg	return FALSE;
226706f2543Smrg
227706f2543Smrg    if (pSrc->transform || (pMask && pMask->transform))
228706f2543Smrg	return FALSE;
229706f2543Smrg
230706f2543Smrg    if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
231706f2543Smrg	return FALSE;
232706f2543Smrg
233706f2543Smrg    if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) ||
234706f2543Smrg	(pMask && pMask->repeat && pMask->repeatType != RepeatNormal))
235706f2543Smrg    {
236706f2543Smrg	return FALSE;
237706f2543Smrg    }
238706f2543Smrg
239706f2543Smrg    xDst += pDst->pDrawable->x;
240706f2543Smrg    yDst += pDst->pDrawable->y;
241706f2543Smrg    xSrc += pSrc->pDrawable->x;
242706f2543Smrg    ySrc += pSrc->pDrawable->y;
243706f2543Smrg
244706f2543Smrg    if(pMask) {
245706f2543Smrg	if(pMask->componentAlpha)
246706f2543Smrg	    return FALSE;
247706f2543Smrg
248706f2543Smrg	/* for now we only do it if there is a 1x1 (solid) source */
249706f2543Smrg
250706f2543Smrg	if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) {
251706f2543Smrg	   CARD16 red, green, blue, alpha;
252706f2543Smrg           CARD32 pixel =
253706f2543Smrg                *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
254706f2543Smrg
255706f2543Smrg	   if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format))
256706f2543Smrg		return FALSE;
257706f2543Smrg
258706f2543Smrg	   xMask += pMask->pDrawable->x;
259706f2543Smrg	   yMask += pMask->pDrawable->y;
260706f2543Smrg
261706f2543Smrg	   /* pull out color expandable operations here */
262706f2543Smrg	   if((pMask->format == PICT_a1) && (alpha == 0xffff) &&
263706f2543Smrg	       (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat &&
264706f2543Smrg	       !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) &&
265706f2543Smrg	       (!(infoRec->WriteBitmapFlags & RGB_EQUAL) ||
266706f2543Smrg	         ((red == green) && (green == blue))))
267706f2543Smrg	   {
268706f2543Smrg	        PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
269706f2543Smrg		int skipleft;
270706f2543Smrg
271706f2543Smrg	  	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
272706f2543Smrg                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
273706f2543Smrg                                   width, height))
274706f2543Smrg		      return TRUE;
275706f2543Smrg
276706f2543Smrg		nbox = RegionNumRects(&region);
277706f2543Smrg		pbox = RegionRects(&region);
278706f2543Smrg
279706f2543Smrg	        if(!nbox)
280706f2543Smrg		    return TRUE;
281706f2543Smrg
282706f2543Smrg	        XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format);
283706f2543Smrg
284706f2543Smrg	   	xMask -= xDst;
285706f2543Smrg	   	yMask -= yDst;
286706f2543Smrg
287706f2543Smrg	   	while(nbox--) {
288706f2543Smrg		    skipleft = pbox->x1 + xMask;
289706f2543Smrg
290706f2543Smrg	            (*infoRec->WriteBitmap)(infoRec->pScrn,
291706f2543Smrg			        pbox->x1, pbox->y1,
292706f2543Smrg			        pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
293706f2543Smrg			        (unsigned char*)(pPix->devPrivate.ptr) +
294706f2543Smrg				  (pPix->devKind * (pbox->y1 + yMask)) +
295706f2543Smrg			          ((skipleft >> 3) & ~3), pPix->devKind,
296706f2543Smrg				skipleft & 31, pixel, -1, GXcopy, ~0);
297706f2543Smrg	            pbox++;
298706f2543Smrg	   	}
299706f2543Smrg
300706f2543Smrg		/* WriteBitmap sets the Sync flag */
301706f2543Smrg	        RegionUninit(&region);
302706f2543Smrg		return TRUE;
303706f2543Smrg	  }
304706f2543Smrg
305706f2543Smrg	  formats = infoRec->CPUToScreenAlphaTextureFormats;
306706f2543Smrg	  dstformats = infoRec->CPUToScreenAlphaTextureDstFormats;
307706f2543Smrg	  if(!formats || !dstformats)
308706f2543Smrg		return FALSE;
309706f2543Smrg
310706f2543Smrg	  w = pMask->pDrawable->width;
311706f2543Smrg	  h = pMask->pDrawable->height;
312706f2543Smrg
313706f2543Smrg	  if(pMask->repeat) {
314706f2543Smrg	      if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) ||
315706f2543Smrg		   ((infoRec->CPUToScreenAlphaTextureFlags &
316706f2543Smrg                                   XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
317706f2543Smrg				((h & (h - 1)) || (w & (w - 1)))))
318706f2543Smrg	      {
319706f2543Smrg		 return FALSE;
320706f2543Smrg	      }
321706f2543Smrg	      flags |= XAA_RENDER_REPEAT;
322706f2543Smrg	  }
323706f2543Smrg
324706f2543Smrg	  if((alpha != 0xffff) &&
325706f2543Smrg              (infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA))
326706f2543Smrg		return FALSE;
327706f2543Smrg
328706f2543Smrg	  while(*formats != pMask->format) {
329706f2543Smrg		if(!(*formats)) return FALSE;
330706f2543Smrg		formats++;
331706f2543Smrg          }
332706f2543Smrg	  while(*dstformats != pDst->format) {
333706f2543Smrg		if(!(*dstformats))
334706f2543Smrg		    return FALSE;
335706f2543Smrg		dstformats++;
336706f2543Smrg          }
337706f2543Smrg
338706f2543Smrg	  if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
339706f2543Smrg                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
340706f2543Smrg                                   width, height))
341706f2543Smrg		return TRUE;
342706f2543Smrg
343706f2543Smrg	  nbox = RegionNumRects(&region);
344706f2543Smrg	  pbox = RegionRects(&region);
345706f2543Smrg
346706f2543Smrg	  if(!nbox) {
347706f2543Smrg                RegionUninit(&region);
348706f2543Smrg		return TRUE;
349706f2543Smrg	  }
350706f2543Smrg
351706f2543Smrg	  if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn,
352706f2543Smrg			op, red, green, blue, alpha, pMask->format,
353706f2543Smrg			pDst->format,
354706f2543Smrg			((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
355706f2543Smrg			((PixmapPtr)(pMask->pDrawable))->devKind,
356706f2543Smrg			w, h, flags))
357706f2543Smrg	  {
358706f2543Smrg                RegionUninit(&region);
359706f2543Smrg		return FALSE;
360706f2543Smrg	  }
361706f2543Smrg
362706f2543Smrg	   xMask -= xDst;
363706f2543Smrg	   yMask -= yDst;
364706f2543Smrg
365706f2543Smrg	   while(nbox--) {
366706f2543Smrg	      (*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn,
367706f2543Smrg			pbox->x1, pbox->y1,
368706f2543Smrg			pbox->x1 + xMask, pbox->y1 + yMask,
369706f2543Smrg			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
370706f2543Smrg	      pbox++;
371706f2543Smrg	   }
372706f2543Smrg
373706f2543Smrg	   SET_SYNC_FLAG(infoRec);
374706f2543Smrg	   RegionUninit(&region);
375706f2543Smrg	   return TRUE;
376706f2543Smrg	}
377706f2543Smrg    } else {
378706f2543Smrg	formats = infoRec->CPUToScreenTextureFormats;
379706f2543Smrg	dstformats = infoRec->CPUToScreenTextureDstFormats;
380706f2543Smrg	if(!formats || !dstformats)
381706f2543Smrg	    return FALSE;
382706f2543Smrg
383706f2543Smrg        w = pSrc->pDrawable->width;
384706f2543Smrg        h = pSrc->pDrawable->height;
385706f2543Smrg
386706f2543Smrg        if(pSrc->repeat) {
387706f2543Smrg              if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) ||
388706f2543Smrg                   ((infoRec->CPUToScreenTextureFlags &
389706f2543Smrg                                   XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
390706f2543Smrg                                ((h & (h - 1)) || (w & (w - 1)))))
391706f2543Smrg              {
392706f2543Smrg                 return FALSE;
393706f2543Smrg              }
394706f2543Smrg              flags |= XAA_RENDER_REPEAT;
395706f2543Smrg        }
396706f2543Smrg
397706f2543Smrg	while(*formats != pSrc->format) {
398706f2543Smrg	    if(!(*formats)) return FALSE;
399706f2543Smrg	    formats++;
400706f2543Smrg	}
401706f2543Smrg	while(*dstformats != pDst->format) {
402706f2543Smrg	    if(!(*dstformats))
403706f2543Smrg		return FALSE;
404706f2543Smrg	    dstformats++;
405706f2543Smrg	}
406706f2543Smrg
407706f2543Smrg	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
408706f2543Smrg                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
409706f2543Smrg                                   width, height))
410706f2543Smrg		return TRUE;
411706f2543Smrg
412706f2543Smrg	nbox = RegionNumRects(&region);
413706f2543Smrg	pbox = RegionRects(&region);
414706f2543Smrg
415706f2543Smrg        if(!nbox) {
416706f2543Smrg             RegionUninit(&region);
417706f2543Smrg             return TRUE;
418706f2543Smrg        }
419706f2543Smrg
420706f2543Smrg	if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn,
421706f2543Smrg			op, pSrc->format, pDst->format,
422706f2543Smrg			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
423706f2543Smrg			((PixmapPtr)(pSrc->pDrawable))->devKind,
424706f2543Smrg			w, h, flags))
425706f2543Smrg        {
426706f2543Smrg              RegionUninit(&region);
427706f2543Smrg              return FALSE;
428706f2543Smrg        }
429706f2543Smrg
430706f2543Smrg
431706f2543Smrg	xSrc -= xDst;
432706f2543Smrg	ySrc -= yDst;
433706f2543Smrg
434706f2543Smrg	while(nbox--) {
435706f2543Smrg	    (*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn,
436706f2543Smrg			pbox->x1, pbox->y1,
437706f2543Smrg			pbox->x1 + xSrc, pbox->y1 + ySrc,
438706f2543Smrg			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
439706f2543Smrg	    pbox++;
440706f2543Smrg	 }
441706f2543Smrg
442706f2543Smrg	SET_SYNC_FLAG(infoRec);
443706f2543Smrg	RegionUninit(&region);
444706f2543Smrg	return TRUE;
445706f2543Smrg    }
446706f2543Smrg
447706f2543Smrg
448706f2543Smrg    return FALSE;
449706f2543Smrg}
450706f2543Smrg
451706f2543Smrgstatic void
452706f2543SmrgXAACompositeSrcCopy (PicturePtr pSrc,
453706f2543Smrg		     PicturePtr pDst,
454706f2543Smrg		     INT16      xSrc,
455706f2543Smrg		     INT16      ySrc,
456706f2543Smrg		     INT16      xDst,
457706f2543Smrg		     INT16      yDst,
458706f2543Smrg		     CARD16     width,
459706f2543Smrg		     CARD16     height)
460706f2543Smrg{
461706f2543Smrg    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
462706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
463706f2543Smrg    int i, nbox;
464706f2543Smrg    int xoff, yoff;
465706f2543Smrg    BoxPtr pbox;
466706f2543Smrg    DDXPointPtr pptSrc;
467706f2543Smrg    RegionRec region;
468706f2543Smrg
469706f2543Smrg    xDst += pDst->pDrawable->x;
470706f2543Smrg    yDst += pDst->pDrawable->y;
471706f2543Smrg    xSrc += pSrc->pDrawable->x;
472706f2543Smrg    ySrc += pSrc->pDrawable->y;
473706f2543Smrg
474706f2543Smrg    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
475706f2543Smrg				   xSrc, ySrc, 0, 0, xDst, yDst,
476706f2543Smrg				   width, height))
477706f2543Smrg	return;
478706f2543Smrg
479706f2543Smrg    nbox = RegionNumRects(&region);
480706f2543Smrg    pbox = RegionRects(&region);
481706f2543Smrg
482706f2543Smrg    if(!nbox) {
483706f2543Smrg	RegionUninit(&region);
484706f2543Smrg	return;
485706f2543Smrg    }
486706f2543Smrg    pptSrc = malloc(sizeof(DDXPointRec) * nbox);
487706f2543Smrg    if (!pptSrc) {
488706f2543Smrg	RegionUninit(&region);
489706f2543Smrg	return;
490706f2543Smrg    }
491706f2543Smrg    xoff = xSrc - xDst;
492706f2543Smrg    yoff = ySrc - yDst;
493706f2543Smrg    for (i = 0; i < nbox; i++) {
494706f2543Smrg	pptSrc[i].x = pbox[i].x1 + xoff;
495706f2543Smrg	pptSrc[i].y = pbox[i].y1 + yoff;
496706f2543Smrg    }
497706f2543Smrg
498706f2543Smrg    infoRec->ScratchGC.planemask = ~0L;
499706f2543Smrg    infoRec->ScratchGC.alu = GXcopy;
500706f2543Smrg
501706f2543Smrg    XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, &region,
502706f2543Smrg		pptSrc);
503706f2543Smrg
504706f2543Smrg    free(pptSrc);
505706f2543Smrg    RegionUninit(&region);
506706f2543Smrg    return;
507706f2543Smrg}
508706f2543Smrg
509706f2543Smrgvoid
510706f2543SmrgXAAComposite (CARD8      op,
511706f2543Smrg	      PicturePtr pSrc,
512706f2543Smrg	      PicturePtr pMask,
513706f2543Smrg	      PicturePtr pDst,
514706f2543Smrg	      INT16      xSrc,
515706f2543Smrg	      INT16      ySrc,
516706f2543Smrg	      INT16      xMask,
517706f2543Smrg	      INT16      yMask,
518706f2543Smrg	      INT16      xDst,
519706f2543Smrg	      INT16      yDst,
520706f2543Smrg	      CARD16     width,
521706f2543Smrg	      CARD16     height)
522706f2543Smrg{
523706f2543Smrg    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
524706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
525706f2543Smrg    XAA_RENDER_PROLOGUE(pScreen, Composite);
526706f2543Smrg
527706f2543Smrg    if(!pMask && infoRec->pScrn->vtSema &&
528706f2543Smrg       infoRec->ScreenToScreenBitBlt &&
529706f2543Smrg       pSrc->pDrawable &&
530706f2543Smrg       DRAWABLE_IS_ON_CARD(pSrc->pDrawable) &&
531706f2543Smrg       DRAWABLE_IS_ON_CARD(pDst->pDrawable) &&
532706f2543Smrg       !pSrc->transform &&
533706f2543Smrg       (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 &&
534706f2543Smrg			  xSrc+width<=pSrc->pDrawable->width &&
535706f2543Smrg			  ySrc+height<=pSrc->pDrawable->height)) &&
536706f2543Smrg       ((op == PictOpSrc &&
537706f2543Smrg	 ((pSrc->format==pDst->format) ||
538706f2543Smrg	  (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
539706f2543Smrg	  (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
540706f2543Smrg	(op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
541706f2543Smrg	 pSrc->format==pDst->format &&
542706f2543Smrg	 (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8))))
543706f2543Smrg    {
544706f2543Smrg	XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height);
545706f2543Smrg    } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) ||
546706f2543Smrg              !infoRec->Composite ||
547706f2543Smrg              !(*infoRec->Composite)(op, pSrc, pMask, pDst,
548706f2543Smrg                                     xSrc, ySrc, xMask, yMask, xDst, yDst,
549706f2543Smrg                                     width, height))
550706f2543Smrg    {
551706f2543Smrg        if(infoRec->pScrn->vtSema &&
552706f2543Smrg           ((pSrc->pDrawable &&
553706f2543Smrg             (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
554706f2543Smrg            pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
555706f2543Smrg            SYNC_CHECK(pDst->pDrawable);
556706f2543Smrg        }
557706f2543Smrg        (*GetPictureScreen(pScreen)->Composite) (op,
558706f2543Smrg		       pSrc,
559706f2543Smrg		       pMask,
560706f2543Smrg		       pDst,
561706f2543Smrg		       xSrc,
562706f2543Smrg		       ySrc,
563706f2543Smrg		       xMask,
564706f2543Smrg		       yMask,
565706f2543Smrg		       xDst,
566706f2543Smrg		       yDst,
567706f2543Smrg		       width,
568706f2543Smrg		       height);
569706f2543Smrg    }
570706f2543Smrg
571706f2543Smrg    if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
572706f2543Smrg	(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
573706f2543Smrg
574706f2543Smrg    XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite);
575706f2543Smrg}
576706f2543Smrg
577706f2543SmrgBool
578706f2543SmrgXAADoGlyphs (CARD8         op,
579706f2543Smrg	   PicturePtr    pSrc,
580706f2543Smrg	   PicturePtr    pDst,
581706f2543Smrg	   PictFormatPtr maskFormat,
582706f2543Smrg	   INT16         xSrc,
583706f2543Smrg	   INT16         ySrc,
584706f2543Smrg	   int           nlist,
585706f2543Smrg	   GlyphListPtr  list,
586706f2543Smrg	   GlyphPtr      *glyphs)
587706f2543Smrg{
588706f2543Smrg    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
589706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
590706f2543Smrg
591706f2543Smrg    if(!RegionNumRects(pDst->pCompositeClip))
592706f2543Smrg	return TRUE;
593706f2543Smrg
594706f2543Smrg    if(!infoRec->pScrn->vtSema ||
595706f2543Smrg      ((pDst->pDrawable->type != DRAWABLE_WINDOW) &&
596706f2543Smrg	!IS_OFFSCREEN_PIXMAP(pDst->pDrawable)))
597706f2543Smrg	return FALSE;
598706f2543Smrg
599706f2543Smrg    if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) ||
600706f2543Smrg        IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))
601706f2543Smrg        return FALSE;
602706f2543Smrg
603706f2543Smrg    /*
604706f2543Smrg     * If it looks like we have a chance of being able to draw these
605706f2543Smrg     * glyphs with an accelerated Composite, do that now to avoid
606706f2543Smrg     * unneeded and costly syncs.
607706f2543Smrg     */
608706f2543Smrg    if(maskFormat) {
609706f2543Smrg        if(!infoRec->CPUToScreenAlphaTextureFormats)
610706f2543Smrg            return FALSE;
611706f2543Smrg    } else {
612706f2543Smrg        if(!infoRec->CPUToScreenTextureFormats)
613706f2543Smrg            return FALSE;
614706f2543Smrg    }
615706f2543Smrg
616706f2543Smrg    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
617706f2543Smrg
618706f2543Smrg    return TRUE;
619706f2543Smrg}
620706f2543Smrg
621706f2543Smrg
622706f2543Smrgvoid
623706f2543SmrgXAAGlyphs (CARD8         op,
624706f2543Smrg	   PicturePtr    pSrc,
625706f2543Smrg	   PicturePtr    pDst,
626706f2543Smrg	   PictFormatPtr maskFormat,
627706f2543Smrg	   INT16         xSrc,
628706f2543Smrg	   INT16         ySrc,
629706f2543Smrg	   int           nlist,
630706f2543Smrg	   GlyphListPtr  list,
631706f2543Smrg	   GlyphPtr      *glyphs)
632706f2543Smrg{
633706f2543Smrg    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
634706f2543Smrg    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
635706f2543Smrg    XAA_RENDER_PROLOGUE(pScreen, Glyphs);
636706f2543Smrg
637706f2543Smrg    if(!pSrc->pDrawable || !infoRec->Glyphs ||
638706f2543Smrg       !(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat,
639706f2543Smrg                           xSrc, ySrc, nlist, list, glyphs))
640706f2543Smrg    {
641706f2543Smrg        if(infoRec->pScrn->vtSema &&
642706f2543Smrg           ((pSrc->pDrawable &&
643706f2543Smrg             (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
644706f2543Smrg            pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
645706f2543Smrg            SYNC_CHECK(pDst->pDrawable);
646706f2543Smrg        }
647706f2543Smrg       (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat,
648706f2543Smrg					  xSrc, ySrc, nlist, list, glyphs);
649706f2543Smrg    }
650706f2543Smrg
651706f2543Smrg    if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
652706f2543Smrg	(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
653706f2543Smrg
654706f2543Smrg    XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs);
655706f2543Smrg}
656