2 * Copyright 2009 Nouveau Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "nv_include.h"
24 #include "nv04_pushbuf.h"
25 #if !defined(__AROS__)
29 NVAccelMemcpyRect(char *dst
, const char *src
, int height
, int dst_pitch
,
30 int src_pitch
, int line_len
)
32 if ((src_pitch
== line_len
) && (src_pitch
== dst_pitch
)) {
33 memcpy(dst
, src
, line_len
*height
);
36 memcpy(dst
, src
, line_len
);
46 #if !defined(__AROS__)
48 NVAccelDownloadM2MF(PixmapPtr pspix
, int x
, int y
, int w
, int h
,
49 char *dst
, unsigned dst_pitch
)
51 ScrnInfoPtr pScrn
= xf86Screens
[pspix
->drawable
.pScreen
->myNum
];
54 NVAccelDownloadM2MF(PixmapPtr pspix
, int x
, int y
, int w
, int h
,
55 char *dst
, unsigned dst_pitch
,
56 HIDDT_StdPixFmt dstPixFmt
, OOP_Class
*cl
, OOP_Object
*o
)
58 ScrnInfoPtr pScrn
= globalcarddataptr
;
60 NVPtr pNv
= NVPTR(pScrn
);
61 struct nouveau_channel
*chan
= pNv
->chan
;
62 struct nouveau_grobj
*m2mf
= pNv
->NvMemFormat
;
63 struct nouveau_bo
*bo
= nouveau_pixmap_bo(pspix
);
64 #if !defined(__AROS__)
65 unsigned cpp
= pspix
->drawable
.bitsPerPixel
/ 8;
67 unsigned cpp
= pspix
->depth
> 16 ? 4 : 2;
69 unsigned line_len
= w
* cpp
;
70 unsigned src_offset
= 0, src_pitch
= 0, linear
= 0;
71 /* Maximum DMA transfer */
72 unsigned line_count
= pNv
->GART
->size
/ line_len
;
74 if (!nv50_style_tiled_pixmap(pspix
)) {
76 src_pitch
= exaGetPixmapPitch(pspix
);
77 src_offset
+= (y
* src_pitch
) + (x
* cpp
);
81 if (line_count
> 2047)
91 if (MARK_RING(chan
, 32, 6))
94 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
95 if (OUT_RELOCo(chan
, bo
, NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
|
97 OUT_RELOCo(chan
, pNv
->GART
, NOUVEAU_BO_GART
|
103 if (pNv
->Architecture
>= NV_ARCH_50
) {
105 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN
, 7);
107 OUT_RING (chan
, bo
->tile_mode
<< 4);
108 #if !defined(__AROS__)
109 OUT_RING (chan
, pspix
->drawable
.width
* cpp
);
110 OUT_RING (chan
, pspix
->drawable
.height
);
112 OUT_RING (chan
, pspix
->width
* cpp
);
113 OUT_RING (chan
, pspix
->height
);
117 OUT_RING (chan
, (y
<< 16) | (x
* cpp
));
119 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN
, 1);
123 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT
, 1);
126 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH
, 2);
127 if (OUT_RELOCh(chan
, bo
, src_offset
, NOUVEAU_BO_GART
|
128 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
) ||
129 OUT_RELOCh(chan
, pNv
->GART
, 0, NOUVEAU_BO_GART
|
136 BEGIN_RING(chan
, m2mf
,
137 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
138 if (OUT_RELOCl(chan
, bo
, src_offset
, NOUVEAU_BO_GART
|
139 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
) ||
140 OUT_RELOCl(chan
, pNv
->GART
, 0, NOUVEAU_BO_GART
|
145 OUT_RING (chan
, src_pitch
);
146 OUT_RING (chan
, line_len
);
147 OUT_RING (chan
, line_len
);
148 OUT_RING (chan
, line_count
);
149 OUT_RING (chan
, (1<<8)|1);
152 if (nouveau_bo_map(pNv
->GART
, NOUVEAU_BO_RD
)) {
156 src
= pNv
->GART
->map
;
157 #if !defined(__AROS__)
158 if (dst_pitch
== line_len
) {
159 memcpy(dst
, src
, dst_pitch
* line_count
);
160 dst
+= dst_pitch
* line_count
;
162 for (i
= 0; i
< line_count
; i
++) {
163 memcpy(dst
, src
, line_len
);
170 HiddNouveauReadIntoRAM(
172 dst
, dst_pitch
, dstPixFmt
,
175 dst
+= dst_pitch
* line_count
;
177 nouveau_bo_unmap(pNv
->GART
);
180 src_offset
+= line_count
* src_pitch
;
188 #if !defined(__AROS__)
190 NVAccelUploadM2MF(PixmapPtr pdpix
, int x
, int y
, int w
, int h
,
191 const char *src
, int src_pitch
)
193 ScrnInfoPtr pScrn
= xf86Screens
[pdpix
->drawable
.pScreen
->myNum
];
196 NVAccelUploadM2MF(PixmapPtr pdpix
, int x
, int y
, int w
, int h
,
197 const char *src
, int src_pitch
,
198 HIDDT_StdPixFmt srcPixFmt
, OOP_Class
*cl
, OOP_Object
*o
)
200 ScrnInfoPtr pScrn
= globalcarddataptr
;
202 NVPtr pNv
= NVPTR(pScrn
);
203 struct nouveau_channel
*chan
= pNv
->chan
;
204 struct nouveau_grobj
*m2mf
= pNv
->NvMemFormat
;
205 struct nouveau_bo
*bo
= nouveau_pixmap_bo(pdpix
);
206 #if !defined(__AROS__)
207 unsigned cpp
= pdpix
->drawable
.bitsPerPixel
/ 8;
209 unsigned cpp
= pdpix
->depth
> 16 ? 4 : 2;
211 unsigned line_len
= w
* cpp
;
212 unsigned dst_offset
= 0, dst_pitch
= 0, linear
= 0;
213 /* Maximum DMA transfer */
214 unsigned line_count
= pNv
->GART
->size
/ line_len
;
216 if (!nv50_style_tiled_pixmap(pdpix
)) {
218 dst_pitch
= exaGetPixmapPitch(pdpix
);
219 dst_offset
+= (y
* dst_pitch
) + (x
* cpp
);
223 if (line_count
> 2047)
234 if (nouveau_bo_map(pNv
->GART
, NOUVEAU_BO_WR
))
236 dst
= pNv
->GART
->map
;
237 #if !defined(__AROS__)
238 if (src_pitch
== line_len
) {
239 memcpy(dst
, src
, src_pitch
* line_count
);
240 src
+= src_pitch
* line_count
;
242 for (i
= 0; i
< line_count
; i
++) {
243 memcpy(dst
, src
, line_len
);
250 HiddNouveauWriteFromRAM(
251 (APTR
)src
, src_pitch
, srcPixFmt
,
255 src
+= src_pitch
* line_count
;
257 nouveau_bo_unmap(pNv
->GART
);
259 if (MARK_RING(chan
, 32, 6))
262 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
263 if (OUT_RELOCo(chan
, pNv
->GART
, NOUVEAU_BO_GART
|
265 OUT_RELOCo(chan
, bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
|
271 if (pNv
->Architecture
>= NV_ARCH_50
) {
272 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_IN
, 1);
276 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT
, 7);
278 OUT_RING (chan
, bo
->tile_mode
<< 4);
279 #if !defined(__AROS__)
280 OUT_RING (chan
, pdpix
->drawable
.width
* cpp
);
281 OUT_RING (chan
, pdpix
->drawable
.height
);
283 OUT_RING (chan
, pdpix
->width
* cpp
);
284 OUT_RING (chan
, pdpix
->height
);
288 OUT_RING (chan
, (y
<< 16) | (x
* cpp
));
290 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_LINEAR_OUT
, 1);
294 BEGIN_RING(chan
, m2mf
, NV50_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN_HIGH
, 2);
295 if (OUT_RELOCh(chan
, pNv
->GART
, 0, NOUVEAU_BO_GART
|
297 OUT_RELOCh(chan
, bo
, dst_offset
, NOUVEAU_BO_VRAM
|
298 NOUVEAU_BO_GART
| NOUVEAU_BO_WR
)) {
305 BEGIN_RING(chan
, m2mf
,
306 NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
307 if (OUT_RELOCl(chan
, pNv
->GART
, 0, NOUVEAU_BO_GART
|
309 OUT_RELOCl(chan
, bo
, dst_offset
, NOUVEAU_BO_VRAM
|
310 NOUVEAU_BO_GART
| NOUVEAU_BO_WR
)) {
314 OUT_RING (chan
, line_len
);
315 OUT_RING (chan
, dst_pitch
);
316 OUT_RING (chan
, line_len
);
317 OUT_RING (chan
, line_count
);
318 OUT_RING (chan
, (1<<8)|1);
323 dst_offset
+= line_count
* dst_pitch
;
331 #if !defined(__AROS__)
333 nouveau_exa_mark_sync(ScreenPtr pScreen
)
339 nouveau_exa_wait_marker(ScreenPtr pScreen
, int marker
)
344 nouveau_exa_prepare_access(PixmapPtr ppix
, int index
)
346 struct nouveau_bo
*bo
= nouveau_pixmap_bo(ppix
);
347 NVPtr pNv
= NVPTR(xf86Screens
[ppix
->drawable
.pScreen
->myNum
]);
349 if (nv50_style_tiled_pixmap(ppix
) && !pNv
->wfb_enabled
)
351 if (nouveau_bo_map(bo
, NOUVEAU_BO_RDWR
))
353 ppix
->devPrivate
.ptr
= bo
->map
;
358 nouveau_exa_finish_access(PixmapPtr ppix
, int index
)
360 struct nouveau_bo
*bo
= nouveau_pixmap_bo(ppix
);
362 nouveau_bo_unmap(bo
);
366 nouveau_exa_pixmap_is_offscreen(PixmapPtr ppix
)
368 return nouveau_pixmap_bo(ppix
) != NULL
;
372 nouveau_exa_create_pixmap(ScreenPtr pScreen
, int width
, int height
, int depth
,
373 int usage_hint
, int bitsPerPixel
, int *new_pitch
)
375 ScrnInfoPtr scrn
= xf86Screens
[pScreen
->myNum
];
376 NVPtr pNv
= NVPTR(scrn
);
377 struct nouveau_pixmap
*nvpix
;
380 if (!width
|| !height
)
381 return calloc(1, sizeof(*nvpix
));
383 if (!pNv
->exa_force_cp
&&
384 pNv
->dev
->vm_vram_size
<= 32*1024*1024)
387 nvpix
= calloc(1, sizeof(*nvpix
));
391 ret
= nouveau_allocate_surface(scrn
, width
, height
, bitsPerPixel
,
392 usage_hint
, new_pitch
, &nvpix
->bo
);
402 nouveau_exa_destroy_pixmap(ScreenPtr pScreen
, void *priv
)
404 struct nouveau_pixmap
*nvpix
= priv
;
409 nouveau_bo_ref(NULL
, &nvpix
->bo
);
415 nv50_style_tiled_pixmap(PixmapPtr ppix
)
417 #if !defined(__AROS__)
418 ScrnInfoPtr pScrn
= xf86Screens
[ppix
->drawable
.pScreen
->myNum
];
420 ScrnInfoPtr pScrn
= globalcarddataptr
;
422 NVPtr pNv
= NVPTR(pScrn
);
424 return pNv
->Architecture
>= NV_ARCH_50
&&
425 (nouveau_pixmap_bo(ppix
)->tile_flags
&
426 NOUVEAU_BO_TILE_LAYOUT_MASK
);
429 #if !defined(__AROS__)
431 nouveau_exa_download_from_screen(PixmapPtr pspix
, int x
, int y
, int w
, int h
,
432 char *dst
, int dst_pitch
)
434 ScrnInfoPtr pScrn
= xf86Screens
[pspix
->drawable
.pScreen
->myNum
];
435 NVPtr pNv
= NVPTR(pScrn
);
436 struct nouveau_bo
*bo
;
437 int src_pitch
, cpp
, offset
;
441 src_pitch
= exaGetPixmapPitch(pspix
);
442 cpp
= pspix
->drawable
.bitsPerPixel
>> 3;
443 offset
= (y
* src_pitch
) + (x
* cpp
);
446 if (pNv
->Architecture
>= NV_ARCH_C0
) {
447 if (NVC0AccelDownloadM2MF(pspix
, x
, y
, w
, h
,
451 if (NVAccelDownloadM2MF(pspix
, x
, y
, w
, h
,
457 bo
= nouveau_pixmap_bo(pspix
);
458 if (nouveau_bo_map(bo
, NOUVEAU_BO_RD
))
460 src
= (char *)bo
->map
+ offset
;
461 ret
= NVAccelMemcpyRect(dst
, src
, h
, dst_pitch
, src_pitch
, w
*cpp
);
462 nouveau_bo_unmap(bo
);
467 nouveau_exa_upload_to_screen(PixmapPtr pdpix
, int x
, int y
, int w
, int h
,
468 char *src
, int src_pitch
)
470 ScrnInfoPtr pScrn
= xf86Screens
[pdpix
->drawable
.pScreen
->myNum
];
471 NVPtr pNv
= NVPTR(pScrn
);
472 struct nouveau_bo
*bo
;
477 dst_pitch
= exaGetPixmapPitch(pdpix
);
478 cpp
= pdpix
->drawable
.bitsPerPixel
>> 3;
480 /* try hostdata transfer */
481 if (w
* h
* cpp
< 16*1024) /* heuristic */
483 if (pNv
->Architecture
< NV_ARCH_50
) {
484 if (NV04EXAUploadIFC(pScrn
, src
, src_pitch
, pdpix
,
486 exaMarkSync(pdpix
->drawable
.pScreen
);
490 if (pNv
->Architecture
< NV_ARCH_C0
) {
491 if (NV50EXAUploadSIFC(src
, src_pitch
, pdpix
,
493 exaMarkSync(pdpix
->drawable
.pScreen
);
497 if (NVC0EXAUploadSIFC(src
, src_pitch
, pdpix
,
499 exaMarkSync(pdpix
->drawable
.pScreen
);
505 /* try gart-based transfer */
507 if (pNv
->Architecture
< NV_ARCH_C0
) {
508 ret
= NVAccelUploadM2MF(pdpix
, x
, y
, w
, h
,
511 ret
= NVC0AccelUploadM2MF(pdpix
, x
, y
, w
, h
,
516 exaMarkSync(pdpix
->drawable
.pScreen
);
521 /* fallback to memcpy-based transfer */
522 bo
= nouveau_pixmap_bo(pdpix
);
523 if (nouveau_bo_map(bo
, NOUVEAU_BO_WR
))
525 dst
= (char *)bo
->map
+ (y
* dst_pitch
) + (x
* cpp
);
526 ret
= NVAccelMemcpyRect(dst
, src
, h
, dst_pitch
, src_pitch
, w
*cpp
);
527 nouveau_bo_unmap(bo
);
532 nouveau_exa_pixmap_is_onscreen(PixmapPtr ppix
)
534 ScrnInfoPtr pScrn
= xf86Screens
[ppix
->drawable
.pScreen
->myNum
];
536 if (pScrn
->pScreen
->GetScreenPixmap(pScrn
->pScreen
) == ppix
)
543 nouveau_exa_init(ScreenPtr pScreen
)
545 ScrnInfoPtr pScrn
= xf86Screens
[pScreen
->myNum
];
546 NVPtr pNv
= NVPTR(pScrn
);
549 exa
= exaDriverAlloc();
555 exa
->exa_major
= EXA_VERSION_MAJOR
;
556 exa
->exa_minor
= EXA_VERSION_MINOR
;
557 exa
->flags
= EXA_OFFSCREEN_PIXMAPS
;
559 #ifdef EXA_SUPPORTS_PREPARE_AUX
560 exa
->flags
|= EXA_SUPPORTS_PREPARE_AUX
;
563 exa
->PixmapIsOffscreen
= nouveau_exa_pixmap_is_offscreen
;
564 exa
->PrepareAccess
= nouveau_exa_prepare_access
;
565 exa
->FinishAccess
= nouveau_exa_finish_access
;
567 exa
->flags
|= (EXA_HANDLES_PIXMAPS
| EXA_MIXED_PIXMAPS
);
568 exa
->pixmapOffsetAlign
= 256;
569 exa
->pixmapPitchAlign
= 64;
571 exa
->CreatePixmap2
= nouveau_exa_create_pixmap
;
572 exa
->DestroyPixmap
= nouveau_exa_destroy_pixmap
;
574 if (pNv
->Architecture
>= NV_ARCH_50
) {
578 if (pNv
->Architecture
>= NV_ARCH_10
) {
586 exa
->MarkSync
= nouveau_exa_mark_sync
;
587 exa
->WaitMarker
= nouveau_exa_wait_marker
;
589 exa
->DownloadFromScreen
= nouveau_exa_download_from_screen
;
590 exa
->UploadToScreen
= nouveau_exa_upload_to_screen
;
592 if (pNv
->Architecture
< NV_ARCH_50
) {
593 exa
->PrepareCopy
= NV04EXAPrepareCopy
;
594 exa
->Copy
= NV04EXACopy
;
595 exa
->DoneCopy
= NV04EXADoneCopy
;
597 exa
->PrepareSolid
= NV04EXAPrepareSolid
;
598 exa
->Solid
= NV04EXASolid
;
599 exa
->DoneSolid
= NV04EXADoneSolid
;
601 if (pNv
->Architecture
< NV_ARCH_C0
) {
602 exa
->PrepareCopy
= NV50EXAPrepareCopy
;
603 exa
->Copy
= NV50EXACopy
;
604 exa
->DoneCopy
= NV50EXADoneCopy
;
606 exa
->PrepareSolid
= NV50EXAPrepareSolid
;
607 exa
->Solid
= NV50EXASolid
;
608 exa
->DoneSolid
= NV50EXADoneSolid
;
610 exa
->PrepareCopy
= NVC0EXAPrepareCopy
;
611 exa
->Copy
= NVC0EXACopy
;
612 exa
->DoneCopy
= NVC0EXADoneCopy
;
614 exa
->PrepareSolid
= NVC0EXAPrepareSolid
;
615 exa
->Solid
= NVC0EXASolid
;
616 exa
->DoneSolid
= NVC0EXADoneSolid
;
619 switch (pNv
->Architecture
) {
622 exa
->CheckComposite
= NV10EXACheckComposite
;
623 exa
->PrepareComposite
= NV10EXAPrepareComposite
;
624 exa
->Composite
= NV10EXAComposite
;
625 exa
->DoneComposite
= NV10EXADoneComposite
;
628 exa
->CheckComposite
= NV30EXACheckComposite
;
629 exa
->PrepareComposite
= NV30EXAPrepareComposite
;
630 exa
->Composite
= NV30EXAComposite
;
631 exa
->DoneComposite
= NV30EXADoneComposite
;
634 exa
->CheckComposite
= NV40EXACheckComposite
;
635 exa
->PrepareComposite
= NV40EXAPrepareComposite
;
636 exa
->Composite
= NV40EXAComposite
;
637 exa
->DoneComposite
= NV40EXADoneComposite
;
640 exa
->CheckComposite
= NV50EXACheckComposite
;
641 exa
->PrepareComposite
= NV50EXAPrepareComposite
;
642 exa
->Composite
= NV50EXAComposite
;
643 exa
->DoneComposite
= NV50EXADoneComposite
;
646 exa
->CheckComposite
= NVC0EXACheckComposite
;
647 exa
->PrepareComposite
= NVC0EXAPrepareComposite
;
648 exa
->Composite
= NVC0EXAComposite
;
649 exa
->DoneComposite
= NVC0EXADoneComposite
;
655 if (!exaDriverInit(pScreen
, exa
))
658 pNv
->EXADriverPtr
= exa
;
666 Bool
NVC0AccelUploadM2MF(PixmapPtr pdpix
, int x
, int y
, int w
, int h
,
667 const char *src
, int src_pitch
,
668 HIDDT_StdPixFmt srcPixFmt
, OOP_Class
*cl
, OOP_Object
*o
);
670 /* NOTE: Assumes lock on bitmap is already made */
671 /* NOTE: Assumes lock on GART object is already made */
672 /* NOTE: Assumes buffer is not mapped */
673 BOOL
HiddNouveauNVAccelUploadM2MF(
674 UBYTE
* srcpixels
, ULONG srcpitch
, HIDDT_StdPixFmt srcPixFmt
,
675 LONG x
, LONG y
, LONG width
, LONG height
,
676 OOP_Class
*cl
, OOP_Object
*o
)
678 struct HIDDNouveauBitMapData
* bmdata
= OOP_INST_DATA(cl
, o
);
679 struct CardData
* carddata
= &(SD(cl
)->carddata
);
681 if (carddata
->architecture
>= NV_ARCH_C0
)
682 return NVC0AccelUploadM2MF(bmdata
, x
, y
, width
, height
,
683 srcpixels
, srcpitch
, srcPixFmt
, cl
, o
);
685 return NVAccelUploadM2MF(bmdata
, x
, y
, width
, height
,
686 srcpixels
, srcpitch
, srcPixFmt
, cl
, o
);
690 NVC0AccelDownloadM2MF(PixmapPtr pspix
, int x
, int y
, int w
, int h
,
691 char *dst
, unsigned dst_pitch
,
692 HIDDT_StdPixFmt dstPixFmt
, OOP_Class
*cl
, OOP_Object
*o
);
694 /* NOTE: Assumes lock on bitmap is already made */
695 /* NOTE: Assumes lock on GART object is already made */
696 /* NOTE: Assumes buffer is not mapped */
697 BOOL
HiddNouveauNVAccelDownloadM2MF(
698 UBYTE
* dstpixels
, ULONG dstpitch
, HIDDT_StdPixFmt dstPixFmt
,
699 LONG x
, LONG y
, LONG width
, LONG height
,
700 OOP_Class
*cl
, OOP_Object
*o
)
702 struct HIDDNouveauBitMapData
* bmdata
= OOP_INST_DATA(cl
, o
);
703 struct CardData
* carddata
= &(SD(cl
)->carddata
);
705 if (carddata
->architecture
>= NV_ARCH_C0
)
706 return NVC0AccelDownloadM2MF(bmdata
, x
, y
, width
, height
,
707 dstpixels
, dstpitch
, dstPixFmt
, cl
, o
);
709 return NVAccelDownloadM2MF(bmdata
, x
, y
, width
, height
,
710 dstpixels
, dstpitch
, dstPixFmt
, cl
, o
);