From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Eduardo Habkost <ehabkost@redhat.com>,
Marcel Apfelbaum <marcel.apfelbaum@gmail.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
qemu-arm@nongnu.org, Richard Henderson <rth@twiddle.net>,
Peter Maydell <peter.maydell@linaro.org>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PULL 2/4] hw/display: add ramfb, a simple boot framebuffer living in guest ram
Date: Mon, 18 Jun 2018 11:57:56 +0200 [thread overview]
Message-ID: <20180618095758.5006-3-kraxel@redhat.com> (raw)
In-Reply-To: <20180618095758.5006-1-kraxel@redhat.com>
The boot framebuffer is expected to be configured by the firmware, so it
uses fw_cfg as interface. Initialization goes as follows:
(1) Check whenever etc/ramfb is present.
(2) Allocate framebuffer from RAM.
(3) Fill struct RAMFBCfg, write it to etc/ramfb.
Done. You can write stuff to the framebuffer now, and it should appear
automagically on the screen.
Note that this isn't very efficient because it does a full display
update on each refresh. No dirty tracking. Dirty tracking would have
to be active for the whole ram slot, so that wouldn't be very efficient
either. For a boot display which is active for a short time only this
isn't a big deal. As permanent guest display something better should be
used (if possible).
This is the ramfb core code. Some windup is needed for display devices
which want have a ramfb boot display.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 20180613122948.18149-2-kraxel@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
include/hw/display/ramfb.h | 9 +++++
hw/display/ramfb.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++
hw/display/Makefile.objs | 2 +
3 files changed, 106 insertions(+)
create mode 100644 include/hw/display/ramfb.h
create mode 100644 hw/display/ramfb.c
diff --git a/include/hw/display/ramfb.h b/include/hw/display/ramfb.h
new file mode 100644
index 0000000000..a3d4c79942
--- /dev/null
+++ b/include/hw/display/ramfb.h
@@ -0,0 +1,9 @@
+#ifndef RAMFB_H
+#define RAMFB_H
+
+/* ramfb.c */
+typedef struct RAMFBState RAMFBState;
+void ramfb_display_update(QemuConsole *con, RAMFBState *s);
+RAMFBState *ramfb_setup(Error **errp);
+
+#endif /* RAMFB_H */
diff --git a/hw/display/ramfb.c b/hw/display/ramfb.c
new file mode 100644
index 0000000000..6867bce8ae
--- /dev/null
+++ b/hw/display/ramfb.c
@@ -0,0 +1,95 @@
+/*
+ * early boot framebuffer in guest ram
+ * configured using fw_cfg
+ *
+ * Copyright Red Hat, Inc. 2017
+ *
+ * Author:
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/loader.h"
+#include "hw/display/ramfb.h"
+#include "ui/console.h"
+#include "sysemu/sysemu.h"
+
+struct QEMU_PACKED RAMFBCfg {
+ uint64_t addr;
+ uint32_t fourcc;
+ uint32_t flags;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+};
+
+struct RAMFBState {
+ DisplaySurface *ds;
+ uint32_t width, height;
+ struct RAMFBCfg cfg;
+};
+
+static void ramfb_fw_cfg_write(void *dev, off_t offset, size_t len)
+{
+ RAMFBState *s = dev;
+ void *framebuffer;
+ uint32_t stride, fourcc, format;
+ hwaddr addr, length;
+
+ s->width = be32_to_cpu(s->cfg.width);
+ s->height = be32_to_cpu(s->cfg.height);
+ stride = be32_to_cpu(s->cfg.stride);
+ fourcc = be32_to_cpu(s->cfg.fourcc);
+ addr = be64_to_cpu(s->cfg.addr);
+ length = stride * s->height;
+ format = qemu_drm_format_to_pixman(fourcc);
+
+ fprintf(stderr, "%s: %dx%d @ 0x%" PRIx64 "\n", __func__,
+ s->width, s->height, addr);
+ framebuffer = address_space_map(&address_space_memory,
+ addr, &length, false,
+ MEMTXATTRS_UNSPECIFIED);
+ if (!framebuffer || length < stride * s->height) {
+ s->width = 0;
+ s->height = 0;
+ return;
+ }
+ s->ds = qemu_create_displaysurface_from(s->width, s->height,
+ format, stride, framebuffer);
+}
+
+void ramfb_display_update(QemuConsole *con, RAMFBState *s)
+{
+ if (!s->width || !s->height) {
+ return;
+ }
+
+ if (s->ds) {
+ dpy_gfx_replace_surface(con, s->ds);
+ s->ds = NULL;
+ }
+
+ /* simple full screen update */
+ dpy_gfx_update_full(con);
+}
+
+RAMFBState *ramfb_setup(Error **errp)
+{
+ FWCfgState *fw_cfg = fw_cfg_find();
+ RAMFBState *s;
+
+ if (!fw_cfg || !fw_cfg->dma_enabled) {
+ error_setg(errp, "ramfb device requires fw_cfg with DMA");
+ return NULL;
+ }
+
+ s = g_new0(RAMFBState, 1);
+
+ fw_cfg_add_file_callback(fw_cfg, "etc/ramfb",
+ NULL, ramfb_fw_cfg_write, s,
+ &s->cfg, sizeof(s->cfg), false);
+ return s;
+}
diff --git a/hw/display/Makefile.objs b/hw/display/Makefile.objs
index b5d97ab26d..0af04985d2 100644
--- a/hw/display/Makefile.objs
+++ b/hw/display/Makefile.objs
@@ -1,3 +1,5 @@
+common-obj-y += ramfb.o
+
common-obj-$(CONFIG_ADS7846) += ads7846.o
common-obj-$(CONFIG_VGA_CIRRUS) += cirrus_vga.o
common-obj-$(CONFIG_G364FB) += g364fb.o
--
2.9.3
next prev parent reply other threads:[~2018-06-18 9:58 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-18 9:57 [Qemu-devel] [PULL 0/4] Vga 20180618 patches Gerd Hoffmann
2018-06-18 9:57 ` [Qemu-devel] [PULL 1/4] configure: print virglrenderer version Gerd Hoffmann
2018-06-18 9:57 ` Gerd Hoffmann [this message]
2018-06-18 9:57 ` [Qemu-devel] [PULL 3/4] hw/display: add standalone ramfb device Gerd Hoffmann
2018-06-18 9:57 ` [Qemu-devel] [PULL 4/4] Add ramfb MAINTAINERS entry Gerd Hoffmann
2018-06-19 13:33 ` [Qemu-devel] [PULL 0/4] Vga 20180618 patches Peter Maydell
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=20180618095758.5006-3-kraxel@redhat.com \
--to=kraxel@redhat.com \
--cc=ehabkost@redhat.com \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/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).