Anthony Liguori <anth...@codemonkey.ws> writes:

> Gerd Hoffmann <kra...@redhat.com> writes:
>
>> Stop reinventing the wheel.  Use the pixman library for raster ops.
>>
>> Signed-off-by: Gerd Hoffmann <kra...@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.

Nevermind, I see that cairo uses pixman under the covers...

Regards,

Anthony Liguori

>
> 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

Reply via email to