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"
52 static void setM2MFDirection(ScrnInfoPtr pScrn, int dir)
54 NVPtr pNv = NVPTR(pScrn);
56 if (pNv->M2MFDirection != dir) {
58 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
59 NVDmaNext (pNv, dir ? NvDmaTT : NvDmaFB);
60 NVDmaNext (pNv, dir ? NvDmaFB : NvDmaTT);
61 pNv->M2MFDirection = dir;
65 static CARD32 rectFormat(DrawablePtr pDrawable)
67 switch(pDrawable->bitsPerPixel) {
70 return RECT_FORMAT_DEPTH24;
73 return RECT_FORMAT_DEPTH16;
76 return RECT_FORMAT_DEPTH8;
81 /* EXA acceleration hooks */
82 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
84 NVSync(xf86Screens[pScreen->myNum]);
87 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
92 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
93 NVPtr pNv = NVPTR(pScrn);
96 planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
97 if (planemask != ~0 || alu != GXcopy) {
98 if (pPixmap->drawable.bitsPerPixel == 32)
100 NVDmaStart(pNv, NvSubRectangle, 0x2fc, 1);
101 NVDmaNext (pNv, 1 /* ROP_AND */);
102 NVSetRopSolid(pScrn, alu, planemask);
104 NVDmaStart(pNv, NvSubRectangle, 0x2fc, 1);
105 NVDmaNext (pNv, 3 /* SRCCOPY */);
108 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, &fmt))
111 /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
112 * alpha channel gets forced to 0xFF for some reason. We're using
113 * SURFACE_FORMAT_Y32 as a workaround
115 if (fmt == SURFACE_FORMAT_A8R8G8B8)
118 if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt))
121 NVDmaStart(pNv, NvSubRectangle, RECT_FORMAT, 1);
122 NVDmaNext (pNv, rectFormat(&pPixmap->drawable));
123 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
126 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
130 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
132 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
133 NVPtr pNv = NVPTR(pScrn);
137 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_RECTS(0), 2);
138 NVDmaNext (pNv, (x1 << 16) | y1);
139 NVDmaNext (pNv, (width << 16) | height);
141 if((width * height) >= 512)
145 static void NVExaDoneSolid (PixmapPtr pPixmap)
149 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
150 PixmapPtr pDstPixmap,
156 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
157 NVPtr pNv = NVPTR(pScrn);
160 if (pSrcPixmap->drawable.bitsPerPixel !=
161 pDstPixmap->drawable.bitsPerPixel)
164 planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
165 if (planemask != ~0 || alu != GXcopy) {
166 if (pDstPixmap->drawable.bitsPerPixel == 32)
168 NVDmaStart(pNv, NvSubImageBlit, 0x2fc, 1);
169 NVDmaNext (pNv, 1 /* ROP_AND */);
170 NVSetRopSolid(pScrn, alu, planemask);
172 NVDmaStart(pNv, NvSubImageBlit, 0x2fc, 1);
173 NVDmaNext (pNv, 3 /* SRCCOPY */);
176 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
178 if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt))
181 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
185 static void NVExaCopy(PixmapPtr pDstPixmap,
193 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
194 NVPtr pNv = NVPTR(pScrn);
196 /* Now check whether we have the same values for srcY and dstY and
197 whether the used chipset is buggy. Currently we flag all of G70
198 cards as buggy, which is probably much to broad. KoalaBR
199 16 is an abritrary threshold. It should define the maximum number
200 of lines between dstY and srcY If the number of lines is below
201 we guess, that the bug won't trigger...
203 if ( ((abs(srcY - dstY)< 16)||(abs(srcX-dstX)<16)) &&
204 ((((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
205 ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
206 ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
207 ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
208 ((pNv->Chipset & 0xfff0) == CHIPSET_C512))) )
210 int dx=abs(srcX - dstX),dy=abs(srcY - dstY);
211 // Ok, let's do it manually unless someone comes up with a better idea
212 // 1. If dstY and srcY are really the same, do a copy rowwise
215 NVDEBUG("ExaCopy: Lines identical:\n");
223 for (i = 0; i < width; i++) {
224 NVDmaStart(pNv, NvSubImageBlit, BLIT_POINT_SRC, 3);
225 NVDmaNext (pNv, (srcY << 16) | (srcX+xpos));
226 NVDmaNext (pNv, (dstY << 16) | (dstX+xpos));
227 NVDmaNext (pNv, (height << 16) | 1);
231 // 2. Otherwise we will try a line by line copy in the hope to avoid
234 NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
242 for (i = 0; i < height; i++) {
243 NVDmaStart(pNv, NvSubImageBlit, BLIT_POINT_SRC, 3);
244 NVDmaNext (pNv, ((srcY+ypos) << 16) | srcX);
245 NVDmaNext (pNv, ((dstY+ypos) << 16) | dstX);
246 NVDmaNext (pNv, (1 << 16) | width);
251 NVDEBUG("ExaCopy: Using default path\n");
252 NVDmaStart(pNv, NvSubImageBlit, BLIT_POINT_SRC, 3);
253 NVDmaNext (pNv, (srcY << 16) | srcX);
254 NVDmaNext (pNv, (dstY << 16) | dstX);
255 NVDmaNext (pNv, (height << 16) | width);
258 if((width * height) >= 512)
262 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
264 Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
265 int dst_pitch, int src_pitch, int line_len)
267 if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
268 memcpy(dst, src, line_len*height);
271 memcpy(dst, src, line_len);
281 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
282 int dst_pitch, int src_pitch,
283 int line_len, int line_count)
285 NVPtr pNv = NVPTR(pScrn);
287 setM2MFDirection(pScrn, 0);
290 char *src = pNv->GARTScratch->map;
293 if (line_count * line_len <= pNv->GARTScratch->size) {
296 lc = pNv->GARTScratch->size / line_len;
300 /*XXX: and hw limitations? */
302 NVDmaStart(pNv, NvSubMemFormat,
303 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
304 NVDmaNext (pNv, (uint32_t)src_offset);
305 NVDmaNext (pNv, (uint32_t)pNv->GARTScratch->offset);
306 NVDmaNext (pNv, src_pitch);
307 NVDmaNext (pNv, line_len);
308 NVDmaNext (pNv, line_len);
310 NVDmaNext (pNv, (1<<8)|1);
313 NVNotifierReset(pScrn, pNv->Notifier0);
314 NVDmaStart(pNv, NvSubMemFormat,
315 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
317 NVDmaStart(pNv, NvSubMemFormat, 0x100, 1);
320 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
323 if (dst_pitch == line_len) {
324 memcpy(dst, src, dst_pitch * lc);
325 dst += dst_pitch * lc;
327 for (i = 0; i < lc; i++) {
328 memcpy(dst, src, line_len);
340 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
343 char *dst, int dst_pitch)
345 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
346 NVPtr pNv = NVPTR(pScrn);
347 int src_pitch, cpp, offset;
350 src_pitch = exaGetPixmapPitch(pSrc);
351 cpp = pSrc->drawable.bitsPerPixel >> 3;
352 offset = (y * src_pitch) + (x * cpp);
354 if (pNv->GARTScratch) {
355 if (NVAccelDownloadM2MF(pScrn, dst,
356 NVAccelGetPixmapOffset(pSrc) + offset,
357 dst_pitch, src_pitch, w * cpp, h))
361 src = pSrc->devPrivate.ptr + offset;
362 exaWaitSync(pSrc->drawable.pScreen);
363 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
370 NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
371 int dst_pitch, int src_pitch,
372 int line_len, int line_count)
374 NVPtr pNv = NVPTR(pScrn);
376 setM2MFDirection(pScrn, 1);
379 char *dst = pNv->GARTScratch->map;
382 /* Determine max amount of data we can DMA at once */
383 if (line_count * line_len <= pNv->GARTScratch->size) {
386 lc = pNv->GARTScratch->size / line_len;
390 /*XXX: and hw limitations? */
393 if (src_pitch == line_len) {
394 memcpy(dst, src, src_pitch * lc);
395 src += src_pitch * lc;
397 for (i = 0; i < lc; i++) {
398 memcpy(dst, src, line_len);
405 NVDmaStart(pNv, NvSubMemFormat,
406 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
407 NVDmaNext (pNv, (uint32_t)pNv->GARTScratch->offset);
408 NVDmaNext (pNv, (uint32_t)dst_offset);
409 NVDmaNext (pNv, line_len);
410 NVDmaNext (pNv, dst_pitch);
411 NVDmaNext (pNv, line_len);
413 NVDmaNext (pNv, (1<<8)|1);
416 NVNotifierReset(pScrn, pNv->Notifier0);
417 NVDmaStart(pNv, NvSubMemFormat,
418 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
420 NVDmaStart(pNv, NvSubMemFormat, 0x100, 1);
423 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 0))
432 static Bool NVUploadToScreen(PixmapPtr pDst,
433 int x, int y, int w, int h,
434 char *src, int src_pitch)
436 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
437 NVPtr pNv = NVPTR(pScrn);
438 int dst_offset, dst_pitch, cpp;
441 dst_offset = NVAccelGetPixmapOffset(pDst);
442 dst_pitch = exaGetPixmapPitch(pDst);
443 cpp = pDst->drawable.bitsPerPixel >> 3;
445 if (pNv->GARTScratch) {
446 dst_offset += (y * dst_pitch) + (x * cpp);
447 if (NVAccelUploadM2MF(pScrn, dst_offset, src, dst_pitch,
448 src_pitch, w * cpp, h))
452 dst = pDst->devPrivate.ptr + (y * dst_pitch) + (x * cpp);
453 exaWaitSync(pDst->drawable.pScreen);
454 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
461 static Bool NVCheckComposite(int op,
462 PicturePtr pSrcPicture,
463 PicturePtr pMaskPicture,
464 PicturePtr pDstPicture)
468 /* PictOpOver doesn't work correctly. The HW command assumes
469 * non premuliplied alpha
473 else if (op != PictOpOver && op != PictOpSrc)
475 else if (!pSrcPicture->pDrawable)
477 else if (pSrcPicture->transform || pSrcPicture->repeat)
479 else if (pSrcPicture->alphaMap || pDstPicture->alphaMap)
481 else if (pSrcPicture->format != PICT_a8r8g8b8 &&
482 pSrcPicture->format != PICT_x8r8g8b8 &&
483 pSrcPicture->format != PICT_r5g6b5)
485 else if (pDstPicture->format != PICT_a8r8g8b8 &&
486 pDstPicture->format != PICT_x8r8g8b8 &&
487 pDstPicture->format != PICT_r5g6b5)
493 static CARD32 src_size, src_pitch, src_offset;
495 static Bool NVPrepareComposite(int op,
496 PicturePtr pSrcPicture,
497 PicturePtr pMaskPicture,
498 PicturePtr pDstPicture,
503 ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
504 NVPtr pNv = NVPTR(pScrn);
505 int srcFormat, dstFormat;
507 if (pSrcPicture->format == PICT_a8r8g8b8)
508 srcFormat = STRETCH_BLIT_FORMAT_A8R8G8B8;
509 else if (pSrcPicture->format == PICT_x8r8g8b8)
510 srcFormat = STRETCH_BLIT_FORMAT_X8R8G8B8;
511 else if (pSrcPicture->format == PICT_r5g6b5)
512 srcFormat = STRETCH_BLIT_FORMAT_DEPTH16;
516 if (!NVAccelGetCtxSurf2DFormatFromPicture(pDstPicture, &dstFormat))
518 if (!NVAccelSetCtxSurf2D(pDst, pDst, dstFormat))
521 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
522 NVDmaNext (pNv, srcFormat);
523 NVDmaNext (pNv, (op == PictOpSrc) ? STRETCH_BLIT_OPERATION_COPY :
524 STRETCH_BLIT_OPERATION_BLEND);
526 src_size = ((pSrcPicture->pDrawable->width+3)&~3) |
527 (pSrcPicture->pDrawable->height << 16);
528 src_pitch = exaGetPixmapPitch(pSrc)
529 | (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER << 16)
530 | (STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE << 24);
531 src_offset = NVAccelGetPixmapOffset(pSrc);
536 static void NVComposite(PixmapPtr pDst,
546 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
547 NVPtr pNv = NVPTR(pScrn);
549 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
550 NVDmaNext (pNv, dstX | (dstY << 16));
551 NVDmaNext (pNv, width | (height << 16));
552 NVDmaNext (pNv, dstX | (dstY << 16));
553 NVDmaNext (pNv, width | (height << 16));
554 NVDmaNext (pNv, 1<<20);
555 NVDmaNext (pNv, 1<<20);
557 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
558 NVDmaNext (pNv, src_size);
559 NVDmaNext (pNv, src_pitch);
560 NVDmaNext (pNv, src_offset);
561 NVDmaNext (pNv, srcX | (srcY<<16));
566 static void NVDoneComposite (PixmapPtr pDst)
568 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
569 NVPtr pNv = NVPTR(pScrn);
572 if (pNv->CurrentLayout.depth == 8)
573 format = SURFACE_FORMAT_Y8;
574 else if (pNv->CurrentLayout.depth == 16)
575 format = SURFACE_FORMAT_R5G6B5;
577 format = SURFACE_FORMAT_X8R8G8B8;
579 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
580 NVDmaNext (pNv, format);
582 exaMarkSync(pDst->drawable.pScreen);
585 Bool NVExaInit(ScreenPtr pScreen)
587 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
588 NVPtr pNv = NVPTR(pScrn);
590 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
595 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
596 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
598 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
599 pNv->EXADriverPtr->offScreenBase =
600 pScrn->virtualX * pScrn->virtualY*(pScrn->bitsPerPixel/8);
601 pNv->EXADriverPtr->memorySize = pNv->FB->size;
602 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
603 pNv->EXADriverPtr->pixmapPitchAlign = 64;
604 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
605 pNv->EXADriverPtr->maxX = 32768;
606 pNv->EXADriverPtr->maxY = 32768;
608 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
610 /* Install default hooks */
611 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
612 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
614 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
615 pNv->EXADriverPtr->Copy = NVExaCopy;
616 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
618 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
619 pNv->EXADriverPtr->Solid = NVExaSolid;
620 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
622 switch (pNv->Architecture) {
624 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
625 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
626 pNv->EXADriverPtr->Composite = NV30EXAComposite;
627 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
630 if (!pNv->BlendingPossible)
632 pNv->EXADriverPtr->CheckComposite = NVCheckComposite;
633 pNv->EXADriverPtr->PrepareComposite = NVPrepareComposite;
634 pNv->EXADriverPtr->Composite = NVComposite;
635 pNv->EXADriverPtr->DoneComposite = NVDoneComposite;
639 return exaDriverInit(pScreen, pNv->EXADriverPtr);