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