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

login
register
mail settings
Submitter Gerd Hoffmann
Date Sept. 18, 2012, 7:17 a.m.
Message ID <1347952634-12286-10-git-send-email-kraxel@redhat.com>
Download mbox | patch
Permalink /patch/184644/
State New
Headers show

Comments

Gerd Hoffmann - Sept. 18, 2012, 7:17 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(-)
Stefano Stabellini - Sept. 18, 2012, 3:02 p.m.
On Tue, 18 Sep 2012, Gerd Hoffmann wrote:
> Add support for scaling the guest display.
> Ctrl-Alt-S hotkey toggles scaling.

We could make sdl_zoom generic: sdl_zoom_blit doesn't actually depend on
sdl.


> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
>  ui/fbdev.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
>  1 files changed, 51 insertions(+), 10 deletions(-)
> 
> diff --git a/ui/fbdev.c b/ui/fbdev.c
> index 6835fef..55793ab 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;
> @@ -912,6 +924,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));
> @@ -937,16 +954,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);
> @@ -957,7 +990,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) {
> @@ -1049,6 +1089,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)
> -- 
> 1.7.1
> 
>
Gerd Hoffmann - Sept. 19, 2012, 5:52 a.m.
On 09/18/12 17:02, Stefano Stabellini wrote:
> On Tue, 18 Sep 2012, Gerd Hoffmann wrote:
>> Add support for scaling the guest display.
>> Ctrl-Alt-S hotkey toggles scaling.
> 
> We could make sdl_zoom generic: sdl_zoom_blit doesn't actually depend on
> sdl.

I'd rather go the other way around and make sdl zoom use pixman.

cheers,
  Gerd

Patch

diff --git a/ui/fbdev.c b/ui/fbdev.c
index 6835fef..55793ab 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;
@@ -912,6 +924,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));
@@ -937,16 +954,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);
@@ -957,7 +990,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) {
@@ -1049,6 +1089,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)