1 /*
2  * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Alan Hourihane not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Alan Hourihane makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as is" without express or implied warranty.
13  *
14  * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  * Authors:  Alan Hourihane, <alanh@fairlite.demon.co.uk>
23  *
24  * BladeXP accelerated options.
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include "xf86.h"
32 #include "xf86_OSproc.h"
33 
34 #include "xf86Pci.h"
35 
36 #include "miline.h"
37 
38 #include "trident.h"
39 #include "trident_regs.h"
40 
41 #ifdef HAVE_XAA_H
42 #include "xaarop.h"
43 
44 static void XPSync(ScrnInfoPtr pScrn);
45 #if 0
46 static void XPSetupForDashedLine(ScrnInfoPtr pScrn, int fg, int bg,
47 				int rop, unsigned int planemask, int length,
48     				unsigned char *pattern);
49 static void XPSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
50         			int x, int y, int dmaj, int dmin, int e,
51 				int len, int octant, int phase);
52 static void XPSetupForSolidLine(ScrnInfoPtr pScrn, int color,
53 				int rop, unsigned int planemask);
54 static void XPSubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
55         			int x, int y, int dmaj, int dmin, int e,
56 				int len, int octant);
57 #endif
58 static void XPSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y,
59     				int len, int dir);
60 static void XPSetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
61 				int rop, unsigned int planemask);
62 static void XPSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x,
63 				int y, int w, int h);
64 static void XPSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
65 				int x1, int y1, int x2,
66 				int y2, int w, int h);
67 static void XPSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
68 				int xdir, int ydir, int rop,
69                                 unsigned int planemask,
70 				int transparency_color);
71 static void XPSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
72 				int patternx, int patterny, int fg, int bg,
73 				int rop, unsigned int planemask);
74 static void XPSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
75 				int patternx, int patterny, int x, int y,
76 				int w, int h);
77 #if 0
78 static void XPSetupForScanlineCPUToScreenColorExpandFill(
79 				ScrnInfoPtr pScrn,
80 				int fg, int bg, int rop,
81 				unsigned int planemask);
82 static void XPSubsequentScanlineCPUToScreenColorExpandFill(
83 				ScrnInfoPtr pScrn, int x,
84 				int y, int w, int h, int skipleft);
85 static void XPSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
86 #endif
87 
88 static void
XPInitializeAccelerator(ScrnInfoPtr pScrn)89 XPInitializeAccelerator(ScrnInfoPtr pScrn)
90 {
91     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
92     int shift;
93 
94     /* This forces updating the clipper */
95     pTrident->Clipping = TRUE;
96 
97     CHECKCLIPPING;
98 
99     BLADE_XP_OPERMODE(pTrident->EngineOperation);
100     pTrident->EngineOperation |= 0x40;
101     switch (pScrn->bitsPerPixel) {
102 	case 8:
103 	default:		/* Muffle compiler */
104 		shift = 18;
105 		break;
106 	case 16:
107 		shift = 19;
108 		break;
109 	case 32:
110 		shift = 20;
111 		break;
112     }
113     MMIO_OUT32(pTrident->IOBase, 0x2154, (pScrn->displayWidth) << shift);
114     MMIO_OUT32(pTrident->IOBase, 0x2150, (pScrn->displayWidth) << shift);
115     MMIO_OUT8(pTrident->IOBase, 0x2126, 3);
116 }
117 #endif
118 
119 Bool
XPAccelInit(ScreenPtr pScreen)120 XPAccelInit(ScreenPtr pScreen)
121 {
122 #ifdef HAVE_XAA_H
123     XAAInfoRecPtr infoPtr;
124     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
125     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
126 
127     if (pTrident->NoAccel)
128 	return FALSE;
129 
130     pTrident->AccelInfoRec = infoPtr = XAACreateInfoRec();
131     if (!infoPtr) return FALSE;
132 
133     infoPtr->Flags = PIXMAP_CACHE |
134 		     OFFSCREEN_PIXMAPS |
135 		     LINEAR_FRAMEBUFFER;
136 
137     pTrident->InitializeAccelerator = XPInitializeAccelerator;
138     XPInitializeAccelerator(pScrn);
139 
140     infoPtr->Sync = XPSync;
141 
142 #if 0 /* TO DO for the XP */
143     infoPtr->SolidLineFlags = NO_PLANEMASK;
144     infoPtr->SetupForSolidLine = XPSetupForSolidLine;
145     infoPtr->SolidBresenhamLineErrorTermBits = 12;
146     infoPtr->SubsequentSolidBresenhamLine = XPSubsequentSolidBresenhamLine;
147 
148     infoPtr->DashedLineFlags = LINE_PATTERN_MSBFIRST_LSBJUSTIFIED |
149 			       NO_PLANEMASK |
150 			       LINE_PATTERN_POWER_OF_2_ONLY;
151     infoPtr->SetupForDashedLine = XPSetupForDashedLine;
152     infoPtr->DashedBresenhamLineErrorTermBits = 12;
153     infoPtr->SubsequentDashedBresenhamLine =
154 					XPSubsequentDashedBresenhamLine;
155     infoPtr->DashPatternMaxLength = 16;
156 #endif
157 
158     infoPtr->SolidFillFlags = NO_PLANEMASK;
159     infoPtr->SetupForSolidFill = XPSetupForFillRectSolid;
160     infoPtr->SubsequentSolidFillRect = XPSubsequentFillRectSolid;
161     infoPtr->SubsequentSolidHorVertLine = XPSubsequentSolidHorVertLine;
162 
163     infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK | NO_TRANSPARENCY;
164 
165     infoPtr->SetupForScreenToScreenCopy =
166 				XPSetupForScreenToScreenCopy;
167     infoPtr->SubsequentScreenToScreenCopy =
168 				XPSubsequentScreenToScreenCopy;
169 
170     infoPtr->Mono8x8PatternFillFlags =  NO_PLANEMASK |
171 					HARDWARE_PATTERN_PROGRAMMED_BITS |
172 					BIT_ORDER_IN_BYTE_MSBFIRST;
173 
174     infoPtr->SetupForMono8x8PatternFill =
175 				XPSetupForMono8x8PatternFill;
176     infoPtr->SubsequentMono8x8PatternFillRect =
177 				XPSubsequentMono8x8PatternFillRect;
178 
179 #if 0 /* Needs fixing */
180     infoPtr->ScanlineCPUToScreenColorExpandFillFlags = NO_PLANEMASK |
181 					BIT_ORDER_IN_BYTE_MSBFIRST;
182 
183     pTrident->XAAScanlineColorExpandBuffers[0] =
184 	    xnfalloc(((pScrn->virtualX + 63)) *4* (pScrn->bitsPerPixel / 8));
185 
186     infoPtr->NumScanlineColorExpandBuffers = 1;
187     infoPtr->ScanlineColorExpandBuffers =
188 					pTrident->XAAScanlineColorExpandBuffers;
189 
190     infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
191 			XPSetupForScanlineCPUToScreenColorExpandFill;
192     infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
193 			XPSubsequentScanlineCPUToScreenColorExpandFill;
194     infoPtr->SubsequentColorExpandScanline =
195 			XPSubsequentColorExpandScanline;
196 #endif
197 
198     return(XAAInit(pScreen, infoPtr));
199 #else
200     return FALSE;
201 #endif
202 }
203 
204 #ifdef HAVE_XAA_H
205 static void
XPSync(ScrnInfoPtr pScrn)206 XPSync(ScrnInfoPtr pScrn)
207 {
208     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
209     int count = 0, timeout = 0;
210     int busy;
211 
212     BLADE_XP_OPERMODE(pTrident->EngineOperation);
213 
214     for (;;) {
215 	BLTBUSY(busy);
216 	if (busy != GE_BUSY) {
217 	    return;
218 	}
219 	count++;
220 	if (count == 10000000) {
221 	    ErrorF("XP: BitBLT engine time-out.\n");
222 	    count = 9990000;
223 	    timeout++;
224 	    if (timeout == 8) {
225 		/* Reset BitBLT Engine */
226 		TGUI_STATUS(0x00);
227 		return;
228 	    }
229 	}
230     }
231 }
232 
233 static void
XPClearSync(ScrnInfoPtr pScrn)234 XPClearSync(ScrnInfoPtr pScrn)
235 {
236     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
237     int count = 0, timeout = 0;
238     int busy;
239 
240     for (;;) {
241 	BLTBUSY(busy);
242 	if (busy != GE_BUSY) {
243 	    return;
244 	}
245 	count++;
246 	if (count == 10000000) {
247 	    ErrorF("XP: BitBLT engine time-out.\n");
248 	    count = 9990000;
249 	    timeout++;
250 	    if (timeout == 8) {
251 		/* Reset BitBLT Engine */
252 		TGUI_STATUS(0x00);
253 		return;
254 	    }
255 	}
256     }
257 }
258 
259 static void
XPSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,int xdir,int ydir,int rop,unsigned int planemask,int transparency_color)260 XPSetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
261 				int xdir, int ydir, int rop,
262 				unsigned int planemask, int transparency_color)
263 {
264     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
265     int dst = 0;
266 
267     pTrident->BltScanDirection = 0;
268     if (xdir < 0) pTrident->BltScanDirection |= XNEG;
269     if (ydir < 0) pTrident->BltScanDirection |= YNEG;
270 
271     REPLICATE(transparency_color);
272     if (transparency_color != -1) {
273 	dst |= 3<<16;
274     	MMIO_OUT32(pTrident->IOBase, 0x2134, transparency_color);
275     }
276 
277     TGUI_DRAWFLAG(pTrident->BltScanDirection | SCR2SCR | dst);
278     TGUI_FMIX(XAAGetCopyROP(rop));
279 }
280 
281 static void
XPSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,int x1,int y1,int x2,int y2,int w,int h)282 XPSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
283 					int x2, int y2, int w, int h)
284 {
285     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
286 
287     if (pTrident->BltScanDirection & YNEG) {
288         y1 = y1 + h - 1;
289 	y2 = y2 + h - 1;
290     }
291     if (pTrident->BltScanDirection & XNEG) {
292 	x1 = x1 + w - 1;
293 	x2 = x2 + w - 1;
294     }
295     XP_SRC_XY(x1,y1);
296     XP_DEST_XY(x2,y2);
297     XP_DIM_XY(w,h);
298     TGUI_COMMAND(GE_BLT);
299     XPClearSync(pScrn);
300 }
301 
302 #if 0
303 static void
304 XPSetupForSolidLine(ScrnInfoPtr pScrn, int color,
305 					 int rop, unsigned int planemask)
306 {
307     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
308 
309     pTrident->BltScanDirection = 0;
310     REPLICATE(color);
311     TGUI_FMIX(XAAGetPatternROP(rop));
312     if (pTrident->Chipset >= PROVIDIA9685) {
313     	TGUI_FPATCOL(color);
314     } else {
315     	TGUI_FCOLOUR(color);
316     }
317 }
318 
319 static void
320 XPSubsequentSolidBresenhamLine( ScrnInfoPtr pScrn,
321         int x, int y, int dmaj, int dmin, int e, int len, int octant)
322 {
323     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
324     int tmp = pTrident->BltScanDirection;
325 
326     if (octant & YMAJOR) tmp |= YMAJ;
327     if (octant & XDECREASING) tmp |= XNEG;
328     if (octant & YDECREASING) tmp |= YNEG;
329     TGUI_DRAWFLAG(SOLIDFILL | STENCIL | tmp);
330     XP_SRC_XY(dmin-dmaj,dmin);
331     XP_DEST_XY(x,y);
332     XP_DIM_XY(dmin+e,len);
333     TGUI_COMMAND(GE_BRESLINE);
334     XPSync(pScrn);
335 }
336 #endif
337 
338 static void
XPSubsequentSolidHorVertLine(ScrnInfoPtr pScrn,int x,int y,int len,int dir)339 XPSubsequentSolidHorVertLine(
340     ScrnInfoPtr pScrn,
341     int x, int y,
342     int len, int dir
343 ){
344     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
345 
346     TGUI_DRAWFLAG(SOLIDFILL);
347     if (dir == DEGREES_0) {
348     	XP_DIM_XY(len,1);
349     	XP_DEST_XY(x,y);
350     } else {
351     	XP_DIM_XY(1,len);
352     	XP_DEST_XY(x,y);
353     }
354     TGUI_COMMAND(GE_BLT);
355     XPSync(pScrn);
356 }
357 
358 #if 0
359 void
360 XPSetupForDashedLine(
361     ScrnInfoPtr pScrn,
362     int fg, int bg, int rop,
363     unsigned int planemask,
364     int length,
365     unsigned char *pattern
366 ){
367     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
368     CARD32 *DashPattern = (CARD32*)pattern;
369     CARD32 NiceDashPattern = DashPattern[0];
370 
371     NiceDashPattern = *((CARD16 *)pattern) & ((1<<length) - 1);
372     switch(length) {
373 	case 2:	NiceDashPattern |= NiceDashPattern << 2;
374 	case 4:	NiceDashPattern |= NiceDashPattern << 4;
375 	case 8:	NiceDashPattern |= NiceDashPattern << 8;
376     }
377     pTrident->BltScanDirection = 0;
378     REPLICATE(fg);
379     if (pTrident->Chipset >= PROVIDIA9685) {
380 	TGUI_FPATCOL(fg);
381     	if (bg == -1) {
382 	    pTrident->BltScanDirection |= 1<<12;
383     	    TGUI_BPATCOL(~fg);
384     	} else {
385     	    REPLICATE(bg);
386     	    TGUI_BPATCOL(bg);
387     	}
388     } else {
389     	TGUI_FCOLOUR(fg);
390     	if (bg == -1) {
391 	    pTrident->BltScanDirection |= 1<<12;
392     	    TGUI_BCOLOUR(~fg);
393     	} else {
394     	    REPLICATE(bg);
395     	    TGUI_BCOLOUR(bg);
396     	}
397     }
398     TGUI_FMIX(XAAGetPatternROP(rop));
399     pTrident->LinePattern = NiceDashPattern;
400 }
401 
402 void
403 XPSubsequentDashedBresenhamLine(ScrnInfoPtr pScrn,
404         int x, int y, int dmaj, int dmin, int e, int len, int octant, int phase)
405 {
406     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
407     int tmp = pTrident->BltScanDirection;
408 
409     if (octant & YMAJOR) tmp |= YMAJ;
410     if (octant & XDECREASING) tmp |= XNEG;
411     if (octant & YDECREASING) tmp |= YNEG;
412 
413     TGUI_STYLE(((pTrident->LinePattern >> phase) |
414 		(pTrident->LinePattern << (16-phase))) & 0x0000FFFF);
415     TGUI_DRAWFLAG(STENCIL | tmp);
416     XP_SRC_XY(dmin-dmaj,dmin);
417     XP_DEST_XY(x,y);
418     XP_DIM_XY(e+dmin,len);
419     TGUI_COMMAND(GE_BRESLINE);
420     XPSync(pScrn);
421 }
422 #endif
423 
424 static void
XPSetupForFillRectSolid(ScrnInfoPtr pScrn,int color,int rop,unsigned int planemask)425 XPSetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
426 				    int rop, unsigned int planemask)
427 {
428     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
429 
430     REPLICATE(color);
431     TGUI_FMIX(XAAGetPatternROP(rop));
432     MMIO_OUT32(pTrident->IOBase, 0x2158, color);
433     TGUI_DRAWFLAG(SOLIDFILL);
434 }
435 
436 static void
XPSubsequentFillRectSolid(ScrnInfoPtr pScrn,int x,int y,int w,int h)437 XPSubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h)
438 {
439     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
440 
441     XP_DIM_XY(w,h);
442     XP_DEST_XY(x,y);
443     TGUI_COMMAND(GE_BLT);
444     XPSync(pScrn);
445 }
446 
447 #if 0
448 static void MoveDWORDS(
449    register CARD32* dest,
450    register CARD32* src,
451    register int dwords )
452 {
453      while(dwords & ~0x03) {
454 	*dest = *src;
455 	*(dest + 1) = *(src + 1);
456 	*(dest + 2) = *(src + 2);
457 	*(dest + 3) = *(src + 3);
458 	src += 4;
459 	dest += 4;
460 	dwords -= 4;
461      }
462      if (!dwords) return;
463      *dest = *src;
464      dest += 1;
465      src += 1;
466      if (dwords == 1) return;
467      *dest = *src;
468      dest += 1;
469      src += 1;
470      if (dwords == 2) return;
471      *dest = *src;
472      dest += 1;
473      src += 1;
474 }
475 #endif
476 
477 #if 0
478 static void MoveDWORDS_FixedBase(
479    register CARD32* dest,
480    register CARD32* src,
481    register int dwords )
482 {
483      while(dwords & ~0x03) {
484 	 *dest = *src;
485 	 *dest = *(src + 1);
486 	 *dest = *(src + 2);
487 	 *dest = *(src + 3);
488 	 dwords -= 4;
489 	 src += 4;
490      }
491 
492      if(!dwords) return;
493      *dest = *src;
494      if(dwords == 1) return;
495      *dest = *(src + 1);
496      if(dwords == 2) return;
497      *dest = *(src + 2);
498 }
499 #endif
500 
501 
502 static void
XPSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,int patternx,int patterny,int fg,int bg,int rop,unsigned int planemask)503 XPSetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
504 					   int patternx, int patterny,
505 					   int fg, int bg, int rop,
506 					   unsigned int planemask)
507 {
508     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
509     int drawflag = 0;
510 
511     REPLICATE(fg);
512     MMIO_OUT32(pTrident->IOBase, 0x2158, fg);
513 
514     if (bg == -1) {
515 	drawflag |= 1<<12;
516    	MMIO_OUT32(pTrident->IOBase, 0x215C, ~fg);
517     } else {
518     	REPLICATE(bg);
519    	MMIO_OUT32(pTrident->IOBase, 0x215C, bg);
520     }
521 
522     drawflag |= 7<<18;
523     TGUI_DRAWFLAG(PATMONO | drawflag);
524     MMIO_OUT32(pTrident->IOBase, 0x2180, patternx);
525     MMIO_OUT32(pTrident->IOBase, 0x2184, patterny);
526     TGUI_FMIX(XAAGetPatternROP(rop));
527 }
528 
529 static void
XPSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,int patternx,int patterny,int x,int y,int w,int h)530 XPSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
531 				   int patternx, int patterny,
532 				   int x, int y,
533 				   int w, int h)
534 {
535     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
536 
537     XP_DEST_XY(x,y);
538     XP_DIM_XY(w,h);
539     TGUI_COMMAND(GE_BLT);
540     XPSync(pScrn);
541 }
542 
543 #if 0
544 static void
545 XPSetupForScanlineCPUToScreenColorExpandFill(
546 	ScrnInfoPtr pScrn,
547 	int fg, int bg,
548 	int rop,
549 	unsigned int planemask
550 ){
551     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
552 
553     TGUI_FMIX(XAAGetCopyROP(rop));
554     if (bg == -1) {
555     TGUI_DRAWFLAG(SRCMONO | 1<<12);
556     	REPLICATE(fg);
557 	TGUI_FCOLOUR(fg);
558     } else {
559     TGUI_DRAWFLAG(SRCMONO);
560     	REPLICATE(fg);
561     	REPLICATE(bg);
562 	TGUI_FCOLOUR(fg);
563 	TGUI_BCOLOUR(bg);
564     }
565 }
566 
567 static void
568 XPSubsequentScanlineCPUToScreenColorExpandFill(
569 	ScrnInfoPtr pScrn,
570 	int x, int y, int w, int h,
571 	int skipleft
572 ){
573     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
574     pTrident->dwords = (w + 31) >> 5;
575     pTrident->h = h;
576 
577     XP_DEST_XY(x,y);
578     XP_DIM_XY(w>>1,h);
579     TGUI_COMMAND(GE_BLT);
580 }
581 
582 static void
583 XPSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
584 {
585     TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
586     XAAInfoRecPtr infoRec;
587     infoRec = GET_XAAINFORECPTR_FROM_SCRNINFOPTR(pScrn);
588 
589     MoveDWORDS_FixedBase((CARD32 *)pTrident->IOBase + 0x2160,
590 		(CARD32 *)pTrident->XAAScanlineColorExpandBuffers[0],
591 			pTrident->dwords);
592 
593     pTrident->h--;
594     if (pTrident->h)
595     	XPSync(pScrn);
596 }
597 #endif
598 #endif
599