diff options
Diffstat (limited to 'src/nv04_exa.c')
-rw-r--r-- | src/nv04_exa.c | 524 |
1 files changed, 244 insertions, 280 deletions
diff --git a/src/nv04_exa.c b/src/nv04_exa.c index 29b8c10..77bb3b7 100644 --- a/src/nv04_exa.c +++ b/src/nv04_exa.c @@ -23,229 +23,206 @@ #include "nv_include.h" #include "nv_rop.h" - #include "hwdefs/nv_object.xml.h" #include "hwdefs/nv_m2mf.xml.h" #include "hwdefs/nv01_2d.xml.h" +#include "nv04_accel.h" static void -NV04EXASetPattern(ScrnInfoPtr pScrn, CARD32 clr0, CARD32 clr1, - CARD32 pat0, CARD32 pat1) +NV04EXASetPattern(NVPtr pNv, CARD32 clr0, CARD32 clr1, CARD32 pat0, CARD32 pat1) { - NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - - BEGIN_NV04(chan, NV01_SUBC(MISC, OBJECT), 1); - OUT_RING (chan, pNv->NvImagePattern->handle); - BEGIN_NV04(chan, NV01_PATT(MONOCHROME_COLOR(0)), 4); - OUT_RING (chan, clr0); - OUT_RING (chan, clr1); - OUT_RING (chan, pat0); - OUT_RING (chan, pat1); + struct nouveau_pushbuf *push = pNv->pushbuf; + + BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); + PUSH_DATA (push, pNv->NvImagePattern->handle); + BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR(0)), 4); + PUSH_DATA (push, clr0); + PUSH_DATA (push, clr1); + PUSH_DATA (push, pat0); + PUSH_DATA (push, pat1); } -static void -NV04EXASetROP(ScrnInfoPtr pScrn, CARD32 alu, CARD32 planemask) +static Bool +NV04EXASetROP(PixmapPtr ppix, int subc, int mthd, int alu, Pixel planemask) { + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - - if (planemask != ~0) { - NV04EXASetPattern(pScrn, 0, planemask, ~0, ~0); - if (pNv->currentRop != (alu + 32)) { - BEGIN_NV04(chan, NV01_SUBC(MISC, OBJECT), 1); - OUT_RING (chan, pNv->NvRop->handle); - BEGIN_NV04(chan, NV01_ROP(ROP), 1); - OUT_RING (chan, NVROP[alu].copy_planemask); - pNv->currentRop = alu + 32; + struct nouveau_pushbuf *push = pNv->pushbuf; + + planemask |= ~0 << ppix->drawable.bitsPerPixel; + if (planemask != ~0 || alu != GXcopy) { + if (ppix->drawable.bitsPerPixel == 32) + return FALSE; + if (planemask != ~0) { + NV04EXASetPattern(pNv, 0, planemask, ~0, ~0); + if (pNv->currentRop != (alu + 32)) { + BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); + PUSH_DATA (push, pNv->NvRop->handle); + BEGIN_NV04(push, NV01_ROP(ROP), 1); + PUSH_DATA (push, NVROP[alu].copy_planemask); + pNv->currentRop = alu + 32; + } + } else + if (pNv->currentRop != alu) { + if(pNv->currentRop >= 16) + NV04EXASetPattern(pNv, ~0, ~0, ~0, ~0); + BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); + PUSH_DATA (push, pNv->NvRop->handle); + BEGIN_NV04(push, NV01_ROP(ROP), 1); + PUSH_DATA (push, NVROP[alu].copy); + pNv->currentRop = alu; } - } else - if (pNv->currentRop != alu) { - if(pNv->currentRop >= 16) - NV04EXASetPattern(pScrn, ~0, ~0, ~0, ~0); - BEGIN_NV04(chan, NV01_SUBC(MISC, OBJECT), 1); - OUT_RING (chan, pNv->NvRop->handle); - BEGIN_NV04(chan, NV01_ROP(ROP), 1); - OUT_RING (chan, NVROP[alu].copy); - pNv->currentRop = alu; - } -} -static void -NV04EXAStateSolidResubmit(struct nouveau_channel *chan) -{ - ScrnInfoPtr pScrn = chan->user_private; - NVPtr pNv = NVPTR(pScrn); + BEGIN_NV04(push, subc, mthd, 1); + PUSH_DATA (push, 1); /* ROP_AND */ + } else { + BEGIN_NV04(push, subc, mthd, 1); + PUSH_DATA (push, 3); /* SRCCOPY */ + } - NV04EXAPrepareSolid(pNv->pdpix, pNv->alu, pNv->planemask, pNv->fg_colour); + return TRUE; } Bool -NV04EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg) +NV04EXAPrepareSolid(PixmapPtr ppix, int alu, Pixel planemask, Pixel fg) { - ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - struct nouveau_bo *bo = nouveau_pixmap_bo(pPixmap); - unsigned int fmt, pitch, fmt2 = NV04_GDI_COLOR_FORMAT_A8R8G8B8; + struct nouveau_pushbuf *push = pNv->pushbuf; + struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); + unsigned pitch = exaGetPixmapPitch(ppix); + unsigned surf_fmt, rect_fmt; - if (MARK_RING(chan, 64, 2)) + /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the + * alpha channel gets forced to 0xFF for some reason. We're using + * SURFACE_FORMAT_Y32 as a workaround + */ + if (!NVAccelGetCtxSurf2DFormatFromPixmap(ppix, (int*)&surf_fmt)) return FALSE; - - planemask |= ~0 << pPixmap->drawable.bitsPerPixel; - if (planemask != ~0 || alu != GXcopy) { - if (pPixmap->drawable.bitsPerPixel == 32) - return FALSE; - BEGIN_NV04(chan, NV04_RECT(OPERATION), 1); - OUT_RING (chan, 1); /* ROP_AND */ - NV04EXASetROP(pScrn, alu, planemask); - } else { - BEGIN_NV04(chan, NV04_RECT(OPERATION), 1); - OUT_RING (chan, 3); /* SRCCOPY */ + if (surf_fmt == NV04_SURFACE_2D_FORMAT_A8R8G8B8) + surf_fmt = NV04_SURFACE_2D_FORMAT_Y32; + + rect_fmt = NV04_GDI_COLOR_FORMAT_A8R8G8B8; + if (ppix->drawable.bitsPerPixel == 16) { + if (ppix->drawable.depth == 16) + rect_fmt = NV04_GDI_COLOR_FORMAT_A16R5G6B5; + else + rect_fmt = NV04_GDI_COLOR_FORMAT_X16A1R5G5B5; } - if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap, (int*)&fmt)) + if (!PUSH_SPACE(push, 64)) return FALSE; - pitch = exaGetPixmapPitch(pPixmap); + PUSH_RESET(push); - if (pPixmap->drawable.bitsPerPixel == 16) { - if (pPixmap->drawable.depth == 16) { - fmt2 = NV04_GDI_COLOR_FORMAT_A16R5G6B5; - } else if (pPixmap->drawable.depth == 15) { - fmt2 = NV04_GDI_COLOR_FORMAT_X16A1R5G5B5; - } - } + if (!NV04EXASetROP(ppix, NV04_RECT(OPERATION), alu, planemask)) + return FALSE; - /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the - * alpha channel gets forced to 0xFF for some reason. We're using - * SURFACE_FORMAT_Y32 as a workaround - */ - if (fmt == NV04_SURFACE_2D_FORMAT_A8R8G8B8) - fmt = NV04_SURFACE_2D_FORMAT_Y32; - - BEGIN_NV04(chan, NV04_SF2D(FORMAT), 4); - OUT_RING (chan, fmt); - OUT_RING (chan, (pitch << 16) | pitch); - if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) || - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); + BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); + PUSH_DATA (push, surf_fmt); + PUSH_DATA (push, (pitch << 16) | pitch); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_NV04(push, NV04_RECT(COLOR_FORMAT), 1); + PUSH_DATA (push, rect_fmt); + + nouveau_pushbuf_bufctx(push, pNv->bufctx); + if (nouveau_pushbuf_validate(push)) { + nouveau_pushbuf_bufctx(push, NULL); return FALSE; } - BEGIN_NV04(chan, NV04_RECT(COLOR_FORMAT), 1); - OUT_RING (chan, fmt2); - BEGIN_NV04(chan, NV04_RECT(COLOR1_A), 1); - OUT_RING (chan, fg); - - pNv->pdpix = pPixmap; - pNv->alu = alu; - pNv->planemask = planemask; pNv->fg_colour = fg; - chan->flush_notify = NV04EXAStateSolidResubmit; return TRUE; } void -NV04EXASolid (PixmapPtr pPixmap, int x1, int y1, int x2, int y2) +NV04EXASolid (PixmapPtr pPixmap, int x, int y, int x2, int y2) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - int width = x2-x1; - int height = y2-y1; - - BEGIN_NV04(chan, NV04_RECT(UNCLIPPED_RECTANGLE_POINT(0)), 2); - OUT_RING (chan, (x1 << 16) | y1); - OUT_RING (chan, (width << 16) | height); - - if((width * height) >= 512) - FIRE_RING (chan); + struct nouveau_pushbuf *push = pNv->pushbuf; + int w = x2 - x; + int h = y2 - y; + + if (!PUSH_SPACE(push, 5)) + return; + + BEGIN_NV04(push, NV04_RECT(COLOR1_A), 1); + PUSH_DATA (push, pNv->fg_colour); + BEGIN_NV04(push, NV04_RECT(UNCLIPPED_RECTANGLE_POINT(0)), 2); + PUSH_DATA (push, (x << 16) | y); + PUSH_DATA (push, (w << 16) | h); + if ((w * h) >= 512) + PUSH_KICK(push); } void NV04EXADoneSolid (PixmapPtr pPixmap) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; - NVPtr pNv = NVPTR(pScrn); - - pNv->chan->flush_notify = NULL; -} - -static void -NV04EXAStateCopyResubmit(struct nouveau_channel *chan) -{ - ScrnInfoPtr pScrn = chan->user_private; - NVPtr pNv = NVPTR(pScrn); - - NV04EXAPrepareCopy(pNv->pspix, pNv->pdpix, 0, 0, pNv->alu, - pNv->planemask); + nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL); } Bool -NV04EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int dx, int dy, +NV04EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy, int alu, Pixel planemask) { - ScrnInfoPtr pScrn = xf86Screens[pSrcPixmap->drawable.pScreen->myNum]; + ScrnInfoPtr pScrn = xf86Screens[pspix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; - struct nouveau_bo *src_bo = nouveau_pixmap_bo(pSrcPixmap); - struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pDstPixmap); - int fmt; + struct nouveau_pushbuf *push = pNv->pushbuf; + struct nouveau_bo *src_bo = nouveau_pixmap_bo(pspix); + struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); + int surf_fmt; - if (pSrcPixmap->drawable.bitsPerPixel != - pDstPixmap->drawable.bitsPerPixel) + if (pspix->drawable.bitsPerPixel != pdpix->drawable.bitsPerPixel) return FALSE; - if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap, &fmt)) + if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdpix, &surf_fmt)) return FALSE; - if (MARK_RING(chan, 64, 2)) + if (!PUSH_SPACE(push, 64)) return FALSE; + PUSH_RESET(push); - planemask |= ~0 << pDstPixmap->drawable.bitsPerPixel; - if (planemask != ~0 || alu != GXcopy) { - if (pDstPixmap->drawable.bitsPerPixel == 32) { - MARK_UNDO(chan); - return FALSE; - } - - BEGIN_NV04(chan, NV01_BLIT(OPERATION), 1); - OUT_RING (chan, 1); /* ROP_AND */ - - NV04EXASetROP(pScrn, alu, planemask); - } else { - BEGIN_NV04(chan, NV01_BLIT(OPERATION), 1); - OUT_RING (chan, 3); /* SRCCOPY */ - } + if (!NV04EXASetROP(pdpix, NV01_BLIT(OPERATION), alu, planemask)) + return FALSE; - BEGIN_NV04(chan, NV04_SF2D(FORMAT), 4); - OUT_RING (chan, fmt); - OUT_RING (chan, (exaGetPixmapPitch(pDstPixmap) << 16) | - (exaGetPixmapPitch(pSrcPixmap))); - if (OUT_RELOCl(chan, src_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || - OUT_RELOCl(chan, dst_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); + BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); + PUSH_DATA (push, surf_fmt); + PUSH_DATA (push, (exaGetPixmapPitch(pdpix) << 16) | + exaGetPixmapPitch(pspix)); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), src_bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), dst_bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + nouveau_pushbuf_bufctx(push, pNv->bufctx); + if (nouveau_pushbuf_validate(push)) { + nouveau_pushbuf_bufctx(push, NULL); return FALSE; } - pNv->pspix = pSrcPixmap; - pNv->pdpix = pDstPixmap; - pNv->alu = alu; - pNv->planemask = planemask; - chan->flush_notify = NV04EXAStateCopyResubmit; + pNv->pspix = pspix; + pNv->pmpix = NULL; + pNv->pdpix = pdpix; return TRUE; } void -NV04EXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, +NV04EXACopy(PixmapPtr pdpix, int srcX, int srcY, int dstX, int dstY, int width, int height) { - ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; + ScrnInfoPtr pScrn = xf86Screens[pdpix->drawable.pScreen->myNum]; NVPtr pNv = NVPTR(pScrn); - struct nouveau_channel *chan = pNv->chan; + struct nouveau_pushbuf *push = pNv->pushbuf; int split_dstY = NOUVEAU_ALIGN(dstY + 1, 64); int split_height = split_dstY - dstY; + if (nouveau_pushbuf_space(push, 16, 1, 0)) + return; + if ((width * height) >= 200000 && pNv->pspix != pNv->pdpix && (dstY > srcY || dstX > srcX) && split_height < height) { /* @@ -257,90 +234,59 @@ NV04EXACopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, * different (not nicer) trick to achieve the same * effect. */ - struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pNv->pdpix); - unsigned dst_pitch = exaGetPixmapPitch(pNv->pdpix); - - if (MARK_RING(chan, 10, 1)) - return; - - BEGIN_NV04(chan, NV01_BLIT(POINT_IN), 3); - OUT_RING (chan, (srcY << 16) | srcX); - OUT_RING (chan, (dstY << 16) | dstX); - OUT_RING (chan, (split_height << 16) | width); + struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); + unsigned dst_pitch = exaGetPixmapPitch(pdpix); - BEGIN_NV04(chan, NV04_SF2D(OFFSET_DESTIN), 1); - OUT_RELOCl(chan, dst_bo, split_dstY * dst_pitch, - NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_NV04(push, NV01_BLIT(POINT_IN), 3); + PUSH_DATA (push, (srcY << 16) | srcX); + PUSH_DATA (push, (dstY << 16) | dstX); + PUSH_DATA (push, (split_height << 16) | width); + BEGIN_NV04(push, NV04_SF2D(OFFSET_DESTIN), 1); + PUSH_RELOC(push, dst_bo, split_dstY * dst_pitch, + NOUVEAU_BO_LOW, 0, 0); srcY += split_height; height -= split_height; dstY = 0; + pNv->pmpix = pdpix; + } else + if (pNv->pmpix) { + struct nouveau_bo *dst_bo = nouveau_pixmap_bo(pdpix); + + BEGIN_NV04(push, NV04_SF2D(OFFSET_DESTIN), 1); + PUSH_RELOC(push, dst_bo, 0, NOUVEAU_BO_LOW, 0, 0); + pNv->pmpix = NULL; } - BEGIN_NV04(chan, NV01_BLIT(POINT_IN), 3); - OUT_RING (chan, (srcY << 16) | srcX); - OUT_RING (chan, (dstY << 16) | dstX); - OUT_RING (chan, (height << 16) | width); + BEGIN_NV04(push, NV01_BLIT(POINT_IN), 3); + PUSH_DATA (push, (srcY << 16) | srcX); + PUSH_DATA (push, (dstY << 16) | dstX); + PUSH_DATA (push, (height << 16) | width); - if((width * height) >= 512) - FIRE_RING (chan); + if ((width * height) >= 512) + PUSH_KICK(push); } void -NV04EXADoneCopy(PixmapPtr pDstPixmap) +NV04EXADoneCopy(PixmapPtr pdpix) { - ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; - NVPtr pNv = NVPTR(pScrn); - - pNv->chan->flush_notify = NULL; -} - -static Bool -NV04EXAStateIFCSubmit(struct nouveau_channel *chan) -{ - ScrnInfoPtr pScrn = chan->user_private; - NVPtr pNv = NVPTR(pScrn); - struct nouveau_bo *bo = nouveau_pixmap_bo(pNv->pdpix); - int surf_fmt; - - NVAccelGetCtxSurf2DFormatFromPixmap(pNv->pdpix, &surf_fmt); - - if (MARK_RING(chan, 64, 2)) - return FALSE; - - BEGIN_NV04(chan, NV04_SF2D(FORMAT), 4); - OUT_RING (chan, surf_fmt); - OUT_RING (chan, (exaGetPixmapPitch(pNv->pdpix) << 16) | - exaGetPixmapPitch(pNv->pdpix)); - if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) || - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); - return FALSE; - } - BEGIN_NV04(chan, NV01_IFC(POINT), 3); - OUT_RING (chan, (pNv->point_y << 16) | pNv->point_x); - OUT_RING (chan, (pNv->height_out << 16) | pNv->width_out); - OUT_RING (chan, (pNv->height_in << 16) | pNv->width_in); - - return TRUE; -} - -static void -NV04EXAStateIFCResubmit(struct nouveau_channel *chan) -{ - NV04EXAStateIFCSubmit(chan); + ScrnInfoPtr pScrn = xf86Screens[pdpix->drawable.pScreen->myNum]; + nouveau_pushbuf_bufctx(NVPTR(pScrn)->pushbuf, NULL); } Bool NV04EXAUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, - PixmapPtr pDst, int x, int y, int w, int h, int cpp) + PixmapPtr pdpix, int x, int y, int w, int h, int cpp) { NVPtr pNv = NVPTR(pScrn); - ScreenPtr pScreen = pDst->drawable.pScreen; - struct nouveau_channel *chan = pNv->chan; + ScreenPtr pScreen = pdpix->drawable.pScreen; + struct nouveau_bo *bo = nouveau_pixmap_bo(pdpix); + struct nouveau_pushbuf *push = pNv->pushbuf; int line_len = w * cpp; - int iw, id, surf_fmt, ifc_fmt; + int surf_fmt, ifc_fmt; + int iw, id, py, ph; int padbytes; + Bool ret = FALSE; if (pNv->Architecture >= NV_ARCH_50) return FALSE; @@ -348,7 +294,7 @@ NV04EXAUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, if (h > 1024) return FALSE; - if (line_len<4) + if (line_len < 4) return FALSE; switch (cpp) { @@ -358,7 +304,7 @@ NV04EXAUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, return FALSE; } - if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDst, &surf_fmt)) + if (!NVAccelGetCtxSurf2DFormatFromPixmap(pdpix, &surf_fmt)) return FALSE; /* Pad out input width to cover both COLORA() and COLORB() */ @@ -371,49 +317,67 @@ NV04EXAUploadIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch, if (id > 1792) return FALSE; - BEGIN_NV04(chan, NV01_SUBC(MISC, OBJECT), 1); - OUT_RING (chan, pNv->NvClipRectangle->handle); - BEGIN_NV04(chan, NV01_CLIP(POINT), 2); - OUT_RING (chan, (y << 16) | x); - OUT_RING (chan, (h << 16) | w); - BEGIN_NV04(chan, NV01_IFC(OPERATION), 2); - OUT_RING (chan, NV01_IFC_OPERATION_SRCCOPY); - OUT_RING (chan, ifc_fmt); - - pNv->point_x = x; - pNv->point_y = y; - pNv->height_in = pNv->height_out = h; - pNv->width_in = iw; - pNv->width_out = w; - pNv->pdpix = pDst; - chan->flush_notify = NV04EXAStateIFCResubmit; - if (!NV04EXAStateIFCSubmit(chan)) + if (!PUSH_SPACE(push, 16)) return FALSE; + PUSH_RESET(push); + + BEGIN_NV04(push, NV01_SUBC(MISC, OBJECT), 1); + PUSH_DATA (push, pNv->NvClipRectangle->handle); + BEGIN_NV04(push, NV01_CLIP(POINT), 2); + PUSH_DATA (push, (y << 16) | x); + PUSH_DATA (push, (h << 16) | w); + + BEGIN_NV04(push, NV04_SF2D(FORMAT), 4); + PUSH_DATA (push, surf_fmt); + PUSH_DATA (push, (exaGetPixmapPitch(pdpix) << 16) | + exaGetPixmapPitch(pdpix)); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_SOURCE), bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + PUSH_MTHDl(push, NV04_SF2D(OFFSET_DESTIN), bo, 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + nouveau_pushbuf_bufctx(push, pNv->bufctx); + if (nouveau_pushbuf_validate(push)) + goto out; + + py = y; + ph = h; + while (ph--) { + if (PUSH_AVAIL(push) < id + 1 || (py == y)) { + if (!PUSH_SPACE(push, id + 8)) + goto out; + BEGIN_NV04(push, NV01_IFC(OPERATION), 2); + PUSH_DATA (push, NV01_IFC_OPERATION_SRCCOPY); + PUSH_DATA (push, ifc_fmt); + BEGIN_NV04(push, NV01_IFC(POINT), 3); + PUSH_DATA (push, (py << 16) | x); + PUSH_DATA (push, (h << 16) | w); + PUSH_DATA (push, (h << 16) | iw); + } - if (padbytes) - h--; - while (h--) { /* send a line */ - BEGIN_NV04(chan, NV01_IFC(COLOR(0)), id); - OUT_RINGp (chan, src, id); + if (ph > 0 || !padbytes) { + BEGIN_NV04(push, NV01_IFC(COLOR(0)), id); + PUSH_DATAp(push, src, id); + } else { + char padding[8]; + int aux = (padbytes + 7) >> 2; + memcpy(padding, src + (id - aux) * 4, padbytes); + BEGIN_NV04(push, NV01_IFC(COLOR(0)), id); + PUSH_DATAp(push, src, id - aux); + PUSH_DATAp(push, padding, aux); + } src += src_pitch; - pNv->point_y++; + py++; } - if (padbytes) { - char padding[8]; - int aux = (padbytes + 7) >> 2; - BEGIN_NV04(chan, NV01_IFC(COLOR(0)), id); - OUT_RINGp (chan, src, id - aux); - memcpy(padding, src + (id - aux) * 4, padbytes); - OUT_RINGp (chan, padding, aux); - } - - chan->flush_notify = NULL; - if (pDst == pScreen->GetScreenPixmap(pScreen)) - FIRE_RING(chan); - return TRUE; + ret = TRUE; +out: + nouveau_pushbuf_bufctx(push, NULL); + if (pdpix == pScreen->GetScreenPixmap(pScreen)) + PUSH_KICK(push); + return ret; } Bool @@ -423,7 +387,12 @@ NV04EXARectM2MF(NVPtr pNv, int w, int h, int cpp, struct nouveau_bo *dst, uint32_t dst_off, int dst_dom, int dst_pitch, int dst_h, int dst_x, int dst_y) { - struct nouveau_channel *chan = pNv->chan; + struct nv04_fifo *fifo = pNv->channel->data; + struct nouveau_pushbuf *push = pNv->pushbuf; + struct nouveau_pushbuf_refn refs[] = { + { src, src_dom | NOUVEAU_BO_RD }, + { dst, dst_dom | NOUVEAU_BO_WR }, + }; src_off += src_y * src_pitch + src_x * cpp; dst_off += dst_y * dst_pitch + dst_x * cpp; @@ -434,31 +403,26 @@ NV04EXARectM2MF(NVPtr pNv, int w, int h, int cpp, line_count = 2047; h -= line_count; - if (MARK_RING (chan, 16, 4)) + if (nouveau_pushbuf_space(push, 16, 4, 0) || + nouveau_pushbuf_refn (push, refs, 2)) return FALSE; - BEGIN_NV04(chan, NV03_M2MF(DMA_BUFFER_IN), 2); - if (OUT_RELOCo(chan, src, src_dom | NOUVEAU_BO_RD) || - OUT_RELOCo(chan, dst, dst_dom | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); - return FALSE; - } - BEGIN_NV04(chan, NV03_M2MF(OFFSET_IN), 8); - if (OUT_RELOCl(chan, src, src_off, src_dom | NOUVEAU_BO_RD) || - OUT_RELOCl(chan, dst, dst_off, dst_dom | NOUVEAU_BO_WR)) { - MARK_UNDO(chan); - return FALSE; - } - OUT_RING (chan, src_pitch); - OUT_RING (chan, dst_pitch); - OUT_RING (chan, w * cpp); - OUT_RING (chan, line_count); - OUT_RING (chan, 0x00000101); - OUT_RING (chan, 0x00000000); - BEGIN_NV04(chan, NV04_GRAPH(M2MF, NOP), 1); - OUT_RING (chan, 0x00000000); - BEGIN_NV04(chan, NV03_M2MF(OFFSET_OUT), 1); - OUT_RING (chan, 0x00000000); + BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2); + PUSH_RELOC(push, src, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); + PUSH_RELOC(push, dst, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart); + BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8); + PUSH_RELOC(push, src, src_off, NOUVEAU_BO_LOW, 0, 0); + PUSH_RELOC(push, dst, dst_off, NOUVEAU_BO_LOW, 0, 0); + PUSH_DATA (push, src_pitch); + PUSH_DATA (push, dst_pitch); + PUSH_DATA (push, w * cpp); + PUSH_DATA (push, line_count); + PUSH_DATA (push, 0x00000101); + PUSH_DATA (push, 0x00000000); + BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1); + PUSH_DATA (push, 0x00000000); + BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1); + PUSH_DATA (push, 0x00000000); src_off += src_pitch * line_count; dst_off += dst_pitch * line_count; |