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