qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 7/9] fbdev: move to pixman
Date: Tue, 18 Sep 2012 09:17:12 +0200	[thread overview]
Message-ID: <1347952634-12286-8-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1347952634-12286-1-git-send-email-kraxel@redhat.com>

Stop reinventing the wheel.  Use the pixman library for raster ops.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 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  7:17 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 ` Gerd Hoffmann [this message]
2012-09-18 15:01   ` [Qemu-devel] [PATCH 7/9] fbdev: move to pixman Stefano Stabellini
2012-09-19  5:51     ` Gerd Hoffmann
2012-09-18 19:14   ` Anthony Liguori
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=1347952634-12286-8-git-send-email-kraxel@redhat.com \
    --to=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).