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 const int NVCopyROP[16] =
56 0x44, /* GXandReverse */
58 0x22, /* GXandInverted */
65 0xDD, /* GXorReverse */
66 0x33, /* GXcopyInverted */
67 0xBB, /* GXorInverted */
73 NVSetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1,
74 CARD32 pat0, CARD32 pat1)
76 NVPtr pNv = NVPTR(pScrn);
78 BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
86 NVSetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask)
88 NVPtr pNv = NVPTR(pScrn);
89 int rop = NVCopyROP[alu] & 0xf0;
91 if (planemask != ~0) {
92 NVSetPattern(pScrn, 0, planemask, ~0, ~0);
93 if (pNv->currentRop != (alu + 32)) {
94 BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
95 OUT_RING (rop | 0x0a);
96 pNv->currentRop = alu + 32;
99 if (pNv->currentRop != alu) {
100 if(pNv->currentRop >= 16)
101 NVSetPattern(pScrn, ~0, ~0, ~0, ~0);
102 BEGIN_RING(NvRop, NV03_CONTEXT_ROP_ROP, 1);
103 OUT_RING (rop | (rop >> 4));
104 pNv->currentRop = alu;
108 static CARD32 rectFormat(DrawablePtr pDrawable)
110 switch(pDrawable->bitsPerPixel) {
113 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
116 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
119 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
124 /* EXA acceleration hooks */
125 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
127 NVSync(xf86Screens[pScreen->myNum]);
130 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
135 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
136 NVPtr pNv = NVPTR(pScrn);
137 unsigned int fmt, pitch;
139 planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
140 if (planemask != ~0 || alu != GXcopy) {
141 if (pPixmap->drawable.bitsPerPixel == 32)
143 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
144 OUT_RING (1); /* ROP_AND */
145 NVSetROP(pScrn, alu, planemask);
147 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
148 OUT_RING (3); /* SRCCOPY */
151 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, (int*)&fmt))
153 pitch = exaGetPixmapPitch(pPixmap);
155 /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
156 * alpha channel gets forced to 0xFF for some reason. We're using
157 * SURFACE_FORMAT_Y32 as a workaround
159 if (fmt == NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8)
160 fmt = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
162 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
164 OUT_RING ((pitch << 16) | pitch);
165 OUT_PIXMAPl(pPixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
166 OUT_PIXMAPl(pPixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
168 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
169 OUT_RING (rectFormat(&pPixmap->drawable));
170 BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
176 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
178 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
179 NVPtr pNv = NVPTR(pScrn);
183 BEGIN_RING(NvRectangle,
184 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
185 OUT_RING ((x1 << 16) | y1);
186 OUT_RING ((width << 16) | height);
188 if((width * height) >= 512)
192 static void NVExaDoneSolid (PixmapPtr pPixmap)
196 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
197 PixmapPtr pDstPixmap,
203 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
204 NVPtr pNv = NVPTR(pScrn);
207 if (pSrcPixmap->drawable.bitsPerPixel !=
208 pDstPixmap->drawable.bitsPerPixel)
211 planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
212 if (planemask != ~0 || alu != GXcopy) {
213 if (pDstPixmap->drawable.bitsPerPixel == 32)
215 BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
216 OUT_RING (1); /* ROP_AND */
217 NVSetROP(pScrn, alu, planemask);
219 BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
220 OUT_RING (3); /* SRCCOPY */
223 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
226 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
228 OUT_RING ((exaGetPixmapPitch(pDstPixmap) << 16) |
229 (exaGetPixmapPitch(pSrcPixmap)));
230 OUT_PIXMAPl(pSrcPixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
231 OUT_PIXMAPl(pDstPixmap, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
236 static void NVExaCopy(PixmapPtr pDstPixmap,
244 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
245 NVPtr pNv = NVPTR(pScrn);
247 /* We want to catch people who have this bug, to find a decent fix */
249 /* Now check whether we have the same values for srcY and dstY and
250 whether the used chipset is buggy. Currently we flag all of G70
251 cards as buggy, which is probably much to broad. KoalaBR
252 16 is an abritrary threshold. It should define the maximum number
253 of lines between dstY and srcY If the number of lines is below
254 we guess, that the bug won't trigger...
256 if ( ((abs(srcY - dstY)< 16)||(abs(srcX-dstX)<16)) &&
257 ((((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
258 ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
259 ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
260 ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
261 ((pNv->Chipset & 0xfff0) == CHIPSET_C512))) )
263 int dx=abs(srcX - dstX),dy=abs(srcY - dstY);
264 // Ok, let's do it manually unless someone comes up with a better idea
265 // 1. If dstY and srcY are really the same, do a copy rowwise
268 NVDEBUG("ExaCopy: Lines identical:\n");
276 for (i = 0; i < width; i++) {
277 BEGIN_RING(NvImageBlit,
278 NV_IMAGE_BLIT_POINT_IN, 3);
279 OUT_RING ((srcY << 16) | (srcX+xpos));
280 OUT_RING ((dstY << 16) | (dstX+xpos));
281 OUT_RING ((height << 16) | 1);
285 // 2. Otherwise we will try a line by line copy in the hope to avoid
288 NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
296 for (i = 0; i < height; i++) {
297 BEGIN_RING(NvImageBlit,
298 NV_IMAGE_BLIT_POINT_IN, 3);
299 OUT_RING (((srcY+ypos) << 16) | srcX);
300 OUT_RING (((dstY+ypos) << 16) | dstX);
301 OUT_RING ((1 << 16) | width);
306 NVDEBUG("ExaCopy: Using default path\n");
307 BEGIN_RING(NvImageBlit, NV_IMAGE_BLIT_POINT_IN, 3);
308 OUT_RING ((srcY << 16) | srcX);
309 OUT_RING ((dstY << 16) | dstX);
310 OUT_RING ((height << 16) | width);
314 NVDEBUG("ExaCopy: Using default path\n");
315 BEGIN_RING(NvImageBlit, NV01_IMAGE_BLIT_POINT_IN, 3);
316 OUT_RING ((srcY << 16) | srcX);
317 OUT_RING ((dstY << 16) | dstX);
318 OUT_RING ((height << 16) | width);
320 if((width * height) >= 512)
324 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
326 static inline Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
327 int dst_pitch, int src_pitch, int line_len)
329 if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
330 memcpy(dst, src, line_len*height);
333 memcpy(dst, src, line_len);
343 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, PixmapPtr pspix,
344 uint32_t src_offset, int dst_pitch, int src_pitch,
345 int line_len, int line_count)
347 NVPtr pNv = NVPTR(pScrn);
349 BEGIN_RING(NvMemFormat, 0x184, 2);
350 OUT_PIXMAPo(pspix, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
351 OUT_RELOCo(pNv->GART, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
354 char *src = pNv->GART->map;
357 if (line_count * line_len <= pNv->GART->size) {
360 lc = pNv->GART->size / line_len;
369 if (pNv->Architecture >= NV_ARCH_50) {
370 BEGIN_RING(NvMemFormat, 0x200, 1);
372 BEGIN_RING(NvMemFormat, 0x21c, 1);
374 /* probably high-order bits of address */
375 BEGIN_RING(NvMemFormat, 0x238, 2);
376 OUT_PIXMAPh(pspix, src_offset, NOUVEAU_BO_GART |
377 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
378 OUT_RELOCh(pNv->GART, 0, NOUVEAU_BO_GART |
382 BEGIN_RING(NvMemFormat,
383 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
384 OUT_PIXMAPl(pspix, src_offset, NOUVEAU_BO_GART |
385 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
386 OUT_RELOCl(pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
387 OUT_RING (src_pitch);
394 nouveau_notifier_reset(pNv->notify0, 0);
395 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
397 BEGIN_RING(NvMemFormat, 0x100, 1);
400 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0,
404 if (dst_pitch == line_len) {
405 memcpy(dst, src, dst_pitch * lc);
406 dst += dst_pitch * lc;
408 for (i = 0; i < lc; i++) {
409 memcpy(dst, src, line_len);
416 src_offset += lc * src_pitch;
423 NVExaPixmapMap(PixmapPtr pPix)
426 #if NOUVEAU_EXA_PIXMAPS
427 struct nouveau_pixmap *nvpix;
429 nvpix = exaGetPixmapDriverPrivate(pPix);
430 if (!nvpix || !nvpix->bo)
433 map = nvpix->bo->map;
435 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
436 NVPtr pNv = NVPTR(pScrn);
437 map = pNv->FB->map + exaGetPixmapOffset(pPix);
438 #endif /* NOUVEAU_EXA_PIXMAPS */
442 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
445 char *dst, int dst_pitch)
447 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
448 NVPtr pNv = NVPTR(pScrn);
449 int src_pitch, cpp, offset;
452 src_pitch = exaGetPixmapPitch(pSrc);
453 cpp = pSrc->drawable.bitsPerPixel >> 3;
454 offset = (y * src_pitch) + (x * cpp);
457 if (NVAccelDownloadM2MF(pScrn, dst, pSrc, offset,
458 dst_pitch, src_pitch, w * cpp, h))
462 src = NVExaPixmapMap(pSrc);
466 exaWaitSync(pSrc->drawable.pScreen);
467 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
474 NVAccelUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch,
475 PixmapPtr pDst, int x, int y, int w, int h, int cpp)
477 NVPtr pNv = NVPTR(pScrn);
478 int line_len = w * cpp;
479 int iw, id, surf_fmt, ifc_fmt;
481 if (pNv->Architecture >= NV_ARCH_50)
488 case 2: ifc_fmt = 1; break;
489 case 4: ifc_fmt = 4; break;
494 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &surf_fmt))
497 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
499 OUT_RING ((exaGetPixmapPitch(pDst) << 16) | exaGetPixmapPitch(pDst));
500 OUT_PIXMAPl(pDst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
501 OUT_PIXMAPl(pDst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
503 /* Pad out input width to cover both COLORA() and COLORB() */
504 iw = (line_len + 7) & ~7;
505 id = iw / 4; /* line push size */
508 /* Don't support lines longer than max push size yet.. */
512 BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
514 OUT_RING (0x7FFF7FFF);
516 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
517 OUT_RING (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
519 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_POINT, 3);
520 OUT_RING ((y << 16) | x); /* dst point */
521 OUT_RING ((h << 16) | w); /* width/height out */
522 OUT_RING ((h << 16) | iw); /* width/height in */
526 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
536 NVAccelUploadM2MF(ScrnInfoPtr pScrn, PixmapPtr pdpix, uint32_t dst_offset,
537 const char *src, int dst_pitch, int src_pitch,
538 int line_len, int line_count)
540 NVPtr pNv = NVPTR(pScrn);
542 BEGIN_RING(NvMemFormat, 0x184, 2);
543 OUT_RELOCo(pNv->GART, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
544 OUT_PIXMAPo(pdpix, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
547 char *dst = pNv->GART->map;
550 /* Determine max amount of data we can DMA at once */
551 if (line_count * line_len <= pNv->GART->size) {
554 lc = pNv->GART->size / line_len;
564 if (src_pitch == line_len) {
565 memcpy(dst, src, src_pitch * lc);
566 src += src_pitch * lc;
568 for (i = 0; i < lc; i++) {
569 memcpy(dst, src, line_len);
575 if (pNv->Architecture >= NV_ARCH_50) {
576 BEGIN_RING(NvMemFormat, 0x200, 1);
578 BEGIN_RING(NvMemFormat, 0x21c, 1);
580 /* probably high-order bits of address */
581 BEGIN_RING(NvMemFormat, 0x238, 2);
582 OUT_RELOCh(pNv->GART, 0, NOUVEAU_BO_GART |
584 OUT_PIXMAPh(pdpix, 0, NOUVEAU_BO_VRAM |
585 NOUVEAU_BO_GART | NOUVEAU_BO_WR);
589 BEGIN_RING(NvMemFormat,
590 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
591 OUT_RELOCl(pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
592 OUT_PIXMAPl(pdpix, dst_offset, NOUVEAU_BO_VRAM |
593 NOUVEAU_BO_GART | NOUVEAU_BO_WR);
595 OUT_RING (dst_pitch);
601 nouveau_notifier_reset(pNv->notify0, 0);
602 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
604 BEGIN_RING(NvMemFormat, 0x100, 1);
607 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 2000))
610 dst_offset += lc * dst_pitch;
617 static Bool NVUploadToScreen(PixmapPtr pDst,
618 int x, int y, int w, int h,
619 char *src, int src_pitch)
621 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
622 NVPtr pNv = NVPTR(pScrn);
626 dst_pitch = exaGetPixmapPitch(pDst);
627 cpp = pDst->drawable.bitsPerPixel >> 3;
629 /* try hostdata transfer */
630 if (w * h * cpp < 16*1024) /* heuristic */
632 if (pNv->Architecture < NV_ARCH_50) {
633 if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst,
635 exaMarkSync(pDst->drawable.pScreen);
639 if (NV50EXAUploadSIFC(pScrn, src, src_pitch, pDst,
641 exaMarkSync(pDst->drawable.pScreen);
647 /* try gart-based transfer */
649 if (NVAccelUploadM2MF(pScrn, pDst, (y * dst_pitch) + (x * cpp),
650 src, dst_pitch, src_pitch, w * cpp, h))
654 /* fallback to memcpy-based transfer */
655 dst = NVExaPixmapMap(pDst);
658 dst += (y * dst_pitch) + (x * cpp);
659 exaWaitSync(pDst->drawable.pScreen);
660 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
666 #ifdef NOUVEAU_EXA_PIXMAPS
668 NVExaPrepareAccess(PixmapPtr pPix, int index)
670 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
671 NVPtr pNv = NVPTR(pScrn);
672 struct nouveau_pixmap *nvpix;
675 nvpix = exaGetPixmapDriverPrivate(pPix);
676 if (!nvpix || !nvpix->bo)
679 /*XXX: ho hum.. sync if needed */
684 if (nouveau_bo_map(nvpix->bo, NOUVEAU_BO_RDWR))
686 pPix->devPrivate.ptr = nvpix->bo->map;
687 nvpix->mapped = TRUE;
692 NVExaFinishAccess(PixmapPtr pPix, int index)
694 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
695 NVPtr pNv = NVPTR(pScrn);
696 struct nouveau_pixmap *nvpix;
699 nvpix = exaGetPixmapDriverPrivate(pPix);
700 if (!nvpix || !nvpix->bo || !nvpix->mapped)
703 nouveau_bo_unmap(nvpix->bo);
704 pPix->devPrivate.ptr = NULL;
705 nvpix->mapped = FALSE;
709 NVExaPixmapIsOffscreen(PixmapPtr pPix)
711 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
712 NVPtr pNv = NVPTR(pScrn);
713 struct nouveau_pixmap *nvpix;
716 nvpix = exaGetPixmapDriverPrivate(pPix);
717 if (!nvpix || !nvpix->bo)
724 NVExaCreatePixmap(ScreenPtr pScreen, int size, int align)
726 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
727 NVPtr pNv = NVPTR(pScrn);
728 struct nouveau_pixmap *nvpix;
730 nvpix = xcalloc(1, sizeof(struct nouveau_pixmap));
735 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM, 0, size,
746 NVExaDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
748 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
749 NVPtr pNv = NVPTR(pScrn);
750 struct nouveau_pixmap *nvpix = driverPriv;
755 /*XXX: only if pending relocs reference this buffer..*/
758 nouveau_bo_del(&nvpix->bo);
763 NVExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
764 int bitsPerPixel, int devKind, pointer pPixData)
766 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
767 NVPtr pNv = NVPTR(pScrn);
768 struct nouveau_pixmap *nvpix;
770 if (pPixData == pNv->FB->map) {
771 nvpix = exaGetPixmapDriverPrivate(pPixmap);
775 if (nouveau_bo_ref(pNv->dev, pNv->FB->handle, &nvpix->bo))
778 miModifyPixmapHeader(pPixmap, width, height, depth,
779 bitsPerPixel, devKind, NULL);
788 NVExaPixmapIsOnscreen(PixmapPtr pPixmap)
790 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
791 NVPtr pNv = NVPTR(pScrn);
793 #if NOUVEAU_EXA_PIXMAPS
794 struct nouveau_pixmap *nvpix;
795 nvpix = exaGetPixmapDriverPrivate(pPixmap);
797 if (nvpix && nvpix->bo == pNv->FB)
801 unsigned long offset = exaGetPixmapOffset(pPixmap);
803 if (offset < pNv->EXADriverPtr->offScreenBase)
805 #endif /* NOUVEAU_EXA_PIXMAPS */
811 NVExaInit(ScreenPtr pScreen)
813 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
814 NVPtr pNv = NVPTR(pScrn);
816 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
821 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
822 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
824 #ifdef NOUVEAU_EXA_PIXMAPS
825 if (NOUVEAU_EXA_PIXMAPS) {
826 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS |
828 pNv->EXADriverPtr->PrepareAccess = NVExaPrepareAccess;
829 pNv->EXADriverPtr->FinishAccess = NVExaFinishAccess;
830 pNv->EXADriverPtr->PixmapIsOffscreen = NVExaPixmapIsOffscreen;
831 pNv->EXADriverPtr->CreatePixmap = NVExaCreatePixmap;
832 pNv->EXADriverPtr->DestroyPixmap = NVExaDestroyPixmap;
833 pNv->EXADriverPtr->ModifyPixmapHeader = NVExaModifyPixmapHeader;
837 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
838 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
839 pNv->EXADriverPtr->offScreenBase =
840 NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY,64) *
841 (pScrn->bitsPerPixel / 8);
842 pNv->EXADriverPtr->memorySize = pNv->FB->size;
844 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
845 pNv->EXADriverPtr->pixmapPitchAlign = 64;
847 if (pNv->Architecture >= NV_ARCH_50) {
848 pNv->EXADriverPtr->maxX = 8192;
849 pNv->EXADriverPtr->maxY = 8192;
851 if (pNv->Architecture >= NV_ARCH_20) {
852 pNv->EXADriverPtr->maxX = 4096;
853 pNv->EXADriverPtr->maxY = 4096;
855 pNv->EXADriverPtr->maxX = 2048;
856 pNv->EXADriverPtr->maxY = 2048;
859 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
861 /* Install default hooks */
862 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
863 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
865 if (pNv->Architecture < NV_ARCH_50) {
866 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
867 pNv->EXADriverPtr->Copy = NVExaCopy;
868 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
870 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
871 pNv->EXADriverPtr->Solid = NVExaSolid;
872 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
874 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
875 pNv->EXADriverPtr->Copy = NV50EXACopy;
876 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
878 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
879 pNv->EXADriverPtr->Solid = NV50EXASolid;
880 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
883 switch (pNv->Architecture) {
887 pNv->EXADriverPtr->CheckComposite = NV10CheckComposite;
888 pNv->EXADriverPtr->PrepareComposite = NV10PrepareComposite;
889 pNv->EXADriverPtr->Composite = NV10Composite;
890 pNv->EXADriverPtr->DoneComposite = NV10DoneComposite;
893 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
894 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
895 pNv->EXADriverPtr->Composite = NV30EXAComposite;
896 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
899 pNv->EXADriverPtr->CheckComposite = NV40EXACheckComposite;
900 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
901 pNv->EXADriverPtr->Composite = NV40EXAComposite;
902 pNv->EXADriverPtr->DoneComposite = NV40EXADoneComposite;
910 if (!exaDriverInit(pScreen, pNv->EXADriverPtr))
913 /* EXA init catches this, but only for xserver >= 1.4 */
914 if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) {
915 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n");