qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Anthony Liguori <anthony@codemonkey.ws>
To: Gerd Hoffmann <kraxel@redhat.com>, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH 7/9] fbdev: move to pixman
Date: Tue, 18 Sep 2012 14:14:53 -0500	[thread overview]
Message-ID: <87txuvqh1u.fsf@codemonkey.ws> (raw)
In-Reply-To: <1347952634-12286-8-git-send-email-kraxel@redhat.com>

Gerd Hoffmann <kraxel@redhat.com> writes:

> Stop reinventing the wheel.  Use the pixman library for raster ops.
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

Why not cairo?  I already have a cairo backend that uses GTK that
supports scaling.  That would be a good opportunity for sharing even
more code.

Regards,

Anthony Liguori

> ---
>  configure  |   12 ++++
>  ui/fbdev.c |  172 +++++++++++++++++++++++++++++++++++------------------------
>  2 files changed, 114 insertions(+), 70 deletions(-)
>
> diff --git a/configure b/configure
> index c4ba338..d10ff78 100755
> --- a/configure
> +++ b/configure
> @@ -148,6 +148,7 @@ docs=""
>  fdt=""
>  nptl=""
>  sdl=""
> +pixman=""
>  fbdev="no"
>  virtfs=""
>  vnc="yes"
> @@ -2153,6 +2154,17 @@ else
>      exit 1
>  fi
>  
> +if $pkg_config pixman-1 > /dev/null 2>&1
> +then
> +    pixman="yes"
> +    pixman_cflags=`$pkg_config --cflags pixman-1 2>/dev/null`
> +    pixman_libs=`$pkg_config --libs pixman-1 2>/dev/null`
> +    QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags"
> +    libs_softmmu="$libs_softmmu $pixman_libs"
> +else
> +    fbdev="no"
> +fi
> +
>  ##########################################
>  # libcap probe
>  
> diff --git a/ui/fbdev.c b/ui/fbdev.c
> index 40fc7d4..4cb4d1d 100644
> --- a/ui/fbdev.c
> +++ b/ui/fbdev.c
> @@ -23,11 +23,12 @@
>  #include <linux/vt.h>
>  #include <linux/fb.h>
>  
> +#include <pixman.h>
> +
>  #include "qemu-common.h"
>  #include "console.h"
>  #include "keymaps.h"
>  #include "sysemu.h"
> -#include "pflib.h"
>  
>  /*
>   * must be last so we get the linux input layer
> @@ -70,19 +71,82 @@ static bool                       key_down[KEY_CNT];
>  #define FB_ACQ_REQ   3
>  static int fb_switch_state;
>  
> -/* qdev windup */
> +/* qemu windup */
>  static DisplayChangeListener      *dcl;
> -static QemuPfConv                 *conv;
> -static PixelFormat                fbpf;
>  static int                        resize_screen;
>  static int                        redraw_screen;
>  static int                        cx, cy, cw, ch;
>  static Notifier                   exit_notifier;
> +static pixman_image_t             *surface;
> +static pixman_image_t             *framebuffer;
> +static pixman_transform_t         transform;
> +static pixman_region16_t          dirty;
>  
>  /* fwd decls */
>  static int fbdev_activate_vt(int tty, int vtno, bool wait);
>  
>  /* -------------------------------------------------------------------- */
> +/* pixman helpers                                                       */
> +
> +static int pixman_shifts_to_type(int rshift, int gshift, int bshift)
> +{
> +    int type = PIXMAN_TYPE_OTHER;
> +
> +    if (rshift > gshift && gshift > bshift) {
> +        if (bshift == 0) {
> +            type = PIXMAN_TYPE_ARGB;
> +        } else {
> +#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0, 21, 8)
> +            type = PIXMAN_TYPE_RGBA;
> +#endif
> +        }
> +    } else if (rshift < gshift && gshift < bshift) {
> +        if (rshift == 0) {
> +            type = PIXMAN_TYPE_ABGR;
> +        } else {
> +            type = PIXMAN_TYPE_BGRA;
> +        }
> +    }
> +    return type;
> +}
> +
> +static pixman_image_t *pixman_from_displaystate(DisplayState *ds)
> +{
> +    PixelFormat *pf = &ds->surface->pf;
> +    pixman_format_code_t format;
> +    pixman_image_t *image;
> +    int type;
> +
> +    type = pixman_shifts_to_type(pf->rshift, pf->gshift, pf->bshift);
> +    format = PIXMAN_FORMAT(pf->bits_per_pixel, type,
> +                           pf->abits, pf->rbits, pf->gbits, pf->bbits);
> +    image = pixman_image_create_bits(format, ds_get_width(ds),
> +                                     ds_get_height(ds),
> +                                     (void *)ds_get_data(ds),
> +                                     ds_get_linesize(ds));
> +    return image;
> +}
> +
> +static pixman_image_t *pixman_from_framebuffer(void)
> +{
> +    pixman_format_code_t format;
> +    pixman_image_t *image;
> +    int type;
> +
> +    type = pixman_shifts_to_type(fb_var.red.offset,
> +                                 fb_var.green.offset,
> +                                 fb_var.blue.offset);
> +    format = PIXMAN_FORMAT(fb_var.bits_per_pixel, type,
> +                           fb_var.transp.length,
> +                           fb_var.red.length,
> +                           fb_var.green.length,
> +                           fb_var.blue.length);
> +    image = pixman_image_create_bits(format, fb_var.xres, fb_var.yres,
> +                                     (void *)fb_mem, fb_fix.line_length);
> +    return image;
> +}
> +
> +/* -------------------------------------------------------------------- */
>  /* mouse                                                                */
>  
>  static void read_mouse(void *opaque)
> @@ -529,6 +593,17 @@ static void fbdev_cleanup(void)
>  {
>      trace_fbdev_cleanup();
>  
> +    /* release pixman stuff */
> +    pixman_region_fini(&dirty);
> +    if (framebuffer) {
> +        pixman_image_unref(framebuffer);
> +        framebuffer = NULL;
> +    }
> +    if (surface) {
> +        pixman_image_unref(surface);
> +        surface = NULL;
> +    }
> +
>      /* restore console */
>      if (fb_mem != NULL) {
>          munmap(fb_mem, fb_fix.smem_len+fb_mem_offset);
> @@ -681,36 +756,8 @@ static int fbdev_init(const char *device)
>      start_mediumraw(tty);
>      qemu_set_fd_handler(tty, read_mediumraw, NULL, NULL);
>  
> -    /* create PixelFormat from fbdev structs */
> -    fbpf.bits_per_pixel  = fb_var.bits_per_pixel;
> -    fbpf.bytes_per_pixel = (fb_var.bits_per_pixel+7)/8;
> -    fbpf.depth           = fb_var.bits_per_pixel == 32
> -        ? 24 : fb_var.bits_per_pixel;
> -    fbpf.rshift          = fb_var.red.offset;
> -    fbpf.rbits           = fb_var.red.length;
> -    fbpf.gshift          = fb_var.green.offset;
> -    fbpf.gbits           = fb_var.green.length;
> -    fbpf.bshift          = fb_var.blue.offset;
> -    fbpf.bbits           = fb_var.blue.length;
> -    fbpf.ashift          = fb_var.transp.offset;
> -    fbpf.abits           = fb_var.transp.length;
> -
> -    if (fbpf.rbits) {
> -        fbpf.rmax   = (1 << fbpf.rbits) - 1;
> -        fbpf.rmask  = fbpf.rmax << fbpf.rshift;
> -    }
> -    if (fbpf.gbits) {
> -        fbpf.gmax   = (1 << fbpf.gbits) - 1;
> -        fbpf.gmask  = fbpf.gmax << fbpf.gshift;
> -    }
> -    if (fbpf.bbits) {
> -        fbpf.bmax   = (1 << fbpf.bbits) - 1;
> -        fbpf.bmask  = fbpf.bmax << fbpf.bshift;
> -    }
> -    if (fbpf.abits) {
> -        fbpf.amax   = (1 << fbpf.abits) - 1;
> -        fbpf.amask  = fbpf.amax << fbpf.ashift;
> -    }
> +    framebuffer = pixman_from_framebuffer();
> +    pixman_region_init(&dirty);
>      return 0;
>  
>  err_early:
> @@ -818,36 +865,15 @@ static int fbdev_switch_init(void)
>  /* -------------------------------------------------------------------- */
>  /* rendering                                                            */
>  
> -static void fbdev_render(DisplayState *ds, int x, int y, int w, int h)
> +static void fbdev_render(DisplayState *ds)
>  {
> -    uint8_t *dst;
> -    uint8_t *src;
> -    int line;
> -
> -    if (!conv) {
> -        return;
> -    }
> -
> -    src = ds_get_data(ds) + y * ds_get_linesize(ds)
> -        + x * ds_get_bytes_per_pixel(ds);
> -    dst = fb_mem + y * fb_fix.line_length
> -        + x * fbpf.bytes_per_pixel;
> -
> -    dst += cy * fb_fix.line_length;
> -    dst += cx * fbpf.bytes_per_pixel;
> +    assert(surface);
>  
> -    if (h > fb_var.yres - y) {
> -        h = fb_var.yres - y;
> -    }
> -    if (w > fb_var.xres - x) {
> -        w = fb_var.xres - x;
> -    }
> -
> -    for (line = y; line < y+h; line++) {
> -        qemu_pf_conv_run(conv, dst, src, w);
> -        dst += fb_fix.line_length;
> -        src += ds_get_linesize(ds);
> -    }
> +    pixman_image_set_clip_region(surface, &dirty);
> +    pixman_image_composite(PIXMAN_OP_SRC, surface, NULL, framebuffer,
> +                           0, 0, 0, 0, 0, 0, fb_var.xres, fb_var.yres);
> +    pixman_region_fini(&dirty);
> +    pixman_region_init(&dirty);
>  }
>  
>  /* -------------------------------------------------------------------- */
> @@ -871,14 +897,16 @@ static void fbdev_update(DisplayState *ds, int x, int y, int w, int h)
>          if (ds_get_height(ds) < fb_var.yres) {
>              cy = (fb_var.yres - ds_get_height(ds)) / 2;
>          }
> -
> -        if (conv) {
> -            qemu_pf_conv_put(conv);
> -        }
> -        conv = qemu_pf_conv_get(&fbpf, &ds->surface->pf);
> -        if (conv == NULL) {
> -            fprintf(stderr, "fbdev: unsupported PixelFormat conversion\n");
> +        if (surface) {
> +            pixman_image_unref(surface);
>          }
> +        surface = pixman_from_displaystate(ds);
> +
> +        pixman_transform_init_identity(&transform);
> +        pixman_transform_translate(&transform, NULL,
> +                                   pixman_int_to_fixed(-cx),
> +                                   pixman_int_to_fixed(-cy));
> +        pixman_image_set_transform(surface, &transform);
>      }
>  
>      if (redraw_screen) {
> @@ -888,7 +916,7 @@ static void fbdev_update(DisplayState *ds, int x, int y, int w, int h)
>          x = 0; y = 0; w = ds_get_width(ds); h = ds_get_height(ds);
>      }
>  
> -    fbdev_render(ds, x, y, w, h);
> +    pixman_region_union_rect(&dirty, &dirty, x, y, w, h);
>  }
>  
>  static void fbdev_resize(DisplayState *ds)
> @@ -924,6 +952,10 @@ static void fbdev_refresh(DisplayState *ds)
>      if (redraw_screen) {
>          fbdev_update(ds, 0, 0, 0, 0);
>      }
> +
> +    if (pixman_region_not_empty(&dirty)) {
> +        fbdev_render(ds);
> +    }
>  }
>  
>  static void fbdev_exit_notifier(Notifier *notifier, void *data)
> -- 
> 1.7.1

  parent reply	other threads:[~2012-09-18 19:15 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-18  7:17 [Qemu-devel] [PULL 0/9] linux framebuffer display driver Gerd Hoffmann
2012-09-18  7:17 ` [Qemu-devel] [PATCH 1/9] QLIST-ify display change listeners Gerd Hoffmann
2012-09-18  7:17 ` [Qemu-devel] [PATCH 2/9] add unregister_displaychangelistener Gerd Hoffmann
2012-09-18 10:54   ` Stefano Stabellini
2012-09-18  7:17 ` [Qemu-devel] [PATCH 3/9] move set_mouse + cursor_define callbacks Gerd Hoffmann
2012-09-18 14:10   ` Stefano Stabellini
2012-09-18 16:31     ` Gerd Hoffmann
2012-09-18 16:44       ` Stefano Stabellini
2012-09-18  7:17 ` [Qemu-devel] [PATCH 4/9] fbdev: add linux framebuffer display driver Gerd Hoffmann
2012-09-18 15:01   ` Stefano Stabellini
2012-09-19  5:19     ` Gerd Hoffmann
2012-09-19 18:37   ` Blue Swirl
2012-09-18  7:17 ` [Qemu-devel] [PATCH 5/9] fbdev: add monitor command to enable/disable Gerd Hoffmann
2012-09-18 12:47   ` Luiz Capitulino
2012-09-18  7:17 ` [Qemu-devel] [PATCH 6/9] fbdev: make configurable at compile time Gerd Hoffmann
2012-09-18  7:17 ` [Qemu-devel] [PATCH 7/9] fbdev: move to pixman Gerd Hoffmann
2012-09-18 15:01   ` Stefano Stabellini
2012-09-19  5:51     ` Gerd Hoffmann
2012-09-18 19:14   ` Anthony Liguori [this message]
2012-09-18 21:08     ` Anthony Liguori
2012-11-26 18:42     ` Alexander Graf
2012-11-26 20:01       ` Gerd Hoffmann
2012-11-26 20:05         ` Alexander Graf
2012-09-18 20:30   ` Søren Sandmann
2012-09-19  5:56     ` Gerd Hoffmann
2012-09-18  7:17 ` [Qemu-devel] [PATCH 8/9] fbdev: add mouse pointer support Gerd Hoffmann
2012-09-18  7:17 ` [Qemu-devel] [PATCH 9/9] fbdev: add display scaling support Gerd Hoffmann
2012-09-18 15:02   ` Stefano Stabellini
2012-09-19  5:52     ` Gerd Hoffmann
  -- strict thread matches above, loose matches on Subject: below --
2012-09-19 11:15 [Qemu-devel] [PATCH v4 0/9] linux framebuffer display driver Gerd Hoffmann
2012-09-19 11:15 ` [Qemu-devel] [PATCH 7/9] fbdev: move to pixman Gerd Hoffmann
2012-09-19 18:10   ` Stefano Stabellini
2012-09-20  6:16     ` Gerd Hoffmann
2012-09-20 11:33       ` Stefano Stabellini
2012-09-20 13:51         ` Gerd Hoffmann
2012-09-20 15:20           ` Stefano Stabellini
2012-09-20 15:27             ` Gerd Hoffmann
2012-09-20 15:28               ` Stefano Stabellini
2012-09-20 15:33                 ` Stefano Stabellini
2012-09-21  5:40                   ` Gerd Hoffmann
2012-09-21 10:48                     ` Stefano Stabellini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87txuvqh1u.fsf@codemonkey.ws \
    --to=anthony@codemonkey.ws \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).