diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-12-14 15:39:01 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-14 15:48:38 +1000 |
commit | 11510f9ce8c9eab15e7f6d5962b83fc0052c8619 (patch) | |
tree | 2ac14ef186fb09df2442ff7dfdd65fd2a5a766b9 | |
parent | 214ea264cdb386520a1308a29f204e441f349cb1 (diff) | |
download | xorg-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.c | 31 | ||||
-rw-r--r-- | src/nv50_accel.c | 22 | ||||
-rw-r--r-- | src/nv50_xv.c | 136 | ||||
-rw-r--r-- | src/nv_proto.h | 2 |
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 |