1 /***************************************************************************\
3 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
5 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
6 |* international laws. Users and possessors of this source code are *|
7 |* hereby granted a nonexclusive, royalty-free copyright license to *|
8 |* use this code in individual and commercial software. *|
10 |* Any use of this source code must include, in the user documenta- *|
11 |* tion and internal comments to the code, notices to the end user *|
14 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
16 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
17 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
18 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
19 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
20 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
21 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
22 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
23 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
24 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
25 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
26 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
28 |* U.S. Government End Users. This source code is a "commercial *|
29 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
30 |* consisting of "commercial computer software" and "commercial *|
31 |* computer software documentation," as such terms are used in *|
32 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
33 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
34 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
35 |* all U.S. Government End Users acquire the source code with only *|
36 |* those rights set forth herein. *|
38 \***************************************************************************/
41 Exa Modifications (c) Lars Knoll (lars@trolltech.com)
44 #include "nv_include.h"
47 #if (EXA_VERSION_MAJOR < 2)
48 #error You need EXA >=2.0.0
56 static CARD32 getPitch(DrawablePtr pDrawable)
58 return (pDrawable->width*(pDrawable->bitsPerPixel >> 3) + 63) & ~63;
61 static CARD32 getOffset(NVPtr pNv, DrawablePtr pDrawable)
64 if (pDrawable->type == DRAWABLE_WINDOW)
67 pPixmap = (PixmapPtr)pDrawable;
68 return (CARD32)((unsigned long)pPixmap->devPrivate.ptr - (unsigned long)pNv->FbBase);
71 static CARD32 surfaceFormat(DrawablePtr pDrawable)
73 switch(pDrawable->bitsPerPixel) {
76 return SURFACE_FORMAT_X8R8G8B8;
79 return SURFACE_FORMAT_R5G6B5;
82 return SURFACE_FORMAT_Y8;
87 static CARD32 rectFormat(DrawablePtr pDrawable)
89 switch(pDrawable->bitsPerPixel) {
92 return RECT_FORMAT_DEPTH24;
95 return RECT_FORMAT_DEPTH16;
98 return RECT_FORMAT_DEPTH8;
103 /* EXA acceleration hooks */
105 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
107 NVSync(xf86Screens[pScreen->myNum]);
110 static Bool NVExaPrepareSolid (PixmapPtr pPixmap,
115 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
116 NVPtr pNv = NVPTR(pScrn);
119 planemask |= ~0 << pNv->CurrentLayout.depth;
121 NVSetRopSolid(pScrn, alu, planemask);
123 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4);
125 NVDmaNext (pNv, surfaceFormat(&pPixmap->drawable));
127 pitch = getPitch(&pPixmap->drawable);
128 NVDmaNext (pNv, (pitch<<16)|pitch);
130 NVDmaNext (pNv, getOffset(pNv, &pPixmap->drawable));
131 NVDmaNext (pNv, getOffset(pNv, &pPixmap->drawable));
133 NVDmaStart(pNv, NvSubRectangle, RECT_FORMAT, 1);
134 NVDmaNext(pNv, rectFormat(&pPixmap->drawable));
135 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
138 pNv->DMAKickoffCallback = NVDMAKickoffCallback;
143 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
145 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
146 NVPtr pNv = NVPTR(pScrn);
150 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_RECTS(0), 2);
151 NVDmaNext (pNv, (x1 << 16) | y1);
152 NVDmaNext (pNv, (width << 16) | height);
154 if((width * height) >= 512)
158 static void NVExaDoneSolid (PixmapPtr pPixmap)
162 static Bool NVExaPrepareCopy (PixmapPtr pSrcPixmap,
163 PixmapPtr pDstPixmap,
169 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
170 NVPtr pNv = NVPTR(pScrn);
171 CARD32 srcPitch, dstPitch;
173 planemask |= ~0 << pNv->CurrentLayout.depth;
175 NVSetRopSolid(pScrn, alu, planemask);
177 dstPitch = getPitch(&pDstPixmap->drawable);
178 srcPitch = getPitch(&pSrcPixmap->drawable);
179 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_PITCH, 3);
180 NVDmaNext (pNv, (dstPitch<<16)|srcPitch);
181 NVDmaNext (pNv, getOffset(pNv, &pSrcPixmap->drawable));
182 NVDmaNext (pNv, getOffset(pNv, &pDstPixmap->drawable));
184 pNv->DMAKickoffCallback = NVDMAKickoffCallback;
188 static void NVExaCopy (PixmapPtr pDstPixmap,
196 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
197 NVPtr pNv = NVPTR(pScrn);
199 NVDmaStart(pNv, NvSubImageBlit, BLIT_POINT_SRC, 3);
200 NVDmaNext (pNv, (srcY << 16) | srcX);
201 NVDmaNext (pNv, (dstY << 16) | dstX);
202 NVDmaNext (pNv, (height << 16) | width);
204 if((width * height) >= 512)
208 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
210 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
213 char *dst, int dst_pitch)
215 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
216 NVPtr pNv = NVPTR(pScrn);
217 CARD32 offset_in, pitch_in, max_lines, line_length;
220 pitch_in = getPitch(&pSrc->drawable);
221 offset_in = getOffset(pNv, &pSrc->drawable);
222 offset_in += y*pitch_in;
223 offset_in += x * (pSrc->drawable.bitsPerPixel >> 3);
224 max_lines = 65536/dst_pitch + 1;
225 line_length = w * (pSrc->drawable.bitsPerPixel >> 3);
227 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvGraphicsToAGP);
229 NVDEBUG("NVDownloadFromScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
230 NVDEBUG(" pitch_in=%x dst_pitch=%x offset_in=%x", pitch_in, dst_pitch, offset_in);
232 NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
233 int nlines = h > max_lines ? max_lines : h;
234 /* reset the notification object */
235 memset(pNv->agpMemory, 0xff, 0x100);
236 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_NOTIFY, 1);
238 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_OFFSET_IN, 8);
239 NVDmaNext (pNv, offset_in);
241 NVDmaNext (pNv, pitch_in);
242 NVDmaNext (pNv, dst_pitch);
243 NVDmaNext (pNv, line_length);
244 NVDmaNext (pNv, nlines);
245 NVDmaNext (pNv, 0x101);
248 if (!NVDmaWaitForNotifier(pNv, NV_DMA_TARGET_AGP, 0)) {
253 if (memcmp(pNv->FbBase + offset_in, pNv->agpMemory + 0x10000, nlines*dst_pitch) != 0)
254 ErrorF("DMA transfer wrong!\n");
256 memcpy(dst, pNv->agpMemory + 0x10000, nlines*dst_pitch);
258 offset_in += nlines*pitch_in;
259 dst += nlines*dst_pitch;
263 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvScaledImage);
264 exaMarkSync(pSrc->drawable.pScreen);
268 static Bool NVUploadToScreen(PixmapPtr pDst,
269 int x, int y, int w, int h,
270 char *src, int src_pitch)
272 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
273 NVPtr pNv = NVPTR(pScrn);
274 CARD32 offset_out, pitch_out, max_lines, line_length;
279 w = pDst->drawable.width;
280 h = pDst->drawable.height;
283 pitch_out = getPitch(&pDst->drawable);
284 offset_out = getOffset(pNv, &pDst->drawable);
285 offset_out += y*pitch_out;
286 offset_out += x * (pDst->drawable.bitsPerPixel >> 3);
288 max_lines = 65536/src_pitch + 1;
289 line_length = w * (pDst->drawable.bitsPerPixel >> 3);
291 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvAGPToGraphics);
293 NVDEBUG("NVUploadToScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
295 NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
296 int nlines = h > max_lines ? max_lines : h;
297 /* reset the notification object */
298 memset(pNv->agpMemory, 0xff, 0x100);
299 memcpy(pNv->agpMemory + 0x10000, src, nlines*src_pitch);
300 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_NOTIFY, 1);
302 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_OFFSET_IN, 8);
304 NVDmaNext (pNv, offset_out);
305 NVDmaNext (pNv, src_pitch);
306 NVDmaNext (pNv, pitch_out);
307 NVDmaNext (pNv, line_length);
308 NVDmaNext (pNv, nlines);
309 NVDmaNext (pNv, 0x101);
312 if (!NVDmaWaitForNotifier(pNv, NV_DMA_TARGET_AGP, 0)) {
317 offset_out += nlines*pitch_out;
318 src += nlines*src_pitch;
322 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvScaledImage);
323 exaMarkSync(pDst->drawable.pScreen);
328 static Bool NVCheckComposite (int op,
329 PicturePtr pSrcPicture,
330 PicturePtr pMaskPicture,
331 PicturePtr pDstPicture)
336 /* PictOpOver doesn't work correctly. The HW command assumes non premuliplied alpha */
337 else if (op != PictOpOver && op != PictOpSrc)
339 else if (!pSrcPicture->pDrawable)
341 else if (pSrcPicture->transform || pSrcPicture->repeat)
343 else if (pSrcPicture->alphaMap || pDstPicture->alphaMap)
345 else if (pSrcPicture->format != PICT_a8r8g8b8 &&
346 pSrcPicture->format != PICT_x8r8g8b8 &&
347 pSrcPicture->format != PICT_r5g6b5)
349 else if (pDstPicture->format != PICT_a8r8g8b8 &&
350 pDstPicture->format != PICT_x8r8g8b8 &&
351 pDstPicture->format != PICT_r5g6b5)
356 static CARD32 src_size, src_pitch, src_offset;
358 static Bool NVPrepareComposite (int op,
359 PicturePtr pSrcPicture,
360 PicturePtr pMaskPicture,
361 PicturePtr pDstPicture,
366 ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
367 NVPtr pNv = NVPTR(pScrn);
369 int srcFormat, dstFormat;
370 if (pSrcPicture->format == PICT_a8r8g8b8)
371 srcFormat = STRETCH_BLIT_FORMAT_A8R8G8B8;
372 else if (pSrcPicture->format == PICT_x8r8g8b8)
373 srcFormat = STRETCH_BLIT_FORMAT_X8R8G8B8;
375 srcFormat = STRETCH_BLIT_FORMAT_DEPTH16;
377 if (pDstPicture->format == PICT_a8r8g8b8)
378 dstFormat = SURFACE_FORMAT_A8R8G8B8;
379 else if (pDstPicture->format == PICT_x8r8g8b8)
380 dstFormat = SURFACE_FORMAT_X8R8G8B8;
382 dstFormat = SURFACE_FORMAT_R5G6B5;
385 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
386 NVDmaNext (pNv, dstFormat);
387 NVDmaNext (pNv, getPitch(pSrcPicture->pDrawable)|(getPitch(pDstPicture->pDrawable) << 16));
388 NVDmaNext (pNv, getOffset(pNv, pSrcPicture->pDrawable));
389 NVDmaNext (pNv, getOffset(pNv, pDstPicture->pDrawable));
391 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
392 NVDmaNext (pNv, srcFormat);
393 NVDmaNext (pNv, (op == PictOpSrc) ? STRETCH_BLIT_OPERATION_COPY : STRETCH_BLIT_OPERATION_BLEND);
395 src_size = pSrcPicture->pDrawable->width | (pSrcPicture->pDrawable->height << 16);
396 src_pitch = getPitch(pSrcPicture->pDrawable)
397 | (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER << 16)
398 | (STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE << 24);
399 src_offset = getOffset(pNv, pSrcPicture->pDrawable);
403 static void NVComposite (PixmapPtr pDst,
413 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
414 NVPtr pNv = NVPTR(pScrn);
416 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
417 NVDmaNext (pNv, dstX | (dstY << 16));
418 NVDmaNext (pNv, width | (height << 16));
419 NVDmaNext (pNv, dstX | (dstY << 16));
420 NVDmaNext (pNv, width | (height << 16));
421 NVDmaNext (pNv, 1<<20);
422 NVDmaNext (pNv, 1<<20);
424 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
425 NVDmaNext (pNv, src_size);
426 NVDmaNext (pNv, src_pitch);
427 NVDmaNext (pNv, src_offset);
428 NVDmaNext (pNv, srcX | (srcY<<16));
433 static void NVDoneComposite (PixmapPtr pDst)
435 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
436 NVPtr pNv = NVPTR(pScrn);
438 if (pNv->CurrentLayout.depth == 8)
439 format = SURFACE_FORMAT_Y8;
440 else if (pNv->CurrentLayout.depth == 16)
441 format = SURFACE_FORMAT_R5G6B5;
443 format = SURFACE_FORMAT_X8R8G8B8;
444 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
445 NVDmaNext (pNv, format);
446 exaMarkSync(pDst->drawable.pScreen);
449 Bool NVExaInit(ScreenPtr pScreen)
451 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
452 NVPtr pNv = NVPTR(pScrn);
454 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
459 pNv->EXADriverPtr->memoryBase = pNv->FbStart;
460 pNv->EXADriverPtr->offScreenBase = pScrn->virtualX*pScrn->virtualY*pScrn->depth;
461 pNv->EXADriverPtr->memorySize = pNv->ScratchBufferStart;
462 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
463 pNv->EXADriverPtr->pixmapPitchAlign = 64;
464 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
465 pNv->EXADriverPtr->maxX = 32768;
466 pNv->EXADriverPtr->maxY = 32768;
468 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
470 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
471 pNv->EXADriverPtr->Copy = NVExaCopy;
472 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
474 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
475 pNv->EXADriverPtr->Solid = NVExaSolid;
476 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
478 if (pNv->agpMemory) {
479 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
480 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
482 if (pNv->BlendingPossible) {
483 /* install composite hooks */
484 pNv->EXADriverPtr->CheckComposite = NVCheckComposite;
485 pNv->EXADriverPtr->PrepareComposite = NVPrepareComposite;
486 pNv->EXADriverPtr->Composite = NVComposite;
487 pNv->EXADriverPtr->DoneComposite = NVDoneComposite;
493 struct timeval tv, tv2;
494 ErrorF("\nTiming upload:\n");
495 gettimeofday(&tv, 0);
496 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvAGPToGraphics);
498 for (i = 0; i < 0x10000; ++i)
499 ((CARD32 *)(pNv->agpMemory+0x10000))[i] = (i<<16) | (0xffff-i);
500 for (i = 0; i < 0x10000; ++i)
501 ((CARD32 *)(pNv->FbBase))[i] = 0;
503 /* reset the notification object */
504 memset(pNv->agpMemory, 0xff, 0x100);
505 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_NOTIFY, 1);
507 NVDmaStart(pNv, NvSubGraphicsToAGP, MEMFORMAT_OFFSET_IN, 8);
510 NVDmaNext (pNv, 1024);
511 NVDmaNext (pNv, 1024);
512 NVDmaNext (pNv, 1024);
513 NVDmaNext (pNv, 1024);
514 NVDmaNext (pNv, 0x101);
517 if (!NVDmaWaitForNotifier(pNv, NV_DMA_TARGET_AGP, 0))
518 ErrorF("DMA transfer error!\n");
520 NVDmaSetObjectOnSubchannel(pNv, NvSubGraphicsToAGP, NvScaledImage);
521 gettimeofday(&tv2, 0);
522 for (i = 0; i < 0x10000; i += 256)
523 ErrorF("%x %x %x %x\n", ((CARD32 *)(pNv->FbBase))[i], ((CARD32 *)(pNv->FbBase))[i+1],
524 ((CARD32 *)(pNv->FbBase))[i+2], ((CARD32 *)(pNv->FbBase))[i+3]);
525 ErrorF("Download from Screen %f MB/s\n",
527 /((int)tv2.tv_usec- (int)tv.tv_usec + 1000000*(tv2.tv_sec-tv.tv_sec)+1));
531 return exaDriverInit(pScreen, pNv->EXADriverPtr);