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 void setM2MFDirection(NVPtr pNv, int dir)
58 if (pNv->M2MFDirection != dir) {
59 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
60 NVDmaNext (pNv, dir ? NvDmaAGP : NvDmaFB);
61 NVDmaNext (pNv, dir ? NvDmaFB : NvDmaAGP);
62 pNv->M2MFDirection = dir;
66 static CARD32 getPitch(DrawablePtr pDrawable)
68 return (pDrawable->width*(pDrawable->bitsPerPixel >> 3) + 63) & ~63;
71 static CARD32 getOffset(NVPtr pNv, DrawablePtr pDrawable)
76 if (pDrawable->type == DRAWABLE_WINDOW) {
77 offset = pNv->FB->offset - pNv->VRAMPhysical;
79 pPixmap = (PixmapPtr)pDrawable;
80 offset = (CARD32)((unsigned long)pPixmap->devPrivate.ptr - (unsigned long)pNv->FB->map);
81 offset += pNv->FB->offset - pNv->VRAMPhysical;
87 static CARD32 surfaceFormat(DrawablePtr pDrawable)
89 switch(pDrawable->bitsPerPixel) {
92 return SURFACE_FORMAT_X8R8G8B8;
95 return SURFACE_FORMAT_R5G6B5;
98 return SURFACE_FORMAT_Y8;
103 static CARD32 rectFormat(DrawablePtr pDrawable)
105 switch(pDrawable->bitsPerPixel) {
108 return RECT_FORMAT_DEPTH24;
111 return RECT_FORMAT_DEPTH16;
114 return RECT_FORMAT_DEPTH8;
119 /* EXA acceleration hooks */
121 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
123 NVSync(xf86Screens[pScreen->myNum]);
126 static Bool NVExaPrepareSolid (PixmapPtr pPixmap,
131 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
132 NVPtr pNv = NVPTR(pScrn);
135 planemask |= ~0 << pNv->CurrentLayout.depth;
137 NVSetRopSolid(pScrn, alu, planemask);
139 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 4);
141 NVDmaNext (pNv, surfaceFormat(&pPixmap->drawable));
143 pitch = getPitch(&pPixmap->drawable);
144 NVDmaNext (pNv, (pitch<<16)|pitch);
146 NVDmaNext (pNv, getOffset(pNv, &pPixmap->drawable));
147 NVDmaNext (pNv, getOffset(pNv, &pPixmap->drawable));
149 NVDmaStart(pNv, NvSubRectangle, RECT_FORMAT, 1);
150 NVDmaNext(pNv, rectFormat(&pPixmap->drawable));
151 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_COLOR, 1);
154 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
159 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
161 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
162 NVPtr pNv = NVPTR(pScrn);
166 NVDmaStart(pNv, NvSubRectangle, RECT_SOLID_RECTS(0), 2);
167 NVDmaNext (pNv, (x1 << 16) | y1);
168 NVDmaNext (pNv, (width << 16) | height);
170 if((width * height) >= 512)
174 static void NVExaDoneSolid (PixmapPtr pPixmap)
178 static Bool NVExaPrepareCopy (PixmapPtr pSrcPixmap,
179 PixmapPtr pDstPixmap,
185 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
186 NVPtr pNv = NVPTR(pScrn);
187 CARD32 srcPitch, dstPitch;
189 planemask |= ~0 << pNv->CurrentLayout.depth;
191 NVSetRopSolid(pScrn, alu, planemask);
193 dstPitch = getPitch(&pDstPixmap->drawable);
194 srcPitch = getPitch(&pSrcPixmap->drawable);
195 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_PITCH, 3);
196 NVDmaNext (pNv, (dstPitch<<16)|srcPitch);
197 NVDmaNext (pNv, getOffset(pNv, &pSrcPixmap->drawable));
198 NVDmaNext (pNv, getOffset(pNv, &pDstPixmap->drawable));
200 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
204 static void NVExaCopy (PixmapPtr pDstPixmap,
212 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
213 NVPtr pNv = NVPTR(pScrn);
215 NVDmaStart(pNv, NvSubImageBlit, BLIT_POINT_SRC, 3);
216 NVDmaNext (pNv, (srcY << 16) | srcX);
217 NVDmaNext (pNv, (dstY << 16) | dstX);
218 NVDmaNext (pNv, (height << 16) | width);
220 if((width * height) >= 512)
224 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
226 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
229 char *dst, int dst_pitch)
231 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
232 NVPtr pNv = NVPTR(pScrn);
233 CARD32 offset_in, pitch_in, max_lines, line_length;
236 pitch_in = getPitch(&pSrc->drawable);
237 offset_in = getOffset(pNv, &pSrc->drawable);
238 offset_in += y*pitch_in;
239 offset_in += x * (pSrc->drawable.bitsPerPixel >> 3);
240 max_lines = 65536/dst_pitch + 1;
241 line_length = w * (pSrc->drawable.bitsPerPixel >> 3);
243 setM2MFDirection(pNv, 0);
245 NVDEBUG("NVDownloadFromScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
246 NVDEBUG(" pitch_in=%x dst_pitch=%x offset_in=%x", pitch_in, dst_pitch, offset_in);
248 NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
249 int nlines = h > max_lines ? max_lines : h;
250 /* reset the notification object */
251 memset(pNv->Notifier0->map, 0xff, pNv->Notifier0->size);
252 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1);
254 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8);
255 NVDmaNext (pNv, offset_in);
257 NVDmaNext (pNv, pitch_in);
258 NVDmaNext (pNv, dst_pitch);
259 NVDmaNext (pNv, line_length);
260 NVDmaNext (pNv, nlines);
261 NVDmaNext (pNv, 0x101);
264 if (!NVDmaWaitForNotifier(pNv, pNv->Notifier0->map)) {
269 memcpy(dst, pNv->AGPScratch->map, nlines*dst_pitch);
271 offset_in += nlines*pitch_in;
272 dst += nlines*dst_pitch;
276 exaMarkSync(pSrc->drawable.pScreen);
280 static Bool NVUploadToScreen(PixmapPtr pDst,
281 int x, int y, int w, int h,
282 char *src, int src_pitch)
284 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
285 NVPtr pNv = NVPTR(pScrn);
286 CARD32 offset_out, pitch_out, max_lines, line_length;
291 w = pDst->drawable.width;
292 h = pDst->drawable.height;
295 pitch_out = getPitch(&pDst->drawable);
296 offset_out = getOffset(pNv, &pDst->drawable);
297 offset_out += y*pitch_out;
298 offset_out += x * (pDst->drawable.bitsPerPixel >> 3);
300 max_lines = 65536/src_pitch + 1;
301 line_length = w * (pDst->drawable.bitsPerPixel >> 3);
303 setM2MFDirection(pNv, 1);
305 NVDEBUG("NVUploadToScreen: x=%d, y=%d, w=%d, h=%d\n", x, y, w, h);
307 NVDEBUG(" max_lines=%d, h=%d\n", max_lines, h);
308 int nlines = h > max_lines ? max_lines : h;
309 /* reset the notification object */
310 memset(pNv->Notifier0->map, 0xff, pNv->Notifier0->size);
311 memcpy(pNv->AGPScratch->map, src, nlines*src_pitch);
312 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_NOTIFY, 1);
314 NVDmaStart(pNv, NvSubMemFormat, MEMFORMAT_OFFSET_IN, 8);
316 NVDmaNext (pNv, offset_out);
317 NVDmaNext (pNv, src_pitch);
318 NVDmaNext (pNv, pitch_out);
319 NVDmaNext (pNv, line_length);
320 NVDmaNext (pNv, nlines);
321 NVDmaNext (pNv, 0x101);
324 if (!NVDmaWaitForNotifier(pNv, pNv->Notifier0->map)) {
329 offset_out += nlines*pitch_out;
330 src += nlines*src_pitch;
334 exaMarkSync(pDst->drawable.pScreen);
339 static Bool NVCheckComposite (int op,
340 PicturePtr pSrcPicture,
341 PicturePtr pMaskPicture,
342 PicturePtr pDstPicture)
347 /* PictOpOver doesn't work correctly. The HW command assumes non premuliplied alpha */
348 else if (op != PictOpOver && op != PictOpSrc)
350 else if (!pSrcPicture->pDrawable)
352 else if (pSrcPicture->transform || pSrcPicture->repeat)
354 else if (pSrcPicture->alphaMap || pDstPicture->alphaMap)
356 else if (pSrcPicture->format != PICT_a8r8g8b8 &&
357 pSrcPicture->format != PICT_x8r8g8b8 &&
358 pSrcPicture->format != PICT_r5g6b5)
360 else if (pDstPicture->format != PICT_a8r8g8b8 &&
361 pDstPicture->format != PICT_x8r8g8b8 &&
362 pDstPicture->format != PICT_r5g6b5)
367 static CARD32 src_size, src_pitch, src_offset;
369 static Bool NVPrepareComposite (int op,
370 PicturePtr pSrcPicture,
371 PicturePtr pMaskPicture,
372 PicturePtr pDstPicture,
377 ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
378 NVPtr pNv = NVPTR(pScrn);
380 int srcFormat, dstFormat;
381 if (pSrcPicture->format == PICT_a8r8g8b8)
382 srcFormat = STRETCH_BLIT_FORMAT_A8R8G8B8;
383 else if (pSrcPicture->format == PICT_x8r8g8b8)
384 srcFormat = STRETCH_BLIT_FORMAT_X8R8G8B8;
386 srcFormat = STRETCH_BLIT_FORMAT_DEPTH16;
388 if (pDstPicture->format == PICT_a8r8g8b8)
389 dstFormat = SURFACE_FORMAT_A8R8G8B8;
390 else if (pDstPicture->format == PICT_x8r8g8b8)
391 dstFormat = SURFACE_FORMAT_X8R8G8B8;
393 dstFormat = SURFACE_FORMAT_R5G6B5;
396 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
397 NVDmaNext (pNv, dstFormat);
398 NVDmaNext (pNv, getPitch(pSrcPicture->pDrawable)|(getPitch(pDstPicture->pDrawable) << 16));
399 NVDmaNext (pNv, getOffset(pNv, pSrcPicture->pDrawable));
400 NVDmaNext (pNv, getOffset(pNv, pDstPicture->pDrawable));
402 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_FORMAT, 2);
403 NVDmaNext (pNv, srcFormat);
404 NVDmaNext (pNv, (op == PictOpSrc) ? STRETCH_BLIT_OPERATION_COPY : STRETCH_BLIT_OPERATION_BLEND);
406 src_size = pSrcPicture->pDrawable->width | (pSrcPicture->pDrawable->height << 16);
407 src_pitch = getPitch(pSrcPicture->pDrawable)
408 | (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER << 16)
409 | (STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE << 24);
410 src_offset = getOffset(pNv, pSrcPicture->pDrawable);
414 static void NVComposite (PixmapPtr pDst,
424 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
425 NVPtr pNv = NVPTR(pScrn);
427 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
428 NVDmaNext (pNv, dstX | (dstY << 16));
429 NVDmaNext (pNv, width | (height << 16));
430 NVDmaNext (pNv, dstX | (dstY << 16));
431 NVDmaNext (pNv, width | (height << 16));
432 NVDmaNext (pNv, 1<<20);
433 NVDmaNext (pNv, 1<<20);
435 NVDmaStart(pNv, NvSubScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
436 NVDmaNext (pNv, src_size);
437 NVDmaNext (pNv, src_pitch);
438 NVDmaNext (pNv, src_offset);
439 NVDmaNext (pNv, srcX | (srcY<<16));
444 static void NVDoneComposite (PixmapPtr pDst)
446 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
447 NVPtr pNv = NVPTR(pScrn);
449 if (pNv->CurrentLayout.depth == 8)
450 format = SURFACE_FORMAT_Y8;
451 else if (pNv->CurrentLayout.depth == 16)
452 format = SURFACE_FORMAT_R5G6B5;
454 format = SURFACE_FORMAT_X8R8G8B8;
455 NVDmaStart(pNv, NvSubContextSurfaces, SURFACE_FORMAT, 1);
456 NVDmaNext (pNv, format);
457 exaMarkSync(pDst->drawable.pScreen);
460 Bool NVExaInit(ScreenPtr pScreen)
462 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
463 NVPtr pNv = NVPTR(pScrn);
465 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
470 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
471 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
473 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
474 pNv->EXADriverPtr->offScreenBase = pScrn->virtualX*pScrn->virtualY*pScrn->depth;
475 pNv->EXADriverPtr->memorySize = pNv->FB->size;
476 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
477 pNv->EXADriverPtr->pixmapPitchAlign = 64;
478 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
479 pNv->EXADriverPtr->maxX = 32768;
480 pNv->EXADriverPtr->maxY = 32768;
482 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
484 /* Install default hooks */
485 if (pNv->AGPScratch) {
486 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
487 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
490 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
491 pNv->EXADriverPtr->Copy = NVExaCopy;
492 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
494 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
495 pNv->EXADriverPtr->Solid = NVExaSolid;
496 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
498 /*darktama: Hard-disabled these for now, I get lockups often when
499 * starting e17 with them enabled.
500 *marcheu: Doesn't crash for me... was it related to the setup being
501 * called twice before ?
503 if (pNv->BlendingPossible) {
504 /* install composite hooks */
505 pNv->EXADriverPtr->CheckComposite = NVCheckComposite;
506 pNv->EXADriverPtr->PrepareComposite = NVPrepareComposite;
507 pNv->EXADriverPtr->Composite = NVComposite;
508 pNv->EXADriverPtr->DoneComposite = NVDoneComposite;
511 /* If we're going to try and use 3D, let the card-specific function
512 * override whatever hooks it wants.
514 if (pNv->use3D) pNv->InitEXA3D(pNv);
516 return exaDriverInit(pScreen, pNv->EXADriverPtr);