Commit 714fa308 authored by Paul Brook's avatar Paul Brook
Browse files

Implement and use shared memory framebuffer device rendering reoutine.


Use DMA mapping API.

Signed-off-by: default avatarPaul Brook <paul@codesourcery.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6965 c046a42c-6fe2-441c-8c8c-71466251a162
parent 602dafcf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -672,6 +672,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
OBJS+= tsc2005.o bt-hci-csr.o
OBJS+= mst_fpga.o mainstone.o
OBJS+= musicpal.o pflash_cfi02.o
OBJS+= framebuffer.o
CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), sh4)

hw/framebuffer.c

0 → 100644
+119 −0
Original line number Diff line number Diff line
/*
 * Framebuffer device helper routines
 *
 * Copyright (c) 2009 CodeSourcery
 * Written by Paul Brook <paul@codesourcery.com>
 *
 * This code is licensed under the GNU GPLv2.
 */

/* TODO:
   - Do something similar for framebuffers with local ram
   - Handle rotation here instead of hacking dest_pitch
   - Use common pixel conversion routines instead of per-device drawfn
   - Remove all DisplayState knowledge from devices.
 */

#include "hw.h"
#include "console.h"
#include "framebuffer.h"
#include "kvm.h"

/* Render an image from a shared memory framebuffer.  */
   
void framebuffer_update_display(
    DisplayState *ds,
    target_phys_addr_t base,
    int cols, /* Width in pixels.  */
    int rows, /* Leight in pixels.  */
    int src_width, /* Length of source line, in bytes.  */
    int dest_row_pitch, /* Bytes between adjacent horizontal output pixels.  */
    int dest_col_pitch, /* Bytes between adjacent vertical output pixels.  */
    int invalidate, /* nonzero to redraw the whole image.  */
    drawfn fn,
    void *opaque,
    int *first_row, /* Input and output.  */
    int *last_row /* Output only */)
{
    target_phys_addr_t src_len;
    uint8_t *dest;
    uint8_t *src;
    uint8_t *src_base;
    int first, last = 0;
    int dirty;
    int i;
    ram_addr_t addr;
    ram_addr_t pd;
    ram_addr_t pd2;

    i = *first_row;
    *first_row = -1;
    src_len = src_width * rows;

    if (kvm_enabled()) {
        kvm_physical_sync_dirty_bitmap(base, src_len);
    }
    pd = cpu_get_physical_page_desc(base);
    pd2 = cpu_get_physical_page_desc(base + src_len - 1);
    /* We should reall check that this is a continuous ram region.
       Instead we just check that the first and last pages are
       both ram, and the right distance apart.  */
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM
        || (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
        return;
    }
    pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK);
    if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) {
        return;
    }

    src_base = cpu_physical_memory_map(base, &src_len, 0);
    /* If we can't map the framebuffer then bail.  We could try harder,
       but it's not really worth it as dirty flag tracking will probably
       already have failed above.  */
    if (!src_base)
        return;
    if (src_len != src_width * rows) {
        cpu_physical_memory_unmap(src_base, src_len, 0, 0);
        return;
    }
    src = src_base;
    dest = ds_get_data(ds);
    if (dest_col_pitch < 0)
        dest -= dest_col_pitch * (cols - 1);
    first = -1;
    addr = pd;

    addr += i * src_width;
    src += i * src_width;
    dest += i * dest_row_pitch;

    for (; i < rows; i++) {
        target_phys_addr_t dirty_offset;
        dirty = 0;
        dirty_offset = 0;
        while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
            dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset,
                                                   VGA_DIRTY_FLAG);
            dirty_offset += TARGET_PAGE_SIZE;
        }

        if (dirty || invalidate) {
            fn(opaque, dest, src, cols, dest_col_pitch);
            if (first == -1)
                first = i;
            last = i;
        }
        addr += src_width;
        src += src_width;
        dest += dest_row_pitch;
    }
    cpu_physical_memory_unmap(src_base, src_len, 0, 0);
    if (first < 0) {
        return;
    }
    cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG);
    *first_row = first;
    *last_row = last;
    return;
}

hw/framebuffer.h

0 → 100644
+22 −0
Original line number Diff line number Diff line
#ifndef QEMU_FRAMEBUFFER_H
#define QEMU_FRAMEBUFFER_H

/* Framebuffer device helper routines.  */

typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int);

void framebuffer_update_display(
    DisplayState *ds,
    target_phys_addr_t base,
    int cols,
    int rows,
    int src_width,
    int dest_row_pitch,
    int dest_col_pitch,
    int invalidate,
    drawfn fn,
    void *opaque,
    int *first_row,
    int *last_row);

#endif
+1 −1
Original line number Diff line number Diff line
@@ -490,7 +490,7 @@ struct omap_dma_lcd_channel_s {
    int dual;

    int current_frame;
    ram_addr_t phys_framebuffer[2];
    target_phys_addr_t phys_framebuffer[2];
    qemu_irq irq;
    struct omap_mpu_state_s *mpu;
} *omap_dma_get_lcdch(struct soc_dma_s *s);
+13 −10
Original line number Diff line number Diff line
@@ -43,9 +43,10 @@
/*
 * 2-bit colour
 */
static void glue(draw_line2_, DEPTH)(
                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
static void glue(draw_line2_, DEPTH)(void *opaque,
                uint8_t *d, const uint8_t *s, int width, int deststep)
{
    uint16_t *pal = opaque;
    uint8_t v, r, g, b;

    do {
@@ -81,9 +82,10 @@ static void glue(draw_line2_, DEPTH)(
/*
 * 4-bit colour
 */
static void glue(draw_line4_, DEPTH)(
                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
static void glue(draw_line4_, DEPTH)(void *opaque,
                uint8_t *d, const uint8_t *s, int width, int deststep)
{
    uint16_t *pal = opaque;
    uint8_t v, r, g, b;

    do {
@@ -107,9 +109,10 @@ static void glue(draw_line4_, DEPTH)(
/*
 * 8-bit colour
 */
static void glue(draw_line8_, DEPTH)(
                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
static void glue(draw_line8_, DEPTH)(void *opaque,
                uint8_t *d, const uint8_t *s, int width, int deststep)
{
    uint16_t *pal = opaque;
    uint8_t v, r, g, b;

    do {
@@ -126,8 +129,8 @@ static void glue(draw_line8_, DEPTH)(
/*
 * 12-bit colour
 */
static void glue(draw_line12_, DEPTH)(
                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
static void glue(draw_line12_, DEPTH)(void *opaque,
                uint8_t *d, const uint8_t *s, int width, int deststep)
{
    uint16_t v;
    uint8_t r, g, b;
@@ -146,8 +149,8 @@ static void glue(draw_line12_, DEPTH)(
/*
 * 16-bit colour
 */
static void glue(draw_line16_, DEPTH)(
                uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
static void glue(draw_line16_, DEPTH)(void *opaque,
                uint8_t *d, const uint8_t *s, int width, int deststep)
{
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
    memcpy(d, s, width * 2);
Loading