pm3_accel.c revision 1fb744b4
1/*
2 * Copyright 2000-2001 by Sven Luther <luther@dpt-info.u-strasbg.fr>.
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 Sven Luther not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Sven Luther 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 * SVEN LUTHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL SVEN LUTHER 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:  Sven Luther, <luther@dpt-info.u-strasbg.fr>
23 *           Alan Hourihane, <alanh@fairlite.demon.co.uk>
24 *
25 * this work is sponsored by Appian Graphics.
26 *
27 * Permedia 3 accelerated options.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <X11/Xarch.h>
35#include "xf86.h"
36#include "xf86_OSproc.h"
37
38#include "xf86Pci.h"
39
40#include "miline.h"
41
42#include "fb.h"
43
44#include "glint_regs.h"
45#include "pm3_regs.h"
46#include "glint.h"
47
48#ifdef HAVE_XAA_H
49#include "xaalocal.h"		/* For replacements */
50
51#define DEBUG 0
52
53#if DEBUG
54# define TRACE_ENTER(str)       ErrorF("pm3_accel: " str " %d\n",pScrn->scrnIndex)
55# define TRACE_EXIT(str)        ErrorF("pm3_accel: " str " done\n")
56# define TRACE(str)             ErrorF("pm3_accel trace: " str "\n")
57#else
58# define TRACE_ENTER(str)
59# define TRACE_EXIT(str)
60# define TRACE(str)
61#endif
62
63#define PM3_WRITEMASK \
64  (pGlint->PM3_UsingSGRAM ? PM3FBHardwareWriteMask : PM3FBSoftwareWriteMask )
65#define PM3_OTHERWRITEMASK \
66  (pGlint->PM3_UsingSGRAM ? PM3FBSoftwareWriteMask : PM3FBHardwareWriteMask )
67
68#define PM3_PLANEMASK(planemask)				\
69{ 								\
70	if (planemask != pGlint->planemask) {			\
71		pGlint->planemask = planemask;			\
72		REPLICATE(planemask); 				\
73		GLINT_WRITE_REG(planemask, PM3_WRITEMASK);	\
74	}							\
75}
76
77/* Clipping */
78static void Permedia3SetClippingRectangle(ScrnInfoPtr pScrn, int x, int y,
79				int w, int h);
80static void Permedia3DisableClipping(ScrnInfoPtr pScrn);
81/* ScreenToScreenCopy */
82static void Permedia3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn,
83				int x1, int y1, int x2,
84				int y2, int w, int h);
85static void Permedia3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
86				int xdir, int ydir, int rop,
87                                unsigned int planemask,
88				int transparency_color);
89/* SolidFill */
90static void Permedia3SetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
91				int rop, unsigned int planemask);
92static void Permedia3SubsequentFillRectSolid(ScrnInfoPtr pScrn, int x,
93				int y, int w, int h);
94static void Permedia3SubsequentFillRectSolid32bpp(ScrnInfoPtr pScrn, int x,
95				int y, int w, int h);
96/* 8x8 Mono Pattern Fills */
97static void Permedia3SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
98				int patternx, int patterny, int fg, int bg,
99				int rop, unsigned int planemask);
100static void Permedia3SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
101				int x_offset, int y_offset, int x, int y,
102				int w, int h);
103static void Permedia3SetupForScanlineCPUToScreenColorExpandFill(
104				ScrnInfoPtr pScrn,
105				int fg, int bg, int rop,
106				unsigned int planemask);
107static void Permedia3SubsequentScanlineCPUToScreenColorExpandFill(
108				ScrnInfoPtr pScrn, int x,
109				int y, int w, int h, int skipleft);
110static void Permedia3SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno);
111static void Permedia3SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
112				unsigned int planemask, int trans_color,
113				int bpp, int depth);
114static void Permedia3SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
115				int x, int y, int w, int h, int skipleft);
116static void Permedia3SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno);
117static void Permedia3RestoreAccelState(ScrnInfoPtr pScrn);
118static void Permedia3WritePixmap(ScrnInfoPtr pScrn, int x, int y, int w, int h,
119				unsigned char *src, int srcwidth, int rop,
120				unsigned int planemask, int transparency_color,
121				int bpp, int depth);
122static void Permedia3WriteBitmap(ScrnInfoPtr pScrn, int x, int y, int w, int h,
123				unsigned char *src, int srcwidth, int skipleft,
124				int fg, int bg, int rop,unsigned int planemask);
125
126void
127Permedia3InitializeEngine(ScrnInfoPtr pScrn)
128{
129    GLINTPtr pGlint = GLINTPTR(pScrn);
130    int colorformat = 0;
131
132    /* Initialize the Accelerator Engine to defaults */
133    TRACE_ENTER("Permedia3InitializeEngine");
134
135    if ((IS_J2000) && (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)) {
136	GLINT_SLOW_WRITE_REG(pGlint->MultiIndex, BroadcastMask);
137    }
138    if (pGlint->MultiAperture) {
139	ErrorF("pm3_accel: SVEN : multiAperture set\n");
140    	/* Only write the following register to the first PM3 */
141    	GLINT_SLOW_WRITE_REG(1, BroadcastMask);
142    	GLINT_SLOW_WRITE_REG(0x00000001,    ScanLineOwnership);
143
144    	/* Only write the following register to the second PM3 */
145    	GLINT_SLOW_WRITE_REG(2, BroadcastMask);
146    	GLINT_SLOW_WRITE_REG(0x00000005,    ScanLineOwnership);
147
148    	/* Make sure the rest of the register writes go to both PM3's */
149    	GLINT_SLOW_WRITE_REG(3, BroadcastMask);
150    }
151
152    /* Disable LocalBuffer. Fixes stripes problems when
153     * doing screen-to-screen copies */
154    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3LBDestReadMode);
155    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3LBDestReadEnables);
156    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3LBSourceReadMode);
157    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3LBWriteMode);
158
159    /* Host out PreInit */
160    /* Set filter mode to enable sync tag & data output */
161    GLINT_SLOW_WRITE_REG(0x400,		FilterMode);
162    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, StatisticMode);
163    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3DeltaMode);
164    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, RasterizerMode);
165    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, ScissorMode);
166    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, LineStippleMode);
167    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, AreaStippleMode);
168    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3GIDMode);
169    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, DepthMode);
170    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, StencilMode);
171    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, ColorDDAMode);
172    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3TextureCoordMode);
173    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3TextureIndexMode0);
174    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3TextureIndexMode1);
175    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, TextureReadMode);
176    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3LUTMode);
177    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, TextureFilterMode);
178    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3TextureCompositeMode);
179    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3TextureApplicationMode);
180    GLINT_SLOW_WRITE_REG(0, PM3TextureCompositeColorMode1);
181    GLINT_SLOW_WRITE_REG(0, PM3TextureCompositeAlphaMode1);
182    GLINT_SLOW_WRITE_REG(0, PM3TextureCompositeColorMode0);
183    GLINT_SLOW_WRITE_REG(0, PM3TextureCompositeAlphaMode0);
184
185    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, FogMode);
186    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, ChromaTestMode);
187    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, AlphaTestMode);
188    /* Not done in P3Lib ??? */
189    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, AntialiasMode);
190    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3AlphaTestMode);
191    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, YUVMode);
192    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3AlphaBlendColorMode);
193    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3AlphaBlendAlphaMode);
194    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, DitherMode);
195    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, LogicalOpMode);
196
197    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, StatisticMode);
198    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, RouterMode);
199    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, PM3Window);
200
201    GLINT_SLOW_WRITE_REG(0, PM3Config2D);
202
203    GLINT_SLOW_WRITE_REG(0xffffffff, PM3SpanColorMask);
204
205    GLINT_SLOW_WRITE_REG(0, PM3XBias);
206    GLINT_SLOW_WRITE_REG(0, PM3YBias);
207
208    GLINT_SLOW_WRITE_REG(0, PM3DeltaControl);
209
210    GLINT_SLOW_WRITE_REG(0xffffffff, BitMaskPattern);
211
212    /* ScissorStippleUnit Initialization (is it needed ?) */
213    pGlint->ClippingOn = FALSE;
214    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, ScissorMode);
215    /* We never use Screen Scissor ...
216    GLINT_SLOW_WRITE_REG(
217	(pScrn->virtualX&0xffff)|((pScrn->virtualY&0xffff)<<16),
218	ScreenSize);
219    GLINT_SLOW_WRITE_REG(
220	(0&0xffff)|((0&0xffff)<<16),
221	WindowOrigin);
222    */
223
224    /* StencilDepthUnit Initialization */
225    GLINT_SLOW_WRITE_REG(0, PM3Window);
226    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, DepthMode);
227    GLINT_SLOW_WRITE_REG(UNIT_DISABLE, StencilMode);
228    GLINT_SLOW_WRITE_REG(0, StencilData);
229
230    /* FBReadUnit Initialization */
231    TRACE("Permedia3InitializeEngine : only syncs upto now");
232    GLINT_SLOW_WRITE_REG(
233	PM3FBDestReadEnables_E(0xff) |
234	PM3FBDestReadEnables_R(0xff) |
235	PM3FBDestReadEnables_ReferenceAlpha(0xff),
236	PM3FBDestReadEnables);
237    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferAddr0);
238    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferOffset0);
239    GLINT_SLOW_WRITE_REG(
240	PM3FBDestReadBufferWidth_Width(pScrn->displayWidth),
241	PM3FBDestReadBufferWidth0);
242    /*
243    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferAddr1);
244    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferOffset1);
245    GLINT_SLOW_WRITE_REG(
246	PM3FBDestReadBufferWidth_Width(pScrn->displayWidth),
247	PM3FBDestReadBufferWidth1);
248    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferAddr2);
249    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferOffset2);
250    GLINT_SLOW_WRITE_REG(
251	PM3FBDestReadBufferWidth_Width(pScrn->displayWidth),
252	PM3FBDestReadBufferWidth2);
253    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferAddr3);
254    GLINT_SLOW_WRITE_REG(0, PM3FBDestReadBufferOffset3);
255    GLINT_SLOW_WRITE_REG(
256	PM3FBDestReadBufferWidth_Width(pScrn->displayWidth),
257	PM3FBDestReadBufferWidth3);
258    */
259    GLINT_SLOW_WRITE_REG(
260	PM3FBDestReadMode_ReadEnable |
261	/* Not needed, since FBDestRead is the same as FBWrite.
262	PM3FBDestReadMode_Blocking |
263	*/
264	PM3FBDestReadMode_Enable0,
265	PM3FBDestReadMode);
266    TRACE("Permedia3InitializeEngine : DestRead");
267    GLINT_SLOW_WRITE_REG(0, PM3FBSourceReadBufferAddr);
268    GLINT_SLOW_WRITE_REG(0, PM3FBSourceReadBufferOffset);
269    GLINT_SLOW_WRITE_REG(
270	PM3FBSourceReadBufferWidth_Width(pScrn->displayWidth),
271	PM3FBSourceReadBufferWidth);
272    GLINT_SLOW_WRITE_REG(
273	PM3FBSourceReadMode_Blocking |
274	PM3FBSourceReadMode_ReadEnable,
275	PM3FBSourceReadMode);
276    TRACE("Permedia3InitializeEngine : SourceRead");
277    switch (pScrn->bitsPerPixel) {
278	case 8:
279	    pGlint->PM3_PixelSize = 2;
280#if X_BYTE_ORDER == X_BIG_ENDIAN
281	    pGlint->RasterizerSwap = 3<<15;	/* Swap host data */
282#endif
283	    break;
284	case 16:
285	    pGlint->PM3_PixelSize = 1;
286#if X_BYTE_ORDER == X_BIG_ENDIAN
287	    pGlint->RasterizerSwap = 2<<15;	/* Swap host data */
288#endif
289	    break;
290	case 32:
291	    pGlint->PM3_PixelSize = 0;
292	    break;
293    }
294    GLINT_SLOW_WRITE_REG(pGlint->PM3_PixelSize, PixelSize);
295#if X_BYTE_ORDER == X_BIG_ENDIAN
296    GLINT_SLOW_WRITE_REG(1 | pGlint->RasterizerSwap, RasterizerMode);
297#endif
298    TRACE("Permedia3InitializeEngine : PixelSize");
299
300    /* LogicalOpUnit Initialization */
301    GLINT_SLOW_WRITE_REG(0xffffffff,	PM3_OTHERWRITEMASK);
302
303    /* FBWriteUnit Initialization */
304    GLINT_SLOW_WRITE_REG(
305	PM3FBWriteMode_WriteEnable|
306	PM3FBWriteMode_OpaqueSpan|
307	PM3FBWriteMode_Enable0,
308	PM3FBWriteMode);
309    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferAddr0);
310    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferOffset0);
311    GLINT_SLOW_WRITE_REG(
312	PM3FBWriteBufferWidth_Width(pScrn->displayWidth),
313	PM3FBWriteBufferWidth0);
314    /*
315    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferAddr1);
316    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferOffset1);
317    GLINT_SLOW_WRITE_REG(
318	PM3FBWriteBufferWidth_Width(pScrn->displayWidth),
319	PM3FBWriteBufferWidth1);
320    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferAddr2);
321    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferOffset2);
322    GLINT_SLOW_WRITE_REG(
323	PM3FBWriteBufferWidth_Width(pScrn->displayWidth),
324	PM3FBWriteBufferWidth2);
325    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferAddr3);
326    GLINT_SLOW_WRITE_REG(0, PM3FBWriteBufferOffset3);
327    GLINT_SLOW_WRITE_REG(
328	PM3FBWriteBufferWidth_Width(pScrn->displayWidth),
329	PM3FBWriteBufferWidth3);
330    */
331    TRACE("Permedia3InitializeEngine : FBWrite");
332    /* SizeOfframebuffer */
333    GLINT_SLOW_WRITE_REG(
334	pScrn->displayWidth *
335	(8 * pGlint->FbMapSize / (pScrn->bitsPerPixel * pScrn->displayWidth)
336	    >4095?4095: 8 * pGlint->FbMapSize /
337	    (pScrn->bitsPerPixel * pScrn->displayWidth)),
338	PM3SizeOfFramebuffer);
339    GLINT_SLOW_WRITE_REG(0xffffffff,	PM3_WRITEMASK);
340    TRACE("Permedia3InitializeEngine : FBHardwareWriteMask & SizeOfFramebuffer");
341    /* Color Format */
342    switch (pScrn->depth) {
343	case 8:
344	    colorformat = 4;
345	    break;
346	case 15:
347	    colorformat = 2;
348	    break;
349	case 16:
350	    colorformat = 3;
351	    break;
352	case 24:
353	case 32:
354	    colorformat = 0;
355	    break;
356    }
357    GLINT_SLOW_WRITE_REG(UNIT_DISABLE|
358	((colorformat&0xf)<<2)|(1<<10),
359	DitherMode);
360
361    /* Other stuff */
362    pGlint->startxdom = 0;
363    pGlint->startxsub = 0;
364    pGlint->starty = 0;
365    pGlint->count = 0;
366    pGlint->dy = 1<<16;
367    pGlint->dxdom = 0;
368    pGlint->x = 0;
369    pGlint->y = 0;
370    pGlint->h = 0;
371    pGlint->w = 0;
372    pGlint->ROP = 0xFF;
373    GLINT_SLOW_WRITE_REG(0, dXDom);
374    GLINT_SLOW_WRITE_REG(0, dXSub);
375    GLINT_SLOW_WRITE_REG(1<<16, dY);
376    GLINT_SLOW_WRITE_REG(0, StartXDom);
377    GLINT_SLOW_WRITE_REG(0, StartXSub);
378    GLINT_SLOW_WRITE_REG(0, StartY);
379    GLINT_SLOW_WRITE_REG(0, GLINTCount);
380    if (*pGlint->AccelInfoRec->Sync != NULL)
381    	(*pGlint->AccelInfoRec->Sync)(pScrn);
382    TRACE_EXIT("Permedia3InitializeEngine");
383}
384#endif
385Bool
386Permedia3AccelInit(ScreenPtr pScreen)
387{
388#ifdef HAVE_XAA_H
389    XAAInfoRecPtr infoPtr;
390    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
391    GLINTPtr pGlint = GLINTPTR(pScrn);
392
393    pGlint->AccelInfoRec = infoPtr = XAACreateInfoRec();
394    if (!infoPtr) return FALSE;
395
396    /* Generic accel engine flags */
397    infoPtr->Flags = PIXMAP_CACHE |
398		     OFFSCREEN_PIXMAPS |
399		     LINEAR_FRAMEBUFFER;
400
401    /* Synchronization of the accel engine */
402    if (pGlint->MultiAperture)
403    	infoPtr->Sync = DualPermedia3Sync;
404    else
405    	infoPtr->Sync = Permedia3Sync;
406
407    Permedia3InitializeEngine(pScrn);
408
409    /* Clipping Setup */
410    infoPtr->ClippingFlags = 0;
411    infoPtr->SetClippingRectangle = Permedia3SetClippingRectangle;
412    infoPtr->DisableClipping = Permedia3DisableClipping;
413
414    /* ScreenToScreenCopy */
415    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
416    infoPtr->SetupForScreenToScreenCopy =
417					Permedia3SetupForScreenToScreenCopy;
418    infoPtr->SubsequentScreenToScreenCopy =
419					Permedia3SubsequentScreenToScreenCopy;
420
421    /* SolidFill */
422    infoPtr->SolidFillFlags = 0;
423    infoPtr->SetupForSolidFill = Permedia3SetupForFillRectSolid;
424    infoPtr->SubsequentSolidFillRect = Permedia3SubsequentFillRectSolid;
425
426    /* 8x8 Mono Pattern Fills */
427    infoPtr->Mono8x8PatternFillFlags =  HARDWARE_PATTERN_PROGRAMMED_BITS |
428    					HARDWARE_PATTERN_PROGRAMMED_ORIGIN |
429    					HARDWARE_PATTERN_SCREEN_ORIGIN |
430					BIT_ORDER_IN_BYTE_LSBFIRST;
431    infoPtr->SetupForMono8x8PatternFill =
432				Permedia3SetupForMono8x8PatternFill;
433    infoPtr->SubsequentMono8x8PatternFillRect =
434				Permedia3SubsequentMono8x8PatternFillRect;
435
436    infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
437						LEFT_EDGE_CLIPPING |
438						LEFT_EDGE_CLIPPING_NEGATIVE_X |
439					       	BIT_ORDER_IN_BYTE_LSBFIRST |
440						CPU_TRANSFER_PAD_DWORD;
441
442    infoPtr->NumScanlineColorExpandBuffers = 1;
443    pGlint->ScratchBuffer                 = malloc(((pScrn->virtualX + 62) / 32 * 4) + (pScrn->virtualX * pScrn->bitsPerPixel / 8));
444    infoPtr->ScanlineColorExpandBuffers =
445					pGlint->XAAScanlineColorExpandBuffers;
446    pGlint->XAAScanlineColorExpandBuffers[0] =
447					pGlint->IOBase + OutputFIFO + 4;
448
449    infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
450			Permedia3SetupForScanlineCPUToScreenColorExpandFill;
451    infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
452			Permedia3SubsequentScanlineCPUToScreenColorExpandFill;
453    infoPtr->SubsequentColorExpandScanline =
454			Permedia3SubsequentColorExpandScanline;
455
456    infoPtr->ScanlineImageWriteFlags = 	NO_GXCOPY |
457					LEFT_EDGE_CLIPPING |
458					LEFT_EDGE_CLIPPING_NEGATIVE_X |
459					BIT_ORDER_IN_BYTE_LSBFIRST |
460					CPU_TRANSFER_PAD_DWORD;
461    infoPtr->NumScanlineImageWriteBuffers = 1;
462    infoPtr->ScanlineImageWriteBuffers =
463					pGlint->XAAScanlineColorExpandBuffers;
464    infoPtr->SetupForScanlineImageWrite =
465	    Permedia3SetupForScanlineImageWrite;
466    infoPtr->SubsequentScanlineImageWriteRect =
467	    Permedia3SubsequentScanlineImageWriteRect;
468    infoPtr->SubsequentImageWriteScanline =
469			Permedia3SubsequentImageWriteScanline;
470
471    infoPtr->WriteBitmap = Permedia3WriteBitmap;
472    infoPtr->WriteBitmapFlags = 0;
473
474    infoPtr->WritePixmap = Permedia3WritePixmap;
475    infoPtr->WritePixmapFlags = 0;
476
477    {
478	Bool shared_accel = FALSE;
479	int i;
480
481	for(i = 0; i < pScrn->numEntities; i++) {
482	    if(xf86IsEntityShared(pScrn->entityList[i]))
483		shared_accel = TRUE;
484	}
485	if(shared_accel == TRUE)
486	    infoPtr->RestoreAccelState = Permedia3RestoreAccelState;
487    }
488
489    Permedia3EnableOffscreen(pScreen);
490
491    return(XAAInit(pScreen, infoPtr));
492#else
493    return FALSE;
494#endif
495}
496
497void
498Permedia3EnableOffscreen (ScreenPtr pScreen)
499{
500    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
501    GLINTPtr pGlint = GLINTPTR(pScrn);
502    BoxRec AvailFBArea;
503
504    /* Available Framebuffer Area for XAA. */
505    AvailFBArea.x1 = 0;
506    AvailFBArea.y1 = 0;
507    AvailFBArea.x2 = pScrn->displayWidth;
508    /* X coords are short's so we have to do this to make sure we dont wrap*/
509    AvailFBArea.y2 = ((pGlint->FbMapSize > 16384*1024) ? 16384*1024 :
510	pGlint->FbMapSize)  / (pScrn->displayWidth *
511	pScrn->bitsPerPixel / 8);
512
513    /* Permedia3 has a maximum 4096x4096 framebuffer */
514    if (AvailFBArea.y2 > 4095) AvailFBArea.y2 = 4095;
515
516    xf86InitFBManager(pScreen, &AvailFBArea);
517}
518
519#ifdef HAVE_XAA_H
520
521#define CHECKCLIPPING				\
522{						\
523    if (pGlint->ClippingOn) {			\
524	pGlint->ClippingOn = FALSE;		\
525	GLINT_WAIT(1);				\
526	GLINT_WRITE_REG(0, ScissorMode);	\
527    }						\
528}
529
530void
531Permedia3Sync(ScrnInfoPtr pScrn)
532{
533    GLINTPtr pGlint = GLINTPTR(pScrn);
534
535    CHECKCLIPPING;
536
537    while (GLINT_READ_REG(DMACount) != 0);
538    GLINT_WAIT(2);
539    GLINT_WRITE_REG(0x400, FilterMode);
540    GLINT_WRITE_REG(0, GlintSync);
541    do {
542   	while(GLINT_READ_REG(OutFIFOWords) == 0);
543    } while (GLINT_READ_REG(OutputFIFO) != Sync_tag);
544}
545
546void
547DualPermedia3Sync(
548	ScrnInfoPtr pScrn
549){
550    GLINTPtr pGlint = GLINTPTR(pScrn);
551
552    CHECKCLIPPING;
553
554    while (GLINT_READ_REG(DMACount) != 0);
555    GLINT_WAIT(3);
556    GLINT_WRITE_REG(3, BroadcastMask); /* hack! this shouldn't need to be reloaded */
557    GLINT_WRITE_REG(0x400, FilterMode);
558    GLINT_WRITE_REG(0, GlintSync);
559
560    /* Read 1st PM3 until Sync Tag shows */
561    ACCESSCHIP1();
562    do {
563   	while(GLINT_READ_REG(OutFIFOWords) == 0);
564    } while (GLINT_READ_REG(OutputFIFO) != Sync_tag);
565
566    ACCESSCHIP2();
567    /* Read 2nd PM3 until Sync Tag shows */
568    do {
569   	while(GLINT_READ_REG(OutFIFOWords) == 0);
570    } while (GLINT_READ_REG(OutputFIFO) != Sync_tag);
571
572    ACCESSCHIP1();
573}
574
575static void
576Permedia3SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
577{
578    GLINTPtr pGlint = GLINTPTR(pScrn);
579    GLINT_WAIT(3);
580    GLINT_WRITE_REG(((y1&0x0fff)<<16)|(x1&0x0fff), ScissorMinXY);
581    GLINT_WRITE_REG(((y2&0x0fff)<<16)|(x2&0x0fff), ScissorMaxXY);
582    GLINT_WRITE_REG(1, ScissorMode);
583    pGlint->ClippingOn = TRUE;
584}
585static void
586Permedia3DisableClipping(ScrnInfoPtr pScrn)
587{
588    GLINTPtr pGlint = GLINTPTR(pScrn);
589    CHECKCLIPPING;
590}
591
592/* ScreenToScreenCopy definition */
593static void
594Permedia3SetupForScreenToScreenCopy(ScrnInfoPtr pScrn,
595				int xdir, int ydir, int rop,
596				unsigned int planemask, int transparency_color)
597{
598    GLINTPtr pGlint = GLINTPTR(pScrn);
599    TRACE_ENTER("Permedia3SetupForScreenToScreenCopy");
600
601    pGlint->PM3_Render2D =
602	PM3Render2D_SpanOperation |
603	PM3Render2D_Operation_Normal;
604
605    pGlint->ClippingOn = TRUE;
606
607    pGlint->PM3_Config2D =
608	PM3Config2D_UserScissorEnable |
609	PM3Config2D_ForegroundROPEnable |
610	PM3Config2D_ForegroundROP(rop) |
611	PM3Config2D_FBWriteEnable;
612
613    if (xdir == 1) pGlint->PM3_Render2D |= PM3Render2D_XPositive;
614    if (ydir == 1) pGlint->PM3_Render2D |= PM3Render2D_YPositive;
615
616    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXnoop)&&(rop!=GXinvert)) {
617	pGlint->PM3_Render2D |= PM3Render2D_FBSourceReadEnable;
618	pGlint->PM3_Config2D |= PM3Config2D_Blocking;
619    }
620
621    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
622	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
623
624    GLINT_WAIT(2);
625    PM3_PLANEMASK(planemask);
626    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
627
628    TRACE_EXIT("Permedia3SetupForScreenToScreenCopy");
629}
630static void
631Permedia3SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
632					int x2, int y2, int w, int h)
633{
634    GLINTPtr pGlint = GLINTPTR(pScrn);
635    /* Spans needs to be 32 bit aligned. */
636    int x_align = x1 & 0x1f;
637    TRACE_ENTER("Permedia3SubsequentScreenToScreenCopy");
638    GLINT_WAIT(5);
639    GLINT_WRITE_REG(((y2&0x0fff)<<16)|(x2&0x0fff), ScissorMinXY);
640    GLINT_WRITE_REG((((y2+h)&0x0fff)<<16)|((x2+w)&0x0fff), ScissorMaxXY);
641    GLINT_WRITE_REG(
642	PM3RectanglePosition_XOffset(x2-x_align) |
643	PM3RectanglePosition_YOffset(y2),
644	PM3RectanglePosition);
645    GLINT_WRITE_REG(
646	PM3FBSourceReadBufferOffset_XOffset(x1-x2)|
647	PM3FBSourceReadBufferOffset_YOffset(y1-y2),
648	PM3FBSourceReadBufferOffset);
649    GLINT_WRITE_REG(pGlint->PM3_Render2D |
650	PM3Render2D_Width(w+x_align)|
651	PM3Render2D_Height(h),
652	PM3Render2D);
653    TRACE_EXIT("Permedia3SubsequentScreenToScreenCopy");
654}
655
656/* Solid Fills */
657static void
658Permedia3SetupForFillRectSolid(ScrnInfoPtr pScrn, int color,
659				    int rop, unsigned int planemask)
660{
661    GLINTPtr pGlint = GLINTPTR(pScrn);
662    TRACE_ENTER("Permedia3SetupForFillRectSolid");
663    /* Prepare Common Render2D & Config2D data */
664    pGlint->PM3_Render2D =
665	PM3Render2D_XPositive |
666	PM3Render2D_YPositive |
667	PM3Render2D_Operation_Normal;
668    pGlint->PM3_Config2D =
669	PM3Config2D_UseConstantSource |
670	PM3Config2D_ForegroundROPEnable |
671	PM3Config2D_ForegroundROP(rop) |
672	PM3Config2D_FBWriteEnable;
673    GLINT_WAIT(3);
674    REPLICATE(color);
675    /* We can't do block fills properly at 32bpp, so we can stick the chip
676     * into 16bpp and double the width and xcoord, but it seems that at
677     * extremely high resolutions (above 1600) it doesn't fill.
678     * so, we fall back to the slower span filling method.
679     */
680    if ((rop == GXcopy) && (pScrn->bitsPerPixel == 32) &&
681	(pScrn->displayWidth <= 1600)) {
682    	pGlint->AccelInfoRec->SubsequentSolidFillRect =
683		Permedia3SubsequentFillRectSolid32bpp;
684	if (pGlint->PM3_UsingSGRAM) {
685	    GLINT_WRITE_REG(color, PM3FBBlockColor);
686	} else {
687	    pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
688	    GLINT_WRITE_REG(color, PM3ForegroundColor);
689	}
690    } else {
691    	pGlint->AccelInfoRec->SubsequentSolidFillRect =
692		Permedia3SubsequentFillRectSolid;
693    	/* Can't do block fills at 8bpp either */
694    	if ((rop == GXcopy) && (pScrn->bitsPerPixel == 16)) {
695	    if (pGlint->PM3_UsingSGRAM) {
696	        GLINT_WRITE_REG(color, PM3FBBlockColor);
697	    } else {
698	        pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
699		GLINT_WRITE_REG(color, PM3ForegroundColor);
700	    }
701        } else {
702	    pGlint->PM3_Render2D |= PM3Render2D_SpanOperation;
703	    GLINT_WRITE_REG(color, PM3ForegroundColor);
704    	}
705    }
706    PM3_PLANEMASK(planemask);
707    if (((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
708      || ((planemask != 0xffffffff) && !(pGlint->PM3_UsingSGRAM)))
709	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
710    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
711    TRACE_EXIT("Permedia3SetupForFillRectSolid");
712}
713
714static void
715Permedia3SubsequentFillRectSolid(ScrnInfoPtr pScrn, int x, int y, int w, int h)
716{
717    GLINTPtr pGlint = GLINTPTR(pScrn);
718    TRACE_ENTER("Permedia3SubsequentFillRectSolid");
719
720    GLINT_WAIT(2);
721    GLINT_WRITE_REG(
722	PM3RectanglePosition_XOffset(x) |
723	PM3RectanglePosition_YOffset(y),
724	PM3RectanglePosition);
725    GLINT_WRITE_REG(pGlint->PM3_Render2D |
726	PM3Render2D_Width(w) | PM3Render2D_Height(h),
727	PM3Render2D);
728
729    TRACE_EXIT("Permedia3SubsequentFillRectSolid");
730}
731
732static void
733Permedia3SubsequentFillRectSolid32bpp(ScrnInfoPtr pScrn, int x, int y, int w, int h)
734{
735    GLINTPtr pGlint = GLINTPTR(pScrn);
736    TRACE_ENTER("Permedia3SubsequentFillRectSolid32bpp");
737
738    GLINT_WAIT(6);
739
740    /* Put the chip into 16bpp mode */
741    GLINT_WRITE_REG(1, PixelSize);
742    /* Now double the displayWidth */
743    GLINT_WRITE_REG(
744	PM3FBWriteBufferWidth_Width(pScrn->displayWidth<<1),
745	PM3FBWriteBufferWidth0);
746
747    /* and double the x,w coords */
748    GLINT_WRITE_REG(
749	PM3RectanglePosition_XOffset(x<<1) |
750	PM3RectanglePosition_YOffset(y),
751	PM3RectanglePosition);
752    GLINT_WRITE_REG(pGlint->PM3_Render2D |
753	PM3Render2D_Width(w<<1) | PM3Render2D_Height(h),
754	PM3Render2D);
755
756    /* Now fixup */
757    GLINT_WRITE_REG(
758	PM3FBWriteBufferWidth_Width(pScrn->displayWidth),
759	PM3FBWriteBufferWidth0);
760    GLINT_WRITE_REG(0, PixelSize);
761    TRACE_EXIT("Permedia3SubsequentFillRectSolid32bpp");
762}
763
764/* 8x8 Mono Pattern Fills */
765static void
766Permedia3SetupForMono8x8PatternFill(ScrnInfoPtr pScrn,
767			   int patternx, int patterny,
768			   int fg, int bg, int rop,
769			   unsigned int planemask)
770{
771    GLINTPtr pGlint = GLINTPTR(pScrn);
772    TRACE_ENTER("Permedia3SetupForMono8x8PatternFill");
773    REPLICATE(fg);
774    pGlint->PM3_Render2D =
775	PM3Render2D_AreaStippleEnable |
776	PM3Render2D_SpanOperation |
777	PM3Render2D_XPositive |
778	PM3Render2D_YPositive |
779	PM3Render2D_Operation_Normal;
780    pGlint->PM3_Config2D =
781	PM3Config2D_UseConstantSource |
782	PM3Config2D_ForegroundROPEnable |
783	PM3Config2D_ForegroundROP(rop) |
784	PM3Config2D_FBWriteEnable;
785    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
786	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
787    pGlint->PM3_AreaStippleMode = 1;
788/* Mirror stipple pattern horizontally */
789#if X_BYTE_ORDER == X_BIG_ENDIAN
790    pGlint->PM3_AreaStippleMode |= (1<<18);
791#endif
792    pGlint->PM3_AreaStippleMode |= (2<<1);
793    pGlint->PM3_AreaStippleMode |= (2<<4);
794    if (bg != -1) {
795	REPLICATE(bg);
796	pGlint->PM3_Config2D |= PM3Config2D_OpaqueSpan;
797	pGlint->PM3_AreaStippleMode |= 1<<20;
798	GLINT_WAIT(12);
799    	GLINT_WRITE_REG(bg, BackgroundColor);
800    }
801    else GLINT_WAIT(11);
802    GLINT_WRITE_REG((patternx & 0xFF), AreaStipplePattern0);
803    GLINT_WRITE_REG((patternx & 0xFF00) >> 8, AreaStipplePattern1);
804    GLINT_WRITE_REG((patternx & 0xFF0000) >> 16, AreaStipplePattern2);
805    GLINT_WRITE_REG((patternx & 0xFF000000) >> 24, AreaStipplePattern3);
806    GLINT_WRITE_REG((patterny & 0xFF), AreaStipplePattern4);
807    GLINT_WRITE_REG((patterny & 0xFF00) >> 8, AreaStipplePattern5);
808    GLINT_WRITE_REG((patterny & 0xFF0000) >> 16, AreaStipplePattern6);
809    GLINT_WRITE_REG((patterny & 0xFF000000) >> 24, AreaStipplePattern7);
810    GLINT_WRITE_REG(fg, PM3ForegroundColor);
811    PM3_PLANEMASK(planemask);
812    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
813    TRACE_EXIT("Permedia3SetupForMono8x8PatternFill");
814}
815static void
816Permedia3SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
817			   int x_offset, int y_offset,
818			   int x, int y, int w, int h)
819{
820    GLINTPtr pGlint = GLINTPTR(pScrn);
821    TRACE_ENTER("Permedia3SubsequentMono8x8PatternFillRect");
822    GLINT_WAIT(3);
823    GLINT_WRITE_REG(
824	PM3RectanglePosition_XOffset(x) |
825	PM3RectanglePosition_YOffset(y),
826	PM3RectanglePosition);
827    GLINT_WRITE_REG(
828	(x_offset&0x7)<<7 | (y_offset&0x7)<<12 |
829	pGlint->PM3_AreaStippleMode,
830	AreaStippleMode);
831    GLINT_WRITE_REG(pGlint->PM3_Render2D |
832	PM3Render2D_Width(w) | PM3Render2D_Height(h),
833	PM3Render2D);
834    TRACE_EXIT("Permedia3SubsequentMono8x8PatternFillRect");
835}
836
837static void
838Permedia3SetupForScanlineCPUToScreenColorExpandFill(
839	ScrnInfoPtr pScrn,
840	int fg, int bg,
841	int rop,
842	unsigned int planemask
843){
844    GLINTPtr pGlint = GLINTPTR(pScrn);
845
846    REPLICATE(fg);
847    pGlint->PM3_Render2D =
848	PM3Render2D_SpanOperation |
849	PM3Render2D_XPositive |
850	PM3Render2D_YPositive |
851	PM3Render2D_Operation_SyncOnBitMask;
852    pGlint->PM3_Config2D =
853	PM3Config2D_UserScissorEnable |
854	PM3Config2D_UseConstantSource |
855	PM3Config2D_ForegroundROPEnable |
856	PM3Config2D_ForegroundROP(rop) |
857	PM3Config2D_FBWriteEnable;
858    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
859	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
860    if (bg != -1) {
861	REPLICATE(bg);
862	pGlint->PM3_Config2D |= PM3Config2D_OpaqueSpan;
863	GLINT_WAIT(4);
864    	GLINT_WRITE_REG(bg, BackgroundColor);
865    }
866    else GLINT_WAIT(3);
867    GLINT_WRITE_REG(fg, PM3ForegroundColor);
868    PM3_PLANEMASK(planemask);
869    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
870}
871
872static void
873Permedia3SubsequentScanlineCPUToScreenColorExpandFill(
874	ScrnInfoPtr pScrn,
875	int x, int y, int w, int h,
876	int skipleft
877){
878    GLINTPtr pGlint = GLINTPTR(pScrn);
879
880    TRACE_ENTER("Permedia2SubsequentScanlineCPUToScreenColorExpandFill");
881
882    pGlint->dwords = ((w + 31) >> 5); /* dwords per scanline */
883
884    pGlint->cpucount = h;
885
886    GLINT_WAIT(5);
887    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
888    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
889    GLINT_WRITE_REG(
890	PM3RectanglePosition_XOffset(x) |
891	PM3RectanglePosition_YOffset(y),
892	PM3RectanglePosition);
893    GLINT_WRITE_REG(pGlint->PM3_Render2D |
894	PM3Render2D_Width(w) | PM3Render2D_Height(h),
895	PM3Render2D);
896
897#if defined(__alpha__)
898    if (0) /* force Alpha to use indirect always */
899#else
900    if ((pGlint->dwords*h) < pGlint->FIFOSize)
901#endif
902    {
903	/* Turn on direct for less than 120 dword colour expansion */
904    	pGlint->XAAScanlineColorExpandBuffers[0] = pGlint->IOBase+OutputFIFO+4;
905	pGlint->ScanlineDirect = 1;
906    	GLINT_WRITE_REG(((pGlint->dwords*h)-1)<<16 | 0x0D, OutputFIFO);
907    	GLINT_WAIT(pGlint->dwords*h);
908    } else {
909	/* Use indirect for anything else */
910    	pGlint->XAAScanlineColorExpandBuffers[0] = pGlint->ScratchBuffer;
911	pGlint->ScanlineDirect   = 0;
912    }
913
914    pGlint->cpucount--;
915}
916
917static void
918Permedia3SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
919{
920    GLINTPtr pGlint = GLINTPTR(pScrn);
921    CARD32 *srcp = (CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno];
922    int dwords = pGlint->dwords;
923
924    if (!pGlint->ScanlineDirect) {
925	while(dwords >= pGlint->FIFOSize) {
926	    GLINT_WAIT(pGlint->FIFOSize);
927            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | 0x0D, OutputFIFO);
928	    GLINT_MoveDWORDS(
929			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
930	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
931	    dwords -= pGlint->FIFOSize - 1;
932	    srcp += pGlint->FIFOSize - 1;
933	}
934	if(dwords) {
935	    GLINT_WAIT(dwords + 1);
936            GLINT_WRITE_REG(((dwords - 1) << 16) | 0x0D, OutputFIFO);
937	    GLINT_MoveDWORDS(
938			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
939	 		(CARD32*)srcp, dwords);
940	}
941    }
942}
943
944/* Images Writes */
945static void Permedia3SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop,
946	unsigned int planemask, int trans_color, int bpp, int depth)
947{
948    GLINTPtr pGlint = GLINTPTR(pScrn);
949    TRACE_ENTER("Permedia3SetupForScanlineImageWrite");
950    pGlint->PM3_Render2D =
951	PM3Render2D_SpanOperation |
952	PM3Render2D_XPositive |
953	PM3Render2D_YPositive |
954	PM3Render2D_Operation_SyncOnHostData;
955    pGlint->PM3_Config2D =
956	PM3Config2D_UserScissorEnable |
957	PM3Config2D_ForegroundROPEnable |
958	PM3Config2D_ForegroundROP(rop) |
959	PM3Config2D_FBWriteEnable;
960    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
961	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
962    GLINT_WAIT(2);
963    PM3_PLANEMASK(planemask);
964    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
965    TRACE_EXIT("Permedia3SetupForScanlineImageWrite");
966}
967
968static void Permedia3SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn,
969	int x, int y, int w, int h, int skipleft)
970{
971    GLINTPtr pGlint = GLINTPTR(pScrn);
972    TRACE_ENTER("Permedia3SubsequentScanlineImageWrite");
973    pGlint->dwords = (((w * pScrn->bitsPerPixel) + 3) >> 2); /* per scanline */
974
975    pGlint->cpucount = h;
976    GLINT_WAIT(5);
977    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
978    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
979    GLINT_WRITE_REG(
980	PM3RectanglePosition_XOffset(x) |
981	PM3RectanglePosition_YOffset(y),
982	PM3RectanglePosition);
983    GLINT_WRITE_REG(pGlint->PM3_Render2D |
984	PM3Render2D_Width(w) | PM3Render2D_Height(h),
985	PM3Render2D);
986
987#if defined(__alpha__)
988    if (0) /* force Alpha to use indirect always */
989#else
990    if (pGlint->dwords < pGlint->FIFOSize)
991#endif
992    {
993	/* Turn on direct for less than 120 dword colour expansion */
994    	pGlint->XAAScanlineColorExpandBuffers[0] = pGlint->IOBase+OutputFIFO+4;
995	pGlint->ScanlineDirect = 1;
996    	GLINT_WRITE_REG(((pGlint->dwords*h)-1)<<16 | (0x15<<4) | 0x05,
997								OutputFIFO);
998    	GLINT_WAIT(pGlint->dwords);
999    } else {
1000	/* Use indirect for anything else */
1001    	pGlint->XAAScanlineColorExpandBuffers[0] = pGlint->ScratchBuffer;
1002	pGlint->ScanlineDirect   = 0;
1003    }
1004
1005    pGlint->cpucount--;
1006    TRACE_EXIT("Permedia3SubsequentScanlineImageWrite");
1007}
1008
1009static void
1010Permedia3SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
1011{
1012    GLINTPtr pGlint = GLINTPTR(pScrn);
1013    int dwords = pGlint->dwords;
1014
1015    if (pGlint->ScanlineDirect) {
1016    	if (pGlint->cpucount--)
1017    	    GLINT_WAIT(dwords);
1018	return;
1019    } else {
1020	while(dwords >= pGlint->FIFOSize) {
1021	    GLINT_WAIT(pGlint->FIFOSize);
1022            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
1023							0x05, OutputFIFO);
1024	    GLINT_MoveDWORDS(
1025			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1026	 		(CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno],
1027			pGlint->FIFOSize - 1);
1028	    dwords -= pGlint->FIFOSize - 1;
1029	}
1030	if(dwords) {
1031	    GLINT_WAIT(dwords + 1);
1032            GLINT_WRITE_REG(((dwords - 1) << 16) | (0x15 << 4) |
1033							0x05, OutputFIFO);
1034	    GLINT_MoveDWORDS(
1035			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1036	 		(CARD32*)pGlint->XAAScanlineColorExpandBuffers[bufno],
1037			dwords);
1038	}
1039    }
1040}
1041
1042static void
1043Permedia3RestoreAccelState(ScrnInfoPtr pScrn)
1044{
1045    GLINTPtr pGlint = GLINTPTR(pScrn);
1046    if ((IS_J2000) && (pGlint->Chipset == PCI_VENDOR_3DLABS_CHIP_GAMMA)) {
1047	GLINT_SLOW_WRITE_REG(pGlint->MultiIndex, BroadcastMask);
1048    }
1049    Permedia3Sync(pScrn);
1050}
1051
1052static void
1053Permedia3WritePixmap(
1054    ScrnInfoPtr pScrn,
1055    int x, int y, int w, int h,
1056    unsigned char *src,
1057    int srcwidth,
1058    int rop,
1059    unsigned int planemask,
1060    int trans,
1061    int bpp, int depth
1062)
1063{
1064    int dwords;
1065    int count;
1066    int skipleft = (long)src & 0x03L;
1067    int Bpp = bpp >> 3;
1068    CARD32 *srcp;
1069    GLINTPtr pGlint = GLINTPTR(pScrn);
1070    TRACE_ENTER("Permedia3WritePixmap");
1071
1072    if (skipleft) {
1073	/* Skipleft is either
1074	 *   - 0, 1, 2 or 3 in 8 bpp
1075	 *   - 0 or 1 in 16 bpp
1076	 *   - 0 in 32 bpp
1077	 */
1078	skipleft /= Bpp;
1079
1080	x -= skipleft;
1081	w += skipleft;
1082
1083	src = (unsigned char*)((long)src & ~0x03L);
1084    }
1085
1086    pGlint->PM3_Render2D =
1087	PM3Render2D_SpanOperation |
1088	PM3Render2D_XPositive |
1089	PM3Render2D_YPositive |
1090	PM3Render2D_Operation_SyncOnHostData;
1091    pGlint->PM3_Config2D =
1092	PM3Config2D_UserScissorEnable |
1093	PM3Config2D_ForegroundROPEnable |
1094	PM3Config2D_ForegroundROP(rop) |
1095	PM3Config2D_FBWriteEnable;
1096    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
1097	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
1098    GLINT_WAIT(6);
1099    PM3_PLANEMASK(planemask);
1100    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
1101    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
1102    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
1103    GLINT_WRITE_REG(
1104	PM3RectanglePosition_XOffset(x) |
1105	PM3RectanglePosition_YOffset(y),
1106	PM3RectanglePosition);
1107    GLINT_WRITE_REG(pGlint->PM3_Render2D |
1108	PM3Render2D_Width(w) | PM3Render2D_Height(h),
1109	PM3Render2D);
1110    /* width of the stuff to copy in 32 bit words */
1111    dwords = ((w * Bpp) + 3) >> 2;
1112
1113    while(h--) {
1114	count = dwords;
1115	srcp = (CARD32*)src;
1116	while(count >= pGlint->FIFOSize) {
1117	    GLINT_WAIT(pGlint->FIFOSize);
1118	    /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
1119            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) | (0x15 << 4) |
1120					0x05, OutputFIFO);
1121	    GLINT_MoveDWORDS(
1122			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1123	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
1124	    count -= pGlint->FIFOSize - 1;
1125	    srcp += pGlint->FIFOSize - 1;
1126	}
1127	if(count) {
1128	    GLINT_WAIT(count + 1);
1129	    /* (0x15 << 4) | 0x05 is the TAG for FBSourceData */
1130            GLINT_WRITE_REG(((count - 1) << 16) | (0x15 << 4) |
1131					0x05, OutputFIFO);
1132	    GLINT_MoveDWORDS(
1133			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1134	 		(CARD32*)srcp, count);
1135	}
1136	src += srcwidth;
1137    }
1138
1139    Permedia3DisableClipping(pScrn);
1140    Permedia3Sync(pScrn);
1141}
1142
1143static void
1144Permedia3WriteBitmap(ScrnInfoPtr pScrn,
1145    int x, int y, int w, int h,
1146    unsigned char *src,
1147    int srcwidth, int skipleft,
1148    int fg, int bg, int rop,
1149    unsigned int planemask
1150)
1151{
1152    int dwords;
1153    GLINTPtr pGlint = GLINTPTR(pScrn);
1154    int count;
1155    CARD32 *srcp;
1156    TRACE_ENTER("Permedia3WriteBitmap");
1157
1158    w += skipleft;
1159    x -= skipleft;
1160    dwords = (w + 31) >>5;
1161
1162    REPLICATE(fg);
1163    pGlint->PM3_Render2D =
1164	PM3Render2D_SpanOperation |
1165	PM3Render2D_XPositive |
1166	PM3Render2D_YPositive |
1167	PM3Render2D_Operation_SyncOnBitMask;
1168    pGlint->PM3_Config2D =
1169	PM3Config2D_UserScissorEnable |
1170	PM3Config2D_UseConstantSource |
1171	PM3Config2D_ForegroundROPEnable |
1172	PM3Config2D_ForegroundROP(rop) |
1173	PM3Config2D_FBWriteEnable;
1174    if ((rop!=GXclear)&&(rop!=GXset)&&(rop!=GXcopy)&&(rop!=GXcopyInverted))
1175	pGlint->PM3_Config2D |= PM3Config2D_FBDestReadEnable;
1176    if (bg != -1) {
1177	REPLICATE(bg);
1178	pGlint->PM3_Config2D |= PM3Config2D_OpaqueSpan;
1179	GLINT_WAIT(8);
1180    	GLINT_WRITE_REG(bg, BackgroundColor);
1181    }
1182    else GLINT_WAIT(7);
1183    GLINT_WRITE_REG(fg, PM3ForegroundColor);
1184    PM3_PLANEMASK(planemask);
1185    GLINT_WRITE_REG(pGlint->PM3_Config2D, PM3Config2D);
1186    GLINT_WRITE_REG(((y&0x0fff)<<16)|((x+skipleft)&0x0fff), ScissorMinXY);
1187    GLINT_WRITE_REG((((y+h)&0x0fff)<<16)|((x+w)&0x0fff), ScissorMaxXY);
1188    GLINT_WRITE_REG(
1189	PM3RectanglePosition_XOffset(x) |
1190	PM3RectanglePosition_YOffset(y),
1191	PM3RectanglePosition);
1192    GLINT_WRITE_REG(pGlint->PM3_Render2D |
1193	PM3Render2D_Width(w) | PM3Render2D_Height(h),
1194	PM3Render2D);
1195
1196    while(h--) {
1197	count = dwords;
1198	srcp = (CARD32*)src;
1199	while(count >= pGlint->FIFOSize) {
1200	    GLINT_WAIT(pGlint->FIFOSize);
1201            GLINT_WRITE_REG(((pGlint->FIFOSize - 2) << 16) |
1202					0x0D, OutputFIFO);
1203	    GLINT_MoveDWORDS(
1204			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1205	 		(CARD32*)srcp, pGlint->FIFOSize - 1);
1206	    count -= pGlint->FIFOSize - 1;
1207	    srcp += pGlint->FIFOSize - 1;
1208	}
1209	if(count) {
1210	    GLINT_WAIT(count + 1);
1211            GLINT_WRITE_REG(((count - 1) << 16) | 0x0D, OutputFIFO);
1212	    GLINT_MoveDWORDS(
1213			(CARD32*)((char*)pGlint->IOBase + OutputFIFO + 4),
1214	 		(CARD32*)srcp, count);
1215	}
1216	src += srcwidth;
1217    }
1218
1219    Permedia3DisableClipping(pScrn);
1220    Permedia3Sync(pScrn);
1221}
1222#endif
1223