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