riva_xaa.c revision a55f3320
1/*
2 * Copyright (c) 1993-1999 NVIDIA, Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24/* Hacked together from mga driver and 3.3.4 NVIDIA driver by
25   Jarno Paananen <jpaana@s2.org> */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "riva_include.h"
32#ifdef HAVE_XAA_H
33#include "xaalocal.h"
34#endif
35#include "xaarop.h"
36#include "miline.h"
37
38static void
39RivaSetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2)
40{
41    int height = y2-y1 + 1;
42    int width  = x2-x1 + 1;
43    RivaPtr pRiva = RivaPTR(pScrn);
44
45    RIVA_FIFO_FREE(pRiva->riva, Clip, 2);
46    pRiva->riva.Clip->TopLeft     = (y1     << 16) | (x1 & 0xffff);
47    pRiva->riva.Clip->WidthHeight = (height << 16) | width;
48}
49
50
51static void
52RivaDisableClipping(ScrnInfoPtr pScrn)
53{
54    RivaSetClippingRectangle(pScrn, 0, 0, 0x7fff, 0x7fff);
55}
56
57/*
58 * Set pattern. Internal routine. The upper bits of the colors
59 * are the ALPHA bits.  0 == transparency.
60 */
61static void
62RivaSetPattern(RivaPtr pRiva, int clr0, int clr1, int pat0, int pat1)
63{
64    RIVA_FIFO_FREE(pRiva->riva, Patt, 4);
65    pRiva->riva.Patt->Color0        = clr0;
66    pRiva->riva.Patt->Color1        = clr1;
67    pRiva->riva.Patt->Monochrome[0] = pat0;
68    pRiva->riva.Patt->Monochrome[1] = pat1;
69}
70
71/*
72 * Set ROP.  Translate X rop into ROP3.  Internal routine.
73 */
74static void
75RivaSetRopSolid(RivaPtr pRiva, int rop)
76{
77    if (pRiva->currentRop != rop) {
78        if (pRiva->currentRop >= 16)
79            RivaSetPattern(pRiva, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
80        pRiva->currentRop = rop;
81        RIVA_FIFO_FREE(pRiva->riva, Rop, 1);
82#ifdef HAVE_XAA_H
83        pRiva->riva.Rop->Rop3 = XAAGetCopyROP(rop);
84#endif
85    }
86}
87
88#ifdef HAVE_XAA_H
89static void
90RivaSetRopPattern(RivaPtr pRiva, int rop)
91{
92    if (pRiva->currentRop != (rop + 16)) {
93        pRiva->currentRop = rop + 16; /* +16 is important */
94        RIVA_FIFO_FREE(pRiva->riva, Rop, 1);
95        pRiva->riva.Rop->Rop3 = XAAGetPatternROP(rop);
96    }
97}
98
99/*
100 * Fill solid rectangles.
101 */
102static
103void RivaSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
104                         unsigned planemask)
105{
106    RivaPtr pRiva = RivaPTR(pScrn);
107
108    RivaSetRopSolid(pRiva, rop);
109    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1);
110    pRiva->riva.Bitmap->Color1A = color;
111}
112
113static void
114RivaSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
115{
116    RivaPtr pRiva = RivaPTR(pScrn);
117
118    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2);
119    pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (x << 16) | y;
120    write_mem_barrier();
121    pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h;
122    write_mem_barrier();
123}
124
125/*
126 * Screen to screen BLTs.
127 */
128static void
129RivaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
130                             unsigned planemask, int transparency_color)
131{
132    RivaSetRopSolid(RivaPTR(pScrn), rop);
133}
134
135static void
136RivaSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
137                               int x2, int y2, int w, int h)
138{
139    RivaPtr pRiva = RivaPTR(pScrn);
140
141    RIVA_FIFO_FREE(pRiva->riva, Blt, 3);
142    pRiva->riva.Blt->TopLeftSrc  = (y1 << 16) | x1;
143    pRiva->riva.Blt->TopLeftDst  = (y2 << 16) | x2;
144    write_mem_barrier();
145    pRiva->riva.Blt->WidthHeight = (h  << 16) | w;
146    write_mem_barrier();
147}
148
149
150/*
151 * Fill 8x8 monochrome pattern rectangles.  patternx and patterny are
152 * the overloaded pattern bits themselves. The pattern colors don't
153 * support 565, only 555. Hack around it.
154 */
155static void
156RivaSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny,
157                             int fg, int bg, int rop, unsigned planemask)
158{
159    RivaPtr pRiva = RivaPTR(pScrn);
160
161    RivaSetRopPattern(pRiva, rop);
162    if (pScrn->depth == 16)
163    {
164        fg = ((fg & 0x0000F800) << 8)
165           | ((fg & 0x000007E0) << 5)
166           | ((fg & 0x0000001F) << 3)
167           |        0xFF000000;
168        if (bg != -1)
169            bg = ((bg & 0x0000F800) << 8)
170               | ((bg & 0x000007E0) << 5)
171               | ((bg & 0x0000001F) << 3)
172               |        0xFF000000;
173        else
174            bg = 0;
175    }
176    else
177    {
178	fg |= pRiva->opaqueMonochrome;
179	bg  = (bg == -1) ? 0 : bg | pRiva->opaqueMonochrome;
180    };
181    RivaSetPattern(pRiva, bg, fg, patternx, patterny);
182    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1);
183    pRiva->riva.Bitmap->Color1A = fg;
184}
185
186static void
187RivaSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
188                                   int patternx, int patterny,
189                                   int x, int y, int w, int h)
190{
191    RivaPtr pRiva = RivaPTR(pScrn);
192
193    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2);
194    pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (x << 16) | y;
195    write_mem_barrier();
196    pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h;
197    write_mem_barrier();
198}
199#endif
200
201void
202RivaResetGraphics(ScrnInfoPtr pScrn)
203{
204    RivaPtr pRiva = RivaPTR(pScrn);
205
206    if(pRiva->NoAccel) return;
207
208    RIVA_FIFO_FREE(pRiva->riva, Patt, 1);
209    pRiva->riva.Patt->Shape = 0;
210    RivaDisableClipping(pScrn);
211    pRiva->currentRop = 16;  /* to force RivaSetRopSolid to reset the pattern */
212    RivaSetRopSolid(pRiva, GXcopy);
213}
214
215
216
217/*
218 * Synchronise with graphics engine.  Make sure it is idle before returning.
219 * Should attempt to yield CPU if busy for awhile.
220 */
221void RivaSync(ScrnInfoPtr pScrn)
222{
223    RivaPtr pRiva = RivaPTR(pScrn);
224    RIVA_BUSY(pRiva->riva);
225}
226
227#ifdef HAVE_XAA_H
228/* Color expansion */
229static void
230RivaSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
231                                             int fg, int bg, int rop,
232                                             unsigned int planemask)
233{
234    RivaPtr pRiva = RivaPTR(pScrn);
235
236    RivaSetRopSolid(pRiva, rop);
237
238    if ( bg == -1 )
239    {
240        /* Transparent case */
241        bg = 0x80000000;
242        pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData1C;
243    }
244    else
245    {
246        pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E;
247        if (pScrn->depth == 16)
248        {
249            bg = ((bg & 0x0000F800) << 8)
250               | ((bg & 0x000007E0) << 5)
251               | ((bg & 0x0000001F) << 3)
252               |        0xFF000000;
253        }
254        else
255        {
256            bg  |= pRiva->opaqueMonochrome;
257        };
258    }
259    pRiva->FgColor = fg;
260    pRiva->BgColor = bg;
261}
262
263static void
264RivaSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
265{
266    RivaPtr pRiva = RivaPTR(pScrn);
267
268    int t = pRiva->expandWidth;
269    CARD32 *pbits = (CARD32*)pRiva->expandBuffer;
270    CARD32 *d = (CARD32*)pRiva->expandFifo;
271
272    while(t >= 16)
273    {
274	RIVA_FIFO_FREE(pRiva->riva, Bitmap, 16);
275	d[0]  = pbits[0];
276	d[1]  = pbits[1];
277	d[2]  = pbits[2];
278	d[3]  = pbits[3];
279	d[4]  = pbits[4];
280	d[5]  = pbits[5];
281	d[6]  = pbits[6];
282	d[7]  = pbits[7];
283	d[8]  = pbits[8];
284	d[9]  = pbits[9];
285	d[10] = pbits[10];
286	d[11] = pbits[11];
287	d[12] = pbits[12];
288	d[13] = pbits[13];
289	d[14] = pbits[14];
290	d[15] = pbits[15];
291	t -= 16; pbits += 16;
292    }
293    if(t) {
294	RIVA_FIFO_FREE(pRiva->riva, Bitmap, t);
295	while(t >= 4)
296	{
297	    d[0]  = pbits[0];
298	    d[1]  = pbits[1];
299	    d[2]  = pbits[2];
300	    d[3]  = pbits[3];
301	    t -= 4; pbits += 4;
302	}
303	while(t--)
304	    *(d++) = *(pbits++);
305    }
306
307    if (!(--pRiva->expandRows)) { /* hardware bug workaround */
308       RIVA_FIFO_FREE(pRiva->riva, Blt, 1);
309       write_mem_barrier();
310       pRiva->riva.Blt->TopLeftSrc = 0;
311    }
312    write_mem_barrier();
313}
314
315static void
316RivaSubsequentColorExpandScanlineFifo(ScrnInfoPtr pScrn, int bufno)
317{
318    RivaPtr pRiva = RivaPTR(pScrn);
319
320    if ( --pRiva->expandRows ) {
321       RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth);
322    } else { /* hardware bug workaround */
323       RIVA_FIFO_FREE(pRiva->riva, Blt, 1);
324       write_mem_barrier();
325       pRiva->riva.Blt->TopLeftSrc = 0;
326    }
327    write_mem_barrier();
328}
329
330static void
331RivaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x,
332                                               int y, int w, int h,
333                                               int skipleft)
334{
335    int bw;
336    RivaPtr pRiva = RivaPTR(pScrn);
337
338    bw = (w + 31) & ~31;
339    pRiva->expandWidth = bw >> 5;
340
341    if ( pRiva->BgColor == 0x80000000 )
342    {
343        /* Use faster transparent method */
344        RIVA_FIFO_FREE(pRiva->riva, Bitmap, 5);
345        pRiva->riva.Bitmap->ClipC.TopLeft     = (y << 16) | ((x+skipleft)
346                                                           & 0xFFFF);
347        pRiva->riva.Bitmap->ClipC.BottomRight = ((y+h) << 16) | ((x+w)&0xffff);
348        pRiva->riva.Bitmap->Color1C           = pRiva->FgColor;
349        pRiva->riva.Bitmap->WidthHeightC      = (h << 16) | bw;
350        write_mem_barrier();
351        pRiva->riva.Bitmap->PointC            = (y << 16) | (x & 0xFFFF);
352        write_mem_barrier();
353    }
354    else
355    {
356        /* Opaque */
357        RIVA_FIFO_FREE(pRiva->riva, Bitmap, 7);
358        pRiva->riva.Bitmap->ClipE.TopLeft     = (y << 16) | ((x+skipleft)
359                                                           & 0xFFFF);
360        pRiva->riva.Bitmap->ClipE.BottomRight = ((y+h) << 16) | ((x+w)&0xffff);
361        pRiva->riva.Bitmap->Color0E           = pRiva->BgColor;
362        pRiva->riva.Bitmap->Color1E           = pRiva->FgColor;
363        pRiva->riva.Bitmap->WidthHeightInE  = (h << 16) | bw;
364        pRiva->riva.Bitmap->WidthHeightOutE = (h << 16) | bw;
365        write_mem_barrier();
366        pRiva->riva.Bitmap->PointE          = (y << 16) | (x & 0xFFFF);
367        write_mem_barrier();
368    }
369
370    pRiva->expandRows = h;
371
372    if(pRiva->expandWidth > (pRiva->riva.FifoEmptyCount >> 2)) {
373	pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandBuffer;
374	pRiva->AccelInfoRec->SubsequentColorExpandScanline =
375				RivaSubsequentColorExpandScanline;
376    } else {
377	pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandFifo;
378	pRiva->AccelInfoRec->SubsequentColorExpandScanline =
379				RivaSubsequentColorExpandScanlineFifo;
380	RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth);
381    }
382}
383
384static void
385RivaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
386{
387    RivaPtr pRiva = RivaPTR(pScrn);
388
389    RivaSetRopSolid(pRiva, rop);
390    pRiva->FgColor = color;
391}
392
393static void
394RivaSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
395{
396    RivaPtr pRiva = RivaPTR(pScrn);
397
398    RIVA_FIFO_FREE(pRiva->riva, Line, 3);
399    pRiva->riva.Line->Color = pRiva->FgColor;
400    pRiva->riva.Line->Lin[0].point0 = ((y << 16) | ( x & 0xffff));
401    write_mem_barrier();
402    if ( dir ==DEGREES_0 )
403        pRiva->riva.Line->Lin[0].point1 = ((y << 16) | (( x + len ) & 0xffff));
404    else
405        pRiva->riva.Line->Lin[0].point1 = (((y + len) << 16) | ( x & 0xffff));
406    write_mem_barrier();
407}
408
409static void
410RivaSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
411                              int x2, int y2, int flags)
412{
413    RivaPtr pRiva = RivaPTR(pScrn);
414    Bool  lastPoint = !(flags & OMIT_LAST);
415
416    RIVA_FIFO_FREE(pRiva->riva, Line, lastPoint ? 5 : 3);
417    pRiva->riva.Line->Color = pRiva->FgColor;
418    pRiva->riva.Line->Lin[0].point0 = ((y1 << 16) | (x1 & 0xffff));
419    write_mem_barrier();
420    pRiva->riva.Line->Lin[0].point1 = ((y2 << 16) | (x2 & 0xffff));
421    write_mem_barrier();
422    if (lastPoint)
423    {
424        pRiva->riva.Line->Lin[1].point0 = ((y2 << 16) | (x2 & 0xffff));
425        write_mem_barrier();
426        pRiva->riva.Line->Lin[1].point1 = (((y2 + 1) << 16) | (x2 & 0xffff));
427        write_mem_barrier();
428    }
429}
430
431static void
432RivaValidatePolyArc(
433   GCPtr        pGC,
434   unsigned long changes,
435   DrawablePtr pDraw
436){
437   if(pGC->planemask != ~0) return;
438
439   if(!pGC->lineWidth &&
440	((pGC->alu != GXcopy) || (pGC->lineStyle != LineSolid)))
441   {
442        pGC->ops->PolyArc = miZeroPolyArc;
443   }
444}
445
446static void
447RivaValidatePolyPoint(
448   GCPtr        pGC,
449   unsigned long changes,
450   DrawablePtr pDraw
451){
452   pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
453
454   if(pGC->planemask != ~0) return;
455
456   if(pGC->alu != GXcopy)
457        pGC->ops->PolyPoint = miPolyPoint;
458}
459#endif
460
461/* Initialize XAA acceleration info */
462Bool
463RivaAccelInit(ScreenPtr pScreen)
464{
465#ifdef HAVE_XAA_H
466    XAAInfoRecPtr infoPtr;
467    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
468    RivaPtr pRiva = RivaPTR(pScrn);
469
470    pRiva->AccelInfoRec = infoPtr = XAACreateInfoRec();
471    if(!infoPtr) return FALSE;
472
473    /* fill out infoPtr here */
474    infoPtr->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
475
476    /* sync */
477    infoPtr->Sync = RivaSync;
478
479    /* solid fills */
480    infoPtr->SolidFillFlags = NO_PLANEMASK;
481    infoPtr->SetupForSolidFill = RivaSetupForSolidFill;
482    infoPtr->SubsequentSolidFillRect = RivaSubsequentSolidFillRect;
483
484    /* screen to screen copy */
485    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK;
486    infoPtr->SetupForScreenToScreenCopy = RivaSetupForScreenToScreenCopy;
487    infoPtr->SubsequentScreenToScreenCopy = RivaSubsequentScreenToScreenCopy;
488
489    /* 8x8 mono patterns */
490    /*
491     * Set pattern opaque bits based on pixel format.
492     */
493    pRiva->opaqueMonochrome = ~((1 << pScrn->depth) - 1);
494
495    infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
496				       HARDWARE_PATTERN_PROGRAMMED_BITS |
497				       NO_PLANEMASK;
498    infoPtr->SetupForMono8x8PatternFill = RivaSetupForMono8x8PatternFill;
499    infoPtr->SubsequentMono8x8PatternFillRect =
500        RivaSubsequentMono8x8PatternFillRect;
501
502    /* Color expansion */
503    infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
504				BIT_ORDER_IN_BYTE_LSBFIRST |
505				NO_PLANEMASK |
506				CPU_TRANSFER_PAD_DWORD |
507				LEFT_EDGE_CLIPPING |
508				LEFT_EDGE_CLIPPING_NEGATIVE_X;
509
510    infoPtr->NumScanlineColorExpandBuffers = 1;
511
512    infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
513        RivaSetupForScanlineCPUToScreenColorExpandFill;
514    infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
515        RivaSubsequentScanlineCPUToScreenColorExpandFill;
516
517    pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E;
518
519    /* Allocate buffer for color expansion and also image writes in the
520       future */
521    pRiva->expandBuffer = xnfalloc(((pScrn->virtualX*pScrn->bitsPerPixel)/8) + 8);
522
523
524    infoPtr->ScanlineColorExpandBuffers = &pRiva->expandBuffer;
525    infoPtr->SubsequentColorExpandScanline = RivaSubsequentColorExpandScanline;
526
527    infoPtr->SolidLineFlags = infoPtr->SolidFillFlags;
528    infoPtr->SetupForSolidLine = RivaSetupForSolidLine;
529    infoPtr->SubsequentSolidHorVertLine =
530		RivaSubsequentSolidHorVertLine;
531    infoPtr->SubsequentSolidTwoPointLine =
532		RivaSubsequentSolidTwoPointLine;
533    infoPtr->SetClippingRectangle = RivaSetClippingRectangle;
534    infoPtr->DisableClipping = RivaDisableClipping;
535    infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
536    miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
537
538    infoPtr->ValidatePolyArc = RivaValidatePolyArc;
539    infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask;
540    infoPtr->ValidatePolyPoint = RivaValidatePolyPoint;
541    infoPtr->PolyPointMask = GCFunction | GCPlaneMask;
542
543    RivaResetGraphics(pScrn);
544
545    return(XAAInit(pScreen, infoPtr));
546#else
547    return FALSE;
548#endif
549}
550