g80_exa.c revision f3561b8b
1/*
2 * Copyright (c) 2007 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
25#ifdef HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include "g80_type.h"
30#include "g80_dma.h"
31#include "g80_xaa.h"
32
33static void
34waitMarker(ScreenPtr pScreen, int marker)
35{
36    G80Sync(xf86Screens[pScreen->myNum]);
37}
38
39static Bool
40setSrc(G80Ptr pNv, PixmapPtr pSrc)
41{
42    CARD32 depth;
43
44    switch(pSrc->drawable.depth) {
45        case  8: depth = 0x000000f3; break;
46        case 15: depth = 0x000000f8; break;
47        case 16: depth = 0x000000e8; break;
48        case 24: depth = 0x000000e6; break;
49        case 32: depth = 0x000000cf; break;
50        default: return FALSE;
51    }
52
53    G80DmaStart(pNv, 0x230, 2);
54    G80DmaNext (pNv, depth);
55    G80DmaNext (pNv, 0x00000001);
56    G80DmaStart(pNv, 0x244, 5);
57    G80DmaNext (pNv, exaGetPixmapPitch(pSrc));
58    G80DmaNext (pNv, pSrc->drawable.width);
59    G80DmaNext (pNv, pSrc->drawable.height);
60    G80DmaNext (pNv, 0x00000000);
61    G80DmaNext (pNv, exaGetPixmapOffset(pSrc));
62
63    return TRUE;
64}
65
66static Bool
67setDst(G80Ptr pNv, PixmapPtr pDst)
68{
69    CARD32 depth, depth2;
70
71    switch(pDst->drawable.depth) {
72        case  8: depth = 0x000000f3; depth2 = 3; break;
73        case 15: depth = 0x000000f8; depth2 = 1; break;
74        case 16: depth = 0x000000e8; depth2 = 0; break;
75        case 24: depth = 0x000000e6; depth2 = 2; break;
76        case 32: depth = 0x000000cf; depth2 = 2; break;
77        default: return FALSE;
78    }
79
80    G80DmaStart(pNv, 0x200, 2);
81    G80DmaNext (pNv, depth);
82    G80DmaNext (pNv, 0x00000001);
83    G80DmaStart(pNv, 0x214, 5);
84    G80DmaNext (pNv, exaGetPixmapPitch(pDst));
85    G80DmaNext (pNv, pDst->drawable.width);
86    G80DmaNext (pNv, pDst->drawable.height);
87    G80DmaNext (pNv, 0x00000000);
88    G80DmaNext (pNv, exaGetPixmapOffset(pDst));
89    G80DmaStart(pNv, 0x2e8, 1);
90    G80DmaNext (pNv, depth2);
91    G80DmaStart(pNv, 0x584, 1);
92    G80DmaNext (pNv, depth);
93    G80SetClip(pNv, 0, 0, pDst->drawable.width, pDst->drawable.height);
94
95    return TRUE;
96}
97
98/* solid fills */
99
100static Bool
101prepareSolid(PixmapPtr      pPixmap,
102             int            alu,
103             Pixel          planemask,
104             Pixel          fg)
105{
106    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
107    G80Ptr pNv = G80PTR(pScrn);
108
109    if(pPixmap->drawable.depth > 24) return FALSE;
110    if(!setDst(pNv, pPixmap)) return FALSE;
111    G80DmaStart(pNv, 0x2ac, 1);
112    G80DmaNext (pNv, 4);
113    G80SetRopSolid(pNv, alu, planemask);
114    G80DmaStart(pNv, 0x580, 1);
115    G80DmaNext (pNv, 4);
116    G80DmaStart(pNv, 0x588, 1);
117    G80DmaNext (pNv, fg);
118
119    pNv->DMAKickoffCallback = G80DMAKickoffCallback;
120    return TRUE;
121}
122
123static void
124solid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
125{
126    ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
127    G80Ptr pNv = G80PTR(pScrn);
128
129    G80DmaStart(pNv, 0x600, 4);
130    G80DmaNext (pNv, x1);
131    G80DmaNext (pNv, y1);
132    G80DmaNext (pNv, x2);
133    G80DmaNext (pNv, y2);
134
135    if((x2 - x1) * (y2 - y1) >= 512)
136        G80DmaKickoff(pNv);
137}
138
139static void
140doneSolid(PixmapPtr pPixmap)
141{
142}
143
144/* screen to screen copies */
145
146static Bool
147prepareCopy(PixmapPtr       pSrcPixmap,
148            PixmapPtr       pDstPixmap,
149            int             dx,
150            int             dy,
151            int             alu,
152            Pixel           planemask)
153{
154    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
155    G80Ptr pNv = G80PTR(pScrn);
156
157    if(!setSrc(pNv, pSrcPixmap)) return FALSE;
158    if(!setDst(pNv, pDstPixmap)) return FALSE;
159    G80DmaStart(pNv, 0x2ac, 1);
160    if(alu == GXcopy && planemask == ~0) {
161        G80DmaNext (pNv, 3);
162    } else {
163        G80DmaNext (pNv, 4);
164        G80SetRopSolid(pNv, alu, planemask);
165    }
166    pNv->DMAKickoffCallback = G80DMAKickoffCallback;
167    return TRUE;
168}
169
170static void
171copy(PixmapPtr pDstPixmap,
172     int       srcX,
173     int       srcY,
174     int       dstX,
175     int       dstY,
176     int       width,
177     int       height)
178{
179    ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
180    G80Ptr pNv = G80PTR(pScrn);
181
182    G80DmaStart(pNv, 0x110, 1);
183    G80DmaNext (pNv, 0);
184    G80DmaStart(pNv, 0x8b0, 12);
185    G80DmaNext (pNv, dstX);
186    G80DmaNext (pNv, dstY);
187    G80DmaNext (pNv, width);
188    G80DmaNext (pNv, height);
189    G80DmaNext (pNv, 0);
190    G80DmaNext (pNv, 1);
191    G80DmaNext (pNv, 0);
192    G80DmaNext (pNv, 1);
193    G80DmaNext (pNv, 0);
194    G80DmaNext (pNv, srcX);
195    G80DmaNext (pNv, 0);
196    G80DmaNext (pNv, srcY);
197
198    if(width * height >= 512)
199        G80DmaKickoff(pNv);
200}
201
202static void
203doneCopy(PixmapPtr pDstPixmap)
204{
205}
206
207/* composite */
208
209static Bool
210checkComposite(int          op,
211               PicturePtr   pSrc,
212               PicturePtr   pMask,
213               PicturePtr   pDst)
214{
215    return FALSE;
216}
217
218/* upload to screen */
219
220static Bool
221upload(PixmapPtr pDst,
222       int       x,
223       int       y,
224       int       w,
225       int       h,
226       char      *src,
227       int       src_pitch)
228{
229    ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
230    G80Ptr pNv = G80PTR(pScrn);
231    const int Bpp = pDst->drawable.bitsPerPixel >> 3;
232    int line_dwords = (w * Bpp + 3) / 4;
233    const Bool kickoff = w * h >= 512;
234    CARD32 depth;
235
236    if(!setDst(pNv, pDst)) return FALSE;
237    switch(pDst->drawable.depth) {
238        case  8: depth = 0x000000f3; break;
239        case 15: depth = 0x000000f8; break;
240        case 16: depth = 0x000000e8; break;
241        case 24: depth = 0x000000e6; break;
242        case 32: depth = 0x000000cf; break;
243        default: return FALSE;
244    }
245
246    G80SetClip(pNv, x, y, w, h);
247    G80DmaStart(pNv, 0x2ac, 1);
248    G80DmaNext (pNv, 3);
249    G80DmaStart(pNv, 0x800, 2);
250    G80DmaNext (pNv, 0);
251    G80DmaNext (pNv, depth);
252    G80DmaStart(pNv, 0x838, 10);
253    G80DmaNext (pNv, (line_dwords * 4) / Bpp);
254    G80DmaNext (pNv, h);
255    G80DmaNext (pNv, 0);
256    G80DmaNext (pNv, 1);
257    G80DmaNext (pNv, 0);
258    G80DmaNext (pNv, 1);
259    G80DmaNext (pNv, 0);
260    G80DmaNext (pNv, x);
261    G80DmaNext (pNv, 0);
262    G80DmaNext (pNv, y);
263
264    while(h-- > 0) {
265        int count = line_dwords;
266        char *p = src;
267
268        while(count) {
269            int size = count > 1792 ? 1792 : count;
270
271            G80DmaStart(pNv, 0x40000860, size);
272            memcpy(&pNv->dmaBase[pNv->dmaCurrent], p, size * 4);
273
274            p += size * Bpp;
275            pNv->dmaCurrent += size;
276
277            count -= size;
278        }
279
280        src += src_pitch;
281    }
282
283    if(kickoff)
284        G80DmaKickoff(pNv);
285    else
286        pNv->DMAKickoffCallback = G80DMAKickoffCallback;
287
288    return TRUE;
289}
290
291/******************************************************************************/
292
293Bool G80ExaInit(ScreenPtr pScreen, ScrnInfoPtr pScrn)
294{
295    G80Ptr pNv = G80PTR(pScrn);
296    ExaDriverPtr exa;
297    const int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
298
299    exa = pNv->exa = exaDriverAlloc();
300    if(!exa) return FALSE;
301
302    exa->exa_major         = EXA_VERSION_MAJOR;
303    exa->exa_minor         = EXA_VERSION_MINOR;
304    exa->memoryBase        = pNv->mem;
305    exa->offScreenBase     = 0;
306    exa->memorySize        = pitch * pNv->offscreenHeight;
307    exa->pixmapOffsetAlign = 256;
308    exa->pixmapPitchAlign  = 256;
309    exa->flags             = EXA_OFFSCREEN_PIXMAPS;
310    exa->maxX              = 8192;
311    exa->maxY              = 8192;
312
313    /**** Rendering ops ****/
314    exa->PrepareSolid     = prepareSolid;
315    exa->Solid            = solid;
316    exa->DoneSolid        = doneSolid;
317    exa->PrepareCopy      = prepareCopy;
318    exa->Copy             = copy;
319    exa->DoneCopy         = doneCopy;
320    exa->CheckComposite   = checkComposite;
321    //exa->PrepareComposite = prepareComposite;
322    //exa->Composite        = composite;
323    //exa->DoneComposite    = doneComposite;
324    exa->UploadToScreen   = upload;
325
326    exa->WaitMarker       = waitMarker;
327
328    return exaDriverInit(pScreen, exa);
329}
330