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;
482 if (pNv->Architecture >= NV_ARCH_50)
489 case 2: ifc_fmt = 1; break;
490 case 4: ifc_fmt = 4; break;
495 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &surf_fmt))
498 BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
500 OUT_RING ((exaGetPixmapPitch(pDst) << 16) | exaGetPixmapPitch(pDst));
501 OUT_PIXMAPl(pDst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
502 OUT_PIXMAPl(pDst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
504 /* Pad out input width to cover both COLORA() and COLORB() */
505 iw = (line_len + 7) & ~7;
506 padbytes = iw - line_len;
507 id = iw / 4; /* line push size */
510 /* Don't support lines longer than max push size yet.. */
514 BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_POINT, 2);
516 OUT_RING (0x7FFF7FFF);
518 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 2);
519 OUT_RING (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
521 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_POINT, 3);
522 OUT_RING ((y << 16) | x); /* dst point */
523 OUT_RING ((h << 16) | w); /* width/height out */
524 OUT_RING ((h << 16) | iw); /* width/height in */
530 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
537 int aux = (padbytes + 7) >> 2;
538 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_COLOR(0), id);
539 OUT_RINGp (src, id - aux);
540 memcpy(padding, src + (id - aux) * 4, padbytes);
541 OUT_RINGp (padding, aux);
548 NVAccelUploadM2MF(ScrnInfoPtr pScrn, PixmapPtr pdpix, uint32_t dst_offset,
549 const char *src, int dst_pitch, int src_pitch,
550 int line_len, int line_count)
552 NVPtr pNv = NVPTR(pScrn);
554 BEGIN_RING(NvMemFormat, 0x184, 2);
555 OUT_RELOCo(pNv->GART, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
556 OUT_PIXMAPo(pdpix, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR);
559 char *dst = pNv->GART->map;
562 /* Determine max amount of data we can DMA at once */
563 if (line_count * line_len <= pNv->GART->size) {
566 lc = pNv->GART->size / line_len;
576 if (src_pitch == line_len) {
577 memcpy(dst, src, src_pitch * lc);
578 src += src_pitch * lc;
580 for (i = 0; i < lc; i++) {
581 memcpy(dst, src, line_len);
587 if (pNv->Architecture >= NV_ARCH_50) {
588 BEGIN_RING(NvMemFormat, 0x200, 1);
590 BEGIN_RING(NvMemFormat, 0x21c, 1);
592 /* probably high-order bits of address */
593 BEGIN_RING(NvMemFormat, 0x238, 2);
594 OUT_RELOCh(pNv->GART, 0, NOUVEAU_BO_GART |
596 OUT_PIXMAPh(pdpix, 0, NOUVEAU_BO_VRAM |
597 NOUVEAU_BO_GART | NOUVEAU_BO_WR);
601 BEGIN_RING(NvMemFormat,
602 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
603 OUT_RELOCl(pNv->GART, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD);
604 OUT_PIXMAPl(pdpix, dst_offset, NOUVEAU_BO_VRAM |
605 NOUVEAU_BO_GART | NOUVEAU_BO_WR);
607 OUT_RING (dst_pitch);
613 nouveau_notifier_reset(pNv->notify0, 0);
614 BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
616 BEGIN_RING(NvMemFormat, 0x100, 1);
619 if (nouveau_notifier_wait_status(pNv->notify0, 0, 0, 2000))
622 dst_offset += lc * dst_pitch;
629 static Bool NVUploadToScreen(PixmapPtr pDst,
630 int x, int y, int w, int h,
631 char *src, int src_pitch)
633 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
634 NVPtr pNv = NVPTR(pScrn);
638 dst_pitch = exaGetPixmapPitch(pDst);
639 cpp = pDst->drawable.bitsPerPixel >> 3;
641 /* try hostdata transfer */
642 if (w * h * cpp < 16*1024) /* heuristic */
644 if (pNv->Architecture < NV_ARCH_50) {
645 if (NVAccelUploadIFC(pScrn, src, src_pitch, pDst,
647 exaMarkSync(pDst->drawable.pScreen);
651 if (NV50EXAUploadSIFC(pScrn, src, src_pitch, pDst,
653 exaMarkSync(pDst->drawable.pScreen);
659 /* try gart-based transfer */
661 if (NVAccelUploadM2MF(pScrn, pDst, (y * dst_pitch) + (x * cpp),
662 src, dst_pitch, src_pitch, w * cpp, h))
666 /* fallback to memcpy-based transfer */
667 dst = NVExaPixmapMap(pDst);
670 dst += (y * dst_pitch) + (x * cpp);
671 exaWaitSync(pDst->drawable.pScreen);
672 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
678 #ifdef NOUVEAU_EXA_PIXMAPS
680 NVExaPrepareAccess(PixmapPtr pPix, int index)
682 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
683 NVPtr pNv = NVPTR(pScrn);
684 struct nouveau_pixmap *nvpix;
687 nvpix = exaGetPixmapDriverPrivate(pPix);
688 if (!nvpix || !nvpix->bo)
691 /*XXX: ho hum.. sync if needed */
696 if (nouveau_bo_map(nvpix->bo, NOUVEAU_BO_RDWR))
698 pPix->devPrivate.ptr = nvpix->bo->map;
699 nvpix->mapped = TRUE;
704 NVExaFinishAccess(PixmapPtr pPix, int index)
706 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
707 NVPtr pNv = NVPTR(pScrn);
708 struct nouveau_pixmap *nvpix;
711 nvpix = exaGetPixmapDriverPrivate(pPix);
712 if (!nvpix || !nvpix->bo || !nvpix->mapped)
715 nouveau_bo_unmap(nvpix->bo);
716 pPix->devPrivate.ptr = NULL;
717 nvpix->mapped = FALSE;
721 NVExaPixmapIsOffscreen(PixmapPtr pPix)
723 ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum];
724 NVPtr pNv = NVPTR(pScrn);
725 struct nouveau_pixmap *nvpix;
728 nvpix = exaGetPixmapDriverPrivate(pPix);
729 if (!nvpix || !nvpix->bo)
736 NVExaCreatePixmap(ScreenPtr pScreen, int size, int align)
738 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
739 NVPtr pNv = NVPTR(pScrn);
740 struct nouveau_pixmap *nvpix;
742 nvpix = xcalloc(1, sizeof(struct nouveau_pixmap));
747 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM, 0, size,
758 NVExaDestroyPixmap(ScreenPtr pScreen, void *driverPriv)
760 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
761 NVPtr pNv = NVPTR(pScrn);
762 struct nouveau_pixmap *nvpix = driverPriv;
767 /*XXX: only if pending relocs reference this buffer..*/
770 nouveau_bo_del(&nvpix->bo);
775 NVExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
776 int bitsPerPixel, int devKind, pointer pPixData)
778 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
779 NVPtr pNv = NVPTR(pScrn);
780 struct nouveau_pixmap *nvpix;
782 if (pPixData == pNv->FB->map) {
783 nvpix = exaGetPixmapDriverPrivate(pPixmap);
787 if (nouveau_bo_ref(pNv->dev, pNv->FB->handle, &nvpix->bo))
790 miModifyPixmapHeader(pPixmap, width, height, depth,
791 bitsPerPixel, devKind, NULL);
800 NVExaPixmapIsOnscreen(PixmapPtr pPixmap)
802 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
803 NVPtr pNv = NVPTR(pScrn);
805 #if NOUVEAU_EXA_PIXMAPS
806 struct nouveau_pixmap *nvpix;
807 nvpix = exaGetPixmapDriverPrivate(pPixmap);
809 if (nvpix && nvpix->bo == pNv->FB)
813 unsigned long offset = exaGetPixmapOffset(pPixmap);
815 if (offset < pNv->EXADriverPtr->offScreenBase)
817 #endif /* NOUVEAU_EXA_PIXMAPS */
823 NVExaInit(ScreenPtr pScreen)
825 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
826 NVPtr pNv = NVPTR(pScrn);
828 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
833 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
834 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
836 #ifdef NOUVEAU_EXA_PIXMAPS
837 if (NOUVEAU_EXA_PIXMAPS) {
838 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS |
840 pNv->EXADriverPtr->PrepareAccess = NVExaPrepareAccess;
841 pNv->EXADriverPtr->FinishAccess = NVExaFinishAccess;
842 pNv->EXADriverPtr->PixmapIsOffscreen = NVExaPixmapIsOffscreen;
843 pNv->EXADriverPtr->CreatePixmap = NVExaCreatePixmap;
844 pNv->EXADriverPtr->DestroyPixmap = NVExaDestroyPixmap;
845 pNv->EXADriverPtr->ModifyPixmapHeader = NVExaModifyPixmapHeader;
849 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
850 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
851 pNv->EXADriverPtr->offScreenBase =
852 NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY,64) *
853 (pScrn->bitsPerPixel / 8);
854 pNv->EXADriverPtr->memorySize = pNv->FB->size;
856 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
857 pNv->EXADriverPtr->pixmapPitchAlign = 64;
859 if (pNv->Architecture >= NV_ARCH_50) {
860 pNv->EXADriverPtr->maxX = 8192;
861 pNv->EXADriverPtr->maxY = 8192;
863 if (pNv->Architecture >= NV_ARCH_20) {
864 pNv->EXADriverPtr->maxX = 4096;
865 pNv->EXADriverPtr->maxY = 4096;
867 pNv->EXADriverPtr->maxX = 2048;
868 pNv->EXADriverPtr->maxY = 2048;
871 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
873 /* Install default hooks */
874 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
875 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
877 if (pNv->Architecture < NV_ARCH_50) {
878 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
879 pNv->EXADriverPtr->Copy = NVExaCopy;
880 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
882 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
883 pNv->EXADriverPtr->Solid = NVExaSolid;
884 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
886 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
887 pNv->EXADriverPtr->Copy = NV50EXACopy;
888 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
890 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
891 pNv->EXADriverPtr->Solid = NV50EXASolid;
892 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
895 switch (pNv->Architecture) {
899 pNv->EXADriverPtr->CheckComposite = NV10CheckComposite;
900 pNv->EXADriverPtr->PrepareComposite = NV10PrepareComposite;
901 pNv->EXADriverPtr->Composite = NV10Composite;
902 pNv->EXADriverPtr->DoneComposite = NV10DoneComposite;
905 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
906 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
907 pNv->EXADriverPtr->Composite = NV30EXAComposite;
908 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
911 pNv->EXADriverPtr->CheckComposite = NV40EXACheckComposite;
912 pNv->EXADriverPtr->PrepareComposite = NV40EXAPrepareComposite;
913 pNv->EXADriverPtr->Composite = NV40EXAComposite;
914 pNv->EXADriverPtr->DoneComposite = NV40EXADoneComposite;
922 if (!exaDriverInit(pScreen, pNv->EXADriverPtr))
925 /* EXA init catches this, but only for xserver >= 1.4 */
926 if (pNv->VRAMPhysicalSize / 2 < NOUVEAU_ALIGN(pScrn->virtualX, 64) * NOUVEAU_ALIGN(pScrn->virtualY, 64) * (pScrn->bitsPerPixel >> 3)) {
927 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "The virtual screen size's resolution is too big for the video RAM framebuffer at this colour depth.\n");