summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-12-14 15:39:01 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-12-14 15:48:38 +1000
commit11510f9ce8c9eab15e7f6d5962b83fc0052c8619 (patch)
tree2ac14ef186fb09df2442ff7dfdd65fd2a5a766b9
parent214ea264cdb386520a1308a29f204e441f349cb1 (diff)
downloadxorg-driver-xf86-video-nouveau-11510f9ce8c9eab15e7f6d5962b83fc0052c8619.tar.gz
nv50/xv: implement brightness/contrast/saturation/hue controls
Adapted from the code in xf86-video-ati. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--src/nouveau_xv.c31
-rw-r--r--src/nv50_accel.c22
-rw-r--r--src/nv50_xv.c136
-rw-r--r--src/nv_proto.h2
4 files changed, 159 insertions, 32 deletions
diff --git a/src/nouveau_xv.c b/src/nouveau_xv.c
index 695c620..dba153c 100644
--- a/src/nouveau_xv.c
+++ b/src/nouveau_xv.c
@@ -137,6 +137,17 @@ XF86AttributeRec NVTexturedAttributes[NUM_TEXTURED_ATTRIBUTES] =
{XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
};
+#define NUM_TEXTURED_ATTRIBUTES_NV50 7
+XF86AttributeRec NVTexturedAttributesNV50[NUM_TEXTURED_ATTRIBUTES_NV50] =
+{
+ { XvSettable , 0, 0, "XV_SET_DEFAULTS" },
+ { XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK" },
+ { XvSettable | XvGettable, -1000, 1000, "XV_BRIGHTNESS" },
+ { XvSettable | XvGettable, -1000, 1000, "XV_CONTRAST" },
+ { XvSettable | XvGettable, -1000, 1000, "XV_SATURATION" },
+ { XvSettable | XvGettable, -1000, 1000, "XV_HUE" },
+ { XvSettable | XvGettable, 0, 1, "XV_ITURBT_709" }
+};
#define NUM_IMAGES_YUV 4
#define NUM_IMAGES_ALL 5
@@ -1999,8 +2010,8 @@ NV50SetupTexturedVideo (ScreenPtr pScreen)
for(i = 0; i < NUM_TEXTURE_PORTS; i++)
adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
- adapt->pAttributes = NVTexturedAttributes;
- adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES;
+ adapt->pAttributes = NVTexturedAttributesNV50;
+ adapt->nAttributes = NUM_TEXTURED_ATTRIBUTES_NV50;
adapt->pImages = NV50TexturedImages;
adapt->nImages = sizeof(NV50TexturedImages) /
sizeof(NV50TexturedImages[0]);
@@ -2015,14 +2026,16 @@ NV50SetupTexturedVideo (ScreenPtr pScreen)
adapt->PutImage = NVPutImage;
adapt->QueryImageAttributes = NVQueryImageAttributes;
- pPriv->videoStatus = 0;
- pPriv->grabbedByV4L = FALSE;
- pPriv->blitter = FALSE;
- pPriv->texture = TRUE;
- pPriv->doubleBuffer = FALSE;
- pPriv->SyncToVBlank = TRUE;
-
pNv->textureAdaptor[0] = adapt;
+
+ nv50_xv_set_port_defaults(pScrn, pPriv);
+ nv50_xv_csc_update(pScrn, pPriv);
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvSaturation = MAKE_ATOM("XV_SATURATION");
+ xvHue = MAKE_ATOM("XV_HUE");
+ xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
return adapt;
}
diff --git a/src/nv50_accel.c b/src/nv50_accel.c
index 3972446..0369839 100644
--- a/src/nv50_accel.c
+++ b/src/nv50_accel.c
@@ -408,28 +408,6 @@ NVAccelInitNV50TCL(ScrnInfoPtr pScrn)
OUT_RING (chan, 8192 << NV50TCL_SCREEN_SCISSOR_HORIZ_W_SHIFT);
OUT_RING (chan, 8192 << NV50TCL_SCREEN_SCISSOR_VERT_H_SHIFT);
- BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
- if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_DATA,
- NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
- OUT_RELOCl(chan, pNv->tesla_scratch, PFP_DATA,
- NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
- MARK_UNDO(chan);
- return FALSE;
- }
- OUT_RING (chan, (CB_PFP << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
- BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
- OUT_RING (chan, CB_PFP);
- BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 10);
- OUT_RINGf (chan, 1.164300);
- OUT_RINGf (chan, -0.870660);
- OUT_RINGf (chan, 0.529540);
- OUT_RINGf (chan, -1.081280);
- OUT_RINGf (chan, 0.000000);
- OUT_RINGf (chan, -0.391730);
- OUT_RINGf (chan, 2.017000);
- OUT_RINGf (chan, 1.595800);
- OUT_RINGf (chan, -0.812900);
- OUT_RINGf (chan, 0.000000);
BEGIN_RING(chan, tesla, NV50TCL_SET_PROGRAM_CB, 1);
OUT_RING (chan, 0x00000031 | (CB_PFP << 12));
diff --git a/src/nv50_xv.c b/src/nv50_xv.c
index e02f86d..1538cdc 100644
--- a/src/nv50_xv.c
+++ b/src/nv50_xv.c
@@ -37,6 +37,8 @@
#include "nv50_texture.h"
extern Atom xvSyncToVBlank, xvSetDefaults;
+extern Atom xvBrightness, xvContrast, xvHue, xvSaturation;
+extern Atom xvITURBT709;
static Bool
nv50_xv_check_image_put(PixmapPtr ppix)
@@ -349,6 +351,97 @@ nv50_xv_video_stop(ScrnInfoPtr pScrn, pointer data, Bool exit)
{
}
+/* Reference color space transform data */
+struct REF_TRANSFORM {
+ float RefLuma;
+ float RefRCb;
+ float RefRCr;
+ float RefGCb;
+ float RefGCr;
+ float RefBCb;
+ float RefBCr;
+} trans[] = {
+ { 1.1643, 0.0, 1.5960, -0.3918, -0.8129, 2.0172, 0.0 }, /* BT.601 */
+ { 1.1643, 0.0, 1.7927, -0.2132, -0.5329, 2.1124, 0.0 } /* BT.709 */
+};
+
+#define RTFSaturation(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFBrightness(a) (((a)*1.0)/2000.0)
+#define RTFContrast(a) (1.0 + ((a)*1.0)/1000.0)
+#define RTFHue(a) (((a)*3.1416)/1000.0)
+
+void
+nv50_xv_csc_update(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
+{
+ NVPtr pNv = NVPTR(pScrn);
+ struct nouveau_channel *chan = pNv->chan;
+ struct nouveau_grobj *tesla = pNv->Nv3D;
+ const float Loff = -0.0627;
+ const float Coff = -0.502;
+ float yco, off[3], uco[3], vco[3];
+ float uvcosf, uvsinf;
+ float bright, cont;
+ int ref = pPriv->iturbt_709;
+
+ cont = RTFContrast(pPriv->contrast);
+ bright = RTFBrightness(pPriv->brightness);
+ uvcosf = RTFSaturation(pPriv->saturation) * cos(RTFHue(pPriv->hue));
+ uvsinf = RTFSaturation(pPriv->saturation) * sin(RTFHue(pPriv->hue));
+
+ yco = trans[ref].RefLuma * cont;
+ uco[0] = -trans[ref].RefRCr * uvsinf;
+ uco[1] = trans[ref].RefGCb * uvcosf - trans[ref].RefGCr * uvsinf;
+ uco[2] = trans[ref].RefBCb * uvcosf;
+ vco[0] = trans[ref].RefRCr * uvcosf;
+ vco[1] = trans[ref].RefGCb * uvsinf + trans[ref].RefGCr * uvcosf;
+ vco[2] = trans[ref].RefBCb * uvsinf;
+ off[0] = Loff * yco + Coff * (uco[0] + vco[0]) + bright;
+ off[1] = Loff * yco + Coff * (uco[1] + vco[1]) + bright;
+ off[2] = Loff * yco + Coff * (uco[2] + vco[2]) + bright;
+
+ if (MARK_RING(chan, 64, 2))
+ return;
+
+ BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
+ if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_DATA,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
+ OUT_RELOCl(chan, pNv->tesla_scratch, PFP_DATA,
+ NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
+ MARK_UNDO(chan);
+ return;
+ }
+ OUT_RING (chan, (CB_PFP << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
+ BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
+ OUT_RING (chan, CB_PFP);
+ BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 10);
+ 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]);
+}
+
+void
+nv50_xv_set_port_defaults(ScrnInfoPtr pScrn, NVPortPrivPtr pPriv)
+{
+ pPriv->videoStatus = 0;
+ pPriv->grabbedByV4L = FALSE;
+ pPriv->blitter = FALSE;
+ pPriv->texture = TRUE;
+ pPriv->doubleBuffer = FALSE;
+ pPriv->SyncToVBlank = TRUE;
+ pPriv->brightness = 0;
+ pPriv->contrast = 0;
+ pPriv->saturation = 0;
+ pPriv->hue = 0;
+ pPriv->iturbt_709 = 0;
+}
+
int
nv50_xv_port_attribute_set(ScrnInfoPtr pScrn, Atom attribute,
INT32 value, pointer data)
@@ -360,11 +453,37 @@ nv50_xv_port_attribute_set(ScrnInfoPtr pScrn, Atom attribute,
return BadValue;
pPriv->SyncToVBlank = value;
} else
+ if (attribute == xvBrightness) {
+ if (value < -1000 || value > 1000)
+ return BadValue;
+ pPriv->brightness = value;
+ } else
+ if (attribute == xvContrast) {
+ if (value < -1000 || value > 1000)
+ return BadValue;
+ pPriv->contrast = value;
+ } else
+ if (attribute == xvSaturation) {
+ if (value < -1000 || value > 1000)
+ return BadValue;
+ pPriv->saturation = value;
+ } else
+ if (attribute == xvHue) {
+ if (value < -1000 || value > 1000)
+ return BadValue;
+ pPriv->hue = value;
+ } else
+ if (attribute == xvITURBT709) {
+ if (value < 0 || value > 1)
+ return BadValue;
+ pPriv->iturbt_709 = value;
+ } else
if (attribute == xvSetDefaults) {
- pPriv->SyncToVBlank = true;
+ nv50_xv_set_port_defaults(pScrn, pPriv);
} else
return BadMatch;
+ nv50_xv_csc_update(pScrn, pPriv);
return Success;
}
@@ -377,6 +496,21 @@ nv50_xv_port_attribute_get(ScrnInfoPtr pScrn, Atom attribute,
if (attribute == xvSyncToVBlank)
*value = (pPriv->SyncToVBlank) ? 1 : 0;
else
+ if (attribute == xvBrightness)
+ *value = pPriv->brightness;
+ else
+ if (attribute == xvContrast)
+ *value = pPriv->contrast;
+ else
+ if (attribute == xvSaturation)
+ *value = pPriv->saturation;
+ else
+ if (attribute == xvHue)
+ *value = pPriv->hue;
+ else
+ if (attribute == xvITURBT709)
+ *value = pPriv->iturbt_709;
+ else
return BadMatch;
return Success;
diff --git a/src/nv_proto.h b/src/nv_proto.h
index 888e74e..ba8ca5e 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -158,6 +158,8 @@ int nv50_xv_image_put(ScrnInfoPtr, struct nouveau_bo *, int, int, int, int,
void nv50_xv_video_stop(ScrnInfoPtr, pointer, Bool);
int nv50_xv_port_attribute_set(ScrnInfoPtr, Atom, INT32, pointer);
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);
/* To support EXA 2.0, 2.1 has this in the header */
#ifndef exaMoveInPixmap