aboutsummaryrefslogtreecommitdiff
path: root/hw/display/next-fb.c
diff options
context:
space:
mode:
authorThomas Huth <huth@tuxfamily.org>2018-06-30 07:19:42 +0200
committerThomas Huth <huth@tuxfamily.org>2019-09-07 08:30:34 +0200
commite3355a0ca2d82acc1d65e370284b503e178fa41a (patch)
tree65f3a153cce8dea5c12c31c901e10c87ef3f5fc3 /hw/display/next-fb.c
parent90b1e3afd33226b6078fec6d77a18373712a975c (diff)
m68k: Add NeXTcube framebuffer device emulation
The NeXTcube uses a linear framebuffer with 4 greyscale colors and a fixed resolution of 1120 * 832. This code has been taken from Bryce Lanham's GSoC 2011 NeXT branch at https://github.com/blanham/qemu-NeXT/blob/next-cube/hw/next-fb.c and altered to fit the latest interface of the current QEMU (e.g. the device has been "qdev"-ified etc.). Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20190831074519.32613-2-huth@tuxfamily.org> Signed-off-by: Thomas Huth <huth@tuxfamily.org>
Diffstat (limited to 'hw/display/next-fb.c')
-rw-r--r--hw/display/next-fb.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/hw/display/next-fb.c b/hw/display/next-fb.c
new file mode 100644
index 0000000000..2b726a10f8
--- /dev/null
+++ b/hw/display/next-fb.c
@@ -0,0 +1,146 @@
+/*
+ * NeXT Cube/Station Framebuffer Emulation
+ *
+ * Copyright (c) 2011 Bryce Lanham
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "ui/console.h"
+#include "hw/hw.h"
+#include "hw/boards.h"
+#include "hw/loader.h"
+#include "hw/display/framebuffer.h"
+#include "ui/pixel_ops.h"
+#include "hw/m68k/next-cube.h"
+
+#define NEXTFB(obj) OBJECT_CHECK(NeXTFbState, (obj), TYPE_NEXTFB)
+
+struct NeXTFbState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion fb_mr;
+ MemoryRegionSection fbsection;
+ QemuConsole *con;
+
+ uint32_t cols;
+ uint32_t rows;
+ int invalidate;
+};
+typedef struct NeXTFbState NeXTFbState;
+
+static void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s,
+ int width, int pitch)
+{
+ NeXTFbState *nfbstate = NEXTFB(opaque);
+ static const uint32_t pal[4] = {
+ 0xFFFFFFFF, 0xFFAAAAAA, 0xFF555555, 0xFF000000
+ };
+ uint32_t *buf = (uint32_t *)d;
+ int i = 0;
+
+ for (i = 0; i < nfbstate->cols / 4; i++) {
+ int j = i * 4;
+ uint8_t src = s[i];
+ buf[j + 3] = pal[src & 0x3];
+ src >>= 2;
+ buf[j + 2] = pal[src & 0x3];
+ src >>= 2;
+ buf[j + 1] = pal[src & 0x3];
+ src >>= 2;
+ buf[j + 0] = pal[src & 0x3];
+ }
+}
+
+static void nextfb_update(void *opaque)
+{
+ NeXTFbState *s = NEXTFB(opaque);
+ int dest_width = 4;
+ int src_width;
+ int first = 0;
+ int last = 0;
+ DisplaySurface *surface = qemu_console_surface(s->con);
+
+ src_width = s->cols / 4 + 8;
+ dest_width = s->cols * 4;
+
+ if (s->invalidate) {
+ framebuffer_update_memory_section(&s->fbsection, &s->fb_mr, 0,
+ s->cols, src_width);
+ s->invalidate = 0;
+ }
+
+ framebuffer_update_display(surface, &s->fbsection, s->cols, s->rows,
+ src_width, dest_width, 0, 1, nextfb_draw_line,
+ s, &first, &last);
+
+ dpy_gfx_update(s->con, 0, 0, s->cols, s->rows);
+}
+
+static void nextfb_invalidate(void *opaque)
+{
+ NeXTFbState *s = NEXTFB(opaque);
+ s->invalidate = 1;
+}
+
+static const GraphicHwOps nextfb_ops = {
+ .invalidate = nextfb_invalidate,
+ .gfx_update = nextfb_update,
+};
+
+static void nextfb_realize(DeviceState *dev, Error **errp)
+{
+ NeXTFbState *s = NEXTFB(dev);
+
+ memory_region_init_ram(&s->fb_mr, OBJECT(dev), "next-video", 0x1CB100,
+ &error_fatal);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->fb_mr);
+
+ s->invalidate = 1;
+ s->cols = 1120;
+ s->rows = 832;
+
+ s->con = graphic_console_init(dev, 0, &nextfb_ops, s);
+ qemu_console_resize(s->con, s->cols, s->rows);
+}
+
+static void nextfb_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
+ dc->realize = nextfb_realize;
+
+ /* Note: This device does not any state that we have to reset or migrate */
+}
+
+static const TypeInfo nextfb_info = {
+ .name = TYPE_NEXTFB,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(NeXTFbState),
+ .class_init = nextfb_class_init,
+};
+
+static void nextfb_register_types(void)
+{
+ type_register_static(&nextfb_info);
+}
+
+type_init(nextfb_register_types)