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