nv04_exa.c revision 16ee1e9a
1fda9279dSmrg/* 2fda9279dSmrg * Copyright 2003 NVIDIA, Corporation 3fda9279dSmrg * 4fda9279dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 5fda9279dSmrg * copy of this software and associated documentation files (the "Software"), 6fda9279dSmrg * to deal in the Software without restriction, including without limitation 7fda9279dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fda9279dSmrg * and/or sell copies of the Software, and to permit persons to whom the 9fda9279dSmrg * Software is furnished to do so, subject to the following conditions: 10fda9279dSmrg * 11fda9279dSmrg * The above copyright notice and this permission notice shall be included in 12fda9279dSmrg * all copies or substantial portions of the Software. 13fda9279dSmrg * 14fda9279dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fda9279dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fda9279dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fda9279dSmrg * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18fda9279dSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19fda9279dSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20fda9279dSmrg * SOFTWARE. 21fda9279dSmrg */ 22fda9279dSmrg 23fda9279dSmrg#include "nv_include.h" 24fda9279dSmrg#include "nv_rop.h" 25fda9279dSmrg 26fda9279dSmrg#include "hwdefs/nv_object.xml.h" 27fda9279dSmrg#include "hwdefs/nv_m2mf.xml.h" 28fda9279dSmrg#include "hwdefs/nv01_2d.xml.h" 29fda9279dSmrg#include "nv04_accel.h" 30fda9279dSmrg 31fda9279dSmrgstatic void 32fda9279dSmrgNV04EXASetPattern(NVPtr pNv, CARD32 clr0, CARD32 clr1, CARD32 pat0, CARD32 pat1) 33fda9279dSmrg{ 34fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 35fda9279dSmrg 36fda9279dSmrg BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 37fda9279dSmrg PUSH_DATA (push, pNv->NvImagePattern->handle); 38fda9279dSmrg BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR(0)), 4); 39fda9279dSmrg PUSH_DATA (push, clr0); 40fda9279dSmrg PUSH_DATA (push, clr1); 41fda9279dSmrg PUSH_DATA (push, pat0); 42fda9279dSmrg PUSH_DATA (push, pat1); 43fda9279dSmrg} 44fda9279dSmrg 45fda9279dSmrgstatic Bool 46fda9279dSmrgNV04EXASetROP(PixmapPtr ppix, int subc, int mthd, int alu, Pixel planemask) 47fda9279dSmrg{ 48fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 49fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 50fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 51fda9279dSmrg 5216ee1e9aSmrg if (ppix->drawable.bitsPerPixel < 32) 5316ee1e9aSmrg planemask |= ~0 << ppix->drawable.bitsPerPixel; 54fda9279dSmrg if (planemask != ~0 || alu != GXcopy) { 55fda9279dSmrg if (ppix->drawable.bitsPerPixel == 32) 56fda9279dSmrg return FALSE; 57fda9279dSmrg if (planemask != ~0) { 58fda9279dSmrg NV04EXASetPattern(pNv, 0, planemask, ~0, ~0); 59fda9279dSmrg if (pNv->currentRop != (alu + 32)) { 60fda9279dSmrg BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 61fda9279dSmrg PUSH_DATA (push, pNv->NvRop->handle); 62fda9279dSmrg BEGIN_NV04(push, NV01_ROP(ROP), 1); 63fda9279dSmrg PUSH_DATA (push, NVROP[alu].copy_planemask); 64fda9279dSmrg pNv->currentRop = alu + 32; 65fda9279dSmrg } 66fda9279dSmrg } else 67fda9279dSmrg if (pNv->currentRop != alu) { 68fda9279dSmrg if(pNv->currentRop >= 16) 69fda9279dSmrg NV04EXASetPattern(pNv, ~0, ~0, ~0, ~0); 70fda9279dSmrg BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 71fda9279dSmrg PUSH_DATA (push, pNv->NvRop->handle); 72fda9279dSmrg BEGIN_NV04(push, NV01_ROP(ROP), 1); 73fda9279dSmrg PUSH_DATA (push, NVROP[alu].copy); 74fda9279dSmrg pNv->currentRop = alu; 75fda9279dSmrg } 76fda9279dSmrg 77fda9279dSmrg BEGIN_NV04(push, subc, mthd, 1); 78fda9279dSmrg PUSH_DATA (push, 1); /* ROP_AND */ 79fda9279dSmrg } else { 80fda9279dSmrg BEGIN_NV04(push, subc, mthd, 1); 81fda9279dSmrg PUSH_DATA (push, 3); /* SRCCOPY */ 82fda9279dSmrg } 83fda9279dSmrg 84fda9279dSmrg return TRUE; 85fda9279dSmrg} 86fda9279dSmrg 87fda9279dSmrgBool 88fda9279dSmrgNV04EXAPrepareSolid(PixmapPtr ppix, int alu, Pixel planemask, Pixel fg) 89fda9279dSmrg{ 90fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); 91fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 92fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 93fda9279dSmrg struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); 94fda9279dSmrg unsigned pitch = exaGetPixmapPitch(ppix); 95fda9279dSmrg unsigned surf_fmt, rect_fmt; 96fda9279dSmrg 97fda9279dSmrg /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the 98fda9279dSmrg * alpha channel gets forced to 0xFF for some reason. We're using 99fda9279dSmrg * SURFACE_FORMAT_Y32 as a workaround 100fda9279dSmrg */ 101fda9279dSmrg if (!NVAccelGetCtxSurf2DFormatFromPixmap(ppix, (int*)&surf_fmt)) 102fda9279dSmrg return FALSE; 103fda9279dSmrg if (surf_fmt == NV04_SURFACE_2D_FORMAT_A8R8G8B8) 104fda9279dSmrg surf_fmt = NV04_SURFACE_2D_FORMAT_Y32; 105fda9279dSmrg 106fda9279dSmrg rect_fmt = NV04_GDI_COLOR_FORMAT_A8R8G8B8; 107fda9279dSmrg if (ppix->drawable.bitsPerPixel == 16) { 108fda9279dSmrg if (ppix->drawable.depth == 16) 109fda9279dSmrg rect_fmt = NV04_GDI_COLOR_FORMAT_A16R5G6B5; 110fda9279dSmrg else 111fda9279dSmrg rect_fmt = NV04_GDI_COLOR_FORMAT_X16A1R5G5B5; 112fda9279dSmrg } 113fda9279dSmrg 114fda9279dSmrg if (!PUSH_SPACE(push, 64)) 115fda9279dSmrg return FALSE; 116fda9279dSmrg PUSH_RESET(push); 117fda9279dSmrg 118fda9279dSmrg if (!NV04EXASetROP(ppix, NV04_RECT(OPERATION), alu, planemask)) 119fda9279dSmrg return FALSE; 120fda9279dSmrg 121fda9279dSmrg BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); 122fda9279dSmrg PUSH_DATA (push, surf_fmt); 123fda9279dSmrg PUSH_DATA (push, (pitch << 16) | pitch); 124fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0, 125fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 126fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0, 127fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 128fda9279dSmrg BEGIN_NV04(push, NV04_RECT(COLOR_FORMAT), 1); 129fda9279dSmrg PUSH_DATA (push, rect_fmt); 130fda9279dSmrg 131fda9279dSmrg nouveau_pushbuf_bufctx(push, pNv->bufctx); 132fda9279dSmrg if (nouveau_pushbuf_validate(push)) { 133fda9279dSmrg nouveau_pushbuf_bufctx(push, NULL); 134fda9279dSmrg return FALSE; 135fda9279dSmrg } 136fda9279dSmrg 137fda9279dSmrg pNv->fg_colour = fg; 138fda9279dSmrg return TRUE; 139fda9279dSmrg} 140fda9279dSmrg 141fda9279dSmrgvoid 142fda9279dSmrgNV04EXASolid (PixmapPtr pPixmap, int x, int y, int x2, int y2) 143fda9279dSmrg{ 144fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); 145fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 146fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 147fda9279dSmrg int w = x2 - x; 148fda9279dSmrg int h = y2 - y; 149fda9279dSmrg 150fda9279dSmrg if (!PUSH_SPACE(push, 5)) 151fda9279dSmrg return; 152fda9279dSmrg 153fda9279dSmrg BEGIN_NV04(push, NV04_RECT(COLOR1_A), 1); 154fda9279dSmrg PUSH_DATA (push, pNv->fg_colour); 155fda9279dSmrg BEGIN_NV04(push, NV04_RECT(UNCLIPPED_RECTANGLE_POINT(0)), 2); 156fda9279dSmrg PUSH_DATA (push, (x << 16) | y); 157fda9279dSmrg PUSH_DATA (push, (w << 16) | h); 158fda9279dSmrg if ((w * h) >= 512) 159fda9279dSmrg PUSH_KICK(push); 160fda9279dSmrg} 161fda9279dSmrg 162fda9279dSmrgvoid 163fda9279dSmrgNV04EXADoneSolid (PixmapPtr pPixmap) 164fda9279dSmrg{ 165fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pPixmap->drawable.pScreen); 166fda9279dSmrg nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL); 167fda9279dSmrg} 168fda9279dSmrg 169fda9279dSmrgBool 170fda9279dSmrgNV04EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy, 171fda9279dSmrg int alu, Pixel planemask) 172fda9279dSmrg{ 173fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pspix->drawable.pScreen); 174fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 175fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 176fda9279dSmrg struct nouveau_bo *src_bo = nouveau_pixmap_bo(pspix); 177fda9279dSmrg struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); 178fda9279dSmrg int surf_fmt; 179fda9279dSmrg 180fda9279dSmrg if (pspix->drawable.bitsPerPixel != pdpix->drawable.bitsPerPixel) 181fda9279dSmrg return FALSE; 182fda9279dSmrg 183fda9279dSmrg if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdpix, &surf_fmt)) 184fda9279dSmrg return FALSE; 185fda9279dSmrg 186fda9279dSmrg if (!PUSH_SPACE(push, 64)) 187fda9279dSmrg return FALSE; 188fda9279dSmrg PUSH_RESET(push); 189fda9279dSmrg 190fda9279dSmrg if (!NV04EXASetROP(pdpix, NV01_BLIT(OPERATION), alu, planemask)) 191fda9279dSmrg return FALSE; 192fda9279dSmrg 193fda9279dSmrg BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); 194fda9279dSmrg PUSH_DATA (push, surf_fmt); 195fda9279dSmrg PUSH_DATA (push, (exaGetPixmapPitch(pdpix) << 16) | 196fda9279dSmrg exaGetPixmapPitch(pspix)); 197fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), src_bo, 0, 198fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 199fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), dst_bo, 0, 200fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 201fda9279dSmrg 202fda9279dSmrg nouveau_pushbuf_bufctx(push, pNv->bufctx); 203fda9279dSmrg if (nouveau_pushbuf_validate(push)) { 204fda9279dSmrg nouveau_pushbuf_bufctx(push, NULL); 205fda9279dSmrg return FALSE; 206fda9279dSmrg } 207fda9279dSmrg 208fda9279dSmrg pNv->pspix = pspix; 209fda9279dSmrg pNv->pmpix = NULL; 210fda9279dSmrg pNv->pdpix = pdpix; 211fda9279dSmrg return TRUE; 212fda9279dSmrg} 213fda9279dSmrg 214fda9279dSmrgvoid 215fda9279dSmrgNV04EXACopy(PixmapPtr pdpix, int srcX, int srcY, int dstX, int dstY, 216fda9279dSmrg int width, int height) 217fda9279dSmrg{ 218fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pdpix->drawable.pScreen); 219fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 220fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 221fda9279dSmrg int split_dstY = NOUVEAU_ALIGN(dstY + 1, 64); 222fda9279dSmrg int split_height = split_dstY - dstY; 223fda9279dSmrg 224fda9279dSmrg if (nouveau_pushbuf_space(push, 16, 2, 0)) 225fda9279dSmrg return; 226fda9279dSmrg 227fda9279dSmrg if ((width * height) >= 200000 && pNv->pspix != pNv->pdpix && 228fda9279dSmrg (dstY > srcY || dstX > srcX) && split_height < height) { 229fda9279dSmrg /* 230fda9279dSmrg * KLUDGE - Split the destination rectangle in an 231fda9279dSmrg * upper misaligned half and a lower tile-aligned 232fda9279dSmrg * half, then get IMAGE_BLIT to blit the lower piece 233fda9279dSmrg * downwards (required for sync-to-vblank if the area 234fda9279dSmrg * to be blitted is large enough). The blob does a 235fda9279dSmrg * different (not nicer) trick to achieve the same 236fda9279dSmrg * effect. 237fda9279dSmrg */ 238fda9279dSmrg struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); 239fda9279dSmrg unsigned dst_pitch = exaGetPixmapPitch(pdpix); 240fda9279dSmrg 241fda9279dSmrg BEGIN_NV04(push, NV01_BLIT(POINT_IN), 3); 242fda9279dSmrg PUSH_DATA (push, (srcY << 16) | srcX); 243fda9279dSmrg PUSH_DATA (push, (dstY << 16) | dstX); 244fda9279dSmrg PUSH_DATA (push, (split_height << 16) | width); 245fda9279dSmrg BEGIN_NV04(push, NV04_SF2D(OFFSET_DESTIN), 1); 246fda9279dSmrg PUSH_RELOC(push, dst_bo, split_dstY * dst_pitch, 247fda9279dSmrg NOUVEAU_BO_LOW, 0, 0); 248fda9279dSmrg 249fda9279dSmrg srcY += split_height; 250fda9279dSmrg height -= split_height; 251fda9279dSmrg dstY = 0; 252fda9279dSmrg pNv->pmpix = pdpix; 253fda9279dSmrg } 254fda9279dSmrg 255fda9279dSmrg BEGIN_NV04(push, NV01_BLIT(POINT_IN), 3); 256fda9279dSmrg PUSH_DATA (push, (srcY << 16) | srcX); 257fda9279dSmrg PUSH_DATA (push, (dstY << 16) | dstX); 258fda9279dSmrg PUSH_DATA (push, (height << 16) | width); 259fda9279dSmrg 260fda9279dSmrg if (pNv->pmpix) { 261fda9279dSmrg struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); 262fda9279dSmrg 263fda9279dSmrg BEGIN_NV04(push, NV04_SF2D(OFFSET_DESTIN), 1); 264fda9279dSmrg PUSH_RELOC(push, dst_bo, 0, NOUVEAU_BO_LOW, 0, 0); 265fda9279dSmrg pNv->pmpix = NULL; 266fda9279dSmrg } 267fda9279dSmrg 268fda9279dSmrg if ((width * height) >= 512) 269fda9279dSmrg PUSH_KICK(push); 270fda9279dSmrg} 271fda9279dSmrg 272fda9279dSmrgvoid 273fda9279dSmrgNV04EXADoneCopy(PixmapPtr pdpix) 274fda9279dSmrg{ 275fda9279dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pdpix->drawable.pScreen); 276fda9279dSmrg nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL); 277fda9279dSmrg} 278fda9279dSmrg 279fda9279dSmrgBool 280fda9279dSmrgNV04EXAUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, 281fda9279dSmrg PixmapPtr pdpix, int x, int y, int w, int h, int cpp) 282fda9279dSmrg{ 283fda9279dSmrg NVPtr pNv = NVPTR(pScrn); 284fda9279dSmrg ScreenPtr pScreen = pdpix->drawable.pScreen; 285fda9279dSmrg struct nouveau_bo *bo = nouveau_pixmap_bo(pdpix); 286fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 287fda9279dSmrg int line_len = w * cpp; 288fda9279dSmrg int surf_fmt, ifc_fmt; 289fda9279dSmrg int iw, id, py, ph; 290fda9279dSmrg int padbytes; 291fda9279dSmrg Bool ret = FALSE; 292fda9279dSmrg 293fda9279dSmrg if (pNv->Architecture >= NV_TESLA) 294fda9279dSmrg return FALSE; 295fda9279dSmrg 296fda9279dSmrg if (h > 1024) 297fda9279dSmrg return FALSE; 298fda9279dSmrg 299fda9279dSmrg if (line_len < 4) 300fda9279dSmrg return FALSE; 301fda9279dSmrg 302fda9279dSmrg switch (cpp) { 303fda9279dSmrg case 2: ifc_fmt = 1; break; 304fda9279dSmrg case 4: ifc_fmt = 4; break; 305fda9279dSmrg default: 306fda9279dSmrg return FALSE; 307fda9279dSmrg } 308fda9279dSmrg 309fda9279dSmrg if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdpix, &surf_fmt)) 310fda9279dSmrg return FALSE; 311fda9279dSmrg 312fda9279dSmrg /* Pad out input width to cover both COLORA() and COLORB() */ 313fda9279dSmrg iw = (line_len + 7) & ~7; 314fda9279dSmrg padbytes = iw - line_len; 315fda9279dSmrg id = iw / 4; /* line push size */ 316fda9279dSmrg iw /= cpp; 317fda9279dSmrg 318fda9279dSmrg /* Don't support lines longer than max push size yet.. */ 319fda9279dSmrg if (id > 1792) 320fda9279dSmrg return FALSE; 321fda9279dSmrg 322fda9279dSmrg if (!PUSH_SPACE(push, 16)) 323fda9279dSmrg return FALSE; 324fda9279dSmrg PUSH_RESET(push); 325fda9279dSmrg 326fda9279dSmrg BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); 327fda9279dSmrg PUSH_DATA (push, pNv->NvClipRectangle->handle); 328fda9279dSmrg BEGIN_NV04(push, NV01_CLIP(POINT), 2); 329fda9279dSmrg PUSH_DATA (push, (y << 16) | x); 330fda9279dSmrg PUSH_DATA (push, (h << 16) | w); 331fda9279dSmrg 332fda9279dSmrg BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); 333fda9279dSmrg PUSH_DATA (push, surf_fmt); 334fda9279dSmrg PUSH_DATA (push, (exaGetPixmapPitch(pdpix) << 16) | 335fda9279dSmrg exaGetPixmapPitch(pdpix)); 336fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0, 337fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 338fda9279dSmrg PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0, 339fda9279dSmrg NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 340fda9279dSmrg 341fda9279dSmrg nouveau_pushbuf_bufctx(push, pNv->bufctx); 342fda9279dSmrg if (nouveau_pushbuf_validate(push)) 343fda9279dSmrg goto out; 344fda9279dSmrg 345fda9279dSmrg py = y; 346fda9279dSmrg ph = h; 347fda9279dSmrg while (ph--) { 348fda9279dSmrg if (PUSH_AVAIL(push) < id + 1 || (py == y)) { 349fda9279dSmrg if (!PUSH_SPACE(push, id + 8)) 350fda9279dSmrg goto out; 351fda9279dSmrg BEGIN_NV04(push, NV01_IFC(OPERATION), 2); 352fda9279dSmrg PUSH_DATA (push, NV01_IFC_OPERATION_SRCCOPY); 353fda9279dSmrg PUSH_DATA (push, ifc_fmt); 354fda9279dSmrg BEGIN_NV04(push, NV01_IFC(POINT), 3); 355fda9279dSmrg PUSH_DATA (push, (py << 16) | x); 356fda9279dSmrg PUSH_DATA (push, (h << 16) | w); 357fda9279dSmrg PUSH_DATA (push, (h << 16) | iw); 358fda9279dSmrg } 359fda9279dSmrg 360fda9279dSmrg /* send a line */ 361fda9279dSmrg if (ph > 0 || !padbytes) { 362fda9279dSmrg BEGIN_NV04(push, NV01_IFC(COLOR(0)), id); 363fda9279dSmrg PUSH_DATAp(push, src, id); 364fda9279dSmrg } else { 365fda9279dSmrg char padding[8]; 366fda9279dSmrg int aux = (padbytes + 7) >> 2; 367fda9279dSmrg memcpy(padding, src + (id - aux) * 4, padbytes); 368fda9279dSmrg BEGIN_NV04(push, NV01_IFC(COLOR(0)), id); 369fda9279dSmrg PUSH_DATAp(push, src, id - aux); 370fda9279dSmrg PUSH_DATAp(push, padding, aux); 371fda9279dSmrg } 372fda9279dSmrg 373fda9279dSmrg src += src_pitch; 374fda9279dSmrg py++; 375fda9279dSmrg } 376fda9279dSmrg 377fda9279dSmrg ret = TRUE; 378fda9279dSmrgout: 379fda9279dSmrg nouveau_pushbuf_bufctx(push, NULL); 380fda9279dSmrg if (pdpix == pScreen->GetScreenPixmap(pScreen)) 381fda9279dSmrg PUSH_KICK(push); 382fda9279dSmrg return ret; 383fda9279dSmrg} 384fda9279dSmrg 385fda9279dSmrgBool 386fda9279dSmrgNV04EXARectM2MF(NVPtr pNv, int w, int h, int cpp, 387fda9279dSmrg struct nouveau_bo *src, uint32_t src_off, int src_dom, 388fda9279dSmrg int src_pitch, int src_h, int src_x, int src_y, 389fda9279dSmrg struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, 390fda9279dSmrg int dst_pitch, int dst_h, int dst_x, int dst_y) 391fda9279dSmrg{ 392fda9279dSmrg struct nv04_fifo *fifo = pNv->channel->data; 393fda9279dSmrg struct nouveau_pushbuf *push = pNv->pushbuf; 394fda9279dSmrg struct nouveau_pushbuf_refn refs[] = { 395fda9279dSmrg { src, src_dom | NOUVEAU_BO_RD }, 396fda9279dSmrg { dst, dst_dom | NOUVEAU_BO_WR }, 397fda9279dSmrg }; 398fda9279dSmrg 399fda9279dSmrg src_off += src_y * src_pitch + src_x * cpp; 400fda9279dSmrg dst_off += dst_y * dst_pitch + dst_x * cpp; 401fda9279dSmrg 402fda9279dSmrg while (h) { 403fda9279dSmrg int line_count = h; 404fda9279dSmrg if (line_count > 2047) 405fda9279dSmrg line_count = 2047; 406fda9279dSmrg h -= line_count; 407fda9279dSmrg 408fda9279dSmrg if (nouveau_pushbuf_space(push, 16, 4, 0) || 409fda9279dSmrg nouveau_pushbuf_refn (push, refs, 2)) 410fda9279dSmrg return FALSE; 411fda9279dSmrg 412fda9279dSmrg BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); 413fda9279dSmrg PUSH_RELOC(push, src, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); 414fda9279dSmrg PUSH_RELOC(push, dst, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); 415fda9279dSmrg BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); 416fda9279dSmrg PUSH_RELOC(push, src, src_off, NOUVEAU_BO_LOW, 0, 0); 417fda9279dSmrg PUSH_RELOC(push, dst, dst_off, NOUVEAU_BO_LOW, 0, 0); 418fda9279dSmrg PUSH_DATA (push, src_pitch); 419fda9279dSmrg PUSH_DATA (push, dst_pitch); 420fda9279dSmrg PUSH_DATA (push, w * cpp); 421fda9279dSmrg PUSH_DATA (push, line_count); 422fda9279dSmrg PUSH_DATA (push, 0x00000101); 423fda9279dSmrg PUSH_DATA (push, 0x00000000); 424fda9279dSmrg BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1); 425fda9279dSmrg PUSH_DATA (push, 0x00000000); 426fda9279dSmrg BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1); 427fda9279dSmrg PUSH_DATA (push, 0x00000000); 428fda9279dSmrg 429fda9279dSmrg src_off += src_pitch * line_count; 430fda9279dSmrg dst_off += dst_pitch * line_count; 431fda9279dSmrg } 432fda9279dSmrg 433fda9279dSmrg return TRUE; 434fda9279dSmrg} 435