s3_accel.c revision bd35f0db
1/*
2 *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
3 *
4 *      XFree86 4.x driver for S3 chipsets
5 *
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation and
11 * that the name of Ani Joshi not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  Ani Joshi makes no representations
14 * about the suitability of this software for any purpose.  It is provided
15 * "as-is" without express or implied warranty.
16 *
17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "xf86.h"
33
34#include "miline.h"
35
36#include "s3.h"
37#include "s3_reg.h"
38
39
40#if 0
41static Bool NicePattern;
42static int DashPatternSize;
43#define MAX_LINE_PATTERN_LENGTH	512
44#define LINE_PATTERN_START	((MAX_LINE_PATTERN_LENGTH >> 5) - 1)
45static CARD32 DashPattern[MAX_LINE_PATTERN_LENGTH >> 5];
46#endif
47
48
49static void S3Sync(ScrnInfoPtr pScrn)
50{
51	WaitIdle();
52}
53
54static void S3SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
55				unsigned int planemask)
56{
57	S3Ptr pS3 = S3PTR(pScrn);
58
59	WaitQueue16_32(4,6);
60	SET_PIX_CNTL(0);
61	SET_FRGD_COLOR(color);
62	SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
63	SET_WRT_MASK(planemask);
64}
65
66static void S3SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y,
67				      int w, int h)
68{
69#ifdef S3_NEWMMIO
70	S3Ptr pS3 = S3PTR(pScrn);
71#endif
72
73	WaitQueue(5);
74	SET_CURPT((short)x, (short)y);
75	SET_AXIS_PCNT(w - 1, h - 1);
76	SET_CMD(CMD_RECT | DRAW | INC_X | INC_Y | WRTDATA);
77}
78
79
80static void S3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
81					 int ydir, int rop,
82					 unsigned int planemask,
83					 int trans_color)
84{
85	S3Ptr pS3 = S3PTR(pScrn);
86
87	pS3->BltDir = CMD_BITBLT | DRAW | WRTDATA;
88
89	if (xdir == 1)
90		pS3->BltDir |= INC_X;
91	if (ydir == 1)
92		pS3->BltDir |= INC_Y;
93
94	pS3->trans_color = trans_color;
95
96	WaitQueue16_32(3,4);
97	SET_PIX_CNTL(0);
98	SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
99	SET_WRT_MASK(planemask);
100}
101
102
103static void S3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
104					   int srcx, int srcy,
105					   int dstx, int dsty,
106					   int w, int h)
107{
108	S3Ptr pS3 = S3PTR(pScrn);
109
110	w--;
111	h--;
112
113	if (!(pS3->BltDir & INC_Y)) {
114		srcy += h;
115		dsty += h;
116	}
117
118	if (!(pS3->BltDir & INC_X)) {
119		srcx += w;
120		dstx += w;
121	}
122
123	if (pS3->trans_color == -1) {
124		WaitQueue(7);
125		SET_CURPT((short)srcx, (short)srcy);
126		SET_DESTSTP((short)dstx, (short)dsty);
127		SET_AXIS_PCNT((short)w, (short)h);
128		SET_CMD(pS3->BltDir);
129	} else {
130		WaitQueue16_32(2,3);
131		SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
132		SET_COLOR_CMP(pS3->trans_color);
133
134		WaitQueue(8);
135		SET_CURPT((short)srcx, (short)srcy);
136		SET_DESTSTP((short)dstx, (short)dsty);
137		SET_AXIS_PCNT((short)w, (short)h);
138		SET_CMD(pS3->BltDir);
139		SET_MULT_MISC(CMD_REG_WIDTH);
140	}
141}
142
143#if 0
144static void S3SetupForColor8x8PatternFill(ScrnInfoPtr pScrn,
145					  int patx, int paty,
146					  int rop, unsigned int planemask,
147					  int trans_color)
148{
149	S3Ptr pS3 = S3PTR(pScrn);
150
151	pS3->trans_color = trans_color;
152
153	WaitQueue16_32(3,4);
154	SET_PIX_CNTL(0);
155	SET_FRGD_MIX(FSS_BITBLT | s3alu[rop]);
156	SET_WRT_MASK(planemask);
157}
158
159static void S3SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn,
160					    	int patx, int paty,
161					    	int x, int y,
162					    	int w, int h)
163{
164	S3Ptr pS3 = S3PTR(pScrn);
165
166	if (pS3->trans_color == -1) {
167		WaitQueue(7);
168		SET_CURPT((short)patx, (short)paty);
169		SET_DESTSTP((short)x, (short)y);
170		SET_AXIS_PCNT(w - 1, h - 1);
171		SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
172	} else {
173		WaitQueue16_32(2,3);
174		SET_MULT_MISC(CMD_REG_WIDTH | 0x0100);
175		SET_COLOR_CMP(pS3->trans_color);
176
177		WaitQueue(8);
178		SET_CURPT((short)patx, (short)paty);
179		SET_DESTSTP((short)x, (short)y);
180		SET_AXIS_PCNT(w - 1, h - 1);
181		SET_CMD(CMD_PFILL | DRAW | INC_Y | INC_X | WRTDATA);
182		SET_MULT_MISC(CMD_REG_WIDTH);
183	}
184}
185#endif
186
187#ifdef S3_NEWMMIO
188static void S3SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
189						 int fg, int bg,
190						 int rop,
191						 unsigned int planemask)
192{
193	S3Ptr pS3 = S3PTR(pScrn);
194
195	WaitQueue16_32(3,4);
196	if (bg == -1) {
197		if (pS3->ColorExpandBug) {
198			SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_XOR);
199			SET_BKGD_COLOR(0);
200		} else
201			SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | MIX_DST);
202	} else {
203		SET_MIX(FSS_FRGDCOL | s3alu[rop], BSS_BKGDCOL | s3alu[rop]);
204		SET_BKGD_COLOR(bg);
205	}
206
207	WaitQueue16_32(3,5);
208	SET_FRGD_COLOR(fg);
209	SET_WRT_MASK(planemask);
210	SET_PIX_CNTL(MIXSEL_EXPPC);
211}
212
213
214static void S3SubsequentCPUToScreenColorExpandFill32(ScrnInfoPtr pScrn,
215						     int x, int y,
216						     int w, int h,
217						     int skipleft)
218{
219	S3Ptr pS3 = S3PTR(pScrn);
220
221	WaitQueue(4);
222	SET_CURPT((short)x, (short)y);
223	SET_AXIS_PCNT((short)w-1, (short)h-1);
224
225	WaitIdle();
226	SET_CMD(CMD_RECT | BYTSEQ | _32BIT | PCDATA | DRAW |
227		PLANAR | INC_Y | INC_X | WRTDATA);
228}
229#endif
230
231#if 0
232#ifndef S3_NEWMMIO
233
234static void S3SetupForScanlineImageWriteNoMMIO(ScrnInfoPtr pScrn, int rop,
235					       unsigned int planemask,
236					       int trans_color,
237					       int bpp, int depth)
238{
239	S3Ptr pS3 = S3PTR(pScrn);
240
241	WaitQueue16_32(3,4)
242	SET_FRGD_MIX(FSS_PCDATA | s3alu[rop]);
243	SET_WRT_MASK(planemask);
244	SET_PIX_CNTL(0);
245}
246
247static void S3SubsequentScanlineImageWriteRectNoMMIO(ScrnInfoPtr pScrn,
248						     int x, int y,
249						     int w, int h,
250						     int skipleft)
251{
252	S3Ptr pS3 = S3PTR(pScrn);
253
254	pS3->imageWidth = w;
255	pS3->imageHeight = h;
256
257	WaitQueue(5);
258	SET_CURPT((short)x, (short)y);
259	SET_AXIS_PCNT((short)w-1, (short)h-1);
260	WaitIdle();
261	SET_CMD(CMD_RECT | BYTSEQ | _16BIT | INC_Y | INC_X | DRAW |
262		PCDATA | WRTDATA);
263}
264
265
266static void S3SubsequentImageWriteScanlineNoMMIO(ScrnInfoPtr pScrn,
267						 int bufno)
268{
269	S3Ptr pS3 = S3PTR(pScrn);
270	int i, j;
271	int w, h;
272	CARD16 *src = (CARD16 *)&pS3->imageBuffer;
273
274	w = pS3->imageWidth * pS3->s3Bpp;
275	h = pS3->imageHeight;
276
277	for(j=0; j<h; j++) {
278		for(i=0; i<(w & ~1); ) {
279			/* XXX not for 32bpp */
280			SET_PIX_TRANS_W(ldw_u(src));
281			src++;
282			i += 2;
283		}
284	}
285}
286
287#endif
288#endif
289
290
291static void S3SetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop,
292				unsigned int planemask)
293{
294	S3Ptr pS3 = S3PTR(pScrn);
295
296	WaitQueue16_32(4,6);
297	SET_PIX_CNTL(0);
298	SET_FRGD_COLOR(color);
299	SET_FRGD_MIX(FSS_FRGDCOL | s3alu[rop]);
300	SET_WRT_MASK(planemask);
301}
302
303
304static void S3SubsequentSolidBresenhamLine(ScrnInfoPtr pScrn,
305					   int x, int y,
306					   int major, int minor,
307					   int err, int len, int octant)
308{
309#ifdef S3_NEWMMIO
310	S3Ptr pS3 = S3PTR(pScrn);
311#endif
312	unsigned short cmd;
313	int error, e1, e2;
314
315	error = minor + err;
316	e1 = minor;   /* was: major, wrong (twini@xfree86.org) */
317	e2 = minor - major;
318
319	if (major) {
320		cmd = CMD_LINE | DRAW | WRTDATA | LASTPIX;
321
322		if (octant & YMAJOR)
323			cmd |= YMAJAXIS;
324		if (!(octant & XDECREASING))
325			cmd |= INC_X;
326		if (!(octant & YDECREASING))
327			cmd |= INC_Y;
328
329		WaitQueue(7);
330		SET_CURPT((short)x, (short)y);
331		SET_ERR_TERM((short)error);
332		SET_DESTSTP((short)e2, (short)e1);
333		SET_MAJ_AXIS_PCNT((short)len);
334		SET_CMD(cmd);
335	} else {
336		WaitQueue(4);
337		SET_CURPT((short)x, (short)y);
338		SET_MAJ_AXIS_PCNT((short)len-1);
339		SET_CMD(CMD_LINE | DRAW | LINETYPE | WRTDATA | VECDIR_270);
340	}
341}
342
343
344
345static void S3SubsequentSolidHorVertLine(ScrnInfoPtr pScrn,
346					 int x, int y, int len, int dir)
347{
348	if (dir == DEGREES_0)
349		S3SubsequentSolidFillRect(pScrn, x, y, len, 1);
350	else
351		S3SubsequentSolidFillRect(pScrn, x, y, 1, len);
352}
353
354
355#if 0
356
357static void S3SetupForDashedLine(ScrnInfoPtr pScrn,
358                                 int fg, int bg,
359                                 int rop, unsigned int planemask,
360                                 int len, unsigned char *pattern)
361{
362#ifdef S3_NEWMMIO
363	S3Ptr pS3 = S3PTR(pScrn);
364
365	S3SetupForCPUToScreenColorExpandFill(pScrn, bg, fg, rop, planemask);
366#endif
367
368	WaitQueue(4);
369
370	NicePattern = FALSE;
371
372	if (len <= 32) {
373		register CARD32 scratch = DashPattern[LINE_PATTERN_START];
374
375		if (len & (len - 1)) {
376			while (len < 16) {
377				scratch |= (scratch >> len);
378				len <<= 1;
379			}
380			scratch |= (scratch >> len);
381			DashPattern[LINE_PATTERN_START] = scratch;
382		} else {
383			switch (len) {
384				case 2:
385					scratch |= scratch >> 2;
386				case 4:
387					scratch |= scratch >> 4;
388				case 8:
389					scratch |= scratch >> 8;
390				case 16:
391					scratch |= scratch >> 16;
392					DashPattern[LINE_PATTERN_START] = scratch;
393				case 32:
394					NicePattern = TRUE;
395				default:
396					break;
397			}
398		}
399	}
400
401	DashPatternSize = len;
402}
403
404
405static void S3SubsequentDashedBresenhamLine32(ScrnInfoPtr pScrn,
406					      int x, int y,
407					      int absmaj, int absmin,
408					      int err, int len,
409					      int octant, int phase)
410{
411#ifdef S3_NEWMMIO
412	S3Ptr pS3 = S3PTR(pScrn);
413#endif
414	register int count = (len + 31) >> 5;
415	register CARD32 pattern;
416	int error, e1, e2;
417
418	error = absmin + err;
419	e1 = absmaj;
420	e2 = absmin - absmaj;
421
422	if (err) {
423		unsigned short cmd = _32BIT | PLANAR | WRTDATA | DRAW |
424				     PCDATA | LASTPIX | CMD_LINE;
425
426		if (octant & YMAJOR)
427			cmd |= YMAJAXIS;
428		if (!(octant & XDECREASING))
429			cmd |= INC_X;
430		if (!(octant & YDECREASING))
431			cmd |= INC_Y;
432
433		WaitQueue(7);
434		SET_CURPT((short)x, (short)y);
435		SET_ERR_TERM((short)error);
436		SET_DESTSTP((short)e2, (short)e1);
437		SET_MAJ_AXIS_PCNT((short)len);
438		SET_CMD(cmd);
439	} else {
440		if (octant & YMAJOR) {
441			WaitQueue(4);
442			SET_CURPT((short)x, (short)y);
443			SET_MAJ_AXIS_PCNT((short)len - 1);
444
445			if (octant & YDECREASING) {
446				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
447					CMD_LINE | LINETYPE | VECDIR_090);
448			} else {
449				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
450					CMD_LINE | LINETYPE | VECDIR_270);
451			}
452		} else {
453			if (octant & XDECREASING) {
454				WaitQueue(4);
455				SET_CURPT((short)x, (short)y);
456				SET_MAJ_AXIS_PCNT((short)len - 1);
457				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
458					PCDATA | CMD_LINE | LINETYPE | VECDIR_180);
459			} else {
460				WaitQueue(4);
461				SET_CURPT((short)x, (short)y);
462				SET_MAJ_AXIS_PCNT((short)len - 1);
463				SET_CMD(_32BIT | PLANAR | WRTDATA | DRAW |
464					PCDATA | CMD_RECT | INC_Y | INC_X);
465			}
466		}
467	}
468
469	if (NicePattern) {
470#ifdef S3_NEWMMIO
471		register CARD32 *dest = (CARD32*)&IMG_TRANS;
472#endif
473
474		pattern = (phase) ? (DashPattern[LINE_PATTERN_START] << phase) |
475			(DashPattern[LINE_PATTERN_START] >> (32 - phase)) :
476			 DashPattern[LINE_PATTERN_START];
477
478#ifdef S3_NEWMMIO
479		while (count & ~0x03) {
480			dest[0] = dest[1] = dest[2] = dest[3] = pattern;
481			dest += 4;
482			count -= 4;
483		}
484		switch (count) {
485		case 1:
486			dest[0] = pattern;
487			break;
488		case 2:
489			dest[0] = dest[1] = pattern;
490			break;
491		case 3:
492			dest[0] = dest[1] = dest[2] = pattern;
493			break;
494		}
495#else
496
497		while (count--)
498			SET_PIX_TRANS_L(pattern);
499#endif
500	} else if (DashPatternSize < 32) {
501		register int offset = phase;
502
503		while (count--) {
504			SET_PIX_TRANS_L((DashPattern[LINE_PATTERN_START] << offset) |
505				(DashPattern[LINE_PATTERN_START] >>
506				(DashPatternSize - offset)));
507			offset += 32;
508			while (offset > DashPatternSize)
509				offset -= DashPatternSize;
510		}
511	} else {
512		int offset = phase;
513		register unsigned char *srcp = (unsigned char *)(DashPattern) +
514			(MAX_LINE_PATTERN_LENGTH >> 3) - 1;
515		register CARD32 *scratch;
516		int scratch2, shift;
517
518		while (count--) {
519			shift = DashPatternSize - offset;
520			scratch = (CARD32*)(srcp - (offset >> 3) - 3);
521			scratch2 = offset & 0x07;
522
523			if (shift & ~31) {
524				if (scratch2) {
525					pattern = (*scratch << scratch2) |
526						  (*(scratch - 1) >> (32 - scratch2));
527				} else
528					pattern = *scratch;
529			} else {
530				pattern = (*((CARD32*)(srcp - 3)) >> shift) |
531					  (*scratch << scratch2);
532			}
533			SET_PIX_TRANS_L(pattern);
534			offset += 32;
535			while (offset >= DashPatternSize)
536				offset -= DashPatternSize;
537		}
538	}
539}
540
541#endif
542
543#ifdef S3_NEWMMIO
544Bool S3AccelInitNewMMIO(ScreenPtr pScreen)
545#else
546Bool S3AccelInitPIO(ScreenPtr pScreen)
547#endif
548{
549	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
550	S3Ptr pS3 = S3PTR(pScrn);
551	XAAInfoRecPtr pXAA;
552
553	if (pS3->Chipset == PCI_CHIP_968)
554		pS3->ColorExpandBug = TRUE;
555	else
556		pS3->ColorExpandBug = FALSE;
557
558	if (!(pXAA = XAACreateInfoRec()))
559		return FALSE;
560
561	pS3->pXAA = pXAA;
562
563	pXAA->Flags = (PIXMAP_CACHE | OFFSCREEN_PIXMAPS |
564		       LINEAR_FRAMEBUFFER);
565
566	pXAA->Sync = S3Sync;
567
568	pXAA->SetupForSolidFill = S3SetupForSolidFill;
569	pXAA->SubsequentSolidFillRect = S3SubsequentSolidFillRect;
570
571	pXAA->SetupForScreenToScreenCopy = S3SetupForScreenToScreenCopy;
572	pXAA->SubsequentScreenToScreenCopy = S3SubsequentScreenToScreenCopy;
573	pXAA->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
574
575#if 0
576/*
577  8x8 color pattern filling doesn't work properly after introducing
578  framebuffer manager initialization before XAA initialization. There
579  are problems with addressing a colour patterns from offscreen area.
580*/
581	pXAA->SetupForColor8x8PatternFill = S3SetupForColor8x8PatternFill;
582	pXAA->SubsequentColor8x8PatternFillRect = S3SubsequentColor8x8PatternFillRect;
583	pXAA->Color8x8PatternFillFlags = NO_TRANSPARENCY |
584		HARDWARE_PATTERN_SCREEN_ORIGIN |
585		BIT_ORDER_IN_BYTE_MSBFIRST;
586
587	pXAA->CachePixelGranularity = 0;
588#endif
589
590#ifdef S3_NEWMMIO
591	pXAA->SetupForCPUToScreenColorExpandFill =
592		S3SetupForCPUToScreenColorExpandFill;
593	pXAA->SubsequentCPUToScreenColorExpandFill =
594		S3SubsequentCPUToScreenColorExpandFill32;
595	pXAA->ColorExpandBase = (void *) &IMG_TRANS;
596	pXAA->ColorExpandRange = 0x8000;
597	pXAA->CPUToScreenColorExpandFillFlags = CPU_TRANSFER_PAD_DWORD |
598						BIT_ORDER_IN_BYTE_MSBFIRST |
599						SCANLINE_PAD_DWORD;
600#endif
601
602#if 0
603#ifndef S3_NEWMMIO
604	pXAA->ScanlineImageWriteFlags = NO_TRANSPARENCY;
605	pXAA->SetupForScanlineImageWrite =
606		S3SetupForScanlineImageWriteNoMMIO;
607	pXAA->SubsequentScanlineImageWriteRect =
608		S3SubsequentScanlineImageWriteRectNoMMIO;
609	pXAA->SubsequentImageWriteScanline =
610		S3SubsequentImageWriteScanlineNoMMIO;
611	pXAA->NumScanlineImageWriteBuffers = 1;
612	pXAA->ScanlineImageWriteBuffers = &pS3->imageBuffer;
613#endif
614#endif
615
616	pXAA->SetupForSolidLine = S3SetupForSolidLine;
617	pXAA->SubsequentSolidBresenhamLine = S3SubsequentSolidBresenhamLine;
618	pXAA->SubsequentSolidHorVertLine = S3SubsequentSolidHorVertLine;
619	pXAA->SolidBresenhamLineErrorTermBits = 12;
620#if 0
621	/* kinda buggy...  and its faster without it */
622	pXAA->SetupForDashedLine = S3SetupForDashedLine;
623	pXAA->SubsequentDashedBresenhamLine = S3SubsequentDashedBresenhamLine32;
624	pXAA->DashPatternMaxLength = MAX_LINE_PATTERN_LENGTH;
625#endif
626
627	return XAAInit(pScreen, pXAA);
628}
629