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