nv_xaa.c revision 092d2b73
1fc5a983dSmrg/*
2fc5a983dSmrg * Copyright (c) 2003 NVIDIA, Corporation
3fc5a983dSmrg *
4fc5a983dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5fc5a983dSmrg * copy of this software and associated documentation files (the
6fc5a983dSmrg * "Software"), to deal in the Software without restriction, including
7fc5a983dSmrg * without limitation the rights to use, copy, modify, merge, publish,
8fc5a983dSmrg * distribute, sublicense, and/or sell copies of the Software, and to
9fc5a983dSmrg * permit persons to whom the Software is furnished to do so, subject to
10fc5a983dSmrg * the following conditions:
11fc5a983dSmrg *
12fc5a983dSmrg * The above copyright notice and this permission notice shall be included
13fc5a983dSmrg * in all copies or substantial portions of the Software.
14fc5a983dSmrg *
15fc5a983dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16fc5a983dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17fc5a983dSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18fc5a983dSmrg * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19fc5a983dSmrg * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20fc5a983dSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21fc5a983dSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22fc5a983dSmrg */
23fc5a983dSmrg
24fc5a983dSmrg#ifdef HAVE_CONFIG_H
25fc5a983dSmrg#include "config.h"
26fc5a983dSmrg#endif
27fc5a983dSmrg
28fc5a983dSmrg#include "nv_include.h"
29bd304fc0Smrg#ifdef HAVE_XAA_H
30fc5a983dSmrg#include "xaalocal.h"
31bd304fc0Smrg#endif
32fc5a983dSmrg#include "miline.h"
33fc5a983dSmrg#include "nv_dma.h"
34fc5a983dSmrg
35fc5a983dSmrgstatic const int NVCopyROP[16] =
36fc5a983dSmrg{
37fc5a983dSmrg   0x00,            /* GXclear */
38fc5a983dSmrg   0x88,            /* GXand */
39fc5a983dSmrg   0x44,            /* GXandReverse */
40fc5a983dSmrg   0xCC,            /* GXcopy */
41fc5a983dSmrg   0x22,            /* GXandInverted */
42fc5a983dSmrg   0xAA,            /* GXnoop */
43fc5a983dSmrg   0x66,            /* GXxor */
44fc5a983dSmrg   0xEE,            /* GXor */
45fc5a983dSmrg   0x11,            /* GXnor */
46fc5a983dSmrg   0x99,            /* GXequiv */
47fc5a983dSmrg   0x55,            /* GXinvert*/
48fc5a983dSmrg   0xDD,            /* GXorReverse */
49fc5a983dSmrg   0x33,            /* GXcopyInverted */
50fc5a983dSmrg   0xBB,            /* GXorInverted */
51fc5a983dSmrg   0x77,            /* GXnand */
52fc5a983dSmrg   0xFF             /* GXset */
53fc5a983dSmrg};
54fc5a983dSmrg
55fc5a983dSmrgstatic const int NVCopyROP_PM[16] =
56fc5a983dSmrg{
57fc5a983dSmrg   0x0A,            /* GXclear */
58fc5a983dSmrg   0x8A,            /* GXand */
59fc5a983dSmrg   0x4A,            /* GXandReverse */
60fc5a983dSmrg   0xCA,            /* GXcopy */
61fc5a983dSmrg   0x2A,            /* GXandInverted */
62fc5a983dSmrg   0xAA,            /* GXnoop */
63fc5a983dSmrg   0x6A,            /* GXxor */
64fc5a983dSmrg   0xEA,            /* GXor */
65fc5a983dSmrg   0x1A,            /* GXnor */
66fc5a983dSmrg   0x9A,            /* GXequiv */
67fc5a983dSmrg   0x5A,            /* GXinvert*/
68fc5a983dSmrg   0xDA,            /* GXorReverse */
69fc5a983dSmrg   0x3A,            /* GXcopyInverted */
70fc5a983dSmrg   0xBA,            /* GXorInverted */
71fc5a983dSmrg   0x7A,            /* GXnand */
72fc5a983dSmrg   0xFA             /* GXset */
73fc5a983dSmrg};
74fc5a983dSmrg
75fc5a983dSmrgstatic const int NVPatternROP[16] =
76fc5a983dSmrg{
77fc5a983dSmrg   0x00,
78fc5a983dSmrg   0xA0,
79fc5a983dSmrg   0x50,
80fc5a983dSmrg   0xF0,
81fc5a983dSmrg   0x0A,
82fc5a983dSmrg   0xAA,
83fc5a983dSmrg   0x5A,
84fc5a983dSmrg   0xFA,
85fc5a983dSmrg   0x05,
86fc5a983dSmrg   0xA5,
87fc5a983dSmrg   0x55,
88fc5a983dSmrg   0xF5,
89fc5a983dSmrg   0x0F,
90fc5a983dSmrg   0xAF,
91fc5a983dSmrg   0x5F,
92fc5a983dSmrg   0xFF
93fc5a983dSmrg};
94fc5a983dSmrg
95fc5a983dSmrgvoid
96fc5a983dSmrgNVDmaKickoff(NVPtr pNv)
97fc5a983dSmrg{
98fc5a983dSmrg    if(pNv->dmaCurrent != pNv->dmaPut) {
99fc5a983dSmrg        pNv->dmaPut = pNv->dmaCurrent;
100fc5a983dSmrg        WRITE_PUT(pNv,  pNv->dmaPut);
101fc5a983dSmrg    }
102fc5a983dSmrg}
103fc5a983dSmrg
104fc5a983dSmrg
105fc5a983dSmrg/* There is a HW race condition with videoram command buffers.
106fc5a983dSmrg   You can't jump to the location of your put offset.  We write put
107fc5a983dSmrg   at the jump offset + SKIPS dwords with noop padding in between
108fc5a983dSmrg   to solve this problem */
109092d2b73Smacallan#define SKIPS  8
110fc5a983dSmrg
111fc5a983dSmrgvoid
112fc5a983dSmrgNVDmaWait (
113fc5a983dSmrg   NVPtr pNv,
114fc5a983dSmrg   int size
115fc5a983dSmrg){
116fc5a983dSmrg    int dmaGet;
117fc5a983dSmrg
118fc5a983dSmrg    size++;
119fc5a983dSmrg
120fc5a983dSmrg    while(pNv->dmaFree < size) {
121fc5a983dSmrg       dmaGet = READ_GET(pNv);
122fc5a983dSmrg
123fc5a983dSmrg       if(pNv->dmaPut >= dmaGet) {
124fc5a983dSmrg           pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
125fc5a983dSmrg           if(pNv->dmaFree < size) {
126fc5a983dSmrg               NVDmaNext(pNv, 0x20000000);
127fc5a983dSmrg               if(dmaGet <= SKIPS) {
128fc5a983dSmrg                   if(pNv->dmaPut <= SKIPS) /* corner case - will be idle */
129fc5a983dSmrg                      WRITE_PUT(pNv, SKIPS + 1);
130fc5a983dSmrg                   do { dmaGet = READ_GET(pNv); }
131fc5a983dSmrg                   while(dmaGet <= SKIPS);
132fc5a983dSmrg               }
133fc5a983dSmrg               WRITE_PUT(pNv, SKIPS);
134fc5a983dSmrg               pNv->dmaCurrent = pNv->dmaPut = SKIPS;
135fc5a983dSmrg               pNv->dmaFree = dmaGet - (SKIPS + 1);
136fc5a983dSmrg           }
137fc5a983dSmrg       } else
138fc5a983dSmrg           pNv->dmaFree = dmaGet - pNv->dmaCurrent - 1;
139fc5a983dSmrg    }
140fc5a983dSmrg}
141fc5a983dSmrg
142fc5a983dSmrgvoid
143fc5a983dSmrgNVWaitVSync(NVPtr pNv)
144fc5a983dSmrg{
145fc5a983dSmrg    NVDmaStart(pNv, 0x0000A12C, 1);
146fc5a983dSmrg    NVDmaNext (pNv, 0);
147fc5a983dSmrg    NVDmaStart(pNv, 0x0000A134, 1);
148fc5a983dSmrg    NVDmaNext (pNv, pNv->CRTCnumber);
149fc5a983dSmrg    NVDmaStart(pNv, 0x0000A100, 1);
150fc5a983dSmrg    NVDmaNext (pNv, 0);
151fc5a983dSmrg    NVDmaStart(pNv, 0x0000A130, 1);
152fc5a983dSmrg    NVDmaNext (pNv, 0);
153fc5a983dSmrg}
154fc5a983dSmrg
155fc5a983dSmrg/*
156fc5a983dSmrg  currentRop =  0-15  solid fill
157fc5a983dSmrg               16-31  8x8 pattern fill
158fc5a983dSmrg               32-47  solid fill with planemask
159fc5a983dSmrg*/
160fc5a983dSmrg
161fc5a983dSmrgstatic void
162fc5a983dSmrgNVSetPattern(
163fc5a983dSmrg   ScrnInfoPtr pScrn,
164fc5a983dSmrg   CARD32 clr0,
165fc5a983dSmrg   CARD32 clr1,
166fc5a983dSmrg   CARD32 pat0,
167fc5a983dSmrg   CARD32 pat1
168fc5a983dSmrg)
169fc5a983dSmrg{
170fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
171fc5a983dSmrg
172fc5a983dSmrg    NVDmaStart(pNv, PATTERN_COLOR_0, 4);
173fc5a983dSmrg    NVDmaNext (pNv, clr0);
174fc5a983dSmrg    NVDmaNext (pNv, clr1);
175fc5a983dSmrg    NVDmaNext (pNv, pat0);
176fc5a983dSmrg    NVDmaNext (pNv, pat1);
177fc5a983dSmrg}
178fc5a983dSmrg
17905c1003fSmacallanvoid
180fc5a983dSmrgNVSetRopSolid(ScrnInfoPtr pScrn, CARD32 rop, CARD32 planemask)
181fc5a983dSmrg{
182fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
183fc5a983dSmrg
184fc5a983dSmrg    if(planemask != ~0) {
185fc5a983dSmrg        NVSetPattern(pScrn, 0, planemask, ~0, ~0);
186fc5a983dSmrg        if(pNv->currentRop != (rop + 32)) {
187fc5a983dSmrg           NVDmaStart(pNv, ROP_SET, 1);
188fc5a983dSmrg           NVDmaNext (pNv, NVCopyROP_PM[rop]);
189fc5a983dSmrg           pNv->currentRop = rop + 32;
190fc5a983dSmrg        }
191fc5a983dSmrg    } else
192fc5a983dSmrg    if (pNv->currentRop != rop) {
193fc5a983dSmrg        if(pNv->currentRop >= 16)
194fc5a983dSmrg             NVSetPattern(pScrn, ~0, ~0, ~0, ~0);
195fc5a983dSmrg        NVDmaStart(pNv, ROP_SET, 1);
196fc5a983dSmrg        NVDmaNext (pNv, NVCopyROP[rop]);
197fc5a983dSmrg        pNv->currentRop = rop;
198fc5a983dSmrg    }
199fc5a983dSmrg}
200fc5a983dSmrg
201fc5a983dSmrgvoid NVResetGraphics(ScrnInfoPtr pScrn)
202fc5a983dSmrg{
203fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
204fc5a983dSmrg    CARD32 surfaceFormat, patternFormat, rectFormat, lineFormat;
205fc5a983dSmrg    int pitch, i;
206fc5a983dSmrg
207fc5a983dSmrg    if(pNv->NoAccel) return;
208fc5a983dSmrg
209fc5a983dSmrg    pitch = pNv->CurrentLayout.displayWidth *
210fc5a983dSmrg            (pNv->CurrentLayout.bitsPerPixel >> 3);
211fc5a983dSmrg
212fc5a983dSmrg    pNv->dmaBase = (CARD32*)(&pNv->FbStart[pNv->FbUsableSize]);
213fc5a983dSmrg
214fc5a983dSmrg    for(i = 0; i < SKIPS; i++)
215fc5a983dSmrg      pNv->dmaBase[i] = 0x00000000;
216fc5a983dSmrg
217fc5a983dSmrg    pNv->dmaBase[0x0 + SKIPS] = 0x00040000;
218fc5a983dSmrg    pNv->dmaBase[0x1 + SKIPS] = 0x80000010;
219fc5a983dSmrg    pNv->dmaBase[0x2 + SKIPS] = 0x00042000;
220fc5a983dSmrg    pNv->dmaBase[0x3 + SKIPS] = 0x80000011;
221fc5a983dSmrg    pNv->dmaBase[0x4 + SKIPS] = 0x00044000;
222fc5a983dSmrg    pNv->dmaBase[0x5 + SKIPS] = 0x80000012;
223fc5a983dSmrg    pNv->dmaBase[0x6 + SKIPS] = 0x00046000;
224fc5a983dSmrg    pNv->dmaBase[0x7 + SKIPS] = 0x80000013;
225fc5a983dSmrg    pNv->dmaBase[0x8 + SKIPS] = 0x00048000;
226fc5a983dSmrg    pNv->dmaBase[0x9 + SKIPS] = 0x80000014;
227fc5a983dSmrg    pNv->dmaBase[0xA + SKIPS] = 0x0004A000;
228fc5a983dSmrg    pNv->dmaBase[0xB + SKIPS] = 0x80000015;
229fc5a983dSmrg    pNv->dmaBase[0xC + SKIPS] = 0x0004C000;
230fc5a983dSmrg    pNv->dmaBase[0xD + SKIPS] = 0x80000016;
231fc5a983dSmrg    pNv->dmaBase[0xE + SKIPS] = 0x0004E000;
232fc5a983dSmrg    pNv->dmaBase[0xF + SKIPS] = 0x80000017;
233fc5a983dSmrg
234fc5a983dSmrg    pNv->dmaPut = 0;
235fc5a983dSmrg    pNv->dmaCurrent = 16 + SKIPS;
236fc5a983dSmrg    pNv->dmaMax = 8191;
237fc5a983dSmrg    pNv->dmaFree = pNv->dmaMax - pNv->dmaCurrent;
238fc5a983dSmrg
239fc5a983dSmrg    switch(pNv->CurrentLayout.depth) {
240fc5a983dSmrg    case 24:
241fc5a983dSmrg       surfaceFormat = SURFACE_FORMAT_DEPTH24;
242fc5a983dSmrg       patternFormat = PATTERN_FORMAT_DEPTH24;
243fc5a983dSmrg       rectFormat    = RECT_FORMAT_DEPTH24;
244fc5a983dSmrg       lineFormat    = LINE_FORMAT_DEPTH24;
245fc5a983dSmrg       break;
246fc5a983dSmrg    case 16:
247fc5a983dSmrg    case 15:
248fc5a983dSmrg       surfaceFormat = SURFACE_FORMAT_DEPTH16;
249fc5a983dSmrg       patternFormat = PATTERN_FORMAT_DEPTH16;
250fc5a983dSmrg       rectFormat    = RECT_FORMAT_DEPTH16;
251fc5a983dSmrg       lineFormat    = LINE_FORMAT_DEPTH16;
252fc5a983dSmrg       break;
253fc5a983dSmrg    default:
254fc5a983dSmrg       surfaceFormat = SURFACE_FORMAT_DEPTH8;
255fc5a983dSmrg       patternFormat = PATTERN_FORMAT_DEPTH8;
256fc5a983dSmrg       rectFormat    = RECT_FORMAT_DEPTH8;
257fc5a983dSmrg       lineFormat    = LINE_FORMAT_DEPTH8;
258fc5a983dSmrg       break;
259fc5a983dSmrg    }
260fc5a983dSmrg
261fc5a983dSmrg    NVDmaStart(pNv, SURFACE_FORMAT, 4);
262fc5a983dSmrg    NVDmaNext (pNv, surfaceFormat);
263fc5a983dSmrg    NVDmaNext (pNv, pitch | (pitch << 16));
264fc5a983dSmrg    NVDmaNext (pNv, 0);
265fc5a983dSmrg    NVDmaNext (pNv, 0);
266fc5a983dSmrg
267fc5a983dSmrg    NVDmaStart(pNv, PATTERN_FORMAT, 1);
268fc5a983dSmrg    NVDmaNext (pNv, patternFormat);
269fc5a983dSmrg
270fc5a983dSmrg    NVDmaStart(pNv, RECT_FORMAT, 1);
271fc5a983dSmrg    NVDmaNext (pNv, rectFormat);
272fc5a983dSmrg
273fc5a983dSmrg    NVDmaStart(pNv, LINE_FORMAT, 1);
274fc5a983dSmrg    NVDmaNext (pNv, lineFormat);
275fc5a983dSmrg
276fc5a983dSmrg    pNv->currentRop = ~0;  /* set to something invalid */
277fc5a983dSmrg    NVSetRopSolid(pScrn, GXcopy, ~0);
278fc5a983dSmrg
279fc5a983dSmrg    NVDmaKickoff(pNv);
280fc5a983dSmrg}
281fc5a983dSmrg
282fc5a983dSmrgvoid NVSync(ScrnInfoPtr pScrn)
283fc5a983dSmrg{
284fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
28505c1003fSmacallan    int bail = 10000000;
28605c1003fSmacallan
287fc5a983dSmrg    if(pNv->DMAKickoffCallback)
288fc5a983dSmrg       (*pNv->DMAKickoffCallback)(pScrn);
289fc5a983dSmrg
29005c1003fSmacallan    while((READ_GET(pNv) != pNv->dmaPut) && (bail > 0)) bail--;
29105c1003fSmacallan    if (bail == 0) {
29205c1003fSmacallan    	xf86Msg(X_ERROR, "DMA drain timeout\n");
29305c1003fSmacallan    	goto crap;
29405c1003fSmacallan    }
29505c1003fSmacallan
29605c1003fSmacallan    bail = 10000000;
29705c1003fSmacallan    while((pNv->PGRAPH[0x0700/4]) && (bail > 0)) bail--;
29805c1003fSmacallan    if (bail == 0) {
29905c1003fSmacallan    	xf86Msg(X_ERROR, "engine stalled\n");
30005c1003fSmacallan    	goto crap;
30105c1003fSmacallan    }
30205c1003fSmacallan    return;
30305c1003fSmacallan
30405c1003fSmacallancrap:
30505c1003fSmacallan    NVResetGraphics(pScrn);
306fc5a983dSmrg}
307fc5a983dSmrg
30805c1003fSmacallan void
309fc5a983dSmrgNVDMAKickoffCallback (ScrnInfoPtr pScrn)
310fc5a983dSmrg{
311fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
312fc5a983dSmrg
313fc5a983dSmrg   NVDmaKickoff(pNv);
314fc5a983dSmrg   pNv->DMAKickoffCallback = NULL;
315fc5a983dSmrg}
316fc5a983dSmrg
317bd304fc0Smrg#ifdef HAVE_XAA_H
318fc5a983dSmrgstatic void
319fc5a983dSmrgNVSetupForScreenToScreenCopy(
320fc5a983dSmrg   ScrnInfoPtr pScrn,
321fc5a983dSmrg   int xdir, int ydir,
322fc5a983dSmrg   int rop,
323fc5a983dSmrg   unsigned planemask,
324fc5a983dSmrg   int transparency_color
325fc5a983dSmrg)
326fc5a983dSmrg{
327fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
328fc5a983dSmrg
329fc5a983dSmrg    planemask |= ~0 << pNv->CurrentLayout.depth;
330fc5a983dSmrg
331fc5a983dSmrg    NVSetRopSolid(pScrn, rop, planemask);
332fc5a983dSmrg
333fc5a983dSmrg    pNv->DMAKickoffCallback = NVDMAKickoffCallback;
334fc5a983dSmrg}
335fc5a983dSmrg
336fc5a983dSmrgstatic void
337fc5a983dSmrgNVSubsequentScreenToScreenCopy(
338fc5a983dSmrg   ScrnInfoPtr pScrn,
339fc5a983dSmrg   int x1, int y1,
340fc5a983dSmrg   int x2, int y2,
341fc5a983dSmrg   int w, int h
342fc5a983dSmrg)
343fc5a983dSmrg{
344fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
345fc5a983dSmrg
346fc5a983dSmrg    NVDmaStart(pNv, BLIT_POINT_SRC, 3);
347fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | x1);
348fc5a983dSmrg    NVDmaNext (pNv, (y2 << 16) | x2);
349fc5a983dSmrg    NVDmaNext (pNv, (h  << 16) | w);
350fc5a983dSmrg
351fc5a983dSmrg    if((w * h) >= 512)
352fc5a983dSmrg       NVDmaKickoff(pNv);
353fc5a983dSmrg}
354fc5a983dSmrg
355fc5a983dSmrgstatic void
356fc5a983dSmrgNVSetupForSolidFill(
357fc5a983dSmrg   ScrnInfoPtr pScrn,
358fc5a983dSmrg   int color,
359fc5a983dSmrg   int rop,
360fc5a983dSmrg   unsigned planemask
361fc5a983dSmrg)
362fc5a983dSmrg{
363fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
364fc5a983dSmrg
365fc5a983dSmrg   planemask |= ~0 << pNv->CurrentLayout.depth;
366fc5a983dSmrg
367fc5a983dSmrg   NVSetRopSolid(pScrn, rop, planemask);
368fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
369fc5a983dSmrg   NVDmaNext (pNv, color);
370fc5a983dSmrg
371fc5a983dSmrg   pNv->DMAKickoffCallback = NVDMAKickoffCallback;
372fc5a983dSmrg}
373fc5a983dSmrg
374fc5a983dSmrgstatic void
375fc5a983dSmrgNVSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
376fc5a983dSmrg{
377fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
378fc5a983dSmrg
379fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
380fc5a983dSmrg   NVDmaNext (pNv, (x << 16) | y);
381fc5a983dSmrg   NVDmaNext (pNv, (w << 16) | h);
382fc5a983dSmrg
383fc5a983dSmrg   if((w * h) >= 512)
384fc5a983dSmrg      NVDmaKickoff(pNv);
385fc5a983dSmrg}
386fc5a983dSmrg
387fc5a983dSmrgstatic void
388fc5a983dSmrgNVSetupForMono8x8PatternFill (
389fc5a983dSmrg   ScrnInfoPtr pScrn,
390fc5a983dSmrg   int patternx, int patterny,
391fc5a983dSmrg   int fg, int bg,
392fc5a983dSmrg   int rop,
393fc5a983dSmrg   unsigned planemask
394fc5a983dSmrg)
395fc5a983dSmrg{
396fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
397fc5a983dSmrg
398fc5a983dSmrg   planemask = ~0 << pNv->CurrentLayout.depth;
399fc5a983dSmrg
400fc5a983dSmrg   fg |= planemask;
401fc5a983dSmrg   if(bg == -1) bg = 0;
402fc5a983dSmrg   else bg |= planemask;
403fc5a983dSmrg
404fc5a983dSmrg   if (pNv->currentRop != (rop + 16)) {
405fc5a983dSmrg       NVDmaStart(pNv, ROP_SET, 1);
406fc5a983dSmrg       NVDmaNext (pNv, NVPatternROP[rop]);
407fc5a983dSmrg       pNv->currentRop = rop + 16;
408fc5a983dSmrg   }
409fc5a983dSmrg
410fc5a983dSmrg   NVSetPattern(pScrn, bg, fg, patternx, patterny);
411fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
412fc5a983dSmrg   NVDmaNext (pNv, fg);
413fc5a983dSmrg
414fc5a983dSmrg   pNv->DMAKickoffCallback = NVDMAKickoffCallback;
415fc5a983dSmrg}
416fc5a983dSmrg
417fc5a983dSmrgstatic void
418fc5a983dSmrgNVSubsequentMono8x8PatternFillRect(
419fc5a983dSmrg   ScrnInfoPtr pScrn,
420fc5a983dSmrg   int patternx, int patterny,
421fc5a983dSmrg   int x, int y,
422fc5a983dSmrg   int w, int h
423fc5a983dSmrg)
424fc5a983dSmrg{
425fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
426fc5a983dSmrg
427fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
428fc5a983dSmrg   NVDmaNext (pNv, (x << 16) | y);
429fc5a983dSmrg   NVDmaNext (pNv, (w << 16) | h);
430fc5a983dSmrg
431fc5a983dSmrg   if((w * h) >= 512)
432fc5a983dSmrg      NVDmaKickoff(pNv);
433fc5a983dSmrg}
434fc5a983dSmrg
435fc5a983dSmrgstatic CARD32 _bg_pixel;
436fc5a983dSmrgstatic CARD32 _fg_pixel;
437fc5a983dSmrgstatic Bool _transparent;
438fc5a983dSmrgstatic CARD32 _color_expand_dwords;
439fc5a983dSmrgstatic CARD32 _color_expand_offset;
440fc5a983dSmrgstatic int _remaining;
441fc5a983dSmrgstatic unsigned char *_storage_buffer[1];
442fc5a983dSmrg
443fc5a983dSmrgstatic void
444fc5a983dSmrgNVSetupForScanlineCPUToScreenColorExpandFill (
445fc5a983dSmrg   ScrnInfoPtr pScrn,
446fc5a983dSmrg   int fg, int bg,
447fc5a983dSmrg   int rop,
448fc5a983dSmrg   unsigned int planemask
449fc5a983dSmrg)
450fc5a983dSmrg{
451fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
452fc5a983dSmrg
453fc5a983dSmrg   CARD32 mask = ~0 << pNv->CurrentLayout.depth;
454fc5a983dSmrg
455fc5a983dSmrg   planemask |= mask;
456fc5a983dSmrg   _fg_pixel = fg | mask;
457fc5a983dSmrg
458fc5a983dSmrg   if(bg == -1) {
459fc5a983dSmrg      _transparent = TRUE;
460fc5a983dSmrg   } else {
461fc5a983dSmrg      _transparent = FALSE;
462fc5a983dSmrg      _bg_pixel = bg | mask;
463fc5a983dSmrg   }
464fc5a983dSmrg
465fc5a983dSmrg   NVSetRopSolid (pScrn, rop, planemask);
466fc5a983dSmrg}
467fc5a983dSmrg
468fc5a983dSmrgstatic void
469fc5a983dSmrgNVSubsequentScanlineCPUToScreenColorExpandFill (
470fc5a983dSmrg    ScrnInfoPtr pScrn,
471fc5a983dSmrg    int x, int y,
472fc5a983dSmrg    int w, int h,
473fc5a983dSmrg    int skipleft
474fc5a983dSmrg)
475fc5a983dSmrg{
476fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
477fc5a983dSmrg   int bw = (w + 31) & ~31;
478fc5a983dSmrg
479fc5a983dSmrg   _color_expand_dwords = bw >> 5;
480fc5a983dSmrg   _remaining = h;
481fc5a983dSmrg
482fc5a983dSmrg   if(_transparent) {
483fc5a983dSmrg      NVDmaStart(pNv, RECT_EXPAND_ONE_COLOR_CLIP, 5);
484fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | ((x + skipleft) & 0xFFFF));
485fc5a983dSmrg      NVDmaNext (pNv, ((y + h) << 16) | ((x + w) & 0xFFFF));
486fc5a983dSmrg      NVDmaNext (pNv, _fg_pixel);
487fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
488fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | (x & 0xFFFF));
489fc5a983dSmrg      _color_expand_offset = RECT_EXPAND_ONE_COLOR_DATA(0);
490fc5a983dSmrg   } else {
491fc5a983dSmrg      NVDmaStart(pNv, RECT_EXPAND_TWO_COLOR_CLIP, 7);
492fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | ((x + skipleft) & 0xFFFF));
493fc5a983dSmrg      NVDmaNext (pNv, ((y + h) << 16) | ((x + w) & 0xFFFF));
494fc5a983dSmrg      NVDmaNext (pNv, _bg_pixel);
495fc5a983dSmrg      NVDmaNext (pNv, _fg_pixel);
496fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
497fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
498fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | (x & 0xFFFF));
499fc5a983dSmrg      _color_expand_offset = RECT_EXPAND_TWO_COLOR_DATA(0);
500fc5a983dSmrg   }
501fc5a983dSmrg
502fc5a983dSmrg   NVDmaStart(pNv, _color_expand_offset, _color_expand_dwords);
503fc5a983dSmrg   _storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
504fc5a983dSmrg}
505fc5a983dSmrg
506fc5a983dSmrgstatic void
507fc5a983dSmrgNVSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
508fc5a983dSmrg{
509fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
510fc5a983dSmrg
511fc5a983dSmrg   pNv->dmaCurrent += _color_expand_dwords;
512fc5a983dSmrg
513fc5a983dSmrg   if(--_remaining) {
514fc5a983dSmrg       NVDmaStart(pNv, _color_expand_offset, _color_expand_dwords);
515fc5a983dSmrg       _storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
516fc5a983dSmrg   } else {
517fc5a983dSmrg       /* hardware bug workaround */
518fc5a983dSmrg       NVDmaStart(pNv, BLIT_POINT_SRC, 1);
519fc5a983dSmrg       NVDmaNext (pNv, 0);
520fc5a983dSmrg       NVDmaKickoff(pNv);
521fc5a983dSmrg   }
522fc5a983dSmrg}
523fc5a983dSmrg
524fc5a983dSmrgstatic void
525fc5a983dSmrgNVSetupForScanlineImageWrite(
526fc5a983dSmrg   ScrnInfoPtr pScrn, int rop,
527fc5a983dSmrg   unsigned int planemask,
528fc5a983dSmrg   int trans_color,
529fc5a983dSmrg   int bpp, int depth
530fc5a983dSmrg)
531fc5a983dSmrg{
532fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
533fc5a983dSmrg
534fc5a983dSmrg   planemask |= ~0 << pNv->CurrentLayout.depth;
535fc5a983dSmrg
536fc5a983dSmrg   NVSetRopSolid (pScrn, rop, planemask);
537fc5a983dSmrg}
538fc5a983dSmrg
539fc5a983dSmrgstatic CARD32 _image_size;
540fc5a983dSmrgstatic CARD32 _image_srcpoint;
541fc5a983dSmrgstatic CARD32 _image_dstpoint;
542fc5a983dSmrgstatic CARD32 _image_dstpitch;
543fc5a983dSmrg
544fc5a983dSmrgstatic void
545fc5a983dSmrgNVSubsequentScanlineImageWriteRect(
546fc5a983dSmrg   ScrnInfoPtr pScrn,
547fc5a983dSmrg   int x, int y,
548fc5a983dSmrg   int w, int h,
549fc5a983dSmrg   int skipleft
550fc5a983dSmrg)
551fc5a983dSmrg{
552fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
553fc5a983dSmrg   int Bpp = pNv->CurrentLayout.bitsPerPixel >> 3;
554fc5a983dSmrg   int image_srcpitch;
555fc5a983dSmrg
556fc5a983dSmrg   _image_size = (1 << 16) | (w - skipleft);
557fc5a983dSmrg   _image_srcpoint = skipleft;
558fc5a983dSmrg   _image_dstpoint = (y << 16) | (x + skipleft);
559fc5a983dSmrg   _remaining = h;
560fc5a983dSmrg   _image_dstpitch = pNv->CurrentLayout.displayWidth * Bpp;
561fc5a983dSmrg   image_srcpitch =  ((w * Bpp) + 63) & ~63;
562fc5a983dSmrg   _storage_buffer[0] = pNv->FbStart + pNv->ScratchBufferStart;
563fc5a983dSmrg
564fc5a983dSmrg   NVSync(pScrn);
565fc5a983dSmrg
566fc5a983dSmrg   NVDmaStart(pNv, SURFACE_PITCH, 2);
567fc5a983dSmrg   NVDmaNext (pNv, (_image_dstpitch << 16) | image_srcpitch);
568fc5a983dSmrg   NVDmaNext (pNv, pNv->ScratchBufferStart);
569fc5a983dSmrg}
570fc5a983dSmrg
571fc5a983dSmrgstatic void NVSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
572fc5a983dSmrg{
573fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
574fc5a983dSmrg
575fc5a983dSmrg   NVDmaStart(pNv, BLIT_POINT_SRC, 3);
576fc5a983dSmrg   NVDmaNext (pNv, _image_srcpoint);
577fc5a983dSmrg   NVDmaNext (pNv, _image_dstpoint);
578fc5a983dSmrg   NVDmaNext (pNv, _image_size);
579fc5a983dSmrg   NVDmaKickoff(pNv);
580fc5a983dSmrg
581fc5a983dSmrg   if(--_remaining) {
582fc5a983dSmrg      _image_dstpoint += (1 << 16);
583fc5a983dSmrg      NVSync(pScrn);
584fc5a983dSmrg   } else {
585fc5a983dSmrg      NVDmaStart(pNv, SURFACE_PITCH, 2);
586fc5a983dSmrg      NVDmaNext (pNv, _image_dstpitch | (_image_dstpitch << 16));
587fc5a983dSmrg      NVDmaNext (pNv, 0);
588fc5a983dSmrg   }
589fc5a983dSmrg}
590fc5a983dSmrg
591fc5a983dSmrgstatic void
592fc5a983dSmrgNVSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
593fc5a983dSmrg{
594fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
595fc5a983dSmrg
596fc5a983dSmrg    planemask |= ~0 << pNv->CurrentLayout.depth;
597fc5a983dSmrg
598fc5a983dSmrg    NVSetRopSolid(pScrn, rop, planemask);
599fc5a983dSmrg
600fc5a983dSmrg    _fg_pixel = color;
601fc5a983dSmrg
602fc5a983dSmrg    pNv->DMAKickoffCallback = NVDMAKickoffCallback;
603fc5a983dSmrg}
604fc5a983dSmrg
605fc5a983dSmrgstatic void
606fc5a983dSmrgNVSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
607fc5a983dSmrg{
608fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
609fc5a983dSmrg
610fc5a983dSmrg    NVDmaStart(pNv, LINE_COLOR, 1);
611fc5a983dSmrg    NVDmaNext (pNv, _fg_pixel);
612fc5a983dSmrg    NVDmaStart(pNv, LINE_LINES(0), 2);
613fc5a983dSmrg    NVDmaNext (pNv, (y << 16) | ( x & 0xffff));
614fc5a983dSmrg    if(dir == DEGREES_0) {
615fc5a983dSmrg       NVDmaNext (pNv, (y << 16) | ((x + len) & 0xffff));
616fc5a983dSmrg    } else {
617fc5a983dSmrg       NVDmaNext (pNv, ((y + len) << 16) | (x & 0xffff));
618fc5a983dSmrg    }
619fc5a983dSmrg}
620fc5a983dSmrg
621fc5a983dSmrgstatic void
622fc5a983dSmrgNVSubsequentSolidTwoPointLine(
623fc5a983dSmrg   ScrnInfoPtr pScrn,
624fc5a983dSmrg   int x1, int y1,
625fc5a983dSmrg   int x2, int y2,
626fc5a983dSmrg   int flags
627fc5a983dSmrg)
628fc5a983dSmrg{
629fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
630fc5a983dSmrg    Bool drawLast = !(flags & OMIT_LAST);
631fc5a983dSmrg
632fc5a983dSmrg    NVDmaStart(pNv, LINE_COLOR, 1);
633fc5a983dSmrg    NVDmaNext (pNv, _fg_pixel);
634fc5a983dSmrg    NVDmaStart(pNv, LINE_LINES(0), drawLast ? 4 : 2);
635fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | (x1 & 0xffff));
636fc5a983dSmrg    NVDmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
637fc5a983dSmrg    if(drawLast) {
638fc5a983dSmrg        NVDmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
639fc5a983dSmrg        NVDmaNext (pNv, ((y2 + 1) << 16) | (x2 & 0xffff));
640fc5a983dSmrg    }
641fc5a983dSmrg}
642fc5a983dSmrg
643fc5a983dSmrgstatic void
644fc5a983dSmrgNVSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
645fc5a983dSmrg{
646fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
647fc5a983dSmrg    int h = y2 - y1 + 1;
648fc5a983dSmrg    int w = x2 - x1 + 1;
649fc5a983dSmrg
650fc5a983dSmrg    NVDmaStart(pNv, CLIP_POINT, 2);
651fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | x1);
652fc5a983dSmrg    NVDmaNext (pNv, (h << 16) | w);
653fc5a983dSmrg}
654fc5a983dSmrg
655fc5a983dSmrgstatic void
656fc5a983dSmrgNVDisableClipping(ScrnInfoPtr pScrn)
657fc5a983dSmrg{
658fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
659fc5a983dSmrg
660fc5a983dSmrg    NVDmaStart(pNv, CLIP_POINT, 2);
661fc5a983dSmrg    NVDmaNext (pNv, 0);
662fc5a983dSmrg    NVDmaNext (pNv, 0x7FFF7FFF);
663fc5a983dSmrg}
664fc5a983dSmrg
665bd304fc0Smrg#endif
666fc5a983dSmrg
667fc5a983dSmrg/* Initialize XAA acceleration info */
668fc5a983dSmrgBool
669fc5a983dSmrgNVAccelInit(ScreenPtr pScreen)
670fc5a983dSmrg{
671bd304fc0Smrg#ifdef HAVE_XAA_H
672bd304fc0Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
673fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
674fc5a983dSmrg   XAAInfoRecPtr accel;
675fc5a983dSmrg
676fc5a983dSmrg   accel = pNv->AccelInfoRec = XAACreateInfoRec();
677fc5a983dSmrg   if(!accel) return FALSE;
678fc5a983dSmrg
679fc5a983dSmrg   accel->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
680fc5a983dSmrg   accel->Sync = NVSync;
681fc5a983dSmrg
682fc5a983dSmrg   accel->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
683fc5a983dSmrg   accel->SetupForScreenToScreenCopy = NVSetupForScreenToScreenCopy;
684fc5a983dSmrg   accel->SubsequentScreenToScreenCopy = NVSubsequentScreenToScreenCopy;
685fc5a983dSmrg
686fc5a983dSmrg   accel->SolidFillFlags = 0;
687fc5a983dSmrg   accel->SetupForSolidFill = NVSetupForSolidFill;
688fc5a983dSmrg   accel->SubsequentSolidFillRect = NVSubsequentSolidFillRect;
689fc5a983dSmrg
690fc5a983dSmrg   accel->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
691fc5a983dSmrg                                    HARDWARE_PATTERN_PROGRAMMED_BITS |
692fc5a983dSmrg                                    NO_PLANEMASK;
693fc5a983dSmrg   accel->SetupForMono8x8PatternFill = NVSetupForMono8x8PatternFill;
694fc5a983dSmrg   accel->SubsequentMono8x8PatternFillRect = NVSubsequentMono8x8PatternFillRect;
695fc5a983dSmrg
696fc5a983dSmrg   accel->ScanlineCPUToScreenColorExpandFillFlags =
697fc5a983dSmrg                                    BIT_ORDER_IN_BYTE_LSBFIRST |
698fc5a983dSmrg                                    CPU_TRANSFER_PAD_DWORD |
699fc5a983dSmrg                                    LEFT_EDGE_CLIPPING |
700fc5a983dSmrg                                    LEFT_EDGE_CLIPPING_NEGATIVE_X;
701fc5a983dSmrg   accel->NumScanlineColorExpandBuffers = 1;
702fc5a983dSmrg   accel->SetupForScanlineCPUToScreenColorExpandFill =
703fc5a983dSmrg            NVSetupForScanlineCPUToScreenColorExpandFill;
704fc5a983dSmrg   accel->SubsequentScanlineCPUToScreenColorExpandFill =
705fc5a983dSmrg            NVSubsequentScanlineCPUToScreenColorExpandFill;
706fc5a983dSmrg   accel->SubsequentColorExpandScanline =
707fc5a983dSmrg            NVSubsequentColorExpandScanline;
708fc5a983dSmrg   accel->ScanlineColorExpandBuffers = _storage_buffer;
709fc5a983dSmrg
710fc5a983dSmrg   accel->ScanlineImageWriteFlags = NO_GXCOPY |
711fc5a983dSmrg                                    NO_TRANSPARENCY |
712fc5a983dSmrg                                    LEFT_EDGE_CLIPPING |
713fc5a983dSmrg                                    LEFT_EDGE_CLIPPING_NEGATIVE_X;
714fc5a983dSmrg   accel->NumScanlineImageWriteBuffers = 1;
715fc5a983dSmrg   accel->SetupForScanlineImageWrite = NVSetupForScanlineImageWrite;
716fc5a983dSmrg   accel->SubsequentScanlineImageWriteRect = NVSubsequentScanlineImageWriteRect;
717fc5a983dSmrg   accel->SubsequentImageWriteScanline = NVSubsequentImageWriteScanline;
718fc5a983dSmrg   accel->ScanlineImageWriteBuffers = _storage_buffer;
719fc5a983dSmrg
720fc5a983dSmrg   accel->SolidLineFlags = 0;
721fc5a983dSmrg   accel->SetupForSolidLine = NVSetupForSolidLine;
722fc5a983dSmrg   accel->SubsequentSolidHorVertLine = NVSubsequentSolidHorVertLine;
723fc5a983dSmrg   accel->SubsequentSolidTwoPointLine = NVSubsequentSolidTwoPointLine;
724fc5a983dSmrg   accel->SetClippingRectangle = NVSetClippingRectangle;
725fc5a983dSmrg   accel->DisableClipping = NVDisableClipping;
726fc5a983dSmrg   accel->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
727fc5a983dSmrg
728fc5a983dSmrg   miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
729fc5a983dSmrg
730fc5a983dSmrg   return (XAAInit(pScreen, accel));
731bd304fc0Smrg#else
732bd304fc0Smrg   return FALSE;
733bd304fc0Smrg#endif
734fc5a983dSmrg}
735