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