xf86-video-nv: man/nv.man src/g80_display.c src/g80_display.h src/g80_sor.c

Aaron Plattner aplattner at kemper.freedesktop.org
Fri Jul 13 13:32:18 PDT 2007


 man/nv.man        |   19 ++++++++++++++-
 src/g80_display.c |   65 +++++++++++++++++++++++++++++++++++++++++++++++-------
 src/g80_display.h |    7 +++++
 src/g80_sor.c     |   63 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 144 insertions(+), 10 deletions(-)

New commits:
diff-tree f0ebb42ee94eac4b294d12d02f4406a444b347ff (from ec78618d685759a39d386e9929661037b167fe68)
Author: Aaron Plattner <aplattner at nvidia.com>
Date:   Fri Jul 13 13:17:52 2007 -0700

    G80: Add an LVDS flat panel scaling property.
    
    This property controls how non-native resolutions are scaled to the native
    resolution.  Valid values are:
        * center: 1:1 pixel ratio with black borders to center the image.
        * fill: Scale image to the native resolution.
        * aspect: Scale image to fit the screen, adding black bars to preserve
          square pixels.
    Defaults to "aspect".  Change with "xrandr --output LVDS --set scale <foo>".

diff --git a/man/nv.man b/man/nv.man
index 54b637f..f27cd6d 100644
--- a/man/nv.man
+++ b/man/nv.man
@@ -162,10 +162,27 @@ Default: XAA.
 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.
+.
+.\" RandR 1.2
+.PP
+The following RandR 1.2 properties are available for flat panels on G80 and higher GPUs:
+.TP
+.B dither
+Enable or disable flat panel dithering.
+Valid values:
+.BR 0 " (off), " 1 " (on)."
+.TP
+.B scale
+Control how the image is scaled to fit the flat panel.
+Note that some flat panels perform their own scaling, overriding this option.
+Valid values:
+.RB \*q aspect "\*q, \*q" fill "\*q, and \*q" center \*q.
+Default:
+.RB \*q aspect \*q.
 .\" ******************** end G80 section ********************
 .
 .SH "SEE ALSO"
-__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__)
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__), xrandr(__appmansuffix__)
 .SH AUTHORS
 Authors include: David McKay, Jarno Paananen, Chas Inman, Dave Schmenk, 
 Mark Vojkovich, Aaron Plattner
diff --git a/src/g80_display.c b/src/g80_display.c
index 04ae3ec..14352aa 100644
--- a/src/g80_display.c
+++ b/src/g80_display.c
@@ -42,6 +42,7 @@ typedef struct G80CrtcPrivRec {
     Bool cursorVisible;
     Bool skipModeFixup;
     Bool dither;
+    enum G80ScaleMode scale;
 } G80CrtcPrivRec, *G80CrtcPrivPtr;
 
 static void G80CrtcShowHideCursor(xf86CrtcPtr crtc, Bool show, Bool update);
@@ -364,18 +365,11 @@ G80CrtcModeSet(xf86CrtcPtr crtc, Display
         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);
-    } else {
-        C(0x000008A4 + headOff, 0);
-    }
+    G80CrtcSetScale(crtc, adjusted_mode, pPriv->scale, FALSE);
     C(0x000008A8 + headOff, 0x40000);
     C(0x000008C0 + headOff, y << 16 | x);
     C(0x000008C8 + headOff, VDisplay << 16 | HDisplay);
     C(0x000008D4 + headOff, 0);
-    C(0x000008D8 + headOff, adjusted_mode->CrtcVDisplay << 16 | adjusted_mode->CrtcHDisplay);
-    C(0x000008DC + headOff, adjusted_mode->CrtcVDisplay << 16 | adjusted_mode->CrtcHDisplay);
 
     G80CrtcBlankScreen(crtc, FALSE);
 }
@@ -493,6 +487,60 @@ G80CrtcSetDither(xf86CrtcPtr crtc, Bool 
     if(update) C(0x00000080, 0);
 }
 
+static void ComputeAspectScale(DisplayModePtr mode, int *outX, int *outY)
+{
+    float scaleX, scaleY, scale;
+
+    scaleX = mode->CrtcHDisplay / (float)mode->HDisplay;
+    scaleY = mode->CrtcVDisplay / (float)mode->VDisplay;
+
+    if(scaleX > scaleY)
+        scale = scaleY;
+    else
+        scale = scaleX;
+
+    *outX = mode->HDisplay * scale;
+    *outY = mode->VDisplay * scale;
+}
+
+void G80CrtcSetScale(xf86CrtcPtr crtc, DisplayModePtr mode,
+                     enum G80ScaleMode scale, Bool update)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    G80CrtcPrivPtr pPriv = crtc->driver_private;
+    const int headOff = 0x400 * pPriv->head;
+    int outX, outY;
+
+    pPriv->scale = scale;
+
+    switch(scale) {
+        case G80_SCALE_ASPECT:
+            ComputeAspectScale(mode, &outX, &outY);
+            break;
+
+        case G80_SCALE_FILL:
+            outX = mode->CrtcHDisplay;
+            outY = mode->CrtcVDisplay;
+            break;
+
+        case G80_SCALE_CENTER:
+            outX = mode->HDisplay;
+            outY = mode->VDisplay;
+            break;
+    }
+
+    if((mode->Flags & V_DBLSCAN) || (mode->Flags & V_INTERLACE) ||
+       mode->HDisplay != outX || mode->VDisplay != outY) {
+        C(0x000008A4 + headOff, 9);
+    } else {
+        C(0x000008A4 + headOff, 0);
+    }
+    C(0x000008D8 + headOff, outY << 16 | outX);
+    C(0x000008DC + headOff, outY << 16 | outX);
+
+    if(update) C(0x00000080, 0);
+}
+
 static void
 G80CrtcCommit(xf86CrtcPtr crtc)
 {
@@ -552,6 +600,7 @@ G80DispCreateCrtcs(ScrnInfoPtr pScrn)
         g80_crtc = xnfcalloc(sizeof(*g80_crtc), 1);
         g80_crtc->head = head;
         g80_crtc->dither = pNv->Dither;
+        g80_crtc->scale = G80_SCALE_ASPECT;
         crtc->driver_private = g80_crtc;
     }
 }
diff --git a/src/g80_display.h b/src/g80_display.h
index 4ab1d55..8bd3bfb 100644
--- a/src/g80_display.h
+++ b/src/g80_display.h
@@ -1,3 +1,9 @@
+enum G80ScaleMode {
+    G80_SCALE_ASPECT,
+    G80_SCALE_FILL,
+    G80_SCALE_CENTER,
+};
+
 Bool G80DispPreInit(ScrnInfoPtr);
 Bool G80DispInit(ScrnInfoPtr);
 void G80DispShutdown(ScrnInfoPtr);
@@ -13,5 +19,6 @@ void G80CrtcDisableCursor(xf86CrtcPtr, B
 void G80CrtcSetCursorPosition(xf86CrtcPtr, int x, int y);
 void G80CrtcSkipModeFixup(xf86CrtcPtr);
 void G80CrtcSetDither(xf86CrtcPtr, Bool dither, Bool update);
+void G80CrtcSetScale(xf86CrtcPtr, DisplayModePtr, enum G80ScaleMode, Bool update);
 
 void G80DispCreateCrtcs(ScrnInfoPtr pScrn);
diff --git a/src/g80_sor.c b/src/g80_sor.c
index c4c640c..8ba3425 100644
--- a/src/g80_sor.c
+++ b/src/g80_sor.c
@@ -211,6 +211,7 @@ struct property {
 
 static struct {
     struct property dither;
+    struct property scale;
 } properties;
 
 static void
@@ -219,7 +220,9 @@ G80SorCreateResources(xf86OutputPtr outp
     ScrnInfoPtr pScrn = output->scrn;
     G80Ptr pNv = G80PTR(pScrn);
     int data, err;
+    const char *s;
 
+    /******** dithering ********/
     properties.dither.atom = MAKE_ATOM("dither");
     properties.dither.range[0] = 0;
     properties.dither.range[1] = 1;
@@ -240,6 +243,26 @@ G80SorCreateResources(xf86OutputPtr outp
         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                    "Failed to set dithering property for %s: error %d\n",
                    output->name, err);
+
+    /******** scaling ********/
+    properties.scale.atom = MAKE_ATOM("scale");
+    err = RRConfigureOutputProperty(output->randr_output,
+                                    properties.scale.atom, FALSE, FALSE,
+                                    FALSE, 0, NULL);
+    if(err)
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "Failed to configure scaling property for %s: error %d\n",
+                   output->name, err);
+
+    // Set the default value
+    s = "aspect";
+    err = RRChangeOutputProperty(output->randr_output, properties.scale.atom,
+                                 XA_STRING, 8, PropModeReplace, strlen(s),
+                                 (pointer)s, FALSE, FALSE);
+    if(err)
+        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                   "Failed to set scaling property for %s: error %d\n",
+                   output->name, err);
 }
 
 static Bool
@@ -256,9 +279,47 @@ G80SorSetProperty(xf86OutputPtr output, 
             return FALSE;
 
         G80CrtcSetDither(output->crtc, i, TRUE);
+        return TRUE;
+    } else if(prop == properties.scale.atom) {
+        const char *s;
+        enum G80ScaleMode scale;
+        DisplayModePtr mode;
+        int i;
+        const struct {
+            const char *name;
+            enum G80ScaleMode scale;
+        } modes[] = {
+            { "aspect", G80_SCALE_ASPECT },
+            { "fill",   G80_SCALE_FILL },
+            { "center", G80_SCALE_CENTER },
+            { NULL,     0 },
+        };
+
+        if(val->type != XA_STRING || val->format != 8)
+            return FALSE;
+        s = (char*)val->data;
+
+        for(i = 0; modes[i].name; i++) {
+            const char *name = modes[i].name;
+            const int len = strlen(name);
+
+            if(val->size == len && !strncmp(name, s, len)) {
+                scale = modes[i].scale;
+                break;
+            }
+        }
+        if(!modes[i].name)
+            return FALSE;
+
+        /* Need to construct an adjusted mode */
+        mode = xf86DuplicateMode(&output->crtc->mode);
+        output->funcs->mode_fixup(output, &output->crtc->mode, mode);
+        G80CrtcSetScale(output->crtc, mode, scale, TRUE);
+        xfree(mode);
+        return TRUE;
     }
 
-    return TRUE;
+    return FALSE;
 }
 #endif // RANDR_12_INTERFACE
 


More information about the xorg-commit mailing list