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