riva_xaa.c revision bd304fc0
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
88static void
89RivaSetRopPattern(RivaPtr pRiva, int rop)
90{
91    if (pRiva->currentRop != (rop + 16)) {
92        pRiva->currentRop = rop + 16; /* +16 is important */
93        RIVA_FIFO_FREE(pRiva->riva, Rop, 1);
94        pRiva->riva.Rop->Rop3 = XAAGetPatternROP(rop);
95    }
96}
97#ifdef HAVE_XAA_H
98/*
99 * Fill solid rectangles.
100 */
101static
102void RivaSetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop,
103                         unsigned planemask)
104{
105    RivaPtr pRiva = RivaPTR(pScrn);
106
107    RivaSetRopSolid(pRiva, rop);
108    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1);
109    pRiva->riva.Bitmap->Color1A = color;
110}
111
112static void
113RivaSubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h)
114{
115    RivaPtr pRiva = RivaPTR(pScrn);
116
117    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2);
118    pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (x << 16) | y;
119    write_mem_barrier();
120    pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h;
121    write_mem_barrier();
122}
123
124/*
125 * Screen to screen BLTs.
126 */
127static void
128RivaSetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop,
129                             unsigned planemask, int transparency_color)
130{
131    RivaSetRopSolid(RivaPTR(pScrn), rop);
132}
133
134static void
135RivaSubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1,
136                               int x2, int y2, int w, int h)
137{
138    RivaPtr pRiva = RivaPTR(pScrn);
139
140    RIVA_FIFO_FREE(pRiva->riva, Blt, 3);
141    pRiva->riva.Blt->TopLeftSrc  = (y1 << 16) | x1;
142    pRiva->riva.Blt->TopLeftDst  = (y2 << 16) | x2;
143    write_mem_barrier();
144    pRiva->riva.Blt->WidthHeight = (h  << 16) | w;
145    write_mem_barrier();
146}
147
148
149/*
150 * Fill 8x8 monochrome pattern rectangles.  patternx and patterny are
151 * the overloaded pattern bits themselves. The pattern colors don't
152 * support 565, only 555. Hack around it.
153 */
154static void
155RivaSetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int patternx, int patterny,
156                             int fg, int bg, int rop, unsigned planemask)
157{
158    RivaPtr pRiva = RivaPTR(pScrn);
159
160    RivaSetRopPattern(pRiva, rop);
161    if (pScrn->depth == 16)
162    {
163        fg = ((fg & 0x0000F800) << 8)
164           | ((fg & 0x000007E0) << 5)
165           | ((fg & 0x0000001F) << 3)
166           |        0xFF000000;
167        if (bg != -1)
168            bg = ((bg & 0x0000F800) << 8)
169               | ((bg & 0x000007E0) << 5)
170               | ((bg & 0x0000001F) << 3)
171               |        0xFF000000;
172        else
173            bg = 0;
174    }
175    else
176    {
177	fg |= pRiva->opaqueMonochrome;
178	bg  = (bg == -1) ? 0 : bg | pRiva->opaqueMonochrome;
179    };
180    RivaSetPattern(pRiva, bg, fg, patternx, patterny);
181    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 1);
182    pRiva->riva.Bitmap->Color1A = fg;
183}
184
185static void
186RivaSubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn,
187                                   int patternx, int patterny,
188                                   int x, int y, int w, int h)
189{
190    RivaPtr pRiva = RivaPTR(pScrn);
191
192    RIVA_FIFO_FREE(pRiva->riva, Bitmap, 2);
193    pRiva->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (x << 16) | y;
194    write_mem_barrier();
195    pRiva->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (w << 16) | h;
196    write_mem_barrier();
197}
198#endif
199
200void
201RivaResetGraphics(ScrnInfoPtr pScrn)
202{
203    RivaPtr pRiva = RivaPTR(pScrn);
204
205    if(pRiva->NoAccel) return;
206
207    RIVA_FIFO_FREE(pRiva->riva, Patt, 1);
208    pRiva->riva.Patt->Shape = 0;
209    RivaDisableClipping(pScrn);
210    pRiva->currentRop = 16;  /* to force RivaSetRopSolid to reset the pattern */
211    RivaSetRopSolid(pRiva, GXcopy);
212}
213
214
215
216/*
217 * Synchronise with graphics engine.  Make sure it is idle before returning.
218 * Should attempt to yield CPU if busy for awhile.
219 */
220void RivaSync(ScrnInfoPtr pScrn)
221{
222    RivaPtr pRiva = RivaPTR(pScrn);
223    RIVA_BUSY(pRiva->riva);
224}
225
226#ifdef HAVE_XAA_H
227/* Color expansion */
228static void
229RivaSetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn,
230                                             int fg, int bg, int rop,
231                                             unsigned int planemask)
232{
233    RivaPtr pRiva = RivaPTR(pScrn);
234
235    RivaSetRopSolid(pRiva, rop);
236
237    if ( bg == -1 )
238    {
239        /* Transparent case */
240        bg = 0x80000000;
241        pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData1C;
242    }
243    else
244    {
245        pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E;
246        if (pScrn->depth == 16)
247        {
248            bg = ((bg & 0x0000F800) << 8)
249               | ((bg & 0x000007E0) << 5)
250               | ((bg & 0x0000001F) << 3)
251               |        0xFF000000;
252        }
253        else
254        {
255            bg  |= pRiva->opaqueMonochrome;
256        };
257    }
258    pRiva->FgColor = fg;
259    pRiva->BgColor = bg;
260}
261
262static void
263RivaSubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno)
264{
265    RivaPtr pRiva = RivaPTR(pScrn);
266
267    int t = pRiva->expandWidth;
268    CARD32 *pbits = (CARD32*)pRiva->expandBuffer;
269    CARD32 *d = (CARD32*)pRiva->expandFifo;
270
271    while(t >= 16)
272    {
273	RIVA_FIFO_FREE(pRiva->riva, Bitmap, 16);
274	d[0]  = pbits[0];
275	d[1]  = pbits[1];
276	d[2]  = pbits[2];
277	d[3]  = pbits[3];
278	d[4]  = pbits[4];
279	d[5]  = pbits[5];
280	d[6]  = pbits[6];
281	d[7]  = pbits[7];
282	d[8]  = pbits[8];
283	d[9]  = pbits[9];
284	d[10] = pbits[10];
285	d[11] = pbits[11];
286	d[12] = pbits[12];
287	d[13] = pbits[13];
288	d[14] = pbits[14];
289	d[15] = pbits[15];
290	t -= 16; pbits += 16;
291    }
292    if(t) {
293	RIVA_FIFO_FREE(pRiva->riva, Bitmap, t);
294	while(t >= 4)
295	{
296	    d[0]  = pbits[0];
297	    d[1]  = pbits[1];
298	    d[2]  = pbits[2];
299	    d[3]  = pbits[3];
300	    t -= 4; pbits += 4;
301	}
302	while(t--)
303	    *(d++) = *(pbits++);
304    }
305
306    if (!(--pRiva->expandRows)) { /* hardware bug workaround */
307       RIVA_FIFO_FREE(pRiva->riva, Blt, 1);
308       write_mem_barrier();
309       pRiva->riva.Blt->TopLeftSrc = 0;
310    }
311    write_mem_barrier();
312}
313
314static void
315RivaSubsequentColorExpandScanlineFifo(ScrnInfoPtr pScrn, int bufno)
316{
317    RivaPtr pRiva = RivaPTR(pScrn);
318
319    if ( --pRiva->expandRows ) {
320       RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth);
321    } else { /* hardware bug workaround */
322       RIVA_FIFO_FREE(pRiva->riva, Blt, 1);
323       write_mem_barrier();
324       pRiva->riva.Blt->TopLeftSrc = 0;
325    }
326    write_mem_barrier();
327}
328
329static void
330RivaSubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, int x,
331                                               int y, int w, int h,
332                                               int skipleft)
333{
334    int bw;
335    RivaPtr pRiva = RivaPTR(pScrn);
336
337    bw = (w + 31) & ~31;
338    pRiva->expandWidth = bw >> 5;
339
340    if ( pRiva->BgColor == 0x80000000 )
341    {
342        /* Use faster transparent method */
343        RIVA_FIFO_FREE(pRiva->riva, Bitmap, 5);
344        pRiva->riva.Bitmap->ClipC.TopLeft     = (y << 16) | ((x+skipleft)
345                                                           & 0xFFFF);
346        pRiva->riva.Bitmap->ClipC.BottomRight = ((y+h) << 16) | ((x+w)&0xffff);
347        pRiva->riva.Bitmap->Color1C           = pRiva->FgColor;
348        pRiva->riva.Bitmap->WidthHeightC      = (h << 16) | bw;
349        write_mem_barrier();
350        pRiva->riva.Bitmap->PointC            = (y << 16) | (x & 0xFFFF);
351        write_mem_barrier();
352    }
353    else
354    {
355        /* Opaque */
356        RIVA_FIFO_FREE(pRiva->riva, Bitmap, 7);
357        pRiva->riva.Bitmap->ClipE.TopLeft     = (y << 16) | ((x+skipleft)
358                                                           & 0xFFFF);
359        pRiva->riva.Bitmap->ClipE.BottomRight = ((y+h) << 16) | ((x+w)&0xffff);
360        pRiva->riva.Bitmap->Color0E           = pRiva->BgColor;
361        pRiva->riva.Bitmap->Color1E           = pRiva->FgColor;
362        pRiva->riva.Bitmap->WidthHeightInE  = (h << 16) | bw;
363        pRiva->riva.Bitmap->WidthHeightOutE = (h << 16) | bw;
364        write_mem_barrier();
365        pRiva->riva.Bitmap->PointE          = (y << 16) | (x & 0xFFFF);
366        write_mem_barrier();
367    }
368
369    pRiva->expandRows = h;
370
371    if(pRiva->expandWidth > (pRiva->riva.FifoEmptyCount >> 2)) {
372	pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandBuffer;
373	pRiva->AccelInfoRec->SubsequentColorExpandScanline =
374				RivaSubsequentColorExpandScanline;
375    } else {
376	pRiva->AccelInfoRec->ScanlineColorExpandBuffers = &pRiva->expandFifo;
377	pRiva->AccelInfoRec->SubsequentColorExpandScanline =
378				RivaSubsequentColorExpandScanlineFifo;
379	RIVA_FIFO_FREE(pRiva->riva, Bitmap, pRiva->expandWidth);
380    }
381}
382
383static void
384RivaSetupForSolidLine(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask)
385{
386    RivaPtr pRiva = RivaPTR(pScrn);
387
388    RivaSetRopSolid(pRiva, rop);
389    pRiva->FgColor = color;
390}
391
392static void
393RivaSubsequentSolidHorVertLine(ScrnInfoPtr pScrn, int x, int y, int len, int dir)
394{
395    RivaPtr pRiva = RivaPTR(pScrn);
396
397    RIVA_FIFO_FREE(pRiva->riva, Line, 3);
398    pRiva->riva.Line->Color = pRiva->FgColor;
399    pRiva->riva.Line->Lin[0].point0 = ((y << 16) | ( x & 0xffff));
400    write_mem_barrier();
401    if ( dir ==DEGREES_0 )
402        pRiva->riva.Line->Lin[0].point1 = ((y << 16) | (( x + len ) & 0xffff));
403    else
404        pRiva->riva.Line->Lin[0].point1 = (((y + len) << 16) | ( x & 0xffff));
405    write_mem_barrier();
406}
407
408static void
409RivaSubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1,
410                              int x2, int y2, int flags)
411{
412    RivaPtr pRiva = RivaPTR(pScrn);
413    Bool  lastPoint = !(flags & OMIT_LAST);
414
415    RIVA_FIFO_FREE(pRiva->riva, Line, lastPoint ? 5 : 3);
416    pRiva->riva.Line->Color = pRiva->FgColor;
417    pRiva->riva.Line->Lin[0].point0 = ((y1 << 16) | (x1 & 0xffff));
418    write_mem_barrier();
419    pRiva->riva.Line->Lin[0].point1 = ((y2 << 16) | (x2 & 0xffff));
420    write_mem_barrier();
421    if (lastPoint)
422    {
423        pRiva->riva.Line->Lin[1].point0 = ((y2 << 16) | (x2 & 0xffff));
424        write_mem_barrier();
425        pRiva->riva.Line->Lin[1].point1 = (((y2 + 1) << 16) | (x2 & 0xffff));
426        write_mem_barrier();
427    }
428}
429
430static void
431RivaValidatePolyArc(
432   GCPtr        pGC,
433   unsigned long changes,
434   DrawablePtr pDraw
435){
436   if(pGC->planemask != ~0) return;
437
438   if(!pGC->lineWidth &&
439	((pGC->alu != GXcopy) || (pGC->lineStyle != LineSolid)))
440   {
441        pGC->ops->PolyArc = miZeroPolyArc;
442   }
443}
444
445static void
446RivaValidatePolyPoint(
447   GCPtr        pGC,
448   unsigned long changes,
449   DrawablePtr pDraw
450){
451   pGC->ops->PolyPoint = XAAGetFallbackOps()->PolyPoint;
452
453   if(pGC->planemask != ~0) return;
454
455   if(pGC->alu != GXcopy)
456        pGC->ops->PolyPoint = miPolyPoint;
457}
458#endif
459
460/* Initialize XAA acceleration info */
461Bool
462RivaAccelInit(ScreenPtr pScreen)
463{
464#ifdef HAVE_XAA_H
465    XAAInfoRecPtr infoPtr;
466    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
467    RivaPtr pRiva = RivaPTR(pScrn);
468
469    pRiva->AccelInfoRec = infoPtr = XAACreateInfoRec();
470    if(!infoPtr) return FALSE;
471
472    /* fill out infoPtr here */
473    infoPtr->Flags = LINEAR_FRAMEBUFFER | PIXMAP_CACHE | OFFSCREEN_PIXMAPS;
474
475    /* sync */
476    infoPtr->Sync = RivaSync;
477
478    /* solid fills */
479    infoPtr->SolidFillFlags = NO_PLANEMASK;
480    infoPtr->SetupForSolidFill = RivaSetupForSolidFill;
481    infoPtr->SubsequentSolidFillRect = RivaSubsequentSolidFillRect;
482
483    /* screen to screen copy */
484    infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY | NO_PLANEMASK;
485    infoPtr->SetupForScreenToScreenCopy = RivaSetupForScreenToScreenCopy;
486    infoPtr->SubsequentScreenToScreenCopy = RivaSubsequentScreenToScreenCopy;
487
488    /* 8x8 mono patterns */
489    /*
490     * Set pattern opaque bits based on pixel format.
491     */
492    pRiva->opaqueMonochrome = ~((1 << pScrn->depth) - 1);
493
494    infoPtr->Mono8x8PatternFillFlags = HARDWARE_PATTERN_SCREEN_ORIGIN |
495				       HARDWARE_PATTERN_PROGRAMMED_BITS |
496				       NO_PLANEMASK;
497    infoPtr->SetupForMono8x8PatternFill = RivaSetupForMono8x8PatternFill;
498    infoPtr->SubsequentMono8x8PatternFillRect =
499        RivaSubsequentMono8x8PatternFillRect;
500
501    /* Color expansion */
502    infoPtr->ScanlineCPUToScreenColorExpandFillFlags =
503				BIT_ORDER_IN_BYTE_LSBFIRST |
504				NO_PLANEMASK |
505				CPU_TRANSFER_PAD_DWORD |
506				LEFT_EDGE_CLIPPING |
507				LEFT_EDGE_CLIPPING_NEGATIVE_X;
508
509    infoPtr->NumScanlineColorExpandBuffers = 1;
510
511    infoPtr->SetupForScanlineCPUToScreenColorExpandFill =
512        RivaSetupForScanlineCPUToScreenColorExpandFill;
513    infoPtr->SubsequentScanlineCPUToScreenColorExpandFill =
514        RivaSubsequentScanlineCPUToScreenColorExpandFill;
515
516    pRiva->expandFifo = (unsigned char*)&pRiva->riva.Bitmap->MonochromeData01E;
517
518    /* Allocate buffer for color expansion and also image writes in the
519       future */
520    pRiva->expandBuffer = xnfalloc(((pScrn->virtualX*pScrn->bitsPerPixel)/8) + 8);
521
522
523    infoPtr->ScanlineColorExpandBuffers = &pRiva->expandBuffer;
524    infoPtr->SubsequentColorExpandScanline = RivaSubsequentColorExpandScanline;
525
526    infoPtr->SolidLineFlags = infoPtr->SolidFillFlags;
527    infoPtr->SetupForSolidLine = RivaSetupForSolidLine;
528    infoPtr->SubsequentSolidHorVertLine =
529		RivaSubsequentSolidHorVertLine;
530    infoPtr->SubsequentSolidTwoPointLine =
531		RivaSubsequentSolidTwoPointLine;
532    infoPtr->SetClippingRectangle = RivaSetClippingRectangle;
533    infoPtr->DisableClipping = RivaDisableClipping;
534    infoPtr->ClippingFlags = HARDWARE_CLIP_SOLID_LINE;
535    miSetZeroLineBias(pScreen, OCTANT1 | OCTANT3 | OCTANT4 | OCTANT6);
536
537    infoPtr->ValidatePolyArc = RivaValidatePolyArc;
538    infoPtr->PolyArcMask = GCFunction | GCLineWidth | GCPlaneMask;
539    infoPtr->ValidatePolyPoint = RivaValidatePolyPoint;
540    infoPtr->PolyPointMask = GCFunction | GCPlaneMask;
541
542    RivaResetGraphics(pScrn);
543
544    return(XAAInit(pScreen, infoPtr));
545#else
546    return FALSE;
547#endif
548}
549