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)
48 #include "nv_include.h"
56 const int NVCopyROP[16] =
60 0x44, /* GXandReverse */
62 0x22, /* GXandInverted */
69 0xDD, /* GXorReverse */
70 0x33, /* GXcopyInverted */
71 0xBB, /* GXorInverted */
77 NVSetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1,
78 CARD32 pat0, CARD32 pat1)
80 NVPtr pNv = NVPTR(pScrn);
82 NVDmaStart(pNv, NvImagePattern, PATTERN_COLOR_0, 4);
83 NVDmaNext (pNv, clr0);
84 NVDmaNext (pNv, clr1);
85 NVDmaNext (pNv, pat0);
86 NVDmaNext (pNv, pat1);
90 NVSetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask)
92 NVPtr pNv = NVPTR(pScrn);
93 int rop = NVCopyROP[alu] & 0xf0;
95 if (planemask != ~0) {
96 NVSetPattern(pScrn, 0, planemask, ~0, ~0);
97 if (pNv->currentRop != (alu + 32)) {
98 NVDmaStart(pNv, NvRop, ROP_SET, 1);
99 NVDmaNext (pNv, rop | 0x0a);
100 pNv->currentRop = alu + 32;
103 if (pNv->currentRop != alu) {
104 if(pNv->currentRop >= 16)
105 NVSetPattern(pScrn, ~0, ~0, ~0, ~0);
106 NVDmaStart(pNv, NvRop, ROP_SET, 1);
107 NVDmaNext (pNv, rop | (rop >> 4));
108 pNv->currentRop = alu;
112 static void setM2MFDirection(ScrnInfoPtr pScrn, int dir)
114 NVPtr pNv = NVPTR(pScrn);
116 if (pNv->M2MFDirection != dir) {
118 NVDmaStart(pNv, NvMemFormat, MEMFORMAT_DMA_OBJECT_IN, 2);
119 NVDmaNext (pNv, dir ? NvDmaTT : NvDmaFB);
120 NVDmaNext (pNv, dir ? NvDmaFB : NvDmaTT);
121 pNv->M2MFDirection = dir;
125 static CARD32 rectFormat(DrawablePtr pDrawable)
127 switch(pDrawable->bitsPerPixel) {
130 return RECT_FORMAT_DEPTH24;
133 return RECT_FORMAT_DEPTH16;
136 return RECT_FORMAT_DEPTH8;
141 /* EXA acceleration hooks */
142 static void NVExaWaitMarker(ScreenPtr pScreen, int marker)
144 NVSync(xf86Screens[pScreen->myNum]);
147 static Bool NVExaPrepareSolid(PixmapPtr pPixmap,
152 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
153 NVPtr pNv = NVPTR(pScrn);
156 planemask |= ~0 << pPixmap->drawable.bitsPerPixel;
157 if (planemask != ~0 || alu != GXcopy) {
158 if (pPixmap->drawable.bitsPerPixel == 32)
160 NVDmaStart(pNv, NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
161 NVDmaNext (pNv, 1 /* ROP_AND */);
162 NVSetROP(pScrn, alu, planemask);
164 NVDmaStart(pNv, NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
165 NVDmaNext (pNv, 3 /* SRCCOPY */);
168 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, &fmt))
171 /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
172 * alpha channel gets forced to 0xFF for some reason. We're using
173 * SURFACE_FORMAT_Y32 as a workaround
175 if (fmt == SURFACE_FORMAT_A8R8G8B8)
178 if (!NVAccelSetCtxSurf2D(pPixmap, pPixmap, fmt))
181 NVDmaStart(pNv, NvRectangle, RECT_FORMAT, 1);
182 NVDmaNext (pNv, rectFormat(&pPixmap->drawable));
183 NVDmaStart(pNv, NvRectangle, RECT_SOLID_COLOR, 1);
186 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
190 static void NVExaSolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
192 ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
193 NVPtr pNv = NVPTR(pScrn);
197 NVDmaStart(pNv, NvRectangle, RECT_SOLID_RECTS(0), 2);
198 NVDmaNext (pNv, (x1 << 16) | y1);
199 NVDmaNext (pNv, (width << 16) | height);
201 if((width * height) >= 512)
205 static void NVExaDoneSolid (PixmapPtr pPixmap)
209 static Bool NVExaPrepareCopy(PixmapPtr pSrcPixmap,
210 PixmapPtr pDstPixmap,
216 ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum];
217 NVPtr pNv = NVPTR(pScrn);
220 if (pSrcPixmap->drawable.bitsPerPixel !=
221 pDstPixmap->drawable.bitsPerPixel)
224 planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel;
225 if (planemask != ~0 || alu != GXcopy) {
226 if (pDstPixmap->drawable.bitsPerPixel == 32)
228 NVDmaStart(pNv, NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
229 NVDmaNext (pNv, 1 /* ROP_AND */);
230 NVSetROP(pScrn, alu, planemask);
232 NVDmaStart(pNv, NvImageBlit, NV_IMAGE_BLIT_OPERATION, 1);
233 NVDmaNext (pNv, 3 /* SRCCOPY */);
236 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt))
238 if (!NVAccelSetCtxSurf2D(pSrcPixmap, pDstPixmap, fmt))
241 pNv->DMAKickoffCallback = NVDmaKickoffCallback;
245 static void NVExaCopy(PixmapPtr pDstPixmap,
253 ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
254 NVPtr pNv = NVPTR(pScrn);
256 /* Now check whether we have the same values for srcY and dstY and
257 whether the used chipset is buggy. Currently we flag all of G70
258 cards as buggy, which is probably much to broad. KoalaBR
259 16 is an abritrary threshold. It should define the maximum number
260 of lines between dstY and srcY If the number of lines is below
261 we guess, that the bug won't trigger...
263 if ( ((abs(srcY - dstY)< 16)||(abs(srcX-dstX)<16)) &&
264 ((((pNv->Chipset & 0xfff0) == CHIPSET_G70) ||
265 ((pNv->Chipset & 0xfff0) == CHIPSET_G71) ||
266 ((pNv->Chipset & 0xfff0) == CHIPSET_G72) ||
267 ((pNv->Chipset & 0xfff0) == CHIPSET_G73) ||
268 ((pNv->Chipset & 0xfff0) == CHIPSET_C512))) )
270 int dx=abs(srcX - dstX),dy=abs(srcY - dstY);
271 // Ok, let's do it manually unless someone comes up with a better idea
272 // 1. If dstY and srcY are really the same, do a copy rowwise
275 NVDEBUG("ExaCopy: Lines identical:\n");
283 for (i = 0; i < width; i++) {
284 NVDmaStart(pNv, NvImageBlit, BLIT_POINT_SRC, 3);
285 NVDmaNext (pNv, (srcY << 16) | (srcX+xpos));
286 NVDmaNext (pNv, (dstY << 16) | (dstX+xpos));
287 NVDmaNext (pNv, (height << 16) | 1);
291 // 2. Otherwise we will try a line by line copy in the hope to avoid
294 NVDEBUG("ExaCopy: Lines nearly the same srcY=%d, dstY=%d:\n", srcY, dstY);
302 for (i = 0; i < height; i++) {
303 NVDmaStart(pNv, NvImageBlit, BLIT_POINT_SRC, 3);
304 NVDmaNext (pNv, ((srcY+ypos) << 16) | srcX);
305 NVDmaNext (pNv, ((dstY+ypos) << 16) | dstX);
306 NVDmaNext (pNv, (1 << 16) | width);
311 NVDEBUG("ExaCopy: Using default path\n");
312 NVDmaStart(pNv, NvImageBlit, BLIT_POINT_SRC, 3);
313 NVDmaNext (pNv, (srcY << 16) | srcX);
314 NVDmaNext (pNv, (dstY << 16) | dstX);
315 NVDmaNext (pNv, (height << 16) | width);
318 if((width * height) >= 512)
322 static void NVExaDoneCopy (PixmapPtr pDstPixmap) {}
324 Bool NVAccelMemcpyRect(char *dst, const char *src, int height,
325 int dst_pitch, int src_pitch, int line_len)
327 if ((src_pitch == line_len) && (src_pitch == dst_pitch)) {
328 memcpy(dst, src, line_len*height);
331 memcpy(dst, src, line_len);
341 NVAccelDownloadM2MF(ScrnInfoPtr pScrn, char *dst, uint64_t src_offset,
342 int dst_pitch, int src_pitch,
343 int line_len, int line_count)
345 NVPtr pNv = NVPTR(pScrn);
347 setM2MFDirection(pScrn, 0);
350 char *src = pNv->GARTScratch->map;
353 if (line_count * line_len <= pNv->GARTScratch->size) {
356 lc = pNv->GARTScratch->size / line_len;
365 if (pNv->Architecture >= NV_ARCH_50) {
366 NVDmaStart(pNv, NvMemFormat, 0x200, 1);
368 NVDmaStart(pNv, NvMemFormat, 0x21c, 1);
370 /* probably high-order bits of address */
371 NVDmaStart(pNv, NvMemFormat, 0x238, 2);
376 NVDmaStart(pNv, NvMemFormat,
377 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
378 NVDmaNext (pNv, (uint32_t)src_offset);
379 NVDmaNext (pNv, (uint32_t)pNv->GARTScratch->offset);
380 NVDmaNext (pNv, src_pitch);
381 NVDmaNext (pNv, line_len);
382 NVDmaNext (pNv, line_len);
384 NVDmaNext (pNv, (1<<8)|1);
387 NVNotifierReset(pScrn, pNv->Notifier0);
388 NVDmaStart(pNv, NvMemFormat,
389 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
391 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
394 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
397 if (dst_pitch == line_len) {
398 memcpy(dst, src, dst_pitch * lc);
399 dst += dst_pitch * lc;
401 for (i = 0; i < lc; i++) {
402 memcpy(dst, src, line_len);
409 src_offset += lc * src_pitch;
415 static Bool NVDownloadFromScreen(PixmapPtr pSrc,
418 char *dst, int dst_pitch)
420 ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
421 NVPtr pNv = NVPTR(pScrn);
422 int src_pitch, cpp, offset;
425 src_pitch = exaGetPixmapPitch(pSrc);
426 cpp = pSrc->drawable.bitsPerPixel >> 3;
427 offset = (y * src_pitch) + (x * cpp);
429 if (pNv->GARTScratch) {
430 if (NVAccelDownloadM2MF(pScrn, dst,
431 NVAccelGetPixmapOffset(pSrc) + offset,
432 dst_pitch, src_pitch, w * cpp, h))
436 src = pSrc->devPrivate.ptr + offset;
437 exaWaitSync(pSrc->drawable.pScreen);
438 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
445 NVAccelUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch,
446 int x, int y, int w, int h, int cpp)
448 NVPtr pNv = NVPTR(pScrn);
449 int line_len = w * cpp;
452 if (pNv->Architecture >= NV_ARCH_50)
459 case 2: fmt = 1; break;
460 case 4: fmt = 4; break;
465 /* Pad out input width to cover both COLORA() and COLORB() */
466 iw = (line_len + 7) & ~7;
467 id = iw / 4; /* line push size */
470 /* Don't support lines longer than max push size yet.. */
474 NVDmaStart(pNv, NvClipRectangle, CLIP_POINT, 2);
475 NVDmaNext (pNv, 0x0);
476 NVDmaNext (pNv, 0x7FFF7FFF);
478 NVDmaStart(pNv, NvImageFromCpu, NV05_IMAGE_FROM_CPU_OPERATION, 2);
479 NVDmaNext (pNv, 0x3 /* SRCCOPY */);
480 NVDmaNext (pNv, fmt);
481 NVDmaStart(pNv, NvImageFromCpu, NV05_IMAGE_FROM_CPU_POINT, 3);
482 NVDmaNext (pNv, (y << 16) | x); /* dst point */
483 NVDmaNext (pNv, (h << 16) | w); /* width/height out */
484 NVDmaNext (pNv, (h << 16) | iw); /* width/height in */
489 NVDmaStart(pNv, NvImageFromCpu,
490 NV10_IMAGE_FROM_CPU_HLINE, id);
491 dst = (char *)pNv->dmaBase + (pNv->dmaCurrent << 2);
492 memcpy(dst, src, line_len);
493 pNv->dmaCurrent += id;
502 NVAccelUploadM2MF(ScrnInfoPtr pScrn, uint64_t dst_offset, const char *src,
503 int dst_pitch, int src_pitch,
504 int line_len, int line_count)
506 NVPtr pNv = NVPTR(pScrn);
508 setM2MFDirection(pScrn, 1);
511 char *dst = pNv->GARTScratch->map;
514 /* Determine max amount of data we can DMA at once */
515 if (line_count * line_len <= pNv->GARTScratch->size) {
518 lc = pNv->GARTScratch->size / line_len;
528 if (src_pitch == line_len) {
529 memcpy(dst, src, src_pitch * lc);
530 src += src_pitch * lc;
532 for (i = 0; i < lc; i++) {
533 memcpy(dst, src, line_len);
539 if (pNv->Architecture >= NV_ARCH_50) {
540 NVDmaStart(pNv, NvMemFormat, 0x200, 1);
542 NVDmaStart(pNv, NvMemFormat, 0x21c, 1);
544 /* probably high-order bits of address */
545 NVDmaStart(pNv, NvMemFormat, 0x238, 2);
551 NVDmaStart(pNv, NvMemFormat,
552 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
553 NVDmaNext (pNv, (uint32_t)pNv->GARTScratch->offset);
554 NVDmaNext (pNv, (uint32_t)dst_offset);
555 NVDmaNext (pNv, line_len);
556 NVDmaNext (pNv, dst_pitch);
557 NVDmaNext (pNv, line_len);
559 NVDmaNext (pNv, (1<<8)|1);
562 NVNotifierReset(pScrn, pNv->Notifier0);
563 NVDmaStart(pNv, NvMemFormat,
564 NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1);
566 NVDmaStart(pNv, NvMemFormat, 0x100, 1);
569 if (!NVNotifierWaitStatus(pScrn, pNv->Notifier0, 0, 2000))
572 dst_offset += lc * dst_pitch;
579 static Bool NVUploadToScreen(PixmapPtr pDst,
580 int x, int y, int w, int h,
581 char *src, int src_pitch)
583 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
584 NVPtr pNv = NVPTR(pScrn);
585 int dst_offset, dst_pitch, cpp;
588 dst_offset = NVAccelGetPixmapOffset(pDst);
589 dst_pitch = exaGetPixmapPitch(pDst);
590 cpp = pDst->drawable.bitsPerPixel >> 3;
592 /* try hostdata transfer */
593 if (pNv->Architecture < NV_ARCH_50 && w*h*cpp<16*1024) /* heuristic */
597 if (NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &fmt)) {
598 NVAccelSetCtxSurf2D(pDst, pDst, fmt);
599 if (NVAccelUploadIFC(pScrn, src, src_pitch,
601 exaMarkSync(pDst->drawable.pScreen);
607 /* try gart-based transfer */
608 if (pNv->GARTScratch) {
609 dst_offset += (y * dst_pitch) + (x * cpp);
610 if (NVAccelUploadM2MF(pScrn, dst_offset, src, dst_pitch,
611 src_pitch, w * cpp, h))
615 /* fallback to memcpy-based transfer */
616 dst = pDst->devPrivate.ptr + (y * dst_pitch) + (x * cpp);
617 exaWaitSync(pDst->drawable.pScreen);
618 if (NVAccelMemcpyRect(dst, src, h, dst_pitch, src_pitch, w*cpp))
625 static Bool NVCheckComposite(int op,
626 PicturePtr pSrcPicture,
627 PicturePtr pMaskPicture,
628 PicturePtr pDstPicture)
632 /* PictOpOver doesn't work correctly. The HW command assumes
633 * non premuliplied alpha
637 else if (op != PictOpOver && op != PictOpSrc)
639 else if (!pSrcPicture->pDrawable)
641 else if (pSrcPicture->transform || pSrcPicture->repeat)
643 else if (pSrcPicture->alphaMap || pDstPicture->alphaMap)
645 else if (pSrcPicture->format != PICT_a8r8g8b8 &&
646 pSrcPicture->format != PICT_x8r8g8b8 &&
647 pSrcPicture->format != PICT_r5g6b5)
649 else if (pDstPicture->format != PICT_a8r8g8b8 &&
650 pDstPicture->format != PICT_x8r8g8b8 &&
651 pDstPicture->format != PICT_r5g6b5)
657 static CARD32 src_size, src_pitch, src_offset;
659 static Bool NVPrepareComposite(int op,
660 PicturePtr pSrcPicture,
661 PicturePtr pMaskPicture,
662 PicturePtr pDstPicture,
667 ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
668 NVPtr pNv = NVPTR(pScrn);
669 int srcFormat, dstFormat;
671 if (pSrcPicture->format == PICT_a8r8g8b8)
672 srcFormat = STRETCH_BLIT_FORMAT_A8R8G8B8;
673 else if (pSrcPicture->format == PICT_x8r8g8b8)
674 srcFormat = STRETCH_BLIT_FORMAT_X8R8G8B8;
675 else if (pSrcPicture->format == PICT_r5g6b5)
676 srcFormat = STRETCH_BLIT_FORMAT_DEPTH16;
680 if (!NVAccelGetCtxSurf2DFormatFromPicture(pDstPicture, &dstFormat))
682 if (!NVAccelSetCtxSurf2D(pDst, pDst, dstFormat))
685 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_FORMAT, 2);
686 NVDmaNext (pNv, srcFormat);
687 NVDmaNext (pNv, (op == PictOpSrc) ? STRETCH_BLIT_OPERATION_COPY : STRETCH_BLIT_OPERATION_BLEND);
689 src_size = ((pSrcPicture->pDrawable->width+3)&~3) |
690 (pSrcPicture->pDrawable->height << 16);
691 src_pitch = exaGetPixmapPitch(pSrc)
692 | (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER << 16)
693 | (STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE << 24);
694 src_offset = NVAccelGetPixmapOffset(pSrc);
699 static void NVComposite(PixmapPtr pDst,
709 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
710 NVPtr pNv = NVPTR(pScrn);
712 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_CLIP_POINT, 6);
713 NVDmaNext (pNv, dstX | (dstY << 16));
714 NVDmaNext (pNv, width | (height << 16));
715 NVDmaNext (pNv, dstX | (dstY << 16));
716 NVDmaNext (pNv, width | (height << 16));
717 NVDmaNext (pNv, 1<<20);
718 NVDmaNext (pNv, 1<<20);
720 NVDmaStart(pNv, NvScaledImage, STRETCH_BLIT_SRC_SIZE, 4);
721 NVDmaNext (pNv, src_size);
722 NVDmaNext (pNv, src_pitch);
723 NVDmaNext (pNv, src_offset);
724 NVDmaNext (pNv, srcX | (srcY<<16));
729 static void NVDoneComposite (PixmapPtr pDst)
731 ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
732 NVPtr pNv = NVPTR(pScrn);
735 if (pNv->CurrentLayout.depth == 8)
736 format = SURFACE_FORMAT_Y8;
737 else if (pNv->CurrentLayout.depth == 16)
738 format = SURFACE_FORMAT_R5G6B5;
740 format = SURFACE_FORMAT_X8R8G8B8;
742 NVDmaStart(pNv, NvContextSurfaces, SURFACE_FORMAT, 1);
743 NVDmaNext (pNv, format);
745 exaMarkSync(pDst->drawable.pScreen);
748 Bool NVExaInit(ScreenPtr pScreen)
750 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
751 NVPtr pNv = NVPTR(pScrn);
753 if(!(pNv->EXADriverPtr = (ExaDriverPtr) xnfcalloc(sizeof(ExaDriverRec), 1))) {
758 pNv->EXADriverPtr->exa_major = EXA_VERSION_MAJOR;
759 pNv->EXADriverPtr->exa_minor = EXA_VERSION_MINOR;
761 pNv->EXADriverPtr->memoryBase = pNv->FB->map;
762 pNv->EXADriverPtr->offScreenBase =
763 pScrn->virtualX * pScrn->virtualY*(pScrn->bitsPerPixel/8);
764 pNv->EXADriverPtr->memorySize = pNv->FB->size;
765 pNv->EXADriverPtr->pixmapOffsetAlign = 256;
766 pNv->EXADriverPtr->pixmapPitchAlign = 64;
767 pNv->EXADriverPtr->flags = EXA_OFFSCREEN_PIXMAPS;
768 pNv->EXADriverPtr->maxX = 32768;
769 pNv->EXADriverPtr->maxY = 32768;
771 pNv->EXADriverPtr->WaitMarker = NVExaWaitMarker;
773 /* Install default hooks */
774 pNv->EXADriverPtr->DownloadFromScreen = NVDownloadFromScreen;
775 pNv->EXADriverPtr->UploadToScreen = NVUploadToScreen;
777 if (pNv->Architecture < NV_ARCH_50) {
778 pNv->EXADriverPtr->PrepareCopy = NVExaPrepareCopy;
779 pNv->EXADriverPtr->Copy = NVExaCopy;
780 pNv->EXADriverPtr->DoneCopy = NVExaDoneCopy;
782 pNv->EXADriverPtr->PrepareSolid = NVExaPrepareSolid;
783 pNv->EXADriverPtr->Solid = NVExaSolid;
784 pNv->EXADriverPtr->DoneSolid = NVExaDoneSolid;
786 pNv->EXADriverPtr->PrepareCopy = NV50EXAPrepareCopy;
787 pNv->EXADriverPtr->Copy = NV50EXACopy;
788 pNv->EXADriverPtr->DoneCopy = NV50EXADoneCopy;
790 pNv->EXADriverPtr->PrepareSolid = NV50EXAPrepareSolid;
791 pNv->EXADriverPtr->Solid = NV50EXASolid;
792 pNv->EXADriverPtr->DoneSolid = NV50EXADoneSolid;
795 switch (pNv->Architecture) {
796 #if (X_BYTE_ORDER == X_LITTLE_ENDIAN) && defined(ENABLE_NV30EXA)
800 pNv->EXADriverPtr->CheckComposite = NV30EXACheckComposite;
801 pNv->EXADriverPtr->PrepareComposite = NV30EXAPrepareComposite;
802 pNv->EXADriverPtr->Composite = NV30EXAComposite;
803 pNv->EXADriverPtr->DoneComposite = NV30EXADoneComposite;
809 if (!pNv->BlendingPossible)
811 pNv->EXADriverPtr->CheckComposite = NVCheckComposite;
812 pNv->EXADriverPtr->PrepareComposite = NVPrepareComposite;
813 pNv->EXADriverPtr->Composite = NVComposite;
814 pNv->EXADriverPtr->DoneComposite = NVDoneComposite;
818 return exaDriverInit(pScreen, pNv->EXADriverPtr);