smi_xaa.c revision 09885543
1/*
2Copyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
3Copyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9of the Software, and to permit persons to whom the Software is furnished to do
10so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
17NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the names of the XFree86 Project and
23Silicon Motion shall not be used in advertising or otherwise to promote the
24sale, use or other dealings in this Software without prior written
25authorization from the XFree86 Project and silicon Motion.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "smi.h"
33
34#include "miline.h"
35#include "xaalocal.h"
36#include "xaarop.h"
37#include "servermd.h"
38
39static void SMI_SetupForScreenToScreenCopy(ScrnInfoPtr, int, int, int,
40					   unsigned int, int);
41static void SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr, int, int, int, int,
42					     int, int);
43static void SMI_SetupForSolidFill(ScrnInfoPtr, int, int, unsigned);
44static void SMI_SubsequentSolidFillRect(ScrnInfoPtr, int, int, int, int);
45static void SMI_SubsequentSolidHorVertLine(ScrnInfoPtr, int, int, int, int);
46static void SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int,
47						   unsigned int);
48static void SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr, int, int, int,
49						     int, int);
50static void SMI_SetupForMono8x8PatternFill(ScrnInfoPtr, int, int, int, int, int,
51					   unsigned int);
52static void SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr, int, int, int,
53						 int, int, int);
54static void SMI_SetupForColor8x8PatternFill(ScrnInfoPtr, int, int, int,
55					    unsigned int, int);
56static void SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr, int, int, int,
57						  int, int, int);
58#if SMI_USE_IMAGE_WRITES
59static void SMI_SetupForImageWrite(ScrnInfoPtr, int, unsigned int, int, int,
60				   int);
61static void SMI_SubsequentImageWriteRect(ScrnInfoPtr, int, int, int, int, int);
62#endif
63/* #671 */
64static void SMI_ValidatePolylines(GCPtr, unsigned long, DrawablePtr);
65static void SMI_Polylines(DrawablePtr, GCPtr, int, int, DDXPointPtr);
66
67
68Bool
69SMI_XAAInit(ScreenPtr pScreen)
70{
71    XAAInfoRecPtr infoPtr;
72    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
73    SMIPtr pSmi = SMIPTR(pScrn);
74    /*BoxRec AvailFBArea;*/
75    Bool ret;
76    /*int numLines, maxLines;*/
77
78    ENTER_PROC("SMI_XAAInit");
79
80    pSmi->XAAInfoRec = infoPtr = XAACreateInfoRec();
81    if (infoPtr == NULL) {
82	LEAVE_PROC("SMI_AccelInit");
83	return FALSE;
84    }
85
86    infoPtr->Flags = PIXMAP_CACHE
87		   | LINEAR_FRAMEBUFFER
88		   | OFFSCREEN_PIXMAPS;
89
90    infoPtr->Sync = SMI_AccelSync;
91
92    /* Screen to screen copies */
93    infoPtr->ScreenToScreenCopyFlags = NO_PLANEMASK
94				     | ONLY_TWO_BITBLT_DIRECTIONS;
95    infoPtr->SetupForScreenToScreenCopy = SMI_SetupForScreenToScreenCopy;
96    infoPtr->SubsequentScreenToScreenCopy = SMI_SubsequentScreenToScreenCopy;
97    if (pScrn->bitsPerPixel == 24) {
98	infoPtr->ScreenToScreenCopyFlags |= NO_TRANSPARENCY;
99    }
100    if ((pSmi->Chipset == SMI_LYNX3D) && (pScrn->bitsPerPixel == 8)) {
101	infoPtr->ScreenToScreenCopyFlags |= GXCOPY_ONLY;
102    }
103
104    /* Solid Fills */
105    infoPtr->SolidFillFlags = NO_PLANEMASK;
106    infoPtr->SetupForSolidFill = SMI_SetupForSolidFill;
107    infoPtr->SubsequentSolidFillRect = SMI_SubsequentSolidFillRect;
108
109    /* Solid Lines */
110    infoPtr->SolidLineFlags = NO_PLANEMASK;
111    infoPtr->SetupForSolidLine = SMI_SetupForSolidFill;
112    infoPtr->SubsequentSolidHorVertLine = SMI_SubsequentSolidHorVertLine;
113
114    /* Color Expansion Fills */
115    infoPtr->CPUToScreenColorExpandFillFlags = ROP_NEEDS_SOURCE
116					     | NO_PLANEMASK
117					     | BIT_ORDER_IN_BYTE_MSBFIRST
118					     | LEFT_EDGE_CLIPPING
119					     | CPU_TRANSFER_PAD_DWORD
120					     | SCANLINE_PAD_DWORD;
121    infoPtr->ColorExpandBase = pSmi->DataPortBase;
122    infoPtr->ColorExpandRange = pSmi->DataPortSize;
123    infoPtr->SetupForCPUToScreenColorExpandFill =
124	    SMI_SetupForCPUToScreenColorExpandFill;
125    infoPtr->SubsequentCPUToScreenColorExpandFill =
126	    SMI_SubsequentCPUToScreenColorExpandFill;
127
128    /* 8x8 Mono Pattern Fills */
129    infoPtr->Mono8x8PatternFillFlags = NO_PLANEMASK
130				     | HARDWARE_PATTERN_PROGRAMMED_BITS
131				     | HARDWARE_PATTERN_SCREEN_ORIGIN
132				     | BIT_ORDER_IN_BYTE_MSBFIRST;
133    infoPtr->SetupForMono8x8PatternFill = SMI_SetupForMono8x8PatternFill;
134    infoPtr->SubsequentMono8x8PatternFillRect =
135	SMI_SubsequentMono8x8PatternFillRect;
136
137    /* 8x8 Color Pattern Fills */
138    if (!SMI_LYNX3D_SERIES(pSmi->Chipset) || (pScrn->bitsPerPixel != 24)) {
139	infoPtr->Color8x8PatternFillFlags = NO_PLANEMASK
140					  | HARDWARE_PATTERN_SCREEN_ORIGIN;
141	infoPtr->SetupForColor8x8PatternFill =
142		SMI_SetupForColor8x8PatternFill;
143	infoPtr->SubsequentColor8x8PatternFillRect =
144		SMI_SubsequentColor8x8PatternFillRect;
145    }
146
147#if SMI_USE_IMAGE_WRITES
148    /* Image Writes */
149    infoPtr->ImageWriteFlags = ROP_NEEDS_SOURCE
150			     | NO_PLANEMASK
151			     | CPU_TRANSFER_PAD_DWORD
152			     | SCANLINE_PAD_DWORD;
153    infoPtr->ImageWriteBase = pSmi->DataPortBase;
154    infoPtr->ImageWriteRange = pSmi->DataPortSize;
155    infoPtr->SetupForImageWrite = SMI_SetupForImageWrite;
156    infoPtr->SubsequentImageWriteRect = SMI_SubsequentImageWriteRect;
157#endif
158
159    /* Clipping */
160    infoPtr->ClippingFlags = HARDWARE_CLIP_SCREEN_TO_SCREEN_COPY
161			   | HARDWARE_CLIP_MONO_8x8_FILL
162			   | HARDWARE_CLIP_COLOR_8x8_FILL
163			   | HARDWARE_CLIP_SOLID_FILL
164			   | HARDWARE_CLIP_SOLID_LINE
165			   | HARDWARE_CLIP_DASHED_LINE;
166    infoPtr->SetClippingRectangle = SMI_SetClippingRectangle;
167    infoPtr->DisableClipping = SMI_DisableClipping;
168
169    /* Pixmap Cache */
170    if (pScrn->bitsPerPixel == 24) {
171	infoPtr->CachePixelGranularity = 16;
172    } else {
173	infoPtr->CachePixelGranularity = 128 / pScrn->bitsPerPixel;
174    }
175
176    /* Offscreen Pixmaps */
177    infoPtr->maxOffPixWidth  = 4096;
178    infoPtr->maxOffPixHeight = 4096;
179    if (pScrn->bitsPerPixel == 24) {
180	infoPtr->maxOffPixWidth = 4096 / 3;
181
182	if (pSmi->Chipset == SMI_LYNX) {
183	    infoPtr->maxOffPixHeight = 4096 / 3;
184	}
185    }
186
187    SMI_EngineReset(pScrn);
188
189
190    /* CZ 18.06.2001: moved to smi_driver.c before the NoAccel question
191       to have offscreen framebuffer in NoAccel mode */
192#if 0
193    maxLines = pSmi->FBReserved / (pSmi->width * pSmi->Bpp);
194    if (pSmi->rotate) {
195	numLines = maxLines;
196    } else {
197#if SMI_USE_VIDEO
198	numLines = ((pSmi->FBReserved - pSmi->width * pSmi->Bpp * pSmi->height)
199		   * 25 / 100 + pSmi->width * pSmi->Bpp - 1)
200		   / (pSmi->width * pSmi->Bpp);
201	numLines += pSmi->height;
202#else
203	numLines = maxLines;
204#endif
205    }
206
207    AvailFBArea.x1 = 0;
208    AvailFBArea.y1 = 0;
209    AvailFBArea.x2 = pSmi->width;
210    AvailFBArea.y2 = numLines;
211    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FrameBuffer Box: %d,%d - %d,%d\n",
212		AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2, AvailFBArea.y2);
213    xf86InitFBManager(pScreen, &AvailFBArea);
214#endif
215
216    ret = XAAInit(pScreen, infoPtr);
217    if (ret && pSmi->shadowFB)	/* #671 */ {
218	pSmi->ValidatePolylines = infoPtr->ValidatePolylines;
219	infoPtr->ValidatePolylines = SMI_ValidatePolylines;
220    }
221
222    LEAVE_PROC("SMI_XAAInit");
223    return ret;
224}
225
226/******************************************************************************/
227/*	Screen to Screen Copies						      */
228/******************************************************************************/
229
230static void
231SMI_SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
232			       unsigned int planemask, int trans)
233{
234    SMIPtr pSmi = SMIPTR(pScrn);
235
236    ENTER_PROC("SMI_SetupForScreenToScreenCopy");
237    DEBUG((VERBLEV, "xdir=%d ydir=%d rop=%02X trans=%08X\n", xdir, ydir,
238	   rop, trans));
239
240    pSmi->AccelCmd = XAAGetCopyROP(rop)
241		   | SMI_BITBLT
242		   | SMI_START_ENGINE;
243
244    if ((xdir == -1) || (ydir == -1)) {
245	pSmi->AccelCmd |= SMI_RIGHT_TO_LEFT;
246    }
247
248    if (trans != -1) {
249	pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
250	WaitQueue(1);
251	WRITE_DPR(pSmi, 0x20, trans);
252    }
253
254    if (pSmi->ClipTurnedOn) {
255	WaitQueue(1);
256	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
257	pSmi->ClipTurnedOn = FALSE;
258    }
259
260    LEAVE_PROC("SMI_SetupForScreenToScreenCopy");
261}
262
263static void
264SMI_SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, int x2,
265				 int y2, int w, int h)
266{
267    SMIPtr pSmi = SMIPTR(pScrn);
268
269    ENTER_PROC("SMI_SubsequentScreenToScreenCopy");
270    DEBUG((VERBLEV, "x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n", x1, y1, x2, y2, w, h));
271
272    if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
273	x1 += w - 1;
274	y1 += h - 1;
275	x2 += w - 1;
276	y2 += h - 1;
277    }
278
279    if (pScrn->bitsPerPixel == 24) {
280	x1 *= 3;
281	x2 *= 3;
282	w  *= 3;
283
284	if (pSmi->Chipset == SMI_LYNX) {
285	    y1 *= 3;
286	    y2 *= 3;
287	}
288
289	if (pSmi->AccelCmd & SMI_RIGHT_TO_LEFT) {
290	    x1 += 2;
291	    x2 += 2;
292	}
293    }
294
295    WaitQueue(4);
296    WRITE_DPR(pSmi, 0x00, (x1 << 16) + (y1 & 0xFFFF));
297    WRITE_DPR(pSmi, 0x04, (x2 << 16) + (y2 & 0xFFFF));
298    WRITE_DPR(pSmi, 0x08, (w  << 16) + (h  & 0xFFFF));
299    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
300
301    LEAVE_PROC("SMI_SubsequentScreenToScreenCopy");
302}
303
304/******************************************************************************/
305/*   Solid Fills							      */
306/******************************************************************************/
307
308static void
309SMI_SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
310		      unsigned int planemask)
311{
312    SMIPtr pSmi = SMIPTR(pScrn);
313
314    ENTER_PROC("SMI_SetupForSolidFill");
315    DEBUG((VERBLEV, "color=%08X rop=%02X\n", color, rop));
316
317    pSmi->AccelCmd = XAAGetPatternROP(rop)
318		   | SMI_BITBLT
319		   | SMI_START_ENGINE;
320
321    if (pSmi->ClipTurnedOn) {
322	WaitQueue(4);
323	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
324	pSmi->ClipTurnedOn = FALSE;
325    } else {
326	WaitQueue(3);
327    }
328    WRITE_DPR(pSmi, 0x14, color);
329    WRITE_DPR(pSmi, 0x34, 0xFFFFFFFF);
330    WRITE_DPR(pSmi, 0x38, 0xFFFFFFFF);
331
332    LEAVE_PROC("SMI_SetupForSolidFill");
333}
334
335void
336SMI_SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
337{
338    SMIPtr pSmi = SMIPTR(pScrn);
339
340    ENTER_PROC("SMI_SubsequentSolidFillRect");
341    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
342
343    if (pScrn->bitsPerPixel == 24) {
344	x *= 3;
345	w *= 3;
346
347	if (pSmi->Chipset == SMI_LYNX) {
348	    y *= 3;
349	}
350    }
351
352    WaitQueue(3);
353    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
354    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
355    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
356
357    LEAVE_PROC("SMI_SubsequentSolidFillRect");
358}
359
360/******************************************************************************/
361/*   Solid Lines							      */
362/******************************************************************************/
363
364static void
365SMI_SubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len,
366							   int dir)
367{
368    SMIPtr pSmi = SMIPTR(pScrn);
369    int w, h;
370
371    ENTER_PROC("SMI_SubsequentSolidHorVertLine");
372    DEBUG((VERBLEV, "x=%d y=%d len=%d dir=%d\n", x, y, len, dir));
373
374    if (dir == DEGREES_0) {
375	w = len;
376	h = 1;
377    } else {
378	w = 1;
379	h = len;
380    }
381
382    if (pScrn->bitsPerPixel == 24) {
383	x *= 3;
384	w *= 3;
385
386	if (pSmi->Chipset == SMI_LYNX) {
387	    y *= 3;
388	}
389    }
390
391    WaitQueue(3);
392    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
393    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
394    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
395
396    LEAVE_PROC("SMI_SubsequentSolidHorVertLine");
397}
398
399/******************************************************************************/
400/*  Color Expansion Fills						      */
401/******************************************************************************/
402
403static void
404SMI_SetupForCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int fg, int bg,
405				       int rop, unsigned int planemask)
406{
407    SMIPtr pSmi = SMIPTR(pScrn);
408
409    ENTER_PROC("SMI_SetupForCPUToScreenColorExpandFill");
410    DEBUG((VERBLEV, "fg=%08X bg=%08X rop=%02X\n", fg, bg, rop));
411
412    pSmi->AccelCmd = XAAGetCopyROP(rop)
413		   | SMI_HOSTBLT_WRITE
414		   | SMI_SRC_MONOCHROME
415		   | SMI_START_ENGINE;
416
417    if (bg == -1) {
418	pSmi->AccelCmd |= SMI_TRANSPARENT_SRC;
419
420	WaitQueue(3);
421	WRITE_DPR(pSmi, 0x14, fg);
422	WRITE_DPR(pSmi, 0x18, ~fg);
423	WRITE_DPR(pSmi, 0x20, fg);
424    } else {
425	WaitQueue(2);
426	WRITE_DPR(pSmi, 0x14, fg);
427	WRITE_DPR(pSmi, 0x18, bg);
428    }
429
430    LEAVE_PROC("SMI_SetupForCPUToScreenColorExpandFill");
431}
432
433void
434SMI_SubsequentCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x, int y, int w,
435					 int h, int skipleft)
436{
437    SMIPtr pSmi = SMIPTR(pScrn);
438
439    ENTER_PROC("SMI_SubsequentCPUToScreenColorExpandFill");
440    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft));
441
442    if (pScrn->bitsPerPixel == 24) {
443	x        *= 3;
444	w        *= 3;
445	skipleft *= 3;
446
447	if (pSmi->Chipset == SMI_LYNX) {
448	    y *= 3;
449	}
450    }
451
452    if (skipleft) {
453	WaitQueue(5);
454	WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000)
455			      | (x + skipleft) | 0x2000);
456	pSmi->ClipTurnedOn = TRUE;
457    } else {
458	if (pSmi->ClipTurnedOn) {
459	    WaitQueue(5);
460	    WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
461	    pSmi->ClipTurnedOn = FALSE;
462	} else {
463	    WaitQueue(4);
464	}
465    }
466    WRITE_DPR(pSmi, 0x00, 0);
467    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
468    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
469    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
470
471    LEAVE_PROC("SMI_SubsequentCPUToScreenColorExpandFill");
472}
473
474/******************************************************************************/
475/* 8x8 Mono Pattern Fills						      */
476/******************************************************************************/
477
478static void
479SMI_SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int fg,
480			       int bg, int rop, unsigned int planemask)
481{
482    SMIPtr pSmi = SMIPTR(pScrn);
483
484    ENTER_PROC("SMI_SetupForMono8x8PatternFill");
485    DEBUG((VERBLEV, "patx=%08X paty=%08X fg=%08X bg=%08X rop=%02X\n", patx,
486	   paty, fg, bg, rop));
487
488    pSmi->AccelCmd = XAAGetPatternROP(rop)
489		   | SMI_BITBLT
490		   | SMI_START_ENGINE;
491
492    if (pSmi->ClipTurnedOn) {
493	WaitQueue(1);
494	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
495	pSmi->ClipTurnedOn = FALSE;
496    }
497
498    if (bg == -1) {
499	WaitQueue(5);
500	WRITE_DPR(pSmi, 0x14, fg);
501	WRITE_DPR(pSmi, 0x18, ~fg);
502	WRITE_DPR(pSmi, 0x20, fg);
503	WRITE_DPR(pSmi, 0x34, patx);
504	WRITE_DPR(pSmi, 0x38, paty);
505    } else {
506	WaitQueue(4);
507	WRITE_DPR(pSmi, 0x14, fg);
508	WRITE_DPR(pSmi, 0x18, bg);
509	WRITE_DPR(pSmi, 0x34, patx);
510	WRITE_DPR(pSmi, 0x38, paty);
511    }
512
513    LEAVE_PROC("SMI_SetupForMono8x8PatternFill");
514}
515
516static void
517SMI_SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
518				     int x, int y, int w, int h)
519{
520    SMIPtr pSmi = SMIPTR(pScrn);
521
522    ENTER_PROC("SMI_SubsequentMono8x8PatternFillRect");
523    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
524
525    if (pScrn->bitsPerPixel == 24) {
526	x *= 3;
527	w *= 3;
528	if (pSmi->Chipset == SMI_LYNX) {
529	    y *= 3;
530	}
531    }
532
533    WaitQueue(3);
534    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
535    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
536    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
537
538    LEAVE_PROC("SMI_SubsequentMono8x8PatternFillRect");
539}
540
541/******************************************************************************/
542/* 8x8 Color Pattern Fills						      */
543/******************************************************************************/
544
545static void
546SMI_SetupForColor8x8PatternFill(ScrnInfoPtr pScrn, int patx, int paty, int rop,
547				unsigned int planemask, int trans_color)
548{
549    SMIPtr pSmi = SMIPTR(pScrn);
550
551    ENTER_PROC("SMI_SetupForColor8x8PatternFill");
552    DEBUG((VERBLEV, "patx=%d paty=%d rop=%02X trans_color=%08X\n", patx, paty,
553	   rop, trans_color));
554
555    pSmi->AccelCmd = XAAGetPatternROP(rop)
556		   | SMI_BITBLT
557		   | SMI_COLOR_PATTERN
558		   | SMI_START_ENGINE;
559
560    if (pScrn->bitsPerPixel <= 16) {
561	/* PDR#950 */
562	CARD8* pattern = pSmi->FBBase + (patx + paty * pSmi->Stride) * pSmi->Bpp;
563
564	WaitIdleEmpty();
565	WRITE_DPR(pSmi, 0x0C, SMI_BITBLT | SMI_COLOR_PATTERN);
566	memcpy(pSmi->DataPortBase, pattern, 8 * pSmi->Bpp * 8);
567    } else {
568	if (pScrn->bitsPerPixel == 24) {
569	    patx *= 3;
570
571	    if (pSmi->Chipset == SMI_LYNX) {
572		paty *= 3;
573	    }
574	}
575
576	WaitQueue(1);
577	WRITE_DPR(pSmi, 0x00, (patx << 16) | (paty & 0xFFFF));
578    }
579
580    if (trans_color == -1) {
581	pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
582
583	WaitQueue(1);
584	WRITE_DPR(pSmi, 0x20, trans_color);
585    }
586
587    if (pSmi->ClipTurnedOn) {
588	WaitQueue(1);
589	WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
590	pSmi->ClipTurnedOn = FALSE;
591    }
592
593    LEAVE_PROC("SMI_SetupForColor8x8PatternFill");
594}
595
596static void
597SMI_SubsequentColor8x8PatternFillRect(ScrnInfoPtr pScrn, int patx, int paty,
598				      int x, int y, int w, int h)
599{
600    SMIPtr pSmi = SMIPTR(pScrn);
601
602    ENTER_PROC("SMI_SubsequentColor8x8PatternFillRect");
603    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d\n", x, y, w, h));
604
605    if (pScrn->bitsPerPixel == 24) {
606	x *= 3;
607	w *= 3;
608
609	if (pSmi->Chipset == SMI_LYNX) {
610	    y *= 3;
611	}
612    }
613
614    WaitQueue(3);
615    WRITE_DPR(pSmi, 0x04, (x << 16) | (y & 0xFFFF));
616    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));	/* PDR#950 */
617    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
618
619    LEAVE_PROC("SMI_SubsequentColor8x8PatternFillRect");
620}
621
622#if SMI_USE_IMAGE_WRITES
623/******************************************************************************/
624/*  Image Writes							      */
625/******************************************************************************/
626
627static void
628SMI_SetupForImageWrite(ScrnInfoPtr pScrn, int rop, unsigned int planemask,
629		       int trans_color, int bpp, int depth)
630{
631    SMIPtr pSmi = SMIPTR(pScrn);
632
633    ENTER_PROC("SMI_SetupForImageWrite");
634    DEBUG((VERBLEV, "rop=%02X trans_color=%08X bpp=%d depth=%d\n", rop,
635	   trans_color, bpp, depth));
636
637    pSmi->AccelCmd = XAAGetCopyROP(rop)
638		   | SMI_HOSTBLT_WRITE
639		   | SMI_START_ENGINE;
640
641    if (trans_color != -1) {
642	pSmi->AccelCmd |= SMI_TRANSPARENT_SRC | SMI_TRANSPARENT_PXL;
643
644	WaitQueue(1);
645	WRITE_DPR(pSmi, 0x20, trans_color);
646    }
647
648    LEAVE_PROC("SMI_SetupForImageWrite");
649}
650
651static void
652SMI_SubsequentImageWriteRect(ScrnInfoPtr pScrn, int x, int y, int w, int h,
653			     int skipleft)
654{
655    SMIPtr pSmi = SMIPTR(pScrn);
656
657    ENTER_PROC("SMI_SubsequentImageWriteRect");
658    DEBUG((VERBLEV, "x=%d y=%d w=%d h=%d skipleft=%d\n", x, y, w, h, skipleft));
659
660    if (pScrn->bitsPerPixel == 24) {
661	x        *= 3;
662	w        *= 3;
663	skipleft *= 3;
664
665	if (pSmi->Chipset == SMI_LYNX) {
666	    y *= 3;
667	}
668    }
669
670    if (skipleft) {
671	WaitQueue(5);
672	WRITE_DPR(pSmi, 0x2C, (pSmi->ScissorsLeft & 0xFFFF0000) |
673			      (x + skipleft) | 0x2000);
674	pSmi->ClipTurnedOn = TRUE;
675    } else {
676	if (pSmi->ClipTurnedOn) {
677	    WaitQueue(5);
678	    WRITE_DPR(pSmi, 0x2C, pSmi->ScissorsLeft);
679	    pSmi->ClipTurnedOn = FALSE;
680	} else {
681	    WaitQueue(4);
682	}
683    }
684    WRITE_DPR(pSmi, 0x00, 0);
685    WRITE_DPR(pSmi, 0x04, (x << 16) | (y * 0xFFFF));
686    WRITE_DPR(pSmi, 0x08, (w << 16) | (h & 0xFFFF));
687    WRITE_DPR(pSmi, 0x0C, pSmi->AccelCmd);
688
689    LEAVE_PROC("SMI_SubsequentImageWriteRect");
690}
691#endif
692
693/******************************************************************************/
694/*  Polylines							         #671 */
695/******************************************************************************/
696
697/*
698
699In order to speed up the "logout" screen in rotated modes, we need to intercept
700the Polylines function. Normally, the polylines are drawn and the shadowFB is
701then sending a request of the bounding rectangle of those poylines. This should
702be okay, if it weren't for the fact that the Gnome logout screen is drawing
703polylines in rectangles and this asks for a rotation of the entire rectangle.
704This is very slow.
705
706To circumvent this slowness, we intercept the ValidatePolylines function and
707override the default "Fallback" Polylines with our own Polylines function. Our
708Polylines function first draws the polylines through the original Fallback
709function and then rotates the lines, line by line. We then set a flag and
710return control to the shadowFB which will try to rotate the bounding rectangle.
711However, the flag has been set and the RefreshArea function does nothing but
712clear the flag so the next Refresh that comes in shoiuld be handled correctly.
713
714All this code improves the speed quite a bit.
715
716*/
717
718#define IS_VISIBLE(pWin) \
719( \
720    pScrn->vtSema \
721    && (((WindowPtr) pWin)->visibility != VisibilityFullyObscured) \
722)
723
724#define TRIM_BOX(box, pGC) \
725{ \
726    BoxPtr extents = &pGC->pCompositeClip->extents; \
727    if (box.x1 < extents->x1) box.x1 = extents->x1; \
728    if (box.y1 < extents->y1) box.y1 = extents->y1; \
729    if (box.x2 > extents->x2) box.x2 = extents->x2; \
730    if (box.y2 > extents->y2) box.y2 = extents->y2; \
731}
732
733#define TRANSLATE_BOX(box, pDraw) \
734{ \
735    box.x1 += pDraw->x; \
736    box.y1 += pDraw->y; \
737    box.x2 += pDraw->x; \
738    box.y2 += pDraw->y; \
739}
740
741#define BOX_NOT_EMPTY(box) \
742    ((box.x2 > box.x1) && (box.y2 > box.y1))
743
744static void
745SMI_ValidatePolylines(GCPtr pGC, unsigned long changes, DrawablePtr pDraw)
746{
747    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
748    SMIPtr pSmi = SMIPTR(infoRec->pScrn);
749
750    ENTER_PROC("SMI_ValidatePolylines");
751
752    pSmi->ValidatePolylines(pGC, changes, pDraw);
753    if (pGC->ops->Polylines == XAAGetFallbackOps()->Polylines) {
754	/* Override the Polylines function with our own Polylines function. */
755	pGC->ops->Polylines = SMI_Polylines;
756    }
757
758    LEAVE_PROC("SMI_ValidatePolylines");
759}
760
761static void
762SMI_Polylines(DrawablePtr pDraw, GCPtr pGC, int mode, int npt,
763	      DDXPointPtr pptInit)
764{
765    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_GC(pGC);
766    ScrnInfoPtr pScrn = infoRec->pScrn;
767    SMIPtr pSmi = SMIPTR(pScrn);
768
769    ENTER_PROC("SMI_Polylines");
770
771    /* Call the original Polylines function. */
772    pGC->ops->Polylines = XAAGetFallbackOps()->Polylines;
773    (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
774    pGC->ops->Polylines = SMI_Polylines;
775
776    if (IS_VISIBLE(pDraw) && npt) {
777	/* Allocate a temporary buffer for all segments of the polyline. */
778	BoxPtr pBox = xnfcalloc(sizeof(BoxRec), npt);
779	int extra = pGC->lineWidth >> 1, box;
780
781	if (npt > 1) {
782	    /* Adjust the extra space required per polyline segment. */
783	    if (pGC->joinStyle == JoinMiter) {
784		extra = 6 * pGC->lineWidth;
785	    } else if (pGC->capStyle == CapProjecting) {
786		extra = pGC->lineWidth;
787	    }
788	}
789
790	for (box = 0; --npt;) {
791	    /* Setup the bounding box for one polyline segment. */
792	    pBox[box].x1 = pptInit->x;
793	    pBox[box].y1 = pptInit->y;
794	    pptInit++;
795	    pBox[box].x2 = pptInit->x;
796	    pBox[box].y2 = pptInit->y;
797	    if (mode == CoordModePrevious) {
798		pBox[box].x2 += pBox[box].x1;
799		pBox[box].y2 += pBox[box].y1;
800	    }
801
802	    /* Sort coordinates. */
803	    if (pBox[box].x1 > pBox[box].x2) {
804		int tmp = pBox[box].x1;
805		pBox[box].x1 = pBox[box].x2;
806		pBox[box].x2 = tmp;
807	    }
808	    if (pBox[box].y1 > pBox[box].y2) {
809		int tmp = pBox[box].y1;
810		pBox[box].y1 = pBox[box].y2;
811		pBox[box].y2 = tmp;
812	    }
813
814	    /* Add extra space required for each polyline segment. */
815	    pBox[box].x1 -= extra;
816	    pBox[box].y1 -= extra;
817	    pBox[box].x2 += extra + 1;
818	    pBox[box].y2 += extra + 1;
819
820	    /* See if we need to draw this polyline segment. */
821	    TRANSLATE_BOX(pBox[box], pDraw);
822	    TRIM_BOX(pBox[box], pGC);
823	    if (BOX_NOT_EMPTY(pBox[box])) {
824		box++;
825	    }
826	}
827
828	if (box) {
829	    /* Refresh all polyline segments now. */
830	    if (pSmi->Chipset == SMI_COUGAR3DR) {
831		SMI_RefreshArea730(pScrn, box, pBox);
832	    } else {
833		SMI_RefreshArea(pScrn, box, pBox);
834	    }
835	}
836
837	/* Free the temporary buffer. */
838	xfree(pBox);
839    }
840
841    pSmi->polyLines = TRUE;
842    LEAVE_PROC("SMI_Polylines");
843}
844
845