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_XORG_CONFIG_H
25#include <xorg-config.h>
26#endif
27
28#include <string.h>
29
30#include "misc.h"
31#include "xf86.h"
32#include "xf86_OSproc.h"
33
34#include <X11/X.h>
35#include "scrnintstr.h"
36#include "pixmapstr.h"
37#include "windowstr.h"
38#include "xf86str.h"
39#include "mi.h"
40#include "picturestr.h"
41#include "glyphstr.h"
42#include "picture.h"
43#include "mipict.h"
44#include "xaa.h"
45#include "xaalocal.h"
46#include "xaawrap.h"
47#include "xaacexp.h"
48#include "xf86fbman.h"
49#include "servermd.h"
50
51Bool
52XAAGetPixelFromRGBA (
53    CARD32 *pixel,
54    CARD16 red,
55    CARD16 green,
56    CARD16 blue,
57    CARD16 alpha,
58    CARD32 format
59){
60    int rbits, bbits, gbits, abits;
61    int rshift, bshift, gshift, ashift;
62
63    *pixel = 0;
64
65    if(!PICT_FORMAT_COLOR(format))
66    	return FALSE;
67
68    rbits = PICT_FORMAT_R(format);
69    gbits = PICT_FORMAT_G(format);
70    bbits = PICT_FORMAT_B(format);
71    abits = PICT_FORMAT_A(format);
72
73    if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
74        bshift = 0;
75        gshift = bbits;
76	rshift = gshift + gbits;
77	ashift = rshift + rbits;
78    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
79        rshift = 0;
80	gshift = rbits;
81	bshift = gshift + gbits;
82	ashift = bshift + bbits;
83    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
84	bshift = PICT_FORMAT_BPP(format) - bbits;
85	gshift = bshift - gbits;
86	rshift = gshift - rbits;
87	ashift = 0;
88    } else
89	return FALSE;
90
91    *pixel |=  ( blue >> (16 - bbits)) << bshift;
92    *pixel |=  (  red >> (16 - rbits)) << rshift;
93    *pixel |=  (green >> (16 - gbits)) << gshift;
94    *pixel |=  (alpha >> (16 - abits)) << ashift;
95
96    return TRUE;
97}
98
99
100Bool
101XAAGetRGBAFromPixel(
102    CARD32 pixel,
103    CARD16 *red,
104    CARD16 *green,
105    CARD16 *blue,
106    CARD16 *alpha,
107    CARD32 format
108){
109    int rbits, bbits, gbits, abits;
110    int rshift, bshift, gshift, ashift;
111
112    if(!PICT_FORMAT_COLOR(format))
113    	return FALSE;
114
115    rbits = PICT_FORMAT_R(format);
116    gbits = PICT_FORMAT_G(format);
117    bbits = PICT_FORMAT_B(format);
118    abits = PICT_FORMAT_A(format);
119
120    if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB) {
121        bshift = 0;
122        gshift = bbits;
123	rshift = gshift + gbits;
124	ashift = rshift + rbits;
125    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
126        rshift = 0;
127	gshift = rbits;
128	bshift = gshift + gbits;
129	ashift = bshift + bbits;
130    } else if(PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
131	bshift = PICT_FORMAT_BPP(format) - bbits;
132	gshift = bshift - gbits;
133	rshift = gshift - rbits;
134	ashift = 0;
135    } else
136	return FALSE;
137
138    *red = ((pixel >> rshift ) & ((1 << rbits) - 1)) << (16 - rbits);
139    while(rbits < 16) {
140       *red |= *red >> rbits;
141       rbits <<= 1;
142    }
143
144    *green = ((pixel >> gshift ) & ((1 << gbits) - 1)) << (16 - gbits);
145    while(gbits < 16) {
146       *green |= *green >> gbits;
147       gbits <<= 1;
148    }
149
150    *blue = ((pixel >> bshift ) & ((1 << bbits) - 1)) << (16 - bbits);
151    while(bbits < 16) {
152       *blue |= *blue >> bbits;
153       bbits <<= 1;
154    }
155
156    if(abits) {
157       *alpha = ((pixel >> ashift ) & ((1 << abits) - 1)) << (16 - abits);
158       while(abits < 16) {
159          *alpha |= *alpha >> abits;
160          abits <<= 1;
161       }
162    } else *alpha = 0xffff;
163
164    return TRUE;
165}
166
167/* 8:8:8 + PICT_a8 -> 8:8:8:8 texture */
168
169void
170XAA_888_plus_PICT_a8_to_8888 (
171    CARD32 color,
172    CARD8  *alphaPtr,   /* in bytes */
173    int    alphaPitch,
174    CARD32  *dstPtr,
175    int    dstPitch,	/* in dwords */
176    int    width,
177    int    height
178){
179    int x;
180
181    color &= 0x00ffffff;
182
183    while(height--) {
184	for(x = 0; x < width; x++)
185	   dstPtr[x] = color | (alphaPtr[x] << 24);
186	dstPtr += dstPitch;
187	alphaPtr += alphaPitch;
188    }
189}
190
191#define DRAWABLE_IS_ON_CARD(pDraw) \
192    (pDraw->type == DRAWABLE_WINDOW || \
193     (pDraw->type == DRAWABLE_PIXMAP && IS_OFFSCREEN_PIXMAP(pDraw)))
194
195Bool
196XAADoComposite (
197    CARD8      op,
198    PicturePtr pSrc,
199    PicturePtr pMask,
200    PicturePtr pDst,
201    INT16      xSrc,
202    INT16      ySrc,
203    INT16      xMask,
204    INT16      yMask,
205    INT16      xDst,
206    INT16      yDst,
207    CARD16     width,
208    CARD16     height
209){
210    ScreenPtr pScreen = pDst->pDrawable->pScreen;
211    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
212    RegionRec region;
213    CARD32 *formats, *dstformats;
214    int flags = 0;
215    BoxPtr pbox;
216    int nbox, w, h;
217
218    if(!RegionNumRects(pDst->pCompositeClip))
219        return TRUE;
220
221    if(!infoRec->pScrn->vtSema || !DRAWABLE_IS_ON_CARD(pDst->pDrawable))
222	return FALSE;
223
224    if(DRAWABLE_IS_ON_CARD(pSrc->pDrawable))
225	return FALSE;
226
227    if (pSrc->transform || (pMask && pMask->transform))
228	return FALSE;
229
230    if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
231	return FALSE;
232
233    if ((pSrc->repeat && pSrc->repeatType != RepeatNormal) ||
234	(pMask && pMask->repeat && pMask->repeatType != RepeatNormal))
235    {
236	return FALSE;
237    }
238
239    xDst += pDst->pDrawable->x;
240    yDst += pDst->pDrawable->y;
241    xSrc += pSrc->pDrawable->x;
242    ySrc += pSrc->pDrawable->y;
243
244    if(pMask) {
245	if(pMask->componentAlpha)
246	    return FALSE;
247
248	/* for now we only do it if there is a 1x1 (solid) source */
249
250	if((pSrc->pDrawable->width == 1) && (pSrc->pDrawable->height == 1)) {
251	   CARD16 red, green, blue, alpha;
252           CARD32 pixel =
253                *((CARD32*)(((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr));
254
255	   if(!XAAGetRGBAFromPixel(pixel,&red,&green,&blue,&alpha,pSrc->format))
256		return FALSE;
257
258	   xMask += pMask->pDrawable->x;
259	   yMask += pMask->pDrawable->y;
260
261	   /* pull out color expandable operations here */
262	   if((pMask->format == PICT_a1) && (alpha == 0xffff) &&
263	       (op == PictOpOver) && infoRec->WriteBitmap && !pMask->repeat &&
264	       !(infoRec->WriteBitmapFlags & NO_TRANSPARENCY) &&
265	       (!(infoRec->WriteBitmapFlags & RGB_EQUAL) ||
266	         ((red == green) && (green == blue))))
267	   {
268	        PixmapPtr pPix = (PixmapPtr)(pMask->pDrawable);
269		int skipleft;
270
271	  	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
272                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
273                                   width, height))
274		      return TRUE;
275
276		nbox = RegionNumRects(&region);
277		pbox = RegionRects(&region);
278
279	        if(!nbox)
280		    return TRUE;
281
282	        XAAGetPixelFromRGBA(&pixel, red, green, blue, 0, pDst->format);
283
284	   	xMask -= xDst;
285	   	yMask -= yDst;
286
287	   	while(nbox--) {
288		    skipleft = pbox->x1 + xMask;
289
290	            (*infoRec->WriteBitmap)(infoRec->pScrn,
291			        pbox->x1, pbox->y1,
292			        pbox->x2 - pbox->x1, pbox->y2 - pbox->y1,
293			        (unsigned char*)(pPix->devPrivate.ptr) +
294				  (pPix->devKind * (pbox->y1 + yMask)) +
295			          ((skipleft >> 3) & ~3), pPix->devKind,
296				skipleft & 31, pixel, -1, GXcopy, ~0);
297	            pbox++;
298	   	}
299
300		/* WriteBitmap sets the Sync flag */
301	        RegionUninit(&region);
302		return TRUE;
303	  }
304
305	  formats = infoRec->CPUToScreenAlphaTextureFormats;
306	  dstformats = infoRec->CPUToScreenAlphaTextureDstFormats;
307	  if(!formats || !dstformats)
308		return FALSE;
309
310	  w = pMask->pDrawable->width;
311	  h = pMask->pDrawable->height;
312
313	  if(pMask->repeat) {
314	      if((infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_TILE) ||
315		   ((infoRec->CPUToScreenAlphaTextureFlags &
316                                   XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
317				((h & (h - 1)) || (w & (w - 1)))))
318	      {
319		 return FALSE;
320	      }
321	      flags |= XAA_RENDER_REPEAT;
322	  }
323
324	  if((alpha != 0xffff) &&
325              (infoRec->CPUToScreenAlphaTextureFlags & XAA_RENDER_NO_SRC_ALPHA))
326		return FALSE;
327
328	  while(*formats != pMask->format) {
329		if(!(*formats)) return FALSE;
330		formats++;
331          }
332	  while(*dstformats != pDst->format) {
333		if(!(*dstformats))
334		    return FALSE;
335		dstformats++;
336          }
337
338	  if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
339                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
340                                   width, height))
341		return TRUE;
342
343	  nbox = RegionNumRects(&region);
344	  pbox = RegionRects(&region);
345
346	  if(!nbox) {
347                RegionUninit(&region);
348		return TRUE;
349	  }
350
351	  if(!(infoRec->SetupForCPUToScreenAlphaTexture2)(infoRec->pScrn,
352			op, red, green, blue, alpha, pMask->format,
353			pDst->format,
354			((PixmapPtr)(pMask->pDrawable))->devPrivate.ptr,
355			((PixmapPtr)(pMask->pDrawable))->devKind,
356			w, h, flags))
357	  {
358                RegionUninit(&region);
359		return FALSE;
360	  }
361
362	   xMask -= xDst;
363	   yMask -= yDst;
364
365	   while(nbox--) {
366	      (*infoRec->SubsequentCPUToScreenAlphaTexture)(infoRec->pScrn,
367			pbox->x1, pbox->y1,
368			pbox->x1 + xMask, pbox->y1 + yMask,
369			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
370	      pbox++;
371	   }
372
373	   SET_SYNC_FLAG(infoRec);
374	   RegionUninit(&region);
375	   return TRUE;
376	}
377    } else {
378	formats = infoRec->CPUToScreenTextureFormats;
379	dstformats = infoRec->CPUToScreenTextureDstFormats;
380	if(!formats || !dstformats)
381	    return FALSE;
382
383        w = pSrc->pDrawable->width;
384        h = pSrc->pDrawable->height;
385
386        if(pSrc->repeat) {
387              if((infoRec->CPUToScreenTextureFlags & XAA_RENDER_NO_TILE) ||
388                   ((infoRec->CPUToScreenTextureFlags &
389                                   XAA_RENDER_POWER_OF_2_TILE_ONLY) &&
390                                ((h & (h - 1)) || (w & (w - 1)))))
391              {
392                 return FALSE;
393              }
394              flags |= XAA_RENDER_REPEAT;
395        }
396
397	while(*formats != pSrc->format) {
398	    if(!(*formats)) return FALSE;
399	    formats++;
400	}
401	while(*dstformats != pDst->format) {
402	    if(!(*dstformats))
403		return FALSE;
404	    dstformats++;
405	}
406
407	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
408                                   xSrc, ySrc, xMask, yMask, xDst, yDst,
409                                   width, height))
410		return TRUE;
411
412	nbox = RegionNumRects(&region);
413	pbox = RegionRects(&region);
414
415        if(!nbox) {
416             RegionUninit(&region);
417             return TRUE;
418        }
419
420	if(!(infoRec->SetupForCPUToScreenTexture2)(infoRec->pScrn,
421			op, pSrc->format, pDst->format,
422			((PixmapPtr)(pSrc->pDrawable))->devPrivate.ptr,
423			((PixmapPtr)(pSrc->pDrawable))->devKind,
424			w, h, flags))
425        {
426              RegionUninit(&region);
427              return FALSE;
428        }
429
430
431	xSrc -= xDst;
432	ySrc -= yDst;
433
434	while(nbox--) {
435	    (*infoRec->SubsequentCPUToScreenTexture)(infoRec->pScrn,
436			pbox->x1, pbox->y1,
437			pbox->x1 + xSrc, pbox->y1 + ySrc,
438			pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
439	    pbox++;
440	 }
441
442	SET_SYNC_FLAG(infoRec);
443	RegionUninit(&region);
444	return TRUE;
445    }
446
447
448    return FALSE;
449}
450
451static void
452XAACompositeSrcCopy (PicturePtr pSrc,
453		     PicturePtr pDst,
454		     INT16      xSrc,
455		     INT16      ySrc,
456		     INT16      xDst,
457		     INT16      yDst,
458		     CARD16     width,
459		     CARD16     height)
460{
461    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
462    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
463    int i, nbox;
464    int xoff, yoff;
465    BoxPtr pbox;
466    DDXPointPtr pptSrc;
467    RegionRec region;
468
469    xDst += pDst->pDrawable->x;
470    yDst += pDst->pDrawable->y;
471    xSrc += pSrc->pDrawable->x;
472    ySrc += pSrc->pDrawable->y;
473
474    if (!miComputeCompositeRegion (&region, pSrc, NULL, pDst,
475				   xSrc, ySrc, 0, 0, xDst, yDst,
476				   width, height))
477	return;
478
479    nbox = RegionNumRects(&region);
480    pbox = RegionRects(&region);
481
482    if(!nbox) {
483	RegionUninit(&region);
484	return;
485    }
486    pptSrc = malloc(sizeof(DDXPointRec) * nbox);
487    if (!pptSrc) {
488	RegionUninit(&region);
489	return;
490    }
491    xoff = xSrc - xDst;
492    yoff = ySrc - yDst;
493    for (i = 0; i < nbox; i++) {
494	pptSrc[i].x = pbox[i].x1 + xoff;
495	pptSrc[i].y = pbox[i].y1 + yoff;
496    }
497
498    infoRec->ScratchGC.planemask = ~0L;
499    infoRec->ScratchGC.alu = GXcopy;
500
501    XAADoBitBlt(pSrc->pDrawable, pDst->pDrawable, &infoRec->ScratchGC, &region,
502		pptSrc);
503
504    free(pptSrc);
505    RegionUninit(&region);
506    return;
507}
508
509void
510XAAComposite (CARD8      op,
511	      PicturePtr pSrc,
512	      PicturePtr pMask,
513	      PicturePtr pDst,
514	      INT16      xSrc,
515	      INT16      ySrc,
516	      INT16      xMask,
517	      INT16      yMask,
518	      INT16      xDst,
519	      INT16      yDst,
520	      CARD16     width,
521	      CARD16     height)
522{
523    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
524    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
525    XAA_RENDER_PROLOGUE(pScreen, Composite);
526
527    if(!pMask && infoRec->pScrn->vtSema &&
528       infoRec->ScreenToScreenBitBlt &&
529       pSrc->pDrawable &&
530       DRAWABLE_IS_ON_CARD(pSrc->pDrawable) &&
531       DRAWABLE_IS_ON_CARD(pDst->pDrawable) &&
532       !pSrc->transform &&
533       (!pSrc->repeat || (xSrc >= 0 && ySrc >= 0 &&
534			  xSrc+width<=pSrc->pDrawable->width &&
535			  ySrc+height<=pSrc->pDrawable->height)) &&
536       ((op == PictOpSrc &&
537	 ((pSrc->format==pDst->format) ||
538	  (pSrc->format==PICT_a8r8g8b8 && pDst->format==PICT_x8r8g8b8) ||
539	  (pSrc->format==PICT_a8b8g8r8 && pDst->format==PICT_x8b8g8r8))) ||
540	(op == PictOpOver && !pSrc->alphaMap && !pDst->alphaMap &&
541	 pSrc->format==pDst->format &&
542	 (pSrc->format==PICT_x8r8g8b8 || pSrc->format==PICT_x8b8g8r8))))
543    {
544	XAACompositeSrcCopy(pSrc, pDst, xSrc, ySrc, xDst, yDst, width, height);
545    } else if(!pSrc->pDrawable || (pMask && !pMask->pDrawable) ||
546              !infoRec->Composite ||
547              !(*infoRec->Composite)(op, pSrc, pMask, pDst,
548                                     xSrc, ySrc, xMask, yMask, xDst, yDst,
549                                     width, height))
550    {
551        if(infoRec->pScrn->vtSema &&
552           ((pSrc->pDrawable &&
553             (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
554            pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
555            SYNC_CHECK(pDst->pDrawable);
556        }
557        (*GetPictureScreen(pScreen)->Composite) (op,
558		       pSrc,
559		       pMask,
560		       pDst,
561		       xSrc,
562		       ySrc,
563		       xMask,
564		       yMask,
565		       xDst,
566		       yDst,
567		       width,
568		       height);
569    }
570
571    if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
572	(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
573
574    XAA_RENDER_EPILOGUE(pScreen, Composite, XAAComposite);
575}
576
577Bool
578XAADoGlyphs (CARD8         op,
579	   PicturePtr    pSrc,
580	   PicturePtr    pDst,
581	   PictFormatPtr maskFormat,
582	   INT16         xSrc,
583	   INT16         ySrc,
584	   int           nlist,
585	   GlyphListPtr  list,
586	   GlyphPtr      *glyphs)
587{
588    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
589    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
590
591    if(!RegionNumRects(pDst->pCompositeClip))
592	return TRUE;
593
594    if(!infoRec->pScrn->vtSema ||
595      ((pDst->pDrawable->type != DRAWABLE_WINDOW) &&
596	!IS_OFFSCREEN_PIXMAP(pDst->pDrawable)))
597	return FALSE;
598
599    if((pSrc->pDrawable->type != DRAWABLE_PIXMAP) ||
600        IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))
601        return FALSE;
602
603    /*
604     * If it looks like we have a chance of being able to draw these
605     * glyphs with an accelerated Composite, do that now to avoid
606     * unneeded and costly syncs.
607     */
608    if(maskFormat) {
609        if(!infoRec->CPUToScreenAlphaTextureFormats)
610            return FALSE;
611    } else {
612        if(!infoRec->CPUToScreenTextureFormats)
613            return FALSE;
614    }
615
616    miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
617
618    return TRUE;
619}
620
621
622void
623XAAGlyphs (CARD8         op,
624	   PicturePtr    pSrc,
625	   PicturePtr    pDst,
626	   PictFormatPtr maskFormat,
627	   INT16         xSrc,
628	   INT16         ySrc,
629	   int           nlist,
630	   GlyphListPtr  list,
631	   GlyphPtr      *glyphs)
632{
633    ScreenPtr	pScreen = pDst->pDrawable->pScreen;
634    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
635    XAA_RENDER_PROLOGUE(pScreen, Glyphs);
636
637    if(!pSrc->pDrawable || !infoRec->Glyphs ||
638       !(*infoRec->Glyphs)(op, pSrc, pDst, maskFormat,
639                           xSrc, ySrc, nlist, list, glyphs))
640    {
641        if(infoRec->pScrn->vtSema &&
642           ((pSrc->pDrawable &&
643             (pSrc->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pSrc->pDrawable))) ||
644            pDst->pDrawable->type == DRAWABLE_WINDOW || IS_OFFSCREEN_PIXMAP(pDst->pDrawable))) {
645            SYNC_CHECK(pDst->pDrawable);
646        }
647       (*GetPictureScreen(pScreen)->Glyphs) (op, pSrc, pDst, maskFormat,
648					  xSrc, ySrc, nlist, list, glyphs);
649    }
650
651    if(pDst->pDrawable->type == DRAWABLE_PIXMAP)
652	(XAA_GET_PIXMAP_PRIVATE((PixmapPtr)(pDst->pDrawable)))->flags |= DIRTY;
653
654    XAA_RENDER_EPILOGUE(pScreen, Glyphs, XAAGlyphs);
655}
656