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