~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/framebuffer.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

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