Patchwork [v2,9/9] fbdev: add display scaling support

login
register
mail settings
Submitter Gerd Hoffmann
Date Sept. 13, 2012, 9:19 a.m.
Message ID <1347527989-3986-10-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/183580/
State New
Headers show

Comments

Gerd Hoffmann - Sept. 13, 2012, 9:19 a.m.
Add support for scaling the guest display.
Ctrl-Alt-S hotkey toggles scaling.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/fbdev.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 51 insertions(+), 10 deletions(-)

Patch

diff --git a/ui/fbdev.c b/ui/fbdev.c
index 5e700e8..e586f2d 100644
--- a/ui/fbdev.c
+++ b/ui/fbdev.c
@@ -81,6 +81,7 @@  static pixman_image_t             *surface;
 static pixman_image_t             *framebuffer;
 static pixman_transform_t         transform;
 static pixman_region16_t          dirty;
+static double                     scale;
 
 static QEMUCursor                 *ptr_cursor;
 static pixman_image_t             *ptr_image;
@@ -88,6 +89,10 @@  static int                        ptr_refresh;
 static int                        px, py, pw, ph;
 static int                        mx, my, mon;
 
+/* options */
+static int                        use_scale = 1;
+static pixman_filter_t            pfilter = PIXMAN_FILTER_GOOD;
+
 /* fwd decls */
 static int fbdev_activate_vt(int tty, int vtno, bool wait);
 
@@ -182,13 +187,14 @@  static void read_mouse(void *opaque)
         if (ay < 0) {
             ay = 0;
         }
-        if (ax >= cw) {
-            ax = cw-1;
+        if (ax >= cw*scale) {
+            ax = cw*scale-1;
         }
-        if (ay >= ch) {
-            ay = ch-1;
+        if (ay >= ch*scale) {
+            ay = ch*scale-1;
         }
-        kbd_mouse_event(ax * 0x7FFF / cw, ay * 0x7FFF / ch, 0, b);
+        kbd_mouse_event(ax * 0x7FFF / (cw*scale),
+                        ay * 0x7FFF / (ch*scale), 0, b);
     } else {
         kbd_mouse_event(x, y, 0, b);
     }
@@ -543,6 +549,12 @@  static void read_mediumraw(void *opaque)
                             "(ctrl-alt-esc) ===\n");
                     exit(1);
                 }
+                if (keycode == KEY_S) {
+                    use_scale = !use_scale;
+                    resize_screen++;
+                    redraw_screen++;
+                    continue;
+                }
                 if (keycode >= KEY_F1 && keycode <= KEY_F10) {
                     fbdev_activate_vt(tty, keycode+1-KEY_F1, false);
                     key_down[keycode] = false;
@@ -901,6 +913,11 @@  static void fbdev_render_ptr(DisplayState *ds)
     pixman_transform_translate(&transform, NULL,
                                pixman_int_to_fixed(-cx),
                                pixman_int_to_fixed(-cy));
+    if (use_scale) {
+        pixman_transform_scale(&transform, NULL,
+                               pixman_double_to_fixed(1/scale),
+                               pixman_double_to_fixed(1/scale));
+    }
     pixman_transform_translate(&transform, NULL,
                                pixman_int_to_fixed(-px),
                                pixman_int_to_fixed(-py));
@@ -926,16 +943,32 @@  static void fbdev_update(DisplayState *ds, int x, int y, int w, int h)
     }
 
     if (resize_screen) {
+        double xs, ys;
+
         trace_fbdev_dpy_resize(ds_get_width(ds), ds_get_height(ds));
         resize_screen = 0;
         cx = 0; cy = 0;
         cw = ds_get_width(ds);
         ch = ds_get_height(ds);
-        if (ds_get_width(ds) < fb_var.xres) {
-            cx = (fb_var.xres - ds_get_width(ds)) / 2;
-        }
-        if (ds_get_height(ds) < fb_var.yres) {
-            cy = (fb_var.yres - ds_get_height(ds)) / 2;
+
+        if (use_scale) {
+            xs = (double)fb_var.xres / cw;
+            ys = (double)fb_var.yres / ch;
+            if (xs > ys) {
+                scale = ys;
+                cx = (fb_var.xres - ds_get_width(ds)*scale) / 2;
+            } else {
+                scale = xs;
+                cy = (fb_var.yres - ds_get_height(ds)*scale) / 2;
+            }
+        } else {
+            scale = 1;
+            if (ds_get_width(ds) < fb_var.xres) {
+                cx = (fb_var.xres - ds_get_width(ds)) / 2;
+            }
+            if (ds_get_height(ds) < fb_var.yres) {
+                cy = (fb_var.yres - ds_get_height(ds)) / 2;
+            }
         }
         if (surface) {
             pixman_image_unref(surface);
@@ -946,7 +979,14 @@  static void fbdev_update(DisplayState *ds, int x, int y, int w, int h)
         pixman_transform_translate(&transform, NULL,
                                    pixman_int_to_fixed(-cx),
                                    pixman_int_to_fixed(-cy));
+        if (use_scale) {
+            pixman_transform_scale(&transform, NULL,
+                                   pixman_double_to_fixed(1/scale),
+                                   pixman_double_to_fixed(1/scale));
+        }
         pixman_image_set_transform(surface, &transform);
+
+        pixman_image_set_filter(surface, pfilter, NULL, 0);
     }
 
     if (redraw_screen) {
@@ -1029,6 +1069,7 @@  static void fbdev_cursor_define(DisplayState *ds, QEMUCursor *cursor)
                                          cursor->width, cursor->height,
                                          cursor->data,
                                          cursor->width * 4);
+    pixman_image_set_filter(ptr_image, pfilter, NULL, 0);
 }
 
 static void fbdev_exit_notifier(Notifier *notifier, void *data)