1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include "misc.h"
7#include "xf86.h"
8#include "xf86_OSproc.h"
9
10#include <X11/X.h>
11#include "scrnintstr.h"
12#include "pixmapstr.h"
13#include "xf86str.h"
14#include "xaa.h"
15#include "xaalocal.h"
16
17
18static void XAARenderSolidRects(GCPtr, int, BoxPtr, int, int);
19static void XAARenderColor8x8Rects(GCPtr, int, BoxPtr, int, int);
20static void XAARenderMono8x8Rects(GCPtr, int, BoxPtr, int, int);
21static void XAARenderColorExpandRects(GCPtr, int, BoxPtr, int, int);
22static void XAARenderCacheExpandRects(GCPtr, int, BoxPtr, int, int);
23static void XAARenderCacheBltRects(GCPtr, int, BoxPtr, int, int);
24static void XAARenderImageWriteRects(GCPtr, int, BoxPtr, int, int);
25static void XAARenderPixmapCopyRects(GCPtr, int, BoxPtr, int, int);
26
27void
28XAAPolyFillRect(
29    DrawablePtr pDraw,
30    GCPtr pGC,
31    int		nrectFill, 	/* number of rectangles to fill */
32    xRectangle	*prectInit   	/* Pointer to first rectangle to fill */
33){
34    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
35    int		xorg = pDraw->x;
36    int		yorg = pDraw->y;
37    int		type = 0;
38    ClipAndRenderRectsFunc function;
39
40    if((nrectFill <= 0) || !pGC->planemask)
41        return;
42
43    if(!RegionNumRects(pGC->pCompositeClip))
44	return;
45
46    switch(pGC->fillStyle) {
47    case FillSolid:
48	type = DO_SOLID;
49	break;
50    case FillStippled:
51	type = (*infoRec->StippledFillChooser)(pGC);
52	break;
53    case FillOpaqueStippled:
54	if((pGC->fgPixel == pGC->bgPixel) && infoRec->FillSolidRects &&
55                CHECK_PLANEMASK(pGC,infoRec->FillSolidRectsFlags) &&
56                CHECK_ROP(pGC,infoRec->FillSolidRectsFlags) &&
57                CHECK_ROPSRC(pGC,infoRec->FillSolidRectsFlags) &&
58                CHECK_FG(pGC,infoRec->FillSolidRectsFlags))
59	    type = DO_SOLID;
60	else
61	    type = (*infoRec->OpaqueStippledFillChooser)(pGC);
62	break;
63    case FillTiled:
64	type = (*infoRec->TiledFillChooser)(pGC);
65	break;
66    }
67
68    switch(type) {
69    case DO_SOLID:
70	function = XAARenderSolidRects;
71	break;
72    case DO_COLOR_8x8:
73	function = XAARenderColor8x8Rects;
74	break;
75    case DO_MONO_8x8:
76	function = XAARenderMono8x8Rects;
77	break;
78    case DO_CACHE_BLT:
79	function = XAARenderCacheBltRects;
80	break;
81    case DO_COLOR_EXPAND:
82	function = XAARenderColorExpandRects;
83	break;
84    case DO_CACHE_EXPAND:
85	function = XAARenderCacheExpandRects;
86	break;
87    case DO_IMAGE_WRITE:
88	function = XAARenderImageWriteRects;
89	break;
90    case DO_PIXMAP_COPY:
91	function = XAARenderPixmapCopyRects;
92	break;
93    default:
94	(*XAAFallbackOps.PolyFillRect)(pDraw, pGC, nrectFill, prectInit);
95	return;
96    }
97
98    if(xorg | yorg) {
99	int n = nrectFill;
100	xRectangle *prect = prectInit;
101
102	while(n--) {
103	    prect->x += xorg;
104	    prect->y += yorg;
105	    prect++;
106	}
107    }
108
109
110    XAAClipAndRenderRects(pGC, function, nrectFill, prectInit, xorg, yorg);
111}
112
113
114
115	/*********************\
116	|     Solid Rects     |
117	\*********************/
118
119static void
120XAARenderSolidRects(
121   GCPtr pGC,
122   int nboxes,
123   BoxPtr pClipBoxes,
124   int xorg, int yorg
125){
126   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
127
128   (*infoRec->FillSolidRects) (infoRec->pScrn,
129               pGC->fgPixel, pGC->alu, pGC->planemask, nboxes, pClipBoxes);
130}
131
132
133	/************************\
134	|     Mono 8x8 Rects     |
135	\************************/
136
137static void
138XAARenderMono8x8Rects(
139   GCPtr pGC,
140   int nboxes,
141   BoxPtr pClipBoxes,
142   int xorg, int yorg
143){
144   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
145   XAAPixmapPtr pPriv;
146   int fg, bg;
147
148   switch(pGC->fillStyle) {
149   case FillStippled:
150      pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
151      fg = pGC->fgPixel;  bg = -1;
152      break;
153   case FillOpaqueStippled:
154      pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->stipple);
155      fg = pGC->fgPixel;  bg = pGC->bgPixel;
156      break;
157   case FillTiled:
158      pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
159      fg = pPriv->fg;  bg = pPriv->bg;
160      break;
161   default:	/* Muffle compiler */
162      pPriv = NULL;	/* Kaboom */
163      fg = -1;  bg = -1;
164      break;
165   }
166
167   (*infoRec->FillMono8x8PatternRects) (infoRec->pScrn,
168                fg, bg, pGC->alu, pGC->planemask,
169                nboxes, pClipBoxes, pPriv->pattern0, pPriv->pattern1,
170                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y));
171}
172
173	/*************************\
174	|     Color 8x8 Rects     |
175	\*************************/
176
177static void
178XAARenderColor8x8Rects(
179   GCPtr pGC,
180   int nboxes,
181   BoxPtr pClipBoxes,
182   int xorg, int yorg
183){
184   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
185   XAACacheInfoPtr pCache;
186   PixmapPtr pPix;
187   int fg, bg;
188
189   switch(pGC->fillStyle) {
190   case FillStippled:
191      pPix = pGC->stipple;
192      fg = pGC->fgPixel;  bg = -1;
193      break;
194   case FillOpaqueStippled:
195      pPix = pGC->stipple;
196      fg = pGC->fgPixel;  bg = pGC->bgPixel;
197      break;
198   case FillTiled:
199      pPix = pGC->tile.pixmap;
200      fg = -1;  bg = -1;
201      break;
202   default:	/* Muffle compiler */
203      pPix = NULL;
204      fg = -1;  bg = -1;
205      break;
206   }
207
208   pCache = (*infoRec->CacheColor8x8Pattern)(infoRec->pScrn, pPix, fg, bg);
209   (*infoRec->FillColor8x8PatternRects) (infoRec->pScrn,
210                pGC->alu, pGC->planemask, nboxes, pClipBoxes,
211                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pCache);
212}
213
214
215	/****************************\
216	|     Color Expand Rects     |
217	\****************************/
218
219static void
220XAARenderColorExpandRects(
221   GCPtr pGC,
222   int nboxes,
223   BoxPtr pClipBoxes,
224   int xorg, int yorg
225){
226   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
227   int fg, bg;
228
229   switch(pGC->fillStyle) {
230   case FillStippled:
231      fg = pGC->fgPixel;  bg = -1;
232      break;
233   case FillOpaqueStippled:
234      fg = pGC->fgPixel;  bg = pGC->bgPixel;
235      break;
236   default:	/* Muffle compiler */
237      fg = -1;  bg = -1;
238      break;
239   }
240
241   (*infoRec->FillColorExpandRects) (infoRec->pScrn, fg, bg,
242                pGC->alu, pGC->planemask, nboxes, pClipBoxes,
243                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y),
244		pGC->stipple);
245}
246
247
248	/*************************\
249	|     Cache Blt Rects     |
250	\*************************/
251
252static void
253XAARenderCacheBltRects(
254   GCPtr pGC,
255   int nboxes,
256   BoxPtr pClipBoxes,
257   int xorg, int yorg
258){
259   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
260   XAACacheInfoPtr pCache;
261
262   switch(pGC->fillStyle) {
263   case FillStippled:
264      pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple,
265					pGC->fgPixel, -1);
266      break;
267   case FillOpaqueStippled:
268      pCache = (*infoRec->CacheStipple)(infoRec->pScrn, pGC->stipple,
269					pGC->fgPixel, pGC->bgPixel);
270      break;
271   case FillTiled:
272      pCache = (*infoRec->CacheTile)(infoRec->pScrn, pGC->tile.pixmap);
273      break;
274   default:	/* Muffle compiler */
275      pCache = NULL;
276      break;
277   }
278
279   (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu,
280                pGC->planemask, nboxes, pClipBoxes,
281                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y), pCache);
282}
283
284
285	/****************************\
286	|     Cache Expand Rects     |
287	\****************************/
288
289static void
290XAARenderCacheExpandRects(
291   GCPtr pGC,
292   int nboxes,
293   BoxPtr pClipBoxes,
294   int xorg, int yorg
295){
296   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
297   int fg, bg;
298
299   switch(pGC->fillStyle) {
300   case FillStippled:
301      fg = pGC->fgPixel;  bg = -1;
302      break;
303   case FillOpaqueStippled:
304      fg = pGC->fgPixel;  bg = pGC->bgPixel;
305      break;
306   default:	/* Muffle compiler */
307      fg = -1;  bg = -1;
308      break;
309   }
310
311   (*infoRec->FillCacheExpandRects) (infoRec->pScrn, fg, bg,
312                pGC->alu, pGC->planemask, nboxes, pClipBoxes,
313                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y),
314                pGC->stipple);
315}
316
317
318
319	/***************************\
320	|     Image Write Rects     |
321	\***************************/
322
323static void
324XAARenderImageWriteRects(
325   GCPtr pGC,
326   int nboxes,
327   BoxPtr pClipBoxes,
328   int xorg, int yorg
329){
330   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
331
332   (*infoRec->FillImageWriteRects) (infoRec->pScrn, pGC->alu,
333                pGC->planemask, nboxes, pClipBoxes,
334                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y),
335                pGC->tile.pixmap);
336}
337
338
339
340	/***************************\
341	|     Pixmap Copy Rects     |
342	\***************************/
343
344static void
345XAARenderPixmapCopyRects(
346   GCPtr pGC,
347   int nboxes,
348   BoxPtr pClipBoxes,
349   int xorg, int yorg
350){
351   XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
352   XAACacheInfoPtr pCache = &(infoRec->ScratchCacheInfoRec);
353   XAAPixmapPtr pPriv = XAA_GET_PIXMAP_PRIVATE(pGC->tile.pixmap);
354
355   pCache->x = pPriv->offscreenArea->box.x1;
356   pCache->y = pPriv->offscreenArea->box.y1;
357   pCache->w = pCache->orig_w =
358		pPriv->offscreenArea->box.x2 - pCache->x;
359   pCache->h = pCache->orig_h =
360		pPriv->offscreenArea->box.y2 - pCache->y;
361   pCache->trans_color = -1;
362
363   (*infoRec->FillCacheBltRects) (infoRec->pScrn, pGC->alu,
364                pGC->planemask, nboxes, pClipBoxes,
365                (xorg + pGC->patOrg.x), (yorg + pGC->patOrg.y),
366                pCache);
367}
368
369
370
371	/************\
372	|   Solid    |
373	\************/
374
375void
376XAAFillSolidRects(
377    ScrnInfoPtr pScrn,
378    int	fg, int rop,
379    unsigned int planemask,
380    int		nBox, 		/* number of rectangles to fill */
381    BoxPtr	pBox  		/* Pointer to first rectangle to fill */
382){
383    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
384
385    (*infoRec->SetupForSolidFill)(pScrn, fg, rop, planemask);
386     while(nBox--) {
387        (*infoRec->SubsequentSolidFillRect)(pScrn, pBox->x1, pBox->y1,
388 			pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
389	pBox++;
390     }
391     SET_SYNC_FLAG(infoRec);
392}
393
394
395
396
397	/*********************\
398	|  8x8 Mono Patterns  |
399	\*********************/
400
401
402void
403XAAFillMono8x8PatternRectsScreenOrigin(
404    ScrnInfoPtr pScrn,
405    int	fg, int bg, int rop,
406    unsigned int planemask,
407    int	nBox,
408    BoxPtr pBox,
409    int pattern0, int pattern1,
410    int xorigin, int yorigin
411)
412{
413    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
414    int patx = pattern0, paty = pattern1;
415    int xorg = (-xorigin) & 0x07;
416    int yorg = (-yorigin) & 0x07;
417
418
419    if(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS) {
420   	if(!(infoRec->Mono8x8PatternFillFlags &
421				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
422	    XAARotateMonoPattern(&patx, &paty, xorg, yorg,
423				(infoRec->Mono8x8PatternFillFlags &
424				 BIT_ORDER_IN_BYTE_MSBFIRST));
425	    xorg = patx; yorg = paty;
426        }
427    } else {
428	XAACacheInfoPtr pCache =
429		(*infoRec->CacheMono8x8Pattern)(pScrn, pattern0, pattern1);
430	patx = pCache->x;  paty = pCache->y;
431   	if(!(infoRec->Mono8x8PatternFillFlags &
432				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
433	    int slot = (yorg << 3) + xorg;
434	    patx += pCache->offsets[slot].x;
435	    paty += pCache->offsets[slot].y;
436	    xorg = patx;  yorg = paty;
437	}
438    }
439
440    (*infoRec->SetupForMono8x8PatternFill)(pScrn, patx, paty,
441					fg, bg, rop, planemask);
442
443     while(nBox--) {
444        (*infoRec->SubsequentMono8x8PatternFillRect)(pScrn,
445			xorg, yorg, pBox->x1, pBox->y1,
446 			pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
447	pBox++;
448     }
449     SET_SYNC_FLAG(infoRec);
450}
451
452void
453XAAFillMono8x8PatternRects(
454    ScrnInfoPtr pScrn,
455    int	fg, int bg, int rop,
456    unsigned int planemask,
457    int	nBox,
458    BoxPtr pBox,
459    int pattern0, int pattern1,
460    int xorigin, int yorigin
461)
462{
463    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
464    int patx = pattern0, paty = pattern1;
465    int xorg, yorg;
466    XAACacheInfoPtr pCache = NULL;
467
468
469    if(!(infoRec->Mono8x8PatternFillFlags & HARDWARE_PATTERN_PROGRAMMED_BITS)){
470	pCache = (*infoRec->CacheMono8x8Pattern)(pScrn, pattern0, pattern1);
471	patx = pCache->x;  paty = pCache->y;
472    }
473
474
475    (*infoRec->SetupForMono8x8PatternFill)(pScrn, patx, paty,
476					fg, bg, rop, planemask);
477
478
479     while(nBox--) {
480	xorg = (pBox->x1 - xorigin) & 0x07;
481	yorg = (pBox->y1 - yorigin) & 0x07;
482
483   	if(!(infoRec->Mono8x8PatternFillFlags &
484				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
485	    if(infoRec->Mono8x8PatternFillFlags &
486				HARDWARE_PATTERN_PROGRAMMED_BITS) {
487		patx = pattern0; paty = pattern1;
488		XAARotateMonoPattern(&patx, &paty, xorg, yorg,
489				(infoRec->Mono8x8PatternFillFlags &
490				BIT_ORDER_IN_BYTE_MSBFIRST));
491		xorg = patx; yorg = paty;
492	    } else {
493		int slot = (yorg << 3) + xorg;
494	    	xorg = patx + pCache->offsets[slot].x;
495	    	yorg = paty + pCache->offsets[slot].y;
496	    }
497        }
498
499        (*infoRec->SubsequentMono8x8PatternFillRect)(pScrn,
500			xorg, yorg, pBox->x1, pBox->y1,
501 			pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
502	pBox++;
503     }
504
505     SET_SYNC_FLAG(infoRec);
506}
507
508
509	/**********************\
510	|  8x8 Color Patterns  |
511	\**********************/
512
513
514void
515XAAFillColor8x8PatternRectsScreenOrigin(
516   ScrnInfoPtr pScrn,
517   int rop,
518   unsigned int planemask,
519   int nBox,
520   BoxPtr pBox,
521   int xorigin, int yorigin,
522   XAACacheInfoPtr pCache
523){
524    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
525    int patx = pCache->x, paty = pCache->y;
526    int xorg = (-xorigin) & 0x07;
527    int yorg = (-yorigin) & 0x07;
528
529    if(!(infoRec->Color8x8PatternFillFlags &
530					HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
531	int slot = (yorg << 3) + xorg;
532	paty += pCache->offsets[slot].y;
533	patx += pCache->offsets[slot].x;
534	xorg = patx;  yorg = paty;
535    }
536
537    (*infoRec->SetupForColor8x8PatternFill)(pScrn, patx, paty,
538			 rop, planemask, pCache->trans_color);
539
540    while(nBox--) {
541        (*infoRec->SubsequentColor8x8PatternFillRect)(pScrn,
542			xorg, yorg, pBox->x1, pBox->y1,
543 			pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
544	pBox++;
545    }
546    SET_SYNC_FLAG(infoRec);
547}
548
549void
550XAAFillColor8x8PatternRects(
551   ScrnInfoPtr pScrn,
552   int rop,
553   unsigned int planemask,
554   int nBox,
555   BoxPtr pBox,
556   int xorigin, int yorigin,
557   XAACacheInfoPtr pCache
558){
559    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
560    int xorg, yorg;
561
562    (*infoRec->SetupForColor8x8PatternFill)(pScrn, pCache->x, pCache->y,
563			 rop, planemask, pCache->trans_color);
564
565     while(nBox--) {
566	xorg = (pBox->x1 - xorigin) & 0x07;
567	yorg = (pBox->y1 - yorigin) & 0x07;
568
569   	if(!(infoRec->Color8x8PatternFillFlags &
570				HARDWARE_PATTERN_PROGRAMMED_ORIGIN)){
571	    int slot = (yorg << 3) + xorg;
572	    yorg = pCache->y + pCache->offsets[slot].y;
573	    xorg = pCache->x + pCache->offsets[slot].x;
574        }
575
576        (*infoRec->SubsequentColor8x8PatternFillRect)(pScrn,
577			xorg, yorg, pBox->x1, pBox->y1,
578 			pBox->x2 - pBox->x1, pBox->y2 - pBox->y1);
579	pBox++;
580     }
581
582     SET_SYNC_FLAG(infoRec);
583}
584
585
586	/***************\
587	|  Cache Blits  |
588	\***************/
589
590void
591XAAFillCacheBltRects(
592   ScrnInfoPtr pScrn,
593   int rop,
594   unsigned int planemask,
595   int nBox,
596   BoxPtr pBox,
597   int xorg, int yorg,
598   XAACacheInfoPtr pCache
599){
600    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
601    int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h;
602
603    (*infoRec->SetupForScreenToScreenCopy)(pScrn, 1, 1, rop, planemask,
604		pCache->trans_color);
605
606    while(nBox--) {
607	y = pBox->y1;
608	phaseY = (y - yorg) % pCache->orig_h;
609	if(phaseY < 0) phaseY += pCache->orig_h;
610	phaseX = (pBox->x1 - xorg) % pCache->orig_w;
611	if(phaseX < 0) phaseX += pCache->orig_w;
612	height = pBox->y2 - y;
613	width = pBox->x2 - pBox->x1;
614
615#if 0
616	if (rop == GXcopy) {
617	    while(1) {
618		w = width; skipleft = phaseX; x = pBox->x1;
619		blit_h = pCache->h - phaseY;
620		if(blit_h > height) blit_h = height;
621
622		while(1) {
623		    blit_w = pCache->w - skipleft;
624		    if(blit_w > w) blit_w = w;
625		    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
626			pCache->x + skipleft, pCache->y + phaseY,
627			x, y, blit_w, blit_h);
628		    w -= blit_w;
629		    if(!w) break;
630		    x += blit_w;
631		    skipleft = (skipleft + blit_w) % pCache->orig_w;
632		    if(blit_w >= pCache->orig_w) break;
633		}
634
635		/* Expand horizontally */
636		if (w) {
637		    skipleft -= phaseX;
638		    if (skipleft < 0) skipleft += pCache->orig_w;
639		    blit_w = x - pBox->x1 - skipleft;
640		    while(w) {
641			if (blit_w > w) blit_w = w;
642			(*infoRec->SubsequentScreenToScreenCopy)(pScrn,
643			    pBox->x1 + skipleft, y, x, y, blit_w, blit_h);
644			w -= blit_w;
645			x += blit_w;
646			blit_w <<= 1;
647		    }
648		}
649
650		height -= blit_h;
651		if(!height) break;
652		y += blit_h;
653		phaseY = (phaseY + blit_h) % pCache->orig_h;
654		if(blit_h >= pCache->orig_h) break;
655	    }
656
657	    /* Expand vertically */
658	    if (height) {
659		blit_w = pBox->x2 - pBox->x1;
660		phaseY -= (pBox->y1 - yorg) % pCache->orig_h;
661		if (phaseY < 0) phaseY += pCache->orig_h;
662		blit_h = y - pBox->y1  - phaseY;
663		while(height) {
664		    if (blit_h > height) blit_h = height;
665		    (*infoRec->SubsequentScreenToScreenCopy)(pScrn, pBox->x1,
666			pBox->y1 + phaseY, pBox->x1, y, blit_w, blit_h);
667		    height -= blit_h;
668		    y += blit_h;
669		    blit_h <<= 1;
670		}
671	    }
672	} else
673#endif
674	{
675	    while(1) {
676		w = width; skipleft = phaseX; x = pBox->x1;
677		blit_h = pCache->h - phaseY;
678		if(blit_h > height) blit_h = height;
679
680		while(1) {
681		    blit_w = pCache->w - skipleft;
682		    if(blit_w > w) blit_w = w;
683		    (*infoRec->SubsequentScreenToScreenCopy)(pScrn,
684			pCache->x + skipleft, pCache->y + phaseY,
685			x, y, blit_w, blit_h);
686		    w -= blit_w;
687		    if(!w) break;
688		    x += blit_w;
689		    skipleft = (skipleft + blit_w) % pCache->orig_w;
690		}
691		height -= blit_h;
692		if(!height) break;
693		y += blit_h;
694		phaseY = (phaseY + blit_h) % pCache->orig_h;
695	    }
696	}
697	pBox++;
698    }
699
700    SET_SYNC_FLAG(infoRec);
701}
702
703
704
705
706	/*******************\
707	|  Cache Expansion  |
708	\*******************/
709
710
711
712void
713XAAFillCacheExpandRects(
714   ScrnInfoPtr pScrn,
715   int fg, int bg, int rop,
716   unsigned int planemask,
717   int nBox,
718   BoxPtr pBox,
719   int xorg, int yorg,
720   PixmapPtr pPix
721){
722    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
723    int x, y, phaseY, phaseX, skipleft, height, width, w, blit_w, blit_h;
724    int cacheWidth;
725    XAACacheInfoPtr pCache;
726
727    pCache = (*infoRec->CacheMonoStipple)(pScrn, pPix);
728
729    cacheWidth = (pCache->w * pScrn->bitsPerPixel) /
730	infoRec->CacheColorExpandDensity;
731
732    (*infoRec->SetupForScreenToScreenColorExpandFill)(pScrn, fg, bg, rop,
733							planemask);
734
735    while(nBox--) {
736	y = pBox->y1;
737	phaseY = (y - yorg) % pCache->orig_h;
738	if(phaseY < 0) phaseY += pCache->orig_h;
739	phaseX = (pBox->x1 - xorg) % pCache->orig_w;
740	if(phaseX < 0) phaseX += pCache->orig_w;
741	height = pBox->y2 - y;
742	width = pBox->x2 - pBox->x1;
743
744	while(1) {
745	    w = width; skipleft = phaseX; x = pBox->x1;
746	    blit_h = pCache->h - phaseY;
747	    if(blit_h > height) blit_h = height;
748
749	    while(1) {
750		blit_w = cacheWidth - skipleft;
751		if(blit_w > w) blit_w = w;
752		(*infoRec->SubsequentScreenToScreenColorExpandFill)(
753			pScrn, x, y, blit_w, blit_h,
754			pCache->x, pCache->y + phaseY, skipleft);
755		w -= blit_w;
756		if(!w) break;
757		x += blit_w;
758		skipleft = (skipleft + blit_w) % pCache->orig_w;
759	    }
760	    height -= blit_h;
761	    if(!height) break;
762	    y += blit_h;
763	    phaseY = (phaseY + blit_h) % pCache->orig_h;
764	}
765	pBox++;
766    }
767
768    SET_SYNC_FLAG(infoRec);
769}
770
771
772	/******************\
773	|   Image Writes   |
774	\******************/
775
776
777
778/*  This requires all LEFT_EDGE clipping.  You get too many problems
779    with reading past the edge of the pattern otherwise */
780
781static void
782WriteColumnScanlines(
783    ScrnInfoPtr pScrn,
784    unsigned char *pSrc,
785    int x, int y, int w, int h,
786    int xoff, int yoff,
787    int pHeight,
788    int srcwidth,
789    int Bpp
790) {
791    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
792    unsigned char *src;
793    int skipleft, bytes, line, sline;
794    int buffer;
795
796    pSrc += (Bpp * xoff);
797
798    if((skipleft = (long)pSrc & 0x03L)) {
799        if(Bpp == 3)
800           skipleft = 4 - skipleft;
801        else
802           skipleft /= Bpp;
803
804        x -= skipleft;
805        w += skipleft;
806
807        if(Bpp == 3)
808           pSrc -= 3 * skipleft;
809        else   /* is this Alpha friendly ? */
810           pSrc = (unsigned char*)((long)pSrc & ~0x03L);
811    }
812
813    src = pSrc + (yoff * srcwidth);
814
815    bytes = w * Bpp;
816
817    (*infoRec->SubsequentScanlineImageWriteRect)(pScrn, x, y, w, h, skipleft);
818
819    buffer = 0;
820    sline = yoff;
821    for (line = 0; line < h; line++) {
822       memcpy(infoRec->ScanlineImageWriteBuffers[buffer], src, bytes);
823       (*infoRec->SubsequentImageWriteScanline)(pScrn, buffer);
824       buffer++;
825       src += srcwidth;
826       sline++;
827       if (sline >= pHeight) {
828           sline = 0;
829	   src = pSrc;
830       }
831       if (buffer >= infoRec->NumScanlineImageWriteBuffers)
832           buffer = 0;
833    }
834}
835
836void
837XAAFillScanlineImageWriteRects(
838    ScrnInfoPtr pScrn,
839    int rop,
840    unsigned int planemask,
841    int nBox,
842    BoxPtr pBox,
843    int xorg, int yorg,
844    PixmapPtr pPix
845){
846    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
847    int x, phaseY, phaseX, height, width, blit_w;
848    int pHeight = pPix->drawable.height;
849    int pWidth = pPix->drawable.width;
850    int Bpp = pPix->drawable.bitsPerPixel >> 3;
851    int srcwidth = pPix->devKind;
852
853    (*infoRec->SetupForScanlineImageWrite)(pScrn, rop, planemask, -1,
854               pPix->drawable.bitsPerPixel, pPix->drawable.depth);
855
856    while(nBox--) {
857       x = pBox->x1;
858       phaseY = (pBox->y1 - yorg) % pHeight;
859       if(phaseY < 0) phaseY += pHeight;
860       phaseX = (x - xorg) % pWidth;
861       if(phaseX < 0) phaseX += pWidth;
862       height = pBox->y2 - pBox->y1;
863       width = pBox->x2 - x;
864
865       while(1) {
866           blit_w = pWidth - phaseX;
867           if(blit_w > width) blit_w = width;
868
869           WriteColumnScanlines(pScrn, pPix->devPrivate.ptr, x, pBox->y1,
870               blit_w, height, phaseX, phaseY, pHeight, srcwidth, Bpp);
871
872           width -= blit_w;
873           if(!width) break;
874           x += blit_w;
875           phaseX = (phaseX + blit_w) % pWidth;
876       }
877       pBox++;
878    }
879
880    if(infoRec->ScanlineImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
881        (*infoRec->Sync)(pScrn);
882    else SET_SYNC_FLAG(infoRec);
883}
884
885static void
886WriteColumn(
887    ScrnInfoPtr pScrn,
888    unsigned char *pSrc,
889    int x, int y, int w, int h,
890    int xoff, int yoff,
891    int pHeight,
892    int srcwidth,
893    int Bpp
894) {
895    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
896    unsigned char *src;
897    Bool PlusOne = FALSE;
898    int skipleft, dwords;
899
900    pSrc += (Bpp * xoff);
901
902    if((skipleft = (long)pSrc & 0x03L)) {
903        if(Bpp == 3)
904           skipleft = 4 - skipleft;
905        else
906           skipleft /= Bpp;
907
908        x -= skipleft;
909        w += skipleft;
910
911        if(Bpp == 3)
912           pSrc -= 3 * skipleft;
913        else   /* is this Alpha friendly ? */
914           pSrc = (unsigned char*)((long)pSrc & ~0x03L);
915    }
916
917    src = pSrc + (yoff * srcwidth);
918
919    dwords = bytes_to_int32(w * Bpp);
920
921    if((infoRec->ImageWriteFlags & CPU_TRANSFER_PAD_QWORD) &&
922                                                ((dwords * h) & 0x01)) {
923        PlusOne = TRUE;
924    }
925
926    (*infoRec->SubsequentImageWriteRect)(pScrn, x, y, w, h, skipleft);
927
928    if(dwords > infoRec->ImageWriteRange) {
929        while(h--) {
930            XAAMoveDWORDS_FixedBase((CARD32*)infoRec->ImageWriteBase,
931                (CARD32*)src, dwords);
932            src += srcwidth;
933	    yoff++;
934	    if(yoff >= pHeight) {
935		yoff = 0;
936		src = pSrc;
937	    }
938        }
939    } else {
940        if(srcwidth == (dwords << 2)) {
941           int maxLines = infoRec->ImageWriteRange/dwords;
942	   int step;
943
944	   while(h) {
945		step = pHeight - yoff;
946		if(step > maxLines) step = maxLines;
947		if(step > h) step = h;
948
949                XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
950                        (CARD32*)src, dwords * step);
951
952                src += (srcwidth * step);
953		yoff += step;
954		if(yoff >= pHeight) {
955		    yoff = 0;
956		    src = pSrc;
957		}
958                h -= step;
959	   }
960        } else {
961            while(h--) {
962                XAAMoveDWORDS((CARD32*)infoRec->ImageWriteBase,
963                        (CARD32*)src, dwords);
964                src += srcwidth;
965		yoff++;
966		if(yoff >= pHeight) {
967		    yoff = 0;
968		    src = pSrc;
969		}
970            }
971        }
972    }
973
974    if(PlusOne) {
975        CARD32* base = (CARD32*)infoRec->ImageWriteBase;
976        *base = 0x00000000;
977    }
978}
979
980void
981XAAFillImageWriteRects(
982    ScrnInfoPtr pScrn,
983    int rop,
984    unsigned int planemask,
985    int nBox,
986    BoxPtr pBox,
987    int xorg, int yorg,
988    PixmapPtr pPix
989){
990    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
991    int x, phaseY, phaseX, height, width, blit_w;
992    int pHeight = pPix->drawable.height;
993    int pWidth = pPix->drawable.width;
994    int Bpp = pPix->drawable.bitsPerPixel >> 3;
995    int srcwidth = pPix->devKind;
996
997    (*infoRec->SetupForImageWrite)(pScrn, rop, planemask, -1,
998		pPix->drawable.bitsPerPixel, pPix->drawable.depth);
999
1000    while(nBox--) {
1001	x = pBox->x1;
1002	phaseY = (pBox->y1 - yorg) % pHeight;
1003	if(phaseY < 0) phaseY += pHeight;
1004	phaseX = (x - xorg) % pWidth;
1005	if(phaseX < 0) phaseX += pWidth;
1006	height = pBox->y2 - pBox->y1;
1007	width = pBox->x2 - x;
1008
1009	while(1) {
1010	    blit_w = pWidth - phaseX;
1011	    if(blit_w > width) blit_w = width;
1012
1013	    WriteColumn(pScrn, pPix->devPrivate.ptr, x, pBox->y1,
1014		blit_w, height, phaseX, phaseY, pHeight, srcwidth, Bpp);
1015
1016	    width -= blit_w;
1017	    if(!width) break;
1018	    x += blit_w;
1019	    phaseX = (phaseX + blit_w) % pWidth;
1020	}
1021	pBox++;
1022    }
1023
1024    if(infoRec->ImageWriteFlags & SYNC_AFTER_IMAGE_WRITE)
1025        (*infoRec->Sync)(pScrn);
1026    else SET_SYNC_FLAG(infoRec);
1027}
1028
1029
1030	/*************\
1031	|  Utilities  |
1032	\*************/
1033
1034
1035void
1036XAAClipAndRenderRects(
1037   GCPtr pGC,
1038   ClipAndRenderRectsFunc BoxFunc,
1039   int nrectFill,
1040   xRectangle *prect,
1041   int xorg, int yorg
1042){
1043    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
1044    int 	Right, Bottom, MaxBoxes;
1045    BoxPtr 	pextent, pboxClipped, pboxClippedBase;
1046
1047    MaxBoxes = infoRec->PreAllocSize/sizeof(BoxRec);
1048    pboxClippedBase = (BoxPtr)infoRec->PreAllocMem;
1049    pboxClipped = pboxClippedBase;
1050
1051    if (RegionNumRects(pGC->pCompositeClip) == 1) {
1052	pextent = RegionRects(pGC->pCompositeClip);
1053    	while (nrectFill--) {
1054	    pboxClipped->x1 = max(pextent->x1, prect->x);
1055	    pboxClipped->y1 = max(pextent->y1, prect->y);
1056
1057	    Right = (int)prect->x + (int)prect->width;
1058	    pboxClipped->x2 = min(pextent->x2, Right);
1059
1060	    Bottom = (int)prect->y + (int)prect->height;
1061	    pboxClipped->y2 = min(pextent->y2, Bottom);
1062
1063	    prect++;
1064	    if ((pboxClipped->x1 < pboxClipped->x2) &&
1065		(pboxClipped->y1 < pboxClipped->y2)) {
1066		pboxClipped++;
1067		if(pboxClipped >= (pboxClippedBase + MaxBoxes)) {
1068		    (*BoxFunc)(pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
1069		    pboxClipped = pboxClippedBase;
1070		}
1071	    }
1072    	}
1073    } else {
1074	pextent = RegionExtents(pGC->pCompositeClip);
1075    	while (nrectFill--) {
1076	    int n;
1077	    BoxRec box, *pbox;
1078
1079	    box.x1 = max(pextent->x1, prect->x);
1080   	    box.y1 = max(pextent->y1, prect->y);
1081
1082	    Right = (int)prect->x + (int)prect->width;
1083	    box.x2 = min(pextent->x2, Right);
1084
1085	    Bottom = (int)prect->y + (int)prect->height;
1086	    box.y2 = min(pextent->y2, Bottom);
1087
1088	    prect++;
1089
1090	    if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
1091	    	continue;
1092
1093	    n = RegionNumRects (pGC->pCompositeClip);
1094	    pbox = RegionRects(pGC->pCompositeClip);
1095
1096	    /* clip the rectangle to each box in the clip region
1097	       this is logically equivalent to calling Intersect()
1098	    */
1099	    while(n--) {
1100		pboxClipped->x1 = max(box.x1, pbox->x1);
1101		pboxClipped->y1 = max(box.y1, pbox->y1);
1102		pboxClipped->x2 = min(box.x2, pbox->x2);
1103		pboxClipped->y2 = min(box.y2, pbox->y2);
1104		pbox++;
1105
1106		/* see if clipping left anything */
1107		if(pboxClipped->x1 < pboxClipped->x2 &&
1108		   pboxClipped->y1 < pboxClipped->y2) {
1109		    pboxClipped++;
1110		    if(pboxClipped >= (pboxClippedBase + MaxBoxes)) {
1111			(*BoxFunc)(pGC, MaxBoxes, pboxClippedBase, xorg, yorg);
1112			pboxClipped = pboxClippedBase;
1113		    }
1114		}
1115	    }
1116    	}
1117    }
1118
1119    if(pboxClipped != pboxClippedBase)
1120	(*BoxFunc)(pGC, pboxClipped - pboxClippedBase, pboxClippedBase,
1121					xorg, yorg);
1122}
1123
1124
1125int
1126XAAGetRectClipBoxes(
1127    GCPtr pGC,
1128    BoxPtr pboxClippedBase,
1129    int nrectFill,
1130    xRectangle *prectInit
1131){
1132    int 	Right, Bottom;
1133    BoxPtr 	pextent, pboxClipped = pboxClippedBase;
1134    xRectangle	*prect = prectInit;
1135    RegionPtr   prgnClip = pGC->pCompositeClip;
1136
1137    if (RegionNumRects(prgnClip) == 1) {
1138	pextent = RegionRects(prgnClip);
1139    	while (nrectFill--) {
1140	    pboxClipped->x1 = max(pextent->x1, prect->x);
1141	    pboxClipped->y1 = max(pextent->y1, prect->y);
1142
1143	    Right = (int)prect->x + (int)prect->width;
1144	    pboxClipped->x2 = min(pextent->x2, Right);
1145
1146	    Bottom = (int)prect->y + (int)prect->height;
1147	    pboxClipped->y2 = min(pextent->y2, Bottom);
1148
1149	    prect++;
1150	    if ((pboxClipped->x1 < pboxClipped->x2) &&
1151		(pboxClipped->y1 < pboxClipped->y2)) {
1152		pboxClipped++;
1153	    }
1154    	}
1155    } else {
1156	pextent = RegionExtents(prgnClip);
1157    	while (nrectFill--) {
1158	    int n;
1159	    BoxRec box, *pbox;
1160
1161	    box.x1 = max(pextent->x1, prect->x);
1162   	    box.y1 = max(pextent->y1, prect->y);
1163
1164	    Right = (int)prect->x + (int)prect->width;
1165	    box.x2 = min(pextent->x2, Right);
1166
1167	    Bottom = (int)prect->y + (int)prect->height;
1168	    box.y2 = min(pextent->y2, Bottom);
1169
1170	    prect++;
1171
1172	    if ((box.x1 >= box.x2) || (box.y1 >= box.y2))
1173	    	continue;
1174
1175	    n = RegionNumRects (prgnClip);
1176	    pbox = RegionRects(prgnClip);
1177
1178	    /* clip the rectangle to each box in the clip region
1179	       this is logically equivalent to calling Intersect()
1180	    */
1181	    while(n--) {
1182		pboxClipped->x1 = max(box.x1, pbox->x1);
1183		pboxClipped->y1 = max(box.y1, pbox->y1);
1184		pboxClipped->x2 = min(box.x2, pbox->x2);
1185		pboxClipped->y2 = min(box.y2, pbox->y2);
1186		pbox++;
1187
1188		/* see if clipping left anything */
1189		if(pboxClipped->x1 < pboxClipped->x2 &&
1190		   pboxClipped->y1 < pboxClipped->y2) {
1191		    pboxClipped++;
1192		}
1193	    }
1194    	}
1195    }
1196
1197    return pboxClipped - pboxClippedBase;
1198}
1199
1200