summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-12-13 12:00:23 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-12-15 15:13:38 +1000
commit88c1c43302331e1cb8b7035bfb4677a5e7da3090 (patch)
treec7811081aae3428ce3cdf4d12894ea654ef5778d
parentad5b4cfe388a102a0c93f7281cb4bba532b1796b (diff)
downloadxorg-driver-xf86-video-nouveau-88c1c43302331e1cb8b7035bfb4677a5e7da3090.tar.gz
nvc0: add Xv implementation
-rw-r--r--src/Makefile.am1
-rw-r--r--src/nouveau_xv.c26
-rw-r--r--src/nv50_xv.c5
-rw-r--r--src/nv_proto.h9
-rw-r--r--src/nvc0_accel.c106
-rw-r--r--src/nvc0_xv.c425
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]);
+}