1/*
2 * The accel file for the Savage driver.
3 *
4 * Created 20/03/97 by Sebastien Marineau for 3.3.6
5 * Modified 17-Nov-2000 by Tim Roberts for 4.0.1
6 * Modified Feb-2004 by Alex Deucher - integrating DRI support
7 * Modified 2005-2006 by Alex Deucher - adding exa support
8 * Revision:
9 *
10 */
11
12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif
15
16#include <X11/Xarch.h>
17#include "savage_driver.h"
18#ifdef HAVE_XAA_H
19#include "xaalocal.h"
20#include "xaarop.h"
21
22#include "miline.h"
23
24#include "savage_bci.h"
25
26extern int gSavageEntityIndex;
27
28static void SavageSetupForScreenToScreenCopy(
29    ScrnInfoPtr pScrn,
30    int xdir,
31    int ydir,
32    int rop,
33    unsigned planemask,
34    int transparency_color);
35
36static void SavageSubsequentScreenToScreenCopy(
37    ScrnInfoPtr pScrn,
38    int x1,
39    int y1,
40    int x2,
41    int y2,
42    int w,
43    int h);
44
45static void SavageSetupForSolidFill(
46    ScrnInfoPtr pScrn,
47    int color,
48    int rop,
49    unsigned int planemask);
50
51static void SavageSubsequentSolidFillRect(
52    ScrnInfoPtr pScrn,
53    int x,
54    int y,
55    int w,
56    int h);
57
58static void SavageSubsequentSolidBresenhamLine(
59    ScrnInfoPtr pScrn,
60    int x1,
61    int y1,
62    int e1,
63    int e2,
64    int err,
65    int length,
66    int octant);
67
68static void SavageSetupForCPUToScreenColorExpandFill(
69    ScrnInfoPtr pScrn,
70    int fg,
71    int bg,
72    int rop,
73    unsigned int planemask);
74
75static void SavageSubsequentScanlineCPUToScreenColorExpandFill(
76    ScrnInfoPtr pScrn,
77    int x,
78    int y,
79    int w,
80    int h,
81    int skipleft);
82
83static void SavageSubsequentColorExpandScanline(
84    ScrnInfoPtr pScrn,
85    int buffer_no);
86
87static void SavageSetupForMono8x8PatternFill(
88    ScrnInfoPtr pScrn,
89    int patternx,
90    int patterny,
91    int fg,
92    int bg,
93    int rop,
94    unsigned int planemask);
95
96static void SavageSubsequentMono8x8PatternFillRect(
97    ScrnInfoPtr pScrn,
98    int pattern0,
99    int pattern1,
100    int x,
101    int y,
102    int w,
103    int h);
104
105static void SavageSetClippingRectangle(
106    ScrnInfoPtr pScrn,
107    int x1,
108    int y1,
109    int x2,
110    int y2);
111
112static void SavageDisableClipping( ScrnInfoPtr );
113
114/* from savage_image.c: */
115
116void SavageSetupForImageWrite(
117    ScrnInfoPtr pScrn,
118    int rop,
119    unsigned int planemask,
120    int transparency_color,
121    int bpp,
122    int depth);
123
124void SavageSubsequentImageWriteRect(
125    ScrnInfoPtr pScrn,
126    int x,
127    int y,
128    int w,
129    int h,
130    int skipleft);
131
132void SavageWriteBitmapCPUToScreenColorExpand (
133    ScrnInfoPtr pScrn,
134    int x, int y, int w, int h,
135    unsigned char * src,
136    int srcwidth,
137    int skipleft,
138    int fg, int bg,
139    int rop,
140    unsigned int planemask
141);
142
143static
144void SavageRestoreAccelState(ScrnInfoPtr pScrn)
145{
146    SavagePtr psav = SAVPTR(pScrn);
147
148    psav->WaitIdleEmpty(psav);
149
150    return;
151}
152#endif
153
154Bool
155SavageXAAInit(ScreenPtr pScreen)
156{
157#ifdef HAVE_XAA_H
158    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
159    SavagePtr psav = SAVPTR(pScrn);
160    XAAInfoRecPtr xaaptr;
161    BoxRec AvailFBArea;
162    int tmp;
163
164    /* Set-up our GE command primitive */
165
166    if (pScrn->depth == 8) {
167	psav->PlaneMask = 0xFF;
168    }
169    else if (pScrn->depth == 15) {
170	psav->PlaneMask = 0x7FFF;
171    }
172    else if (pScrn->depth == 16) {
173	psav->PlaneMask = 0xFFFF;
174    }
175    else if (pScrn->depth == 24) {
176	psav->PlaneMask = 0xFFFFFF;
177    }
178
179    /* General acceleration flags */
180
181    if (!(xaaptr = psav->AccelInfoRec = XAACreateInfoRec())) {
182	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
183		"Failed to allocate XAAInfoRec.\n");
184	return FALSE;
185    }
186
187    xaaptr->Flags = 0
188    	| PIXMAP_CACHE
189	| OFFSCREEN_PIXMAPS
190	| LINEAR_FRAMEBUFFER
191	;
192
193
194    if(xf86IsEntityShared(pScrn->entityList[0]))
195    {
196        DevUnion* pPriv;
197        SavageEntPtr pEnt;
198        pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
199                gSavageEntityIndex);
200        pEnt = pPriv->ptr;
201
202        /*if there are more than one devices sharing this entity, we
203          have to assign this call back, otherwise the XAA will be
204          disabled */
205        if(pEnt->HasSecondary)
206           xaaptr->RestoreAccelState           = SavageRestoreAccelState;
207    }
208
209    /* Clipping */
210
211    xaaptr->SetClippingRectangle = SavageSetClippingRectangle;
212    xaaptr->DisableClipping = SavageDisableClipping;
213    xaaptr->ClippingFlags = 0
214#if 0
215	| HARDWARE_CLIP_SOLID_FILL
216	| HARDWARE_CLIP_SOLID_LINE
217	| HARDWARE_CLIP_DASHED_LINE
218#endif
219	| HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY
220	| HARDWARE_CLIP_MONO_8x8_FILL
221	| HARDWARE_CLIP_COLOR_8x8_FILL
222	;
223
224    xaaptr->Sync = SavageAccelSync;
225
226    /* ScreenToScreen copies */
227
228#if 1
229
230    xaaptr->SetupForScreenToScreenCopy = SavageSetupForScreenToScreenCopy;
231    xaaptr->SubsequentScreenToScreenCopy = SavageSubsequentScreenToScreenCopy;
232    xaaptr->ScreenToScreenCopyFlags = 0
233	| NO_TRANSPARENCY
234	| NO_PLANEMASK
235	| ROP_NEEDS_SOURCE;
236
237#endif
238
239
240    /* Solid filled rectangles */
241
242#if 1
243    xaaptr->SetupForSolidFill = SavageSetupForSolidFill;
244    xaaptr->SubsequentSolidFillRect = SavageSubsequentSolidFillRect;
245    xaaptr->SolidFillFlags = NO_PLANEMASK | ROP_NEEDS_SOURCE;
246#endif
247
248    /* Mono 8x8 pattern fills */
249
250#if 1
251    xaaptr->SetupForMono8x8PatternFill = SavageSetupForMono8x8PatternFill;
252    xaaptr->SubsequentMono8x8PatternFillRect
253    	= SavageSubsequentMono8x8PatternFillRect;
254    xaaptr->Mono8x8PatternFillFlags = 0
255	| HARDWARE_PATTERN_PROGRAMMED_BITS
256	| HARDWARE_PATTERN_SCREEN_ORIGIN
257	| BIT_ORDER_IN_BYTE_MSBFIRST
258	| ROP_NEEDS_SOURCE
259	;
260    if( psav->Chipset == S3_SAVAGE4 )
261	xaaptr->Mono8x8PatternFillFlags |= NO_TRANSPARENCY;
262#endif
263
264    /* Solid lines */
265
266#if 1
267    xaaptr->SolidLineFlags = NO_PLANEMASK;
268    xaaptr->SetupForSolidLine = SavageSetupForSolidFill;
269    xaaptr->SubsequentSolidBresenhamLine = SavageSubsequentSolidBresenhamLine;
270#if 0
271    xaaptr->SubsequentSolidFillTrap = SavageSubsequentSolidFillTrap;
272#endif
273
274    xaaptr->SolidBresenhamLineErrorTermBits = 13;
275#endif
276
277    /* ImageWrite */
278
279    xaaptr->ImageWriteFlags = 0
280	| NO_PLANEMASK
281	| CPU_TRANSFER_PAD_DWORD
282	| SCANLINE_PAD_DWORD
283	| BIT_ORDER_IN_BYTE_MSBFIRST
284	| LEFT_EDGE_CLIPPING
285	;
286    xaaptr->SetupForImageWrite = SavageSetupForImageWrite;
287    xaaptr->SubsequentImageWriteRect = SavageSubsequentImageWriteRect;
288    xaaptr->NumScanlineImageWriteBuffers = 1;
289    xaaptr->ImageWriteBase = psav->BciMem;
290    xaaptr->ImageWriteRange = 120 * 1024;
291
292
293    /* CPU to Screen color expansion */
294
295    xaaptr->ScanlineCPUToScreenColorExpandFillFlags = 0
296	| NO_PLANEMASK
297	| CPU_TRANSFER_PAD_DWORD
298	| SCANLINE_PAD_DWORD
299	| BIT_ORDER_IN_BYTE_MSBFIRST
300	| LEFT_EDGE_CLIPPING
301	| ROP_NEEDS_SOURCE
302	;
303
304    xaaptr->SetupForScanlineCPUToScreenColorExpandFill =
305            SavageSetupForCPUToScreenColorExpandFill;
306    xaaptr->SubsequentScanlineCPUToScreenColorExpandFill =
307            SavageSubsequentScanlineCPUToScreenColorExpandFill;
308    xaaptr->SubsequentColorExpandScanline =
309	    SavageSubsequentColorExpandScanline;
310    xaaptr->ColorExpandBase = psav->BciMem;
311    xaaptr->ScanlineColorExpandBuffers = &xaaptr->ColorExpandBase;
312    xaaptr->NumScanlineColorExpandBuffers = 1;
313
314    /* Set up screen parameters. */
315
316    psav->Bpp = pScrn->bitsPerPixel / 8;
317    psav->Bpl = pScrn->displayWidth * psav->Bpp;
318    psav->ScissB = (psav->CursorKByte << 10) / psav->Bpl;
319    if (psav->ScissB > 2047)
320        psav->ScissB = 2047;
321
322    /*
323     * Finally, we set up the video memory space available to the pixmap
324     * cache. In this case, all memory from the end of the virtual screen
325     * to the end of the command overflow buffer can be used. If you haven't
326     * enabled the PIXMAP_CACHE flag, then these lines can be omitted.
327     */
328
329    AvailFBArea.x1 = 0;
330    AvailFBArea.y1 = 0;
331    AvailFBArea.x2 = psav->cxMemory;
332    AvailFBArea.y2 = psav->cyMemory;
333    xf86InitFBManager(pScreen, &AvailFBArea);
334    /*
335     * because the alignment requirement,the on-screen need more memory
336     * than (0,0,virtualX,virtualY), but xf86InitFBManager only subtract
337     * (pScrn->virtualX * pScrn->virtualY from (0,0,cxMemory,cyMemory),so
338     * here,we should reserver some memory for on-screen
339     */
340    tmp = ((psav->cxMemory * pScrn->virtualY - pScrn->virtualX * pScrn->virtualY)
341               + psav->cxMemory -1) / (psav->cxMemory);
342    if (tmp)
343        xf86AllocateOffscreenArea(pScreen, psav->cxMemory,tmp, 0, NULL, NULL, NULL);
344
345    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
346                   "Using %d lines for offscreen memory.\n",
347                   psav->cyMemory - pScrn->virtualY );
348
349
350    return XAAInit(pScreen, xaaptr);
351#else
352    return FALSE;
353#endif
354}
355
356/* The sync function for the GE */
357void
358SavageAccelSync(ScrnInfoPtr pScrn)
359{
360    SavagePtr psav = SAVPTR(pScrn);
361    psav->WaitIdleEmpty(psav);
362}
363
364#ifdef HAVE_XAA_H
365/*
366 * The XAA ROP helper routines all assume that a solid color is a
367 * "pattern".  The Savage chips, however, apply a non-stippled solid
368 * color as "source".  Thus, we use a slightly customized version.
369 */
370
371static int
372SavageHelpPatternROP(ScrnInfoPtr pScrn, int *fg, int *bg, unsigned int pm, int *rop)
373{
374    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
375    int ret = 0;
376
377    pm &= infoRec->FullPlanemask;
378
379    if(pm == infoRec->FullPlanemask) {
380	if(!NO_SRC_ROP(*rop))
381	   ret |= ROP_PAT;
382	*rop = XAAGetCopyROP(*rop);
383    } else {
384	switch(*rop) {
385	case GXnoop:
386	    break;
387	case GXset:
388	case GXclear:
389	case GXinvert:
390	    ret |= ROP_PAT;
391	    *fg = pm;
392	    if(*bg != -1)
393		*bg = pm;
394	    break;
395	default:
396	    ret |= ROP_PAT | ROP_SRC;
397	    break;
398	}
399	*rop = XAAGetCopyROP_PM(*rop);
400    }
401
402    return ret;
403}
404
405
406static int
407SavageHelpSolidROP(ScrnInfoPtr pScrn, int *fg, unsigned int pm, int *rop)
408{
409    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
410    int ret = 0;
411
412    pm &= infoRec->FullPlanemask;
413
414    if(pm == infoRec->FullPlanemask) {
415	if(!NO_SRC_ROP(*rop))
416	   ret |= ROP_PAT;
417	*rop = XAAGetCopyROP(*rop);
418    } else {
419	switch(*rop) {
420	case GXnoop:
421	    break;
422	case GXset:
423	case GXclear:
424	case GXinvert:
425	    ret |= ROP_PAT;
426	    *fg = pm;
427	    break;
428	default:
429	    ret |= ROP_PAT | ROP_SRC;
430	    break;
431	}
432	*rop = XAAGetCopyROP_PM(*rop);
433    }
434
435    return ret;
436}
437
438
439
440/* These are the ScreenToScreen bitblt functions. We support all ROPs, all
441 * directions, and a planemask by adjusting the ROP and using the mono pattern
442 * registers.
443 *
444 * (That's a lie; we don't really support planemask.)
445 */
446
447static void
448SavageSetupForScreenToScreenCopy(
449    ScrnInfoPtr pScrn,
450    int xdir,
451    int ydir,
452    int rop,
453    unsigned planemask,
454    int transparency_color)
455{
456    SavagePtr psav = SAVPTR(pScrn);
457    int cmd;
458
459    cmd = BCI_CMD_RECT | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SBD_COLOR_NEW;
460
461    BCI_CMD_SET_ROP( cmd, XAAGetCopyROP(rop) );
462    if (transparency_color != -1)
463        cmd |= BCI_CMD_SEND_COLOR | BCI_CMD_SRC_TRANSPARENT;
464
465    if (xdir == 1 ) cmd |= BCI_CMD_RECT_XP;
466    if (ydir == 1 ) cmd |= BCI_CMD_RECT_YP;
467
468    psav->SavedBciCmd = cmd;
469    psav->SavedBgColor = transparency_color;
470}
471
472static void
473SavageSubsequentScreenToScreenCopy(
474    ScrnInfoPtr pScrn,
475    int x1,
476    int y1,
477    int x2,
478    int y2,
479    int w,
480    int h)
481{
482    SavagePtr psav = SAVPTR(pScrn);
483
484    BCI_GET_PTR;
485
486    if (!w || !h) return;
487
488    if (!(psav->SavedBciCmd & BCI_CMD_RECT_XP)) {
489        w --;
490        x1 += w;
491        x2 += w;
492        w ++;
493    }
494    if (!(psav->SavedBciCmd & BCI_CMD_RECT_YP)) {
495        h --;
496        y1 += h;
497        y2 += h;
498        h ++;
499    }
500
501    psav->WaitQueue(psav,9);
502
503
504    BCI_SEND(psav->SavedBciCmd);
505
506    BCI_SEND(psav->GlobalBD.bd2.LoPart);
507    BCI_SEND(psav->GlobalBD.bd2.HiPart);
508
509    BCI_SEND(psav->GlobalBD.bd2.LoPart);
510    BCI_SEND(psav->GlobalBD.bd2.HiPart);
511
512    if (psav->SavedBgColor != 0xffffffff)
513	BCI_SEND(psav->SavedBgColor);
514    BCI_SEND(BCI_X_Y(x1, y1));
515    BCI_SEND(BCI_X_Y(x2, y2));
516    BCI_SEND(BCI_W_H(w, h));
517}
518
519
520/*
521 * SetupForSolidFill is also called to set up for lines.
522 */
523
524static void
525SavageSetupForSolidFill(
526    ScrnInfoPtr pScrn,
527    int color,
528    int rop,
529    unsigned int planemask)
530{
531    SavagePtr psav = SAVPTR(pScrn);
532    XAAInfoRecPtr xaaptr = GET_XAAINFORECPTR_FROM_SCRNINFOPTR( pScrn );
533    int cmd;
534    int mix;
535
536    cmd = BCI_CMD_RECT
537        | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
538        | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_SOLID;
539
540    /* Don't send a color if we don't have to. */
541
542    if( rop == GXcopy )
543    {
544	if( color == 0 )
545	    rop = GXclear;
546	else if( (unsigned int)color == xaaptr->FullPlanemask )
547	    rop = GXset;
548    }
549
550    mix = SavageHelpSolidROP( pScrn, &color, planemask, &rop );
551
552    if( mix & ROP_PAT )
553	cmd |= BCI_CMD_SEND_COLOR;
554
555    BCI_CMD_SET_ROP( cmd, rop );
556
557    psav->SavedBciCmd = cmd;
558    psav->SavedFgColor = color;
559}
560
561
562static void
563SavageSubsequentSolidFillRect(
564    ScrnInfoPtr pScrn,
565    int x,
566    int y,
567    int w,
568    int h)
569{
570    SavagePtr psav = SAVPTR(pScrn);
571    BCI_GET_PTR;
572
573    if( !w || !h )
574	return;
575
576    psav->WaitQueue(psav,7);
577
578    BCI_SEND(psav->SavedBciCmd);
579
580    BCI_SEND(psav->GlobalBD.bd2.LoPart);
581    BCI_SEND(psav->GlobalBD.bd2.HiPart);
582
583    if( psav->SavedBciCmd & BCI_CMD_SEND_COLOR )
584	BCI_SEND(psav->SavedFgColor);
585    BCI_SEND(BCI_X_Y(x, y));
586    BCI_SEND(BCI_W_H(w, h));
587}
588
589static void
590SavageSetupForCPUToScreenColorExpandFill(
591    ScrnInfoPtr pScrn,
592    int fg,
593    int bg,
594    int rop,
595    unsigned int planemask)
596{
597    SavagePtr psav = SAVPTR(pScrn);
598    int cmd;
599    int mix;
600
601    cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
602	| BCI_CMD_CLIP_LR
603        | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_MONO;
604
605    mix = SavageHelpPatternROP( pScrn, &fg, &bg, planemask, &rop );
606
607    if( mix & ROP_PAT )
608        cmd |= BCI_CMD_SEND_COLOR;
609
610    BCI_CMD_SET_ROP( cmd, rop );
611
612    if (bg != -1)
613        cmd |= BCI_CMD_SEND_COLOR;
614    else
615	cmd |= BCI_CMD_SRC_TRANSPARENT;
616
617    psav->SavedBciCmd = cmd;
618    psav->SavedFgColor = fg;
619    psav->SavedBgColor = bg;
620}
621
622
623static void
624SavageSubsequentScanlineCPUToScreenColorExpandFill(
625    ScrnInfoPtr pScrn,
626    int x,
627    int y,
628    int w,
629    int h,
630    int skipleft)
631{
632    SavagePtr psav = SAVPTR(pScrn);
633    BCI_GET_PTR;
634
635    /* XAA will be sending bitmap data next.  */
636    /* We should probably wait for empty/idle here. */
637
638    psav->WaitQueue(psav,22);
639
640    BCI_SEND(psav->SavedBciCmd);
641
642    BCI_SEND(psav->GlobalBD.bd2.LoPart);
643    BCI_SEND(psav->GlobalBD.bd2.HiPart);
644
645    BCI_SEND(BCI_CLIP_LR(x+skipleft, x+w-1));
646    w = (w + 31) & ~31;
647    if( psav->SavedBciCmd & BCI_CMD_SEND_COLOR )
648	BCI_SEND(psav->SavedFgColor);
649    if( psav->SavedBgColor != 0xffffffff )
650	BCI_SEND(psav->SavedBgColor);
651    BCI_SEND(BCI_X_Y(x, y));
652    BCI_SEND(BCI_W_H(w, 1));
653
654    psav->Rect.x = x;
655    psav->Rect.y = y + 1;
656    psav->Rect.width = w;
657    psav->Rect.height = h - 1;
658}
659
660static void
661SavageSubsequentColorExpandScanline(
662    ScrnInfoPtr pScrn,
663    int buffer_no)
664{
665    /* This gets call after each scanline's image data has been sent. */
666    SavagePtr psav = SAVPTR(pScrn);
667    xRectangle xr = psav->Rect;
668    BCI_GET_PTR;
669
670    if( xr.height )
671    {
672	psav->WaitQueue(psav,20);
673	BCI_SEND(BCI_X_Y( xr.x, xr.y));
674	BCI_SEND(BCI_W_H( xr.width, 1 ));
675        psav->Rect.height--;
676	psav->Rect.y++;
677    }
678}
679
680
681/*
682 * The meaning of the two pattern parameters to Setup & Subsequent for
683 * Mono8x8Patterns varies depending on the flag bits.  We specify
684 * HW_PROGRAMMED_BITS, which means our hardware can handle 8x8 patterns
685 * without caching in the frame buffer.  Thus, Setup gets the pattern bits.
686 * There is no way with BCI to rotate an 8x8 pattern, so we do NOT specify
687 * HW_PROGRAMMED_ORIGIN.  XAA will rotate it for us and pass the rotated
688 * pattern to both Setup and Subsequent.  If we DID specify PROGRAMMED_ORIGIN,
689 * then Setup would get the unrotated pattern, and Subsequent gets the
690 * origin values.
691 */
692
693static void
694SavageSetupForMono8x8PatternFill(
695    ScrnInfoPtr pScrn,
696    int patternx,
697    int patterny,
698    int fg,
699    int bg,
700    int rop,
701    unsigned int planemask)
702{
703    SavagePtr psav = SAVPTR(pScrn);
704    int cmd;
705    int mix;
706
707    mix = XAAHelpPatternROP( pScrn, &fg, &bg, planemask, &rop );
708
709    cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
710        | BCI_CMD_DEST_PBD_NEW;
711
712    if( mix & ROP_PAT )
713	cmd |= BCI_CMD_SEND_COLOR | BCI_CMD_PAT_MONO;
714
715    if (bg == -1)
716	cmd |= BCI_CMD_PAT_TRANSPARENT;
717
718    BCI_CMD_SET_ROP(cmd, rop);
719
720    psav->SavedBciCmd = cmd;
721    psav->SavedFgColor = fg;
722    psav->SavedBgColor = bg;
723}
724
725
726static void
727SavageSubsequentMono8x8PatternFillRect(
728    ScrnInfoPtr pScrn,
729    int pattern0,
730    int pattern1,
731    int x,
732    int y,
733    int w,
734    int h)
735{
736    SavagePtr psav = SAVPTR(pScrn);
737    BCI_GET_PTR;
738
739    /*
740     * I didn't think it was my job to do trivial rejection, but
741     * miFillGeneralPolygon definitely generates null spans, and XAA
742     * just passes them through.
743     */
744
745    if( !w || !h )
746	return;
747
748    psav->WaitQueue(psav,9);
749    BCI_SEND(psav->SavedBciCmd);
750
751    BCI_SEND(psav->GlobalBD.bd2.LoPart);
752    BCI_SEND(psav->GlobalBD.bd2.HiPart);
753
754    if( psav->SavedBciCmd & BCI_CMD_SEND_COLOR )
755	BCI_SEND(psav->SavedFgColor);
756    if( psav->SavedBgColor != 0xffffffff )
757	BCI_SEND(psav->SavedBgColor);
758    BCI_SEND(BCI_X_Y(x, y));
759    BCI_SEND(BCI_W_H(w, h));
760    if( psav->SavedBciCmd & BCI_CMD_PAT_MONO )
761    {
762	BCI_SEND(pattern0);
763	BCI_SEND(pattern1);
764    }
765}
766
767
768#if 0
769static void
770SavageSetupForColor8x8PatternFill(
771    ScrnInfoPtr pScrn,
772    int patternx,
773    int patterny,
774    int rop,
775    unsigned planemask,
776    int trans_col)
777{
778    SavagePtr psav = SAVPTR(pScrn);
779
780    int cmd;
781    unsigned int bd;
782    int pat_offset;
783
784    /* ViRGEs and Savages do not support transparent color patterns. */
785    /* We set the NO_TRANSPARENCY bit, so we should never receive one. */
786
787    pat_offset = (int) (patternx * psav->Bpp + patterny * psav->Bpl);
788
789    cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
790        | BCI_CMD_DEST_GBD | BCI_CMD_PAT_PBD_COLOR_NEW;
791
792    (void) XAAHelpSolidROP( pScrn, &trans_col, planemask, &rop );
793
794    BCI_CMD_SET_ROP(cmd, rop);
795    bd = BCI_BD_BW_DISABLE;
796    BCI_BD_SET_BPP(bd, pScrn->bitsPerPixel);
797    BCI_BD_SET_STRIDE(bd, 8);
798
799    psav->SavedBciCmd = cmd;
800    psav->SavedSbdOffset = pat_offset;
801    psav->SavedSbd = bd;
802    psav->SavedBgColor = trans_col;
803}
804
805
806static void
807SavageSubsequentColor8x8PatternFillRect(
808    ScrnInfoPtr pScrn,
809    int patternx,
810    int patterny,
811    int x,
812    int y,
813    int w,
814    int h)
815{
816    SavagePtr psav = SAVPTR(pScrn);
817    BCI_GET_PTR;
818
819    if( !w || !h )
820	return;
821
822    psav->WaitQueue(psav,6);
823    BCI_SEND(psav->SavedBciCmd);
824    BCI_SEND(psav->SavedSbdOffset);
825    BCI_SEND(psav->SavedSbd);
826    BCI_SEND(BCI_X_Y(patternx,patterny));
827    BCI_SEND(BCI_X_Y(x, y));
828    BCI_SEND(BCI_W_H(w, h));
829}
830#endif
831
832static void
833SavageSubsequentSolidBresenhamLine(
834    ScrnInfoPtr pScrn,
835    int x1,
836    int y1,
837    int e1,
838    int e2,
839    int err,
840    int length,
841    int octant)
842{
843    SavagePtr psav = SAVPTR(pScrn);
844    BCI_GET_PTR;
845    int cmd;
846
847    cmd = (psav->SavedBciCmd & 0x00ffffff);
848    cmd |= BCI_CMD_LINE_LAST_PIXEL;
849
850#ifdef DEBUG_EXTRA
851    ErrorF("BresenhamLine, (%4d,%4d), len %4d, oct %d, err %4d,%4d,%4d clr %08x\n",
852        x1, y1, length, octant, e1, e2, err, psav->SavedFgColor );
853#endif
854
855    psav->WaitQueue(psav, 7 );
856    BCI_SEND(cmd);
857
858    BCI_SEND(psav->GlobalBD.bd2.LoPart);
859    BCI_SEND(psav->GlobalBD.bd2.HiPart);
860
861    if( cmd & BCI_CMD_SEND_COLOR )
862	BCI_SEND( psav->SavedFgColor );
863    BCI_SEND(BCI_LINE_X_Y(x1, y1));
864    BCI_SEND(BCI_LINE_STEPS(e2-e1, e2));
865    BCI_SEND(BCI_LINE_MISC(length,
866    			   (octant & YMAJOR),
867			   !(octant & XDECREASING),
868			   !(octant & YDECREASING),
869			   e2+err));
870}
871
872static void
873SavageSetClippingRectangle(
874    ScrnInfoPtr pScrn,
875    int x1,
876    int y1,
877    int x2,
878    int y2)
879{
880    SavagePtr psav = SAVPTR(pScrn);
881    BCI_GET_PTR;
882    int cmd;
883
884#ifdef DEBUG_EXTRA
885    ErrorF("ClipRect, (%4d,%4d)-(%4d,%4d) \n", x1, y1, x2, y2 );
886#endif
887
888    cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
889    psav->WaitQueue(psav,3);
890    BCI_SEND(cmd);
891    BCI_SEND(BCI_CLIP_TL(y1, x1));
892    BCI_SEND(BCI_CLIP_BR(y2, x2));
893    psav->SavedBciCmd |= BCI_CMD_CLIP_CURRENT;
894}
895
896
897static void SavageDisableClipping( ScrnInfoPtr pScrn )
898{
899    SavagePtr psav = SAVPTR(pScrn);
900#ifdef DEBUG_EXTRA
901    ErrorF("Kill ClipRect\n");
902#endif
903    psav->SavedBciCmd &= ~BCI_CMD_CLIP_CURRENT;
904}
905
906void
907SavageWriteBitmapCPUToScreenColorExpand (
908    ScrnInfoPtr pScrn,
909    int x, int y, int w, int h,
910    unsigned char * src,
911    int srcwidth,
912    int skipleft,
913    int fg, int bg,
914    int rop,
915    unsigned int planemask
916)
917{
918    SavagePtr psav = SAVPTR(pScrn);
919    BCI_GET_PTR;
920    int i, j, count, reset;
921    unsigned int cmd;
922    CARD32 * srcp;
923
924/* We aren't using planemask at all here... */
925
926    if( !srcwidth )
927	return;
928
929    cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
930        | BCI_CMD_SEND_COLOR | BCI_CMD_CLIP_LR
931        | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_MONO;
932    cmd |= XAAGetCopyROP(rop) << 16;
933
934    if( bg == -1 )
935        cmd |= BCI_CMD_SRC_TRANSPARENT;
936
937    BCI_SEND(cmd);
938
939    BCI_SEND(psav->GlobalBD.bd2.LoPart);
940    BCI_SEND(psav->GlobalBD.bd2.HiPart);
941
942    BCI_SEND(BCI_CLIP_LR(x+skipleft, x+w-1));
943    BCI_SEND(fg);
944    if( bg != -1 )
945	BCI_SEND(bg);
946
947    /* Bitmaps come in in units of DWORDS, LSBFirst.  This is exactly */
948    /* reversed of what we expect.  */
949
950    count = (w + 31) / 32;
951/*    src += ((srcx & ~31) / 8); */
952
953    /* The BCI region is 128k bytes.  A screen-sized mono bitmap can */
954    /* exceed that. */
955
956    reset = 65536 / count;
957
958    for (j = 0; j < h; j ++) {
959        BCI_SEND(BCI_X_Y(x, y+j));
960        BCI_SEND(BCI_W_H(w, 1));
961        srcp = (CARD32 *) src;
962        for (i = count; i > 0; srcp ++, i --) {
963            /* We have to invert the bits in each byte. */
964            CARD32 u = *srcp;
965            u = ((u & 0x0f0f0f0f) << 4) | ((u & 0xf0f0f0f0) >> 4);
966            u = ((u & 0x33333333) << 2) | ((u & 0xcccccccc) >> 2);
967            u = ((u & 0x55555555) << 1) | ((u & 0xaaaaaaaa) >> 1);
968            BCI_SEND(u);
969        }
970        src += srcwidth;
971        if( !--reset ) {
972	    BCI_RESET;
973            reset = 65536 / count;
974        }
975    }
976}
977
978void
979SavageSetupForImageWrite(
980    ScrnInfoPtr pScrn,
981    int rop,
982    unsigned planemask,
983    int transparency_color,
984    int bpp,
985    int depth)
986{
987    SavagePtr psav = SAVPTR(pScrn);
988    int cmd;
989
990    cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP
991        | BCI_CMD_CLIP_LR
992        | BCI_CMD_DEST_PBD_NEW | BCI_CMD_SRC_COLOR;
993
994    cmd |= XAAGetCopyROP(rop) << 16;
995
996    if( transparency_color != -1 )
997        cmd |= BCI_CMD_SRC_TRANSPARENT;
998
999    psav->SavedBciCmd = cmd;
1000    psav->SavedBgColor = transparency_color;
1001}
1002
1003
1004void SavageSubsequentImageWriteRect
1005(
1006    ScrnInfoPtr pScrn,
1007    int x,
1008    int y,
1009    int w,
1010    int h,
1011    int skipleft)
1012{
1013    SavagePtr psav = SAVPTR(pScrn);
1014    BCI_GET_PTR;
1015
1016    psav->WaitQueue( psav, 8 );
1017    BCI_SEND(psav->SavedBciCmd);
1018
1019    BCI_SEND(psav->GlobalBD.bd2.LoPart);
1020    BCI_SEND(psav->GlobalBD.bd2.HiPart);
1021
1022    BCI_SEND(BCI_CLIP_LR(x+skipleft, x+w-1));
1023    if( psav->SavedBgColor != 0xffffffff )
1024        BCI_SEND(psav->SavedBgColor);
1025    BCI_SEND(BCI_X_Y(x, y));
1026    BCI_SEND(BCI_W_H(w, h));
1027}
1028
1029#endif
1030