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