nv_xaa.c revision bd304fc0
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 */
109fc5a983dSmrg#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
179fc5a983dSmrgstatic void
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);
285fc5a983dSmrg
286fc5a983dSmrg    if(pNv->DMAKickoffCallback)
287fc5a983dSmrg       (*pNv->DMAKickoffCallback)(pScrn);
288fc5a983dSmrg
289fc5a983dSmrg    while(READ_GET(pNv) != pNv->dmaPut);
290fc5a983dSmrg
291fc5a983dSmrg    while(pNv->PGRAPH[0x0700/4]);
292fc5a983dSmrg}
293fc5a983dSmrg
294fc5a983dSmrgstatic void
295fc5a983dSmrgNVDMAKickoffCallback (ScrnInfoPtr pScrn)
296fc5a983dSmrg{
297fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
298fc5a983dSmrg
299fc5a983dSmrg   NVDmaKickoff(pNv);
300fc5a983dSmrg   pNv->DMAKickoffCallback = NULL;
301fc5a983dSmrg}
302fc5a983dSmrg
303bd304fc0Smrg#ifdef HAVE_XAA_H
304fc5a983dSmrgstatic void
305fc5a983dSmrgNVSetupForScreenToScreenCopy(
306fc5a983dSmrg   ScrnInfoPtr pScrn,
307fc5a983dSmrg   int xdir, int ydir,
308fc5a983dSmrg   int rop,
309fc5a983dSmrg   unsigned planemask,
310fc5a983dSmrg   int transparency_color
311fc5a983dSmrg)
312fc5a983dSmrg{
313fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
314fc5a983dSmrg
315fc5a983dSmrg    planemask |= ~0 << pNv->CurrentLayout.depth;
316fc5a983dSmrg
317fc5a983dSmrg    NVSetRopSolid(pScrn, rop, planemask);
318fc5a983dSmrg
319fc5a983dSmrg    pNv->DMAKickoffCallback = NVDMAKickoffCallback;
320fc5a983dSmrg}
321fc5a983dSmrg
322fc5a983dSmrgstatic void
323fc5a983dSmrgNVSubsequentScreenToScreenCopy(
324fc5a983dSmrg   ScrnInfoPtr pScrn,
325fc5a983dSmrg   int x1, int y1,
326fc5a983dSmrg   int x2, int y2,
327fc5a983dSmrg   int w, int h
328fc5a983dSmrg)
329fc5a983dSmrg{
330fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
331fc5a983dSmrg
332fc5a983dSmrg    NVDmaStart(pNv, BLIT_POINT_SRC, 3);
333fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | x1);
334fc5a983dSmrg    NVDmaNext (pNv, (y2 << 16) | x2);
335fc5a983dSmrg    NVDmaNext (pNv, (h  << 16) | w);
336fc5a983dSmrg
337fc5a983dSmrg    if((w * h) >= 512)
338fc5a983dSmrg       NVDmaKickoff(pNv);
339fc5a983dSmrg}
340fc5a983dSmrg
341fc5a983dSmrgstatic void
342fc5a983dSmrgNVSetupForSolidFill(
343fc5a983dSmrg   ScrnInfoPtr pScrn,
344fc5a983dSmrg   int color,
345fc5a983dSmrg   int rop,
346fc5a983dSmrg   unsigned planemask
347fc5a983dSmrg)
348fc5a983dSmrg{
349fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
350fc5a983dSmrg
351fc5a983dSmrg   planemask |= ~0 << pNv->CurrentLayout.depth;
352fc5a983dSmrg
353fc5a983dSmrg   NVSetRopSolid(pScrn, rop, planemask);
354fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
355fc5a983dSmrg   NVDmaNext (pNv, color);
356fc5a983dSmrg
357fc5a983dSmrg   pNv->DMAKickoffCallback = NVDMAKickoffCallback;
358fc5a983dSmrg}
359fc5a983dSmrg
360fc5a983dSmrgstatic void
361fc5a983dSmrgNVSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
362fc5a983dSmrg{
363fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
364fc5a983dSmrg
365fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
366fc5a983dSmrg   NVDmaNext (pNv, (x << 16) | y);
367fc5a983dSmrg   NVDmaNext (pNv, (w << 16) | h);
368fc5a983dSmrg
369fc5a983dSmrg   if((w * h) >= 512)
370fc5a983dSmrg      NVDmaKickoff(pNv);
371fc5a983dSmrg}
372fc5a983dSmrg
373fc5a983dSmrgstatic void
374fc5a983dSmrgNVSetupForMono8x8PatternFill (
375fc5a983dSmrg   ScrnInfoPtr pScrn,
376fc5a983dSmrg   int patternx, int patterny,
377fc5a983dSmrg   int fg, int bg,
378fc5a983dSmrg   int rop,
379fc5a983dSmrg   unsigned planemask
380fc5a983dSmrg)
381fc5a983dSmrg{
382fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
383fc5a983dSmrg
384fc5a983dSmrg   planemask = ~0 << pNv->CurrentLayout.depth;
385fc5a983dSmrg
386fc5a983dSmrg   fg |= planemask;
387fc5a983dSmrg   if(bg == -1) bg = 0;
388fc5a983dSmrg   else bg |= planemask;
389fc5a983dSmrg
390fc5a983dSmrg   if (pNv->currentRop != (rop + 16)) {
391fc5a983dSmrg       NVDmaStart(pNv, ROP_SET, 1);
392fc5a983dSmrg       NVDmaNext (pNv, NVPatternROP[rop]);
393fc5a983dSmrg       pNv->currentRop = rop + 16;
394fc5a983dSmrg   }
395fc5a983dSmrg
396fc5a983dSmrg   NVSetPattern(pScrn, bg, fg, patternx, patterny);
397fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
398fc5a983dSmrg   NVDmaNext (pNv, fg);
399fc5a983dSmrg
400fc5a983dSmrg   pNv->DMAKickoffCallback = NVDMAKickoffCallback;
401fc5a983dSmrg}
402fc5a983dSmrg
403fc5a983dSmrgstatic void
404fc5a983dSmrgNVSubsequentMono8x8PatternFillRect(
405fc5a983dSmrg   ScrnInfoPtr pScrn,
406fc5a983dSmrg   int patternx, int patterny,
407fc5a983dSmrg   int x, int y,
408fc5a983dSmrg   int w, int h
409fc5a983dSmrg)
410fc5a983dSmrg{
411fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
412fc5a983dSmrg
413fc5a983dSmrg   NVDmaStart(pNv, RECT_SOLID_RECTS(0), 2);
414fc5a983dSmrg   NVDmaNext (pNv, (x << 16) | y);
415fc5a983dSmrg   NVDmaNext (pNv, (w << 16) | h);
416fc5a983dSmrg
417fc5a983dSmrg   if((w * h) >= 512)
418fc5a983dSmrg      NVDmaKickoff(pNv);
419fc5a983dSmrg}
420fc5a983dSmrg
421fc5a983dSmrgstatic CARD32 _bg_pixel;
422fc5a983dSmrgstatic CARD32 _fg_pixel;
423fc5a983dSmrgstatic Bool _transparent;
424fc5a983dSmrgstatic CARD32 _color_expand_dwords;
425fc5a983dSmrgstatic CARD32 _color_expand_offset;
426fc5a983dSmrgstatic int _remaining;
427fc5a983dSmrgstatic unsigned char *_storage_buffer[1];
428fc5a983dSmrg
429fc5a983dSmrgstatic void
430fc5a983dSmrgNVSetupForScanlineCPUToScreenColorExpandFill (
431fc5a983dSmrg   ScrnInfoPtr pScrn,
432fc5a983dSmrg   int fg, int bg,
433fc5a983dSmrg   int rop,
434fc5a983dSmrg   unsigned int planemask
435fc5a983dSmrg)
436fc5a983dSmrg{
437fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
438fc5a983dSmrg
439fc5a983dSmrg   CARD32 mask = ~0 << pNv->CurrentLayout.depth;
440fc5a983dSmrg
441fc5a983dSmrg   planemask |= mask;
442fc5a983dSmrg   _fg_pixel = fg | mask;
443fc5a983dSmrg
444fc5a983dSmrg   if(bg == -1) {
445fc5a983dSmrg      _transparent = TRUE;
446fc5a983dSmrg   } else {
447fc5a983dSmrg      _transparent = FALSE;
448fc5a983dSmrg      _bg_pixel = bg | mask;
449fc5a983dSmrg   }
450fc5a983dSmrg
451fc5a983dSmrg   NVSetRopSolid (pScrn, rop, planemask);
452fc5a983dSmrg}
453fc5a983dSmrg
454fc5a983dSmrgstatic void
455fc5a983dSmrgNVSubsequentScanlineCPUToScreenColorExpandFill (
456fc5a983dSmrg    ScrnInfoPtr pScrn,
457fc5a983dSmrg    int x, int y,
458fc5a983dSmrg    int w, int h,
459fc5a983dSmrg    int skipleft
460fc5a983dSmrg)
461fc5a983dSmrg{
462fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
463fc5a983dSmrg   int bw = (w + 31) & ~31;
464fc5a983dSmrg
465fc5a983dSmrg   _color_expand_dwords = bw >> 5;
466fc5a983dSmrg   _remaining = h;
467fc5a983dSmrg
468fc5a983dSmrg   if(_transparent) {
469fc5a983dSmrg      NVDmaStart(pNv, RECT_EXPAND_ONE_COLOR_CLIP, 5);
470fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | ((x + skipleft) & 0xFFFF));
471fc5a983dSmrg      NVDmaNext (pNv, ((y + h) << 16) | ((x + w) & 0xFFFF));
472fc5a983dSmrg      NVDmaNext (pNv, _fg_pixel);
473fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
474fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | (x & 0xFFFF));
475fc5a983dSmrg      _color_expand_offset = RECT_EXPAND_ONE_COLOR_DATA(0);
476fc5a983dSmrg   } else {
477fc5a983dSmrg      NVDmaStart(pNv, RECT_EXPAND_TWO_COLOR_CLIP, 7);
478fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | ((x + skipleft) & 0xFFFF));
479fc5a983dSmrg      NVDmaNext (pNv, ((y + h) << 16) | ((x + w) & 0xFFFF));
480fc5a983dSmrg      NVDmaNext (pNv, _bg_pixel);
481fc5a983dSmrg      NVDmaNext (pNv, _fg_pixel);
482fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
483fc5a983dSmrg      NVDmaNext (pNv, (h << 16) | bw);
484fc5a983dSmrg      NVDmaNext (pNv, (y << 16) | (x & 0xFFFF));
485fc5a983dSmrg      _color_expand_offset = RECT_EXPAND_TWO_COLOR_DATA(0);
486fc5a983dSmrg   }
487fc5a983dSmrg
488fc5a983dSmrg   NVDmaStart(pNv, _color_expand_offset, _color_expand_dwords);
489fc5a983dSmrg   _storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
490fc5a983dSmrg}
491fc5a983dSmrg
492fc5a983dSmrgstatic void
493fc5a983dSmrgNVSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
494fc5a983dSmrg{
495fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
496fc5a983dSmrg
497fc5a983dSmrg   pNv->dmaCurrent += _color_expand_dwords;
498fc5a983dSmrg
499fc5a983dSmrg   if(--_remaining) {
500fc5a983dSmrg       NVDmaStart(pNv, _color_expand_offset, _color_expand_dwords);
501fc5a983dSmrg       _storage_buffer[0] = (unsigned char*)&pNv->dmaBase[pNv->dmaCurrent];
502fc5a983dSmrg   } else {
503fc5a983dSmrg       /* hardware bug workaround */
504fc5a983dSmrg       NVDmaStart(pNv, BLIT_POINT_SRC, 1);
505fc5a983dSmrg       NVDmaNext (pNv, 0);
506fc5a983dSmrg       NVDmaKickoff(pNv);
507fc5a983dSmrg   }
508fc5a983dSmrg}
509fc5a983dSmrg
510fc5a983dSmrgstatic void
511fc5a983dSmrgNVSetupForScanlineImageWrite(
512fc5a983dSmrg   ScrnInfoPtr pScrn, int rop,
513fc5a983dSmrg   unsigned int planemask,
514fc5a983dSmrg   int trans_color,
515fc5a983dSmrg   int bpp, int depth
516fc5a983dSmrg)
517fc5a983dSmrg{
518fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
519fc5a983dSmrg
520fc5a983dSmrg   planemask |= ~0 << pNv->CurrentLayout.depth;
521fc5a983dSmrg
522fc5a983dSmrg   NVSetRopSolid (pScrn, rop, planemask);
523fc5a983dSmrg}
524fc5a983dSmrg
525fc5a983dSmrgstatic CARD32 _image_size;
526fc5a983dSmrgstatic CARD32 _image_srcpoint;
527fc5a983dSmrgstatic CARD32 _image_dstpoint;
528fc5a983dSmrgstatic CARD32 _image_dstpitch;
529fc5a983dSmrg
530fc5a983dSmrgstatic void
531fc5a983dSmrgNVSubsequentScanlineImageWriteRect(
532fc5a983dSmrg   ScrnInfoPtr pScrn,
533fc5a983dSmrg   int x, int y,
534fc5a983dSmrg   int w, int h,
535fc5a983dSmrg   int skipleft
536fc5a983dSmrg)
537fc5a983dSmrg{
538fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
539fc5a983dSmrg   int Bpp = pNv->CurrentLayout.bitsPerPixel >> 3;
540fc5a983dSmrg   int image_srcpitch;
541fc5a983dSmrg
542fc5a983dSmrg   _image_size = (1 << 16) | (w - skipleft);
543fc5a983dSmrg   _image_srcpoint = skipleft;
544fc5a983dSmrg   _image_dstpoint = (y << 16) | (x + skipleft);
545fc5a983dSmrg   _remaining = h;
546fc5a983dSmrg   _image_dstpitch = pNv->CurrentLayout.displayWidth * Bpp;
547fc5a983dSmrg   image_srcpitch =  ((w * Bpp) + 63) & ~63;
548fc5a983dSmrg   _storage_buffer[0] = pNv->FbStart + pNv->ScratchBufferStart;
549fc5a983dSmrg
550fc5a983dSmrg   NVSync(pScrn);
551fc5a983dSmrg
552fc5a983dSmrg   NVDmaStart(pNv, SURFACE_PITCH, 2);
553fc5a983dSmrg   NVDmaNext (pNv, (_image_dstpitch << 16) | image_srcpitch);
554fc5a983dSmrg   NVDmaNext (pNv, pNv->ScratchBufferStart);
555fc5a983dSmrg}
556fc5a983dSmrg
557fc5a983dSmrgstatic void NVSubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno)
558fc5a983dSmrg{
559fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
560fc5a983dSmrg
561fc5a983dSmrg   NVDmaStart(pNv, BLIT_POINT_SRC, 3);
562fc5a983dSmrg   NVDmaNext (pNv, _image_srcpoint);
563fc5a983dSmrg   NVDmaNext (pNv, _image_dstpoint);
564fc5a983dSmrg   NVDmaNext (pNv, _image_size);
565fc5a983dSmrg   NVDmaKickoff(pNv);
566fc5a983dSmrg
567fc5a983dSmrg   if(--_remaining) {
568fc5a983dSmrg      _image_dstpoint += (1 << 16);
569fc5a983dSmrg      NVSync(pScrn);
570fc5a983dSmrg   } else {
571fc5a983dSmrg      NVDmaStart(pNv, SURFACE_PITCH, 2);
572fc5a983dSmrg      NVDmaNext (pNv, _image_dstpitch | (_image_dstpitch << 16));
573fc5a983dSmrg      NVDmaNext (pNv, 0);
574fc5a983dSmrg   }
575fc5a983dSmrg}
576fc5a983dSmrg
577fc5a983dSmrgstatic void
578fc5a983dSmrgNVSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
579fc5a983dSmrg{
580fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
581fc5a983dSmrg
582fc5a983dSmrg    planemask |= ~0 << pNv->CurrentLayout.depth;
583fc5a983dSmrg
584fc5a983dSmrg    NVSetRopSolid(pScrn, rop, planemask);
585fc5a983dSmrg
586fc5a983dSmrg    _fg_pixel = color;
587fc5a983dSmrg
588fc5a983dSmrg    pNv->DMAKickoffCallback = NVDMAKickoffCallback;
589fc5a983dSmrg}
590fc5a983dSmrg
591fc5a983dSmrgstatic void
592fc5a983dSmrgNVSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
593fc5a983dSmrg{
594fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
595fc5a983dSmrg
596fc5a983dSmrg    NVDmaStart(pNv, LINE_COLOR, 1);
597fc5a983dSmrg    NVDmaNext (pNv, _fg_pixel);
598fc5a983dSmrg    NVDmaStart(pNv, LINE_LINES(0), 2);
599fc5a983dSmrg    NVDmaNext (pNv, (y << 16) | ( x & 0xffff));
600fc5a983dSmrg    if(dir == DEGREES_0) {
601fc5a983dSmrg       NVDmaNext (pNv, (y << 16) | ((x + len) & 0xffff));
602fc5a983dSmrg    } else {
603fc5a983dSmrg       NVDmaNext (pNv, ((y + len) << 16) | (x & 0xffff));
604fc5a983dSmrg    }
605fc5a983dSmrg}
606fc5a983dSmrg
607fc5a983dSmrgstatic void
608fc5a983dSmrgNVSubsequentSolidTwoPointLine(
609fc5a983dSmrg   ScrnInfoPtr pScrn,
610fc5a983dSmrg   int x1, int y1,
611fc5a983dSmrg   int x2, int y2,
612fc5a983dSmrg   int flags
613fc5a983dSmrg)
614fc5a983dSmrg{
615fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
616fc5a983dSmrg    Bool drawLast = !(flags & OMIT_LAST);
617fc5a983dSmrg
618fc5a983dSmrg    NVDmaStart(pNv, LINE_COLOR, 1);
619fc5a983dSmrg    NVDmaNext (pNv, _fg_pixel);
620fc5a983dSmrg    NVDmaStart(pNv, LINE_LINES(0), drawLast ? 4 : 2);
621fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | (x1 & 0xffff));
622fc5a983dSmrg    NVDmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
623fc5a983dSmrg    if(drawLast) {
624fc5a983dSmrg        NVDmaNext (pNv, (y2 << 16) | (x2 & 0xffff));
625fc5a983dSmrg        NVDmaNext (pNv, ((y2 + 1) << 16) | (x2 & 0xffff));
626fc5a983dSmrg    }
627fc5a983dSmrg}
628fc5a983dSmrg
629fc5a983dSmrgstatic void
630fc5a983dSmrgNVSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
631fc5a983dSmrg{
632fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
633fc5a983dSmrg    int h = y2 - y1 + 1;
634fc5a983dSmrg    int w = x2 - x1 + 1;
635fc5a983dSmrg
636fc5a983dSmrg    NVDmaStart(pNv, CLIP_POINT, 2);
637fc5a983dSmrg    NVDmaNext (pNv, (y1 << 16) | x1);
638fc5a983dSmrg    NVDmaNext (pNv, (h << 16) | w);
639fc5a983dSmrg}
640fc5a983dSmrg
641fc5a983dSmrgstatic void
642fc5a983dSmrgNVDisableClipping(ScrnInfoPtr pScrn)
643fc5a983dSmrg{
644fc5a983dSmrg    NVPtr pNv = NVPTR(pScrn);
645fc5a983dSmrg
646fc5a983dSmrg    NVDmaStart(pNv, CLIP_POINT, 2);
647fc5a983dSmrg    NVDmaNext (pNv, 0);
648fc5a983dSmrg    NVDmaNext (pNv, 0x7FFF7FFF);
649fc5a983dSmrg}
650fc5a983dSmrg
651bd304fc0Smrg#endif
652fc5a983dSmrg
653fc5a983dSmrg/* Initialize XAA acceleration info */
654fc5a983dSmrgBool
655fc5a983dSmrgNVAccelInit(ScreenPtr pScreen)
656fc5a983dSmrg{
657bd304fc0Smrg#ifdef HAVE_XAA_H
658bd304fc0Smrg   ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
659fc5a983dSmrg   NVPtr pNv = NVPTR(pScrn);
660fc5a983dSmrg   XAAInfoRecPtr accel;
661fc5a983dSmrg
662fc5a983dSmrg   accel = pNv->AccelInfoRec = XAACreateInfoRec();
663fc5a983dSmrg   if(!accel) return FALSE;
664fc5a983dSmrg
665fc5a983dSmrg   accel->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
666fc5a983dSmrg   accel->Sync = NVSync;
667fc5a983dSmrg
668fc5a983dSmrg   accel->ScreenToScreenCopyFlags = NO_TRANSPARENCY;
669fc5a983dSmrg   accel->SetupForScreenToScreenCopy = NVSetupForScreenToScreenCopy;
670fc5a983dSmrg   accel->SubsequentScreenToScreenCopy = NVSubsequentScreenToScreenCopy;
671fc5a983dSmrg
672fc5a983dSmrg   accel->SolidFillFlags = 0;
673fc5a983dSmrg   accel->SetupForSolidFill = NVSetupForSolidFill;
674fc5a983dSmrg   accel->SubsequentSolidFillRect = NVSubsequentSolidFillRect;
675fc5a983dSmrg
676fc5a983dSmrg   accel->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
677fc5a983dSmrg                                    HARDWARE_PATTERN_PROGRAMMED_BITS |
678fc5a983dSmrg                                    NO_PLANEMASK;
679fc5a983dSmrg   accel->SetupForMono8x8PatternFill = NVSetupForMono8x8PatternFill;
680fc5a983dSmrg   accel->SubsequentMono8x8PatternFillRect = NVSubsequentMono8x8PatternFillRect;
681fc5a983dSmrg
682fc5a983dSmrg   accel->ScanlineCPUToScreenColorExpandFillFlags =
683fc5a983dSmrg                                    BIT_ORDER_IN_BYTE_LSBFIRST |
684fc5a983dSmrg                                    CPU_TRANSFER_PAD_DWORD |
685fc5a983dSmrg                                    LEFT_EDGE_CLIPPING |
686fc5a983dSmrg                                    LEFT_EDGE_CLIPPING_NEGATIVE_X;
687fc5a983dSmrg   accel->NumScanlineColorExpandBuffers = 1;
688fc5a983dSmrg   accel->SetupForScanlineCPUToScreenColorExpandFill =
689fc5a983dSmrg            NVSetupForScanlineCPUToScreenColorExpandFill;
690fc5a983dSmrg   accel->SubsequentScanlineCPUToScreenColorExpandFill =
691fc5a983dSmrg            NVSubsequentScanlineCPUToScreenColorExpandFill;
692fc5a983dSmrg   accel->SubsequentColorExpandScanline =
693fc5a983dSmrg            NVSubsequentColorExpandScanline;
694fc5a983dSmrg   accel->ScanlineColorExpandBuffers = _storage_buffer;
695fc5a983dSmrg
696fc5a983dSmrg   accel->ScanlineImageWriteFlags = NO_GXCOPY |
697fc5a983dSmrg                                    NO_TRANSPARENCY |
698fc5a983dSmrg                                    LEFT_EDGE_CLIPPING |
699fc5a983dSmrg                                    LEFT_EDGE_CLIPPING_NEGATIVE_X;
700fc5a983dSmrg   accel->NumScanlineImageWriteBuffers = 1;
701fc5a983dSmrg   accel->SetupForScanlineImageWrite = NVSetupForScanlineImageWrite;
702fc5a983dSmrg   accel->SubsequentScanlineImageWriteRect = NVSubsequentScanlineImageWriteRect;
703fc5a983dSmrg   accel->SubsequentImageWriteScanline = NVSubsequentImageWriteScanline;
704fc5a983dSmrg   accel->ScanlineImageWriteBuffers = _storage_buffer;
705fc5a983dSmrg
706fc5a983dSmrg   accel->SolidLineFlags = 0;
707fc5a983dSmrg   accel->SetupForSolidLine = NVSetupForSolidLine;
708fc5a983dSmrg   accel->SubsequentSolidHorVertLine = NVSubsequentSolidHorVertLine;
709fc5a983dSmrg   accel->SubsequentSolidTwoPointLine = NVSubsequentSolidTwoPointLine;
710fc5a983dSmrg   accel->SetClippingRectangle = NVSetClippingRectangle;
711fc5a983dSmrg   accel->DisableClipping = NVDisableClipping;
712fc5a983dSmrg   accel->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
713fc5a983dSmrg
714fc5a983dSmrg   miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
715fc5a983dSmrg
716fc5a983dSmrg   return (XAAInit(pScreen, accel));
717bd304fc0Smrg#else
718bd304fc0Smrg   return FALSE;
719bd304fc0Smrg#endif
720fc5a983dSmrg}
721