diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-12-13 12:00:23 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-15 15:13:38 +1000 |
commit | 88c1c43302331e1cb8b7035bfb4677a5e7da3090 (patch) | |
tree | c7811081aae3428ce3cdf4d12894ea654ef5778d /src | |
parent | ad5b4cfe388a102a0c93f7281cb4bba532b1796b (diff) |
nvc0: add Xv implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/nouveau_xv.c | 26 | ||||
-rw-r--r-- | src/nv50_xv.c | 5 | ||||
-rw-r--r-- | src/nv_proto.h | 9 | ||||
-rw-r--r-- | src/nvc0_accel.c | 106 | ||||
-rw-r--r-- | src/nvc0_xv.c | 425 |
6 files changed, 521 insertions, 51 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8f1f704..e9e84ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,6 +60,7 @@ nouveau_drv_la_SOURCES = \ nv50_texture.h \ nvc0_accel.c nvc0_accel.h \ nvc0_exa.c \ + nvc0_xv.c \ drmmode_display.c \ vl_hwmc.c \ vl_hwmc.h diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c index dba153c..b9f24ee 100644 --- a/src/nouveau_xv.c +++ b/src/nouveau_xv.c @@ -243,8 +243,13 @@ nouveau_xv_bo_realloc(ScrnInfoPtr pScrn, unsigned flags, unsigned size, } tile_flags = 0; - if (pNv->Architecture >= NV_ARCH_50 && (flags & NOUVEAU_BO_VRAM)) - tile_flags = 0x7000; + if (flags & NOUVEAU_BO_VRAM) { + if (pNv->Architecture == NV_ARCH_50) + tile_flags = 0x7000; + else + if (pNv->Architecture == NV_ARCH_C0) + tile_flags = 0xfe00; + } ret = nouveau_bo_new_tile(pNv->dev, flags | NOUVEAU_BO_MAP, 0, size, 0, tile_flags, pbo); @@ -1104,6 +1109,12 @@ NVPutImage(ScrnInfoPtr pScrn, short src_x, short src_y, short drw_x, nouveau_bo_unmap(destination_buffer); + if (pNv->Architecture >= NV_ARCH_C0) { + nvc0_xv_m2mf(chan, pPriv->video_mem, uv_offset, dstPitch, + nlines, destination_buffer, line_len); + goto put_image; + } + if (MARK_RING(chan, 64, 4)) return FALSE; @@ -1243,6 +1254,7 @@ CPU_copy: if (pPriv->currentHostBuffer != NO_PRIV_HOST_BUFFER_AVAILABLE) pPriv->currentHostBuffer ^= 1; +put_image: /* If we're not using the hw overlay, we're rendering into a pixmap * and need to take a couple of additional steps... */ @@ -1313,6 +1325,13 @@ CPU_copy: xb, yb, npixels, nlines, src_w, src_h, drw_w, drw_h, clipBoxes, ppix, pPriv); + } else { + ret = nvc0_xv_image_put(pScrn, pPriv->video_mem, + offset, uv_offset, + id, dstPitch, &dstBox, 0, 0, + xb, yb, npixels, nlines, + src_w, src_h, drw_w, drw_h, + clipBoxes, ppix, pPriv); } if (ret != Success) @@ -2039,7 +2058,6 @@ NV50SetupTexturedVideo (ScreenPtr pScreen) return adapt; } - /** * NVInitVideo * tries to initialize the various supported adapters @@ -2082,7 +2100,7 @@ NVInitVideo(ScreenPtr pScreen) textureAdaptor[0] = NV40SetupTexturedVideo(pScreen, FALSE); textureAdaptor[1] = NV40SetupTexturedVideo(pScreen, TRUE); } else - if (pNv->Architecture == NV_ARCH_50) { + if (pNv->Architecture >= NV_ARCH_50) { textureAdaptor[0] = NV50SetupTexturedVideo(pScreen); } } diff --git a/src/nv50_xv.c b/src/nv50_xv.c index 1538cdc..ddeb5bb 100644 --- a/src/nv50_xv.c +++ b/src/nv50_xv.c @@ -399,6 +399,11 @@ nv50_xv_csc_update(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv) off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright; off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright; + if (pNv->Architecture >= NV_ARCH_C0) { + nvc0_xv_csc_update(pNv, yco, off, uco, vco); + return; + } + if (MARK_RING(chan, 64, 2)) return; diff --git a/src/nv_proto.h b/src/nv_proto.h index 5821444..4df559e 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -186,6 +186,15 @@ int nv50_xv_port_attribute_get(ScrnInfoPtr, Atom, INT32 *, pointer); void nv50_xv_set_port_defaults(ScrnInfoPtr, NVPortPrivPtr); void nv50_xv_csc_update(ScrnInfoPtr, NVPortPrivPtr); +/* nvc0_xv.c */ +int nvc0_xv_image_put(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int, + BoxPtr, int, int, int, int, uint16_t, uint16_t, + uint16_t, uint16_t, uint16_t, uint16_t, + RegionPtr, PixmapPtr, NVPortPrivPtr); +void nvc0_xv_m2mf(struct nouveau_channel *, struct nouveau_bo *, int, int, int, + struct nouveau_bo *, int); +void nvc0_xv_csc_update(NVPtr, float, float *, float *, float *); + /* To support EXA 2.0, 2.1 has this in the header */ #ifndef exaMoveInPixmap extern void exaMoveInPixmap(PixmapPtr pPixmap); diff --git a/src/nvc0_accel.c b/src/nvc0_accel.c index 8ee2fdf..123b04a 100644 --- a/src/nvc0_accel.c +++ b/src/nvc0_accel.c @@ -617,11 +617,11 @@ NVAccelInitNVC0TCL(ScrnInfoPtr pScrn) return FALSE; } BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_LINE_LENGTH_IN, 2); - OUT_RING (chan, 16 * 8 + 20 * 4); + OUT_RING (chan, 25 * 8 + 20 * 4); OUT_RING (chan, 1); BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_EXEC, 1); OUT_RING (chan, 0x100111); - BEGIN_RING_NI(chan, NvSubM2MF, NVC0_M2MF_DATA, 16 * 2 + 20); + BEGIN_RING_NI(chan, NvSubM2MF, NVC0_M2MF_DATA, 25 * 2 + 20); OUT_RING (chan, 0x00021462); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x00000000); @@ -642,52 +642,57 @@ NVAccelInitNVC0TCL(ScrnInfoPtr pScrn) OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x0000000f); OUT_RING (chan, 0x00000000); - OUT_RING (chan, 0xfff01c00); - OUT_RING (chan, 0xc07e007c); /* linterp f32 $r0 v[$r63+0x7c] */ - OUT_RING (chan, 0x10001c00); - OUT_RING (chan, 0xc8000000); /* rcp f32 $r0 $r0 */ - OUT_RING (chan, 0x03f0dc40); - OUT_RING (chan, 0xc07e0084); /* pinterp f32 $r3 $r0 v[$r63+0x84] */ - OUT_RING (chan, 0x03f09c40); - OUT_RING (chan, 0xc07e0080); /* pinterp f32 $r2 $r0 v[$r63+0x80] */ - OUT_RING (chan, 0xfc205e86); - OUT_RING (chan, 0x80120000); /* tex { _ _ _ $r1 } $t0 { $r2 $r3 } */ - OUT_RING (chan, 0x03f0dc40); - OUT_RING (chan, 0xc07e0094); /* pinterp f32 $r3 $r0 v[$r63+0x94] */ - OUT_RING (chan, 0x03f09c40); - OUT_RING (chan, 0xc07e0090); /* pinterp f32 $r2 $r0 v[$r63+0x90] */ - OUT_RING (chan, 0xfc211e86); - OUT_RING (chan, 0x80130001); /* tex { _ _ $r4 $r5 } $t1 { $r2 $r3 } */ - OUT_RING (chan, 0x28101c42); - OUT_RING (chan, 0x30fc7757); /* mul ftz f32 $r0 $r1 0.616543 */ - OUT_RING (chan, 0x08109c42); - OUT_RING (chan, 0x32fe8493); /* mul ftz f32 $r2 $r1 -1.258934 */ - OUT_RING (chan, 0xec10dc42); - OUT_RING (chan, 0x32fe0704); /* mul ftz f32 $r3 $r1 -1.013709 */ - OUT_RING (chan, 0x00405c40); - OUT_RING (chan, 0x30004000); /* add ftz f32 $r1 mul $r4 c0[0] $r0 */ - OUT_RING (chan, 0x10409c40); - OUT_RING (chan, 0x30044000); /* add ftz f32 $r2 mul $r4 c0[0x4] $r2 */ - OUT_RING (chan, 0x30501c40); - OUT_RING (chan, 0x30064000); /* add ftz f32 $r0 mul $r5 c0[0xc] $r3 */ - OUT_RING (chan, 0x20505c40); - OUT_RING (chan, 0x30024000); /* add ftz f32 $r1 mul $r5 c0[0x8] $r1 */ - OUT_RING (chan, 0x00001de7); - OUT_RING (chan, 0x80000000); /* exit */ - BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_SIZE, 3); - OUT_RING (chan, 256); - if (OUT_RELOCh(chan, bo, CB_OFFSET, NOUVEAU_BO(VRAM, VRAM, RD)) || - OUT_RELOCl(chan, bo, CB_OFFSET, NOUVEAU_BO(VRAM, VRAM, RD))) { - MARK_UNDO(chan); - return FALSE; - } - BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_POS, 5); - OUT_RING (chan, 0); - OUT_RINGf (chan, -0.391730f); - OUT_RINGf (chan, 2.017000f); - OUT_RINGf (chan, -0.812900f); - OUT_RINGf (chan, 1.595800f); + OUT_RING (chan, 0xfff09c00); + OUT_RING (chan, 0xc07e007c); + OUT_RING (chan, 0x10209c00); + OUT_RING (chan, 0xc8000000); + OUT_RING (chan, 0x0bf01c40); + OUT_RING (chan, 0xc07e0080); + OUT_RING (chan, 0x0bf05c40); + OUT_RING (chan, 0xc07e0084); + OUT_RING (chan, 0xfc001e86); + OUT_RING (chan, 0x80120000); + OUT_RING (chan, 0x00015c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x1050dc20); + OUT_RING (chan, 0x50004000); + OUT_RING (chan, 0x20511c20); + OUT_RING (chan, 0x50004000); + OUT_RING (chan, 0x30515c20); + OUT_RING (chan, 0x50004000); + OUT_RING (chan, 0x0bf01c40); + OUT_RING (chan, 0xc07e0090); + OUT_RING (chan, 0x0bf05c40); + OUT_RING (chan, 0xc07e0094); + OUT_RING (chan, 0xfc001e86); + OUT_RING (chan, 0x80130001); + OUT_RING (chan, 0x40009c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x0830dc20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x50009c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x08411c20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x60009c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x08515c20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x70109c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x08301c20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x90109c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x08509c20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x80105c40); + OUT_RING (chan, 0x58004000); + OUT_RING (chan, 0x04405c20); + OUT_RING (chan, 0x50000000); + OUT_RING (chan, 0x00001de7); + OUT_RING (chan, 0x80000000); BEGIN_RING(chan, NvSub3D, NVC0TCL_CODE_FLUSH, 1); OUT_RING (chan, 0x1111); @@ -700,6 +705,13 @@ NVAccelInitNVC0TCL(ScrnInfoPtr pScrn) BEGIN_RING(chan, NvSub3D, NVC0TCL_SP_GPR_ALLOC(5), 1); OUT_RING (chan, 8); + BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_SIZE, 3); + OUT_RING (chan, 256); + if (OUT_RELOCh(chan, bo, CB_OFFSET, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) || + OUT_RELOCl(chan, bo, CB_OFFSET, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { + MARK_UNDO(chan); + return FALSE; + } BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_BIND(4), 1); OUT_RING (chan, 0x01); diff --git a/src/nvc0_xv.c b/src/nvc0_xv.c new file mode 100644 index 0000000..12daaf3 --- /dev/null +++ b/src/nvc0_xv.c @@ -0,0 +1,425 @@ +/* + * Copyright 2008 Ben Skeggs + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86xv.h" +#include <X11/extensions/Xv.h> +#include "exa.h" +#include "damage.h" +#include "dixstruct.h" +#include "fourcc.h" + +#include "nv_include.h" +#include "nvc0_accel.h" +#include "nv50_texture.h" + +extern Atom xvSyncToVBlank, xvSetDefaults; + +void +nvc0_xv_m2mf(struct nouveau_channel *chan, + struct nouveau_bo *dst, int uv_offset, int dst_pitch, int nlines, + struct nouveau_bo *src, int line_len) +{ + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_TILING_MODE_OUT, 5); + OUT_RING (chan, dst->tile_mode); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, nlines); + OUT_RING (chan, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_TILING_POSITION_OUT_X, 2); + OUT_RING (chan, 0); + OUT_RING (chan, 0); + + if (uv_offset) { + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_IN_HIGH, 2); + OUT_RELOCh(chan, src, line_len * nlines, + NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, src, line_len * nlines, + NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_OUT_HIGH, 2); + OUT_RELOCh(chan, dst, uv_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, dst, uv_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_PITCH_IN, 4); + OUT_RING (chan, line_len); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, line_len); + OUT_RING (chan, nlines >> 1); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_EXEC, 1); + OUT_RING (chan, 0x00100010); + } + + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_IN_HIGH, 2); + OUT_RELOCh(chan, src, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, src, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_OUT_HIGH, 2); + OUT_RELOCh(chan, dst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, dst, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_PITCH_IN, 4); + OUT_RING (chan, line_len); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, line_len); + OUT_RING (chan, nlines); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_EXEC, 1); + OUT_RING (chan, 0x00100010); +} + +static Bool +nvc0_xv_check_image_put(PixmapPtr ppix) +{ + switch (ppix->drawable.bitsPerPixel) { + case 32: + case 24: + case 16: + case 15: + break; + default: + return FALSE; + } + + if (!nv50_style_tiled_pixmap(ppix)) + return FALSE; + + return TRUE; +} + +static Bool +nvc0_xv_state_emit(PixmapPtr ppix, int id, struct nouveau_bo *src, + int packed_y, int uv, int src_w, int src_h) +{ + ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum]; + NVPtr pNv = NVPTR(pScrn); + struct nouveau_channel *chan = pNv->chan; + struct nouveau_bo *bo = nouveau_pixmap_bo(ppix); + const unsigned shd_flags = NOUVEAU_BO_RD | NOUVEAU_BO_VRAM; + const unsigned tcb_flags = NOUVEAU_BO_RDWR | NOUVEAU_BO_VRAM; + uint32_t mode = 0xd0005000 | (src->tile_mode << 18); + + if (MARK_RING(chan, 256, 18)) + return FALSE; + + BEGIN_RING(chan, NvSub3D, NVC0TCL_RT_ADDRESS_HIGH(0), 8); + if (OUT_RELOCh(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; + } + OUT_RING (chan, ppix->drawable.width); + OUT_RING (chan, ppix->drawable.height); + switch (ppix->drawable.bitsPerPixel) { + case 32: OUT_RING (chan, NVC0TCL_RT_FORMAT_A8R8G8B8_UNORM); break; + case 24: OUT_RING (chan, NVC0TCL_RT_FORMAT_X8R8G8B8_UNORM); break; + case 16: OUT_RING (chan, NVC0TCL_RT_FORMAT_R5G6B5_UNORM); break; + case 15: OUT_RING (chan, NVC0TCL_RT_FORMAT_X1R5G5B5_UNORM); break; + } + OUT_RING (chan, bo->tile_mode); + OUT_RING (chan, 1); + OUT_RING (chan, 0); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_BLEND_ENABLE(0), 1); + OUT_RING (chan, 0); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_TIC_ADDRESS_HIGH, 3); + if (OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags) || + OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 15); + + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_OUT_HIGH, 2); + if (OUT_RELOCh(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags) || + OUT_RELOCl(chan, pNv->tesla_scratch, TIC_OFFSET, tcb_flags)) { + MARK_UNDO(chan); + return FALSE; + } + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_LINE_LENGTH_IN, 2); + OUT_RING (chan, 16 * 4); + OUT_RING (chan, 1); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_EXEC, 1); + OUT_RING (chan, 0x00100111); + BEGIN_RING_NI(chan, NvSubM2MF, NVC0_M2MF_DATA, 16); + if (id == FOURCC_YV12 || id == FOURCC_I420) { + OUT_RING (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8); + if (OUT_RELOCl(chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || + OUT_RELOC (chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 0x00300000); + OUT_RING (chan, src_w); + OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h); + OUT_RING (chan, 0x03000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8); + if (OUT_RELOCl(chan, src, uv, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || + OUT_RELOC (chan, src, uv, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 0x00300000); + OUT_RING (chan, src_w >> 1); + OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | (src_h >> 1)); + OUT_RING (chan, 0x03000000); + OUT_RING (chan, 0x00000000); + } else { + if (id == FOURCC_UYVY) { + OUT_RING (chan, NV50TIC_0_0_MAPA_C1 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8); + } else { + OUT_RING (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8); + } + if (OUT_RELOCl(chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || + OUT_RELOC (chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 0x00300000); + OUT_RING (chan, src_w); + OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h); + OUT_RING (chan, 0x03000000); + OUT_RING (chan, 0x00000000); + if (id == FOURCC_UYVY) { + OUT_RING (chan, NV50TIC_0_0_MAPA_C2 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8_8_8); + } else { + OUT_RING (chan, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | + NV50TIC_0_0_MAPB_C1 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEG_UNORM | + NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_FMT_8_8_8_8); + } + if (OUT_RELOCl(chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD) || + OUT_RELOC (chan, src, packed_y, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, mode, mode)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 0x00300000); + OUT_RING (chan, (src_w >> 1)); + OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | src_h); + OUT_RING (chan, 0x03000000); + OUT_RING (chan, 0x00000000); + } + + BEGIN_RING(chan, NvSub3D, NVC0TCL_TSC_ADDRESS_HIGH, 3); + if (OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags) || + OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags)) { + MARK_UNDO(chan); + return FALSE; + } + OUT_RING (chan, 0x00000000); + + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_OFFSET_OUT_HIGH, 2); + if (OUT_RELOCh(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags) || + OUT_RELOCl(chan, pNv->tesla_scratch, TSC_OFFSET, tcb_flags)) { + MARK_UNDO(chan); + return FALSE; + } + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_LINE_LENGTH_IN, 2); + OUT_RING (chan, 16 * 4); + OUT_RING (chan, 1); + BEGIN_RING(chan, NvSubM2MF, NVC0_M2MF_EXEC, 1); + OUT_RING (chan, 0x00100111); + BEGIN_RING_NI(chan, NvSubM2MF, NVC0_M2MF_DATA, 16); + OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | + NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | + NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); + OUT_RING (chan, NV50TSC_1_1_MAGF_LINEAR | + NV50TSC_1_1_MINF_LINEAR | + NV50TSC_1_1_MIPF_NONE); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_EDGE | + NV50TSC_1_0_WRAPT_CLAMP_TO_EDGE | + NV50TSC_1_0_WRAPR_CLAMP_TO_EDGE); + OUT_RING (chan, NV50TSC_1_1_MAGF_LINEAR | + NV50TSC_1_1_MINF_LINEAR | + NV50TSC_1_1_MIPF_NONE); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + OUT_RING (chan, 0x00000000); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_CODE_ADDRESS_HIGH, 2); + if (OUT_RELOCh(chan, pNv->tesla_scratch, CODE_OFFSET, shd_flags) || + OUT_RELOCl(chan, pNv->tesla_scratch, CODE_OFFSET, shd_flags)) { + MARK_UNDO(chan); + return FALSE; + + } + BEGIN_RING(chan, NvSub3D, NVC0TCL_SP_START_ID(5), 1); + OUT_RING (chan, PFP_NV12); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_TSC_FLUSH, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, NvSub3D, NVC0TCL_TIC_FLUSH, 1); + OUT_RING (chan, 0); + BEGIN_RING(chan, NvSub3D, NVC0TCL_TEX_CACHE_CTL, 1); + OUT_RING (chan, 0); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_BIND_TIC(2), 1); + OUT_RING (chan, 1); + BEGIN_RING(chan, NvSub3D, NVC0TCL_BIND_TIC(2), 1); + OUT_RING (chan, 0x203); + + return TRUE; +} + +int +nvc0_xv_image_put(ScrnInfoPtr pScrn, + struct nouveau_bo *src, int packed_y, int uv, + int id, int src_pitch, BoxPtr dstBox, + int x1, int y1, int x2, int y2, + uint16_t width, uint16_t height, + uint16_t src_w, uint16_t src_h, + uint16_t drw_w, uint16_t drw_h, + RegionPtr clipBoxes, PixmapPtr ppix, + NVPortPrivPtr pPriv) +{ + NVPtr pNv = NVPTR(pScrn); + struct nouveau_channel *chan = pNv->chan; + float X1, X2, Y1, Y2; + BoxPtr pbox; + int nbox; + + if (!nvc0_xv_check_image_put(ppix)) + return BadMatch; + if (!nvc0_xv_state_emit(ppix, id, src, packed_y, uv, width, height)) + return BadAlloc; + + if (0 && pPriv->SyncToVBlank) { + NV50SyncToVBlank(ppix, dstBox); + } + + /* These are fixed point values in the 16.16 format. */ + X1 = (float)(x1>>16)+(float)(x1&0xFFFF)/(float)0x10000; + Y1 = (float)(y1>>16)+(float)(y1&0xFFFF)/(float)0x10000; + X2 = (float)(x2>>16)+(float)(x2&0xFFFF)/(float)0x10000; + Y2 = (float)(y2>>16)+(float)(y2&0xFFFF)/(float)0x10000; + + pbox = REGION_RECTS(clipBoxes); + nbox = REGION_NUM_RECTS(clipBoxes); + while(nbox--) { + float tx1=X1+(float)(pbox->x1 - dstBox->x1)*(X2-X1)/(float)(drw_w); + float tx2=X1+(float)(pbox->x2 - dstBox->x1)*(src_w)/(float)(drw_w); + float ty1=Y1+(float)(pbox->y1 - dstBox->y1)*(Y2-Y1)/(float)(drw_h); + float ty2=Y1+(float)(pbox->y2 - dstBox->y1)*(src_h)/(float)(drw_h); + int sx1=pbox->x1; + int sx2=pbox->x2; + int sy1=pbox->y1; + int sy2=pbox->y2; + + tx1 = tx1 / width; + tx2 = tx2 / width; + ty1 = ty1 / height; + ty2 = ty2 / height; + + if (AVAIL_RING(chan) < 64) { + if (!nvc0_xv_state_emit(ppix, id, src, packed_y, uv, + width, height)) + return BadAlloc; + } + + /* NVC0TCL_SCISSOR_VERT_T_SHIFT is wrong, because it was deducted with + * origin lying at the bottom left. This will be changed to _MIN_ and _MAX_ + * later, because it is origin dependent. + */ + BEGIN_RING(chan, NvSub3D, NVC0TCL_SCISSOR_HORIZ(0), 2); + OUT_RING (chan, sx2 << NVC0TCL_SCISSOR_HORIZ_MAX_SHIFT | sx1); + OUT_RING (chan, sy2 << NVC0TCL_SCISSOR_VERT_MAX_SHIFT | sy1 ); + + BEGIN_RING(chan, NvSub3D, NVC0TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, NVC0TCL_VERTEX_BEGIN_MODE_TRIANGLES); + VTX2s(pNv, tx1, ty1, tx1, ty1, sx1, sy1); + VTX2s(pNv, tx2+(tx2-tx1), ty1, tx2+(tx2-tx1), ty1, sx2+(sx2-sx1), sy1); + VTX2s(pNv, tx1, ty2+(ty2-ty1), tx1, ty2+(ty2-ty1), sx1, sy2+(sy2-sy1)); + BEGIN_RING(chan, NvSub3D, NVC0TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + + pbox++; + } + + FIRE_RING (chan); + return Success; +} + +void +nvc0_xv_csc_update(NVPtr pNv, float yco, float *off, float *uco, float *vco) +{ + struct nouveau_channel *chan = pNv->chan; + struct nouveau_bo *bo = pNv->tesla_scratch; + + if (MARK_RING(chan, 64, 2)) + return; + + BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_SIZE, 3); + OUT_RING (chan, 256); + if (OUT_RELOCh(chan, bo, CB_OFFSET, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) || + OUT_RELOCl(chan, bo, CB_OFFSET, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) { + MARK_UNDO(chan); + return; + } + BEGIN_RING(chan, NvSub3D, NVC0TCL_CB_POS, 11); + OUT_RING (chan, 0); + OUT_RINGf (chan, yco); + OUT_RINGf (chan, off[0]); + OUT_RINGf (chan, off[1]); + OUT_RINGf (chan, off[2]); + OUT_RINGf (chan, uco[0]); + OUT_RINGf (chan, uco[1]); + OUT_RINGf (chan, uco[2]); + OUT_RINGf (chan, vco[0]); + OUT_RINGf (chan, vco[1]); + OUT_RINGf (chan, vco[2]); +} |