Statistics
| Branch: | Revision:

root / hw / framebuffer.c @ 34933c8c

History | View | Annotate | Download (3.5 kB)

1 714fa308 pbrook
/*
2 714fa308 pbrook
 * Framebuffer device helper routines
3 714fa308 pbrook
 *
4 714fa308 pbrook
 * Copyright (c) 2009 CodeSourcery
5 714fa308 pbrook
 * Written by Paul Brook <paul@codesourcery.com>
6 714fa308 pbrook
 *
7 714fa308 pbrook
 * This code is licensed under the GNU GPLv2.
8 714fa308 pbrook
 */
9 714fa308 pbrook
10 714fa308 pbrook
/* TODO:
11 714fa308 pbrook
   - Do something similar for framebuffers with local ram
12 714fa308 pbrook
   - Handle rotation here instead of hacking dest_pitch
13 714fa308 pbrook
   - Use common pixel conversion routines instead of per-device drawfn
14 714fa308 pbrook
   - Remove all DisplayState knowledge from devices.
15 714fa308 pbrook
 */
16 714fa308 pbrook
17 714fa308 pbrook
#include "hw.h"
18 714fa308 pbrook
#include "console.h"
19 714fa308 pbrook
#include "framebuffer.h"
20 714fa308 pbrook
21 714fa308 pbrook
/* Render an image from a shared memory framebuffer.  */
22 714fa308 pbrook
   
23 714fa308 pbrook
void framebuffer_update_display(
24 714fa308 pbrook
    DisplayState *ds,
25 c227f099 Anthony Liguori
    target_phys_addr_t base,
26 714fa308 pbrook
    int cols, /* Width in pixels.  */
27 714fa308 pbrook
    int rows, /* Leight in pixels.  */
28 714fa308 pbrook
    int src_width, /* Length of source line, in bytes.  */
29 714fa308 pbrook
    int dest_row_pitch, /* Bytes between adjacent horizontal output pixels.  */
30 714fa308 pbrook
    int dest_col_pitch, /* Bytes between adjacent vertical output pixels.  */
31 714fa308 pbrook
    int invalidate, /* nonzero to redraw the whole image.  */
32 714fa308 pbrook
    drawfn fn,
33 714fa308 pbrook
    void *opaque,
34 714fa308 pbrook
    int *first_row, /* Input and output.  */
35 714fa308 pbrook
    int *last_row /* Output only */)
36 714fa308 pbrook
{
37 c227f099 Anthony Liguori
    target_phys_addr_t src_len;
38 714fa308 pbrook
    uint8_t *dest;
39 714fa308 pbrook
    uint8_t *src;
40 714fa308 pbrook
    uint8_t *src_base;
41 714fa308 pbrook
    int first, last = 0;
42 714fa308 pbrook
    int dirty;
43 714fa308 pbrook
    int i;
44 c227f099 Anthony Liguori
    ram_addr_t addr;
45 c227f099 Anthony Liguori
    ram_addr_t pd;
46 c227f099 Anthony Liguori
    ram_addr_t pd2;
47 714fa308 pbrook
48 714fa308 pbrook
    i = *first_row;
49 714fa308 pbrook
    *first_row = -1;
50 714fa308 pbrook
    src_len = src_width * rows;
51 714fa308 pbrook
52 93102fd6 Jan Kiszka
    cpu_physical_sync_dirty_bitmap(base, base + src_len);
53 714fa308 pbrook
    pd = cpu_get_physical_page_desc(base);
54 714fa308 pbrook
    pd2 = cpu_get_physical_page_desc(base + src_len - 1);
55 714fa308 pbrook
    /* We should reall check that this is a continuous ram region.
56 714fa308 pbrook
       Instead we just check that the first and last pages are
57 714fa308 pbrook
       both ram, and the right distance apart.  */
58 714fa308 pbrook
    if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM
59 714fa308 pbrook
        || (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) {
60 714fa308 pbrook
        return;
61 714fa308 pbrook
    }
62 714fa308 pbrook
    pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK);
63 714fa308 pbrook
    if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) {
64 714fa308 pbrook
        return;
65 714fa308 pbrook
    }
66 714fa308 pbrook
67 714fa308 pbrook
    src_base = cpu_physical_memory_map(base, &src_len, 0);
68 714fa308 pbrook
    /* If we can't map the framebuffer then bail.  We could try harder,
69 714fa308 pbrook
       but it's not really worth it as dirty flag tracking will probably
70 714fa308 pbrook
       already have failed above.  */
71 714fa308 pbrook
    if (!src_base)
72 714fa308 pbrook
        return;
73 714fa308 pbrook
    if (src_len != src_width * rows) {
74 714fa308 pbrook
        cpu_physical_memory_unmap(src_base, src_len, 0, 0);
75 714fa308 pbrook
        return;
76 714fa308 pbrook
    }
77 714fa308 pbrook
    src = src_base;
78 714fa308 pbrook
    dest = ds_get_data(ds);
79 714fa308 pbrook
    if (dest_col_pitch < 0)
80 714fa308 pbrook
        dest -= dest_col_pitch * (cols - 1);
81 714fa308 pbrook
    first = -1;
82 714fa308 pbrook
    addr = pd;
83 714fa308 pbrook
84 714fa308 pbrook
    addr += i * src_width;
85 714fa308 pbrook
    src += i * src_width;
86 714fa308 pbrook
    dest += i * dest_row_pitch;
87 714fa308 pbrook
88 714fa308 pbrook
    for (; i < rows; i++) {
89 c227f099 Anthony Liguori
        target_phys_addr_t dirty_offset;
90 714fa308 pbrook
        dirty = 0;
91 714fa308 pbrook
        dirty_offset = 0;
92 714fa308 pbrook
        while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) {
93 714fa308 pbrook
            dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset,
94 714fa308 pbrook
                                                   VGA_DIRTY_FLAG);
95 714fa308 pbrook
            dirty_offset += TARGET_PAGE_SIZE;
96 714fa308 pbrook
        }
97 714fa308 pbrook
98 714fa308 pbrook
        if (dirty || invalidate) {
99 714fa308 pbrook
            fn(opaque, dest, src, cols, dest_col_pitch);
100 714fa308 pbrook
            if (first == -1)
101 714fa308 pbrook
                first = i;
102 714fa308 pbrook
            last = i;
103 714fa308 pbrook
        }
104 714fa308 pbrook
        addr += src_width;
105 714fa308 pbrook
        src += src_width;
106 714fa308 pbrook
        dest += dest_row_pitch;
107 714fa308 pbrook
    }
108 714fa308 pbrook
    cpu_physical_memory_unmap(src_base, src_len, 0, 0);
109 714fa308 pbrook
    if (first < 0) {
110 714fa308 pbrook
        return;
111 714fa308 pbrook
    }
112 714fa308 pbrook
    cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG);
113 714fa308 pbrook
    *first_row = first;
114 714fa308 pbrook
    *last_row = last;
115 714fa308 pbrook
    return;
116 714fa308 pbrook
}