From e77a2d9b62bc65062e7e2167642be5ab75ac4864 Mon Sep 17 00:00:00 2001 From: Aaron Plattner Date: Tue, 10 Jul 2007 00:41:21 -0700 Subject: G80: Add a dithering property and corresponding config file option. --- man/nv.man | 5 ++++ src/g80_display.c | 17 ++++++++++++++ src/g80_display.h | 1 + src/g80_driver.c | 4 ++++ src/g80_sor.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/g80_type.h | 1 + 6 files changed, 98 insertions(+) diff --git a/man/nv.man b/man/nv.man index e9bcec9..54b637f 100644 --- a/man/nv.man +++ b/man/nv.man @@ -157,6 +157,11 @@ If you choose to use EXA, you might also consider setting .B Option \*qMigrationHeuristic\*q \*qgreedy\*q to improve performance. Default: XAA. +.TP +.BI "Option \*qFPDither\*q \*q" boolean \*q +Enable or disable flat panel dithering by default. +Dithering can also be enabled or disabled using the RandR 1.2 \*qdither\*q output property. +Default: off. .\" ******************** end G80 section ******************** . .SH "SEE ALSO" diff --git a/src/g80_display.c b/src/g80_display.c index d10f2d6..04ae3ec 100644 --- a/src/g80_display.c +++ b/src/g80_display.c @@ -41,6 +41,7 @@ typedef struct G80CrtcPrivRec { int pclk; /* Target pixel clock in kHz */ Bool cursorVisible; Bool skipModeFixup; + Bool dither; } G80CrtcPrivRec, *G80CrtcPrivPtr; static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update); @@ -362,6 +363,7 @@ G80CrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode, case 16: C(0x00000870 + headOff, 0xE800); break; case 24: C(0x00000870 + headOff, 0xCF00); break; } + G80CrtcSetDither(crtc, pPriv->dither, FALSE); if((adjusted_mode->Flags & V_DBLSCAN) || (adjusted_mode->Flags & V_INTERLACE) || adjusted_mode->CrtcHDisplay != HDisplay || adjusted_mode->CrtcVDisplay != VDisplay) { C(0x000008A4 + headOff, 9); @@ -478,6 +480,19 @@ G80CrtcSkipModeFixup(xf86CrtcPtr crtc) pPriv->skipModeFixup = TRUE; } +void +G80CrtcSetDither(xf86CrtcPtr crtc, Bool dither, Bool update) +{ + ScrnInfoPtr pScrn = crtc->scrn; + G80CrtcPrivPtr pPriv = crtc->driver_private; + const int headOff = 0x400 * G80CrtcGetHead(crtc); + + pPriv->dither = dither; + + C(0x000008A0 + headOff, dither ? 0x11 : 0); + if(update) C(0x00000080, 0); +} + static void G80CrtcCommit(xf86CrtcPtr crtc) { @@ -524,6 +539,7 @@ static const xf86CrtcFuncsRec g80_crtc_funcs = { void G80DispCreateCrtcs(ScrnInfoPtr pScrn) { + G80Ptr pNv = G80PTR(pScrn); Head head; xf86CrtcPtr crtc; G80CrtcPrivPtr g80_crtc; @@ -535,6 +551,7 @@ G80DispCreateCrtcs(ScrnInfoPtr pScrn) g80_crtc = xnfcalloc(sizeof(*g80_crtc), 1); g80_crtc->head = head; + g80_crtc->dither = pNv->Dither; crtc->driver_private = g80_crtc; } } diff --git a/src/g80_display.h b/src/g80_display.h index d6f24f4..4ab1d55 100644 --- a/src/g80_display.h +++ b/src/g80_display.h @@ -12,5 +12,6 @@ void G80CrtcEnableCursor(xf86CrtcPtr, Bool update); void G80CrtcDisableCursor(xf86CrtcPtr, Bool update); void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y); void G80CrtcSkipModeFixup(xf86CrtcPtr); +void G80CrtcSetDither(xf86CrtcPtr, Bool dither, Bool update); void G80DispCreateCrtcs(ScrnInfoPtr pScrn); diff --git a/src/g80_driver.c b/src/g80_driver.c index 7801602..8a494b9 100644 --- a/src/g80_driver.c +++ b/src/g80_driver.c @@ -105,12 +105,14 @@ typedef enum { OPTION_HW_CURSOR, OPTION_NOACCEL, OPTION_ACCEL_METHOD, + OPTION_FP_DITHER, } G80Opts; static const OptionInfoRec G80Options[] = { { OPTION_HW_CURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ACCEL_METHOD, "AccelMethod", OPTV_STRING, {0}, FALSE }, + { OPTION_FP_DITHER, "FPDither", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -313,6 +315,8 @@ G80PreInit(ScrnInfoPtr pScrn, int flags) goto fail; } + pNv->Dither = xf86ReturnOptValBool(pNv->Options, OPTION_FP_DITHER, FALSE); + /* Set the bits per RGB for 8bpp mode */ if(pScrn->depth == 8) pScrn->rgbBits = 8; diff --git a/src/g80_sor.c b/src/g80_sor.c index 5ff7318..c4c640c 100644 --- a/src/g80_sor.c +++ b/src/g80_sor.c @@ -27,6 +27,7 @@ #define DPMS_SERVER #include +#include #include "g80_type.h" #include "g80_display.h" @@ -200,6 +201,67 @@ G80SorGetLVDSModes(xf86OutputPtr output) return xf86DuplicateMode(pPriv->nativeMode); } +#ifdef RANDR_12_INTERFACE +#define MAKE_ATOM(a) MakeAtom((a), sizeof(a) - 1, TRUE); + +struct property { + Atom atom; + INT32 range[2]; +}; + +static struct { + struct property dither; +} properties; + +static void +G80SorCreateResources(xf86OutputPtr output) +{ + ScrnInfoPtr pScrn = output->scrn; + G80Ptr pNv = G80PTR(pScrn); + int data, err; + + properties.dither.atom = MAKE_ATOM("dither"); + properties.dither.range[0] = 0; + properties.dither.range[1] = 1; + err = RRConfigureOutputProperty(output->randr_output, + properties.dither.atom, FALSE, TRUE, FALSE, + 2, properties.dither.range); + if(err) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to configure dithering property for %s: error %d\n", + output->name, err); + + // Set the default value + data = pNv->Dither; + err = RRChangeOutputProperty(output->randr_output, properties.dither.atom, + XA_INTEGER, 32, PropModeReplace, 1, &data, + FALSE, FALSE); + if(err) + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to set dithering property for %s: error %d\n", + output->name, err); +} + +static Bool +G80SorSetProperty(xf86OutputPtr output, Atom prop, RRPropertyValuePtr val) +{ + if(prop == properties.dither.atom) { + INT32 i; + + if(val->type != XA_INTEGER || val->format != 32 || val->size != 1) + return FALSE; + + i = *(INT32*)val->data; + if(i < properties.dither.range[0] || i > properties.dither.range[1]) + return FALSE; + + G80CrtcSetDither(output->crtc, i, TRUE); + } + + return TRUE; +} +#endif // RANDR_12_INTERFACE + static const xf86OutputFuncsRec G80SorTMDSOutputFuncs = { .dpms = G80SorDPMSSet, .save = NULL, @@ -211,6 +273,10 @@ static const xf86OutputFuncsRec G80SorTMDSOutputFuncs = { .mode_set = G80SorModeSet, .detect = G80SorDetect, .get_modes = G80OutputGetDDCModes, +#ifdef RANDR_12_INTERFACE + .create_resources = G80SorCreateResources, + .set_property = G80SorSetProperty, +#endif .destroy = G80SorDestroy, }; @@ -225,6 +291,10 @@ static const xf86OutputFuncsRec G80SorLVDSOutputFuncs = { .mode_set = G80SorModeSet, .detect = G80SorLVDSDetect, .get_modes = G80SorGetLVDSModes, +#ifdef RANDR_12_INTERFACE + .create_resources = G80SorCreateResources, + .set_property = G80SorSetProperty, +#endif .destroy = G80SorDestroy, }; diff --git a/src/g80_type.h b/src/g80_type.h index 819a9f6..0830ecc 100644 --- a/src/g80_type.h +++ b/src/g80_type.h @@ -59,6 +59,7 @@ typedef struct G80Rec { Bool HWCursor; Bool NoAccel; AccelMethod AccelMethod; + Bool Dither; /* XAA */ XAAInfoRecPtr xaa; -- cgit v1.2.3