Revision 714fa308
b/Makefile.target | ||
---|---|---|
672 | 672 |
OBJS+= tsc2005.o bt-hci-csr.o |
673 | 673 |
OBJS+= mst_fpga.o mainstone.o |
674 | 674 |
OBJS+= musicpal.o pflash_cfi02.o |
675 |
OBJS+= framebuffer.o |
|
675 | 676 |
CPPFLAGS += -DHAS_AUDIO |
676 | 677 |
endif |
677 | 678 |
ifeq ($(TARGET_BASE_ARCH), sh4) |
b/hw/framebuffer.c | ||
---|---|---|
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 |
#include "kvm.h" |
|
21 |
|
|
22 |
/* Render an image from a shared memory framebuffer. */ |
|
23 |
|
|
24 |
void framebuffer_update_display( |
|
25 |
DisplayState *ds, |
|
26 |
target_phys_addr_t base, |
|
27 |
int cols, /* Width in pixels. */ |
|
28 |
int rows, /* Leight in pixels. */ |
|
29 |
int src_width, /* Length of source line, in bytes. */ |
|
30 |
int dest_row_pitch, /* Bytes between adjacent horizontal output pixels. */ |
|
31 |
int dest_col_pitch, /* Bytes between adjacent vertical output pixels. */ |
|
32 |
int invalidate, /* nonzero to redraw the whole image. */ |
|
33 |
drawfn fn, |
|
34 |
void *opaque, |
|
35 |
int *first_row, /* Input and output. */ |
|
36 |
int *last_row /* Output only */) |
|
37 |
{ |
|
38 |
target_phys_addr_t src_len; |
|
39 |
uint8_t *dest; |
|
40 |
uint8_t *src; |
|
41 |
uint8_t *src_base; |
|
42 |
int first, last = 0; |
|
43 |
int dirty; |
|
44 |
int i; |
|
45 |
ram_addr_t addr; |
|
46 |
ram_addr_t pd; |
|
47 |
ram_addr_t pd2; |
|
48 |
|
|
49 |
i = *first_row; |
|
50 |
*first_row = -1; |
|
51 |
src_len = src_width * rows; |
|
52 |
|
|
53 |
if (kvm_enabled()) { |
|
54 |
kvm_physical_sync_dirty_bitmap(base, src_len); |
|
55 |
} |
|
56 |
pd = cpu_get_physical_page_desc(base); |
|
57 |
pd2 = cpu_get_physical_page_desc(base + src_len - 1); |
|
58 |
/* We should reall check that this is a continuous ram region. |
|
59 |
Instead we just check that the first and last pages are |
|
60 |
both ram, and the right distance apart. */ |
|
61 |
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM |
|
62 |
|| (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { |
|
63 |
return; |
|
64 |
} |
|
65 |
pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK); |
|
66 |
if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) { |
|
67 |
return; |
|
68 |
} |
|
69 |
|
|
70 |
src_base = cpu_physical_memory_map(base, &src_len, 0); |
|
71 |
/* If we can't map the framebuffer then bail. We could try harder, |
|
72 |
but it's not really worth it as dirty flag tracking will probably |
|
73 |
already have failed above. */ |
|
74 |
if (!src_base) |
|
75 |
return; |
|
76 |
if (src_len != src_width * rows) { |
|
77 |
cpu_physical_memory_unmap(src_base, src_len, 0, 0); |
|
78 |
return; |
|
79 |
} |
|
80 |
src = src_base; |
|
81 |
dest = ds_get_data(ds); |
|
82 |
if (dest_col_pitch < 0) |
|
83 |
dest -= dest_col_pitch * (cols - 1); |
|
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 |
} |
b/hw/framebuffer.h | ||
---|---|---|
1 |
#ifndef QEMU_FRAMEBUFFER_H |
|
2 |
#define QEMU_FRAMEBUFFER_H |
|
3 |
|
|
4 |
/* Framebuffer device helper routines. */ |
|
5 |
|
|
6 |
typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); |
|
7 |
|
|
8 |
void framebuffer_update_display( |
|
9 |
DisplayState *ds, |
|
10 |
target_phys_addr_t base, |
|
11 |
int cols, |
|
12 |
int rows, |
|
13 |
int src_width, |
|
14 |
int dest_row_pitch, |
|
15 |
int dest_col_pitch, |
|
16 |
int invalidate, |
|
17 |
drawfn fn, |
|
18 |
void *opaque, |
|
19 |
int *first_row, |
|
20 |
int *last_row); |
|
21 |
|
|
22 |
#endif |
b/hw/omap.h | ||
---|---|---|
490 | 490 |
int dual; |
491 | 491 |
|
492 | 492 |
int current_frame; |
493 |
ram_addr_t phys_framebuffer[2];
|
|
493 |
target_phys_addr_t phys_framebuffer[2];
|
|
494 | 494 |
qemu_irq irq; |
495 | 495 |
struct omap_mpu_state_s *mpu; |
496 | 496 |
} *omap_dma_get_lcdch(struct soc_dma_s *s); |
b/hw/omap_lcd_template.h | ||
---|---|---|
43 | 43 |
/* |
44 | 44 |
* 2-bit colour |
45 | 45 |
*/ |
46 |
static void glue(draw_line2_, DEPTH)( |
|
47 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
|
|
46 |
static void glue(draw_line2_, DEPTH)(void *opaque,
|
|
47 |
uint8_t *d, const uint8_t *s, int width, int deststep)
|
|
48 | 48 |
{ |
49 |
uint16_t *pal = opaque; |
|
49 | 50 |
uint8_t v, r, g, b; |
50 | 51 |
|
51 | 52 |
do { |
... | ... | |
81 | 82 |
/* |
82 | 83 |
* 4-bit colour |
83 | 84 |
*/ |
84 |
static void glue(draw_line4_, DEPTH)( |
|
85 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
|
|
85 |
static void glue(draw_line4_, DEPTH)(void *opaque,
|
|
86 |
uint8_t *d, const uint8_t *s, int width, int deststep)
|
|
86 | 87 |
{ |
88 |
uint16_t *pal = opaque; |
|
87 | 89 |
uint8_t v, r, g, b; |
88 | 90 |
|
89 | 91 |
do { |
... | ... | |
107 | 109 |
/* |
108 | 110 |
* 8-bit colour |
109 | 111 |
*/ |
110 |
static void glue(draw_line8_, DEPTH)( |
|
111 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
|
|
112 |
static void glue(draw_line8_, DEPTH)(void *opaque,
|
|
113 |
uint8_t *d, const uint8_t *s, int width, int deststep)
|
|
112 | 114 |
{ |
115 |
uint16_t *pal = opaque; |
|
113 | 116 |
uint8_t v, r, g, b; |
114 | 117 |
|
115 | 118 |
do { |
... | ... | |
126 | 129 |
/* |
127 | 130 |
* 12-bit colour |
128 | 131 |
*/ |
129 |
static void glue(draw_line12_, DEPTH)( |
|
130 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
|
|
132 |
static void glue(draw_line12_, DEPTH)(void *opaque,
|
|
133 |
uint8_t *d, const uint8_t *s, int width, int deststep)
|
|
131 | 134 |
{ |
132 | 135 |
uint16_t v; |
133 | 136 |
uint8_t r, g, b; |
... | ... | |
146 | 149 |
/* |
147 | 150 |
* 16-bit colour |
148 | 151 |
*/ |
149 |
static void glue(draw_line16_, DEPTH)( |
|
150 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal)
|
|
152 |
static void glue(draw_line16_, DEPTH)(void *opaque,
|
|
153 |
uint8_t *d, const uint8_t *s, int width, int deststep)
|
|
151 | 154 |
{ |
152 | 155 |
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) |
153 | 156 |
memcpy(d, s, width * 2); |
b/hw/omap_lcdc.c | ||
---|---|---|
20 | 20 |
#include "hw.h" |
21 | 21 |
#include "console.h" |
22 | 22 |
#include "omap.h" |
23 |
#include "framebuffer.h" |
|
23 | 24 |
|
24 | 25 |
struct omap_lcd_panel_s { |
25 | 26 |
qemu_irq irq; |
... | ... | |
68 | 69 |
|
69 | 70 |
#include "pixel_ops.h" |
70 | 71 |
|
71 |
typedef void draw_line_func( |
|
72 |
uint8_t *d, const uint8_t *s, int width, const uint16_t *pal); |
|
72 |
#define draw_line_func drawfn |
|
73 | 73 |
|
74 | 74 |
#define DEPTH 8 |
75 | 75 |
#include "omap_lcd_template.h" |
... | ... | |
80 | 80 |
#define DEPTH 32 |
81 | 81 |
#include "omap_lcd_template.h" |
82 | 82 |
|
83 |
static draw_line_func *draw_line_table2[33] = {
|
|
83 |
static draw_line_func draw_line_table2[33] = { |
|
84 | 84 |
[0 ... 32] = 0, |
85 | 85 |
[8] = draw_line2_8, |
86 | 86 |
[15] = draw_line2_15, |
87 | 87 |
[16] = draw_line2_16, |
88 | 88 |
[32] = draw_line2_32, |
89 |
}, *draw_line_table4[33] = {
|
|
89 |
}, draw_line_table4[33] = { |
|
90 | 90 |
[0 ... 32] = 0, |
91 | 91 |
[8] = draw_line4_8, |
92 | 92 |
[15] = draw_line4_15, |
93 | 93 |
[16] = draw_line4_16, |
94 | 94 |
[32] = draw_line4_32, |
95 |
}, *draw_line_table8[33] = {
|
|
95 |
}, draw_line_table8[33] = { |
|
96 | 96 |
[0 ... 32] = 0, |
97 | 97 |
[8] = draw_line8_8, |
98 | 98 |
[15] = draw_line8_15, |
99 | 99 |
[16] = draw_line8_16, |
100 | 100 |
[32] = draw_line8_32, |
101 |
}, *draw_line_table12[33] = {
|
|
101 |
}, draw_line_table12[33] = { |
|
102 | 102 |
[0 ... 32] = 0, |
103 | 103 |
[8] = draw_line12_8, |
104 | 104 |
[15] = draw_line12_15, |
105 | 105 |
[16] = draw_line12_16, |
106 | 106 |
[32] = draw_line12_32, |
107 |
}, *draw_line_table16[33] = {
|
|
107 |
}, draw_line_table16[33] = { |
|
108 | 108 |
[0 ... 32] = 0, |
109 | 109 |
[8] = draw_line16_8, |
110 | 110 |
[15] = draw_line16_15, |
... | ... | |
115 | 115 |
static void omap_update_display(void *opaque) |
116 | 116 |
{ |
117 | 117 |
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; |
118 |
draw_line_func *draw_line; |
|
119 |
int size, dirty[2], minline, maxline, height; |
|
120 |
int line, width, linesize, step, bpp, frame_offset; |
|
121 |
ram_addr_t frame_base, scanline, newline, x; |
|
122 |
uint8_t *s, *d; |
|
118 |
draw_line_func draw_line; |
|
119 |
int size, height, first, last; |
|
120 |
int width, linesize, step, bpp, frame_offset; |
|
121 |
target_phys_addr_t frame_base; |
|
123 | 122 |
|
124 | 123 |
if (!omap_lcd || omap_lcd->plm == 1 || |
125 | 124 |
!omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state)) |
... | ... | |
127 | 126 |
|
128 | 127 |
frame_offset = 0; |
129 | 128 |
if (omap_lcd->plm != 2) { |
130 |
memcpy(omap_lcd->palette, phys_ram_base +
|
|
131 |
omap_lcd->dma->phys_framebuffer[
|
|
132 |
omap_lcd->dma->current_frame], 0x200);
|
|
129 |
cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[
|
|
130 |
omap_lcd->dma->current_frame],
|
|
131 |
(void *)omap_lcd->palette, 0x200);
|
|
133 | 132 |
switch (omap_lcd->palette[0] >> 12 & 7) { |
134 | 133 |
case 3 ... 7: |
135 | 134 |
frame_offset += 0x200; |
... | ... | |
202 | 201 |
if (!ds_get_bits_per_pixel(omap_lcd->state)) |
203 | 202 |
return; |
204 | 203 |
|
205 |
line = 0;
|
|
204 |
first = 0;
|
|
206 | 205 |
height = omap_lcd->height; |
207 | 206 |
if (omap_lcd->subpanel & (1 << 31)) { |
208 | 207 |
if (omap_lcd->subpanel & (1 << 29)) |
209 |
line = (omap_lcd->subpanel >> 16) & 0x3ff;
|
|
208 |
first = (omap_lcd->subpanel >> 16) & 0x3ff;
|
|
210 | 209 |
else |
211 | 210 |
height = (omap_lcd->subpanel >> 16) & 0x3ff; |
212 | 211 |
/* TODO: fill the rest of the panel with DPD */ |
213 | 212 |
} |
213 |
|
|
214 | 214 |
step = width * bpp >> 3; |
215 |
scanline = frame_base + step * line; |
|
216 |
s = (uint8_t *) (phys_ram_base + scanline); |
|
217 |
d = ds_get_data(omap_lcd->state); |
|
218 | 215 |
linesize = ds_get_linesize(omap_lcd->state); |
219 |
|
|
220 |
dirty[0] = dirty[1] = |
|
221 |
cpu_physical_memory_get_dirty(scanline, VGA_DIRTY_FLAG); |
|
222 |
minline = height; |
|
223 |
maxline = line; |
|
224 |
for (; line < height; line ++) { |
|
225 |
newline = scanline + step; |
|
226 |
for (x = scanline + TARGET_PAGE_SIZE; x < newline; |
|
227 |
x += TARGET_PAGE_SIZE) { |
|
228 |
dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); |
|
229 |
dirty[0] |= dirty[1]; |
|
230 |
} |
|
231 |
if (dirty[0] || omap_lcd->invalidate) { |
|
232 |
draw_line(d, s, width, omap_lcd->palette); |
|
233 |
if (line < minline) |
|
234 |
minline = line; |
|
235 |
maxline = line + 1; |
|
236 |
} |
|
237 |
scanline = newline; |
|
238 |
dirty[0] = dirty[1]; |
|
239 |
s += step; |
|
240 |
d += linesize; |
|
241 |
} |
|
242 |
|
|
243 |
if (maxline >= minline) { |
|
244 |
dpy_update(omap_lcd->state, 0, minline, width, maxline); |
|
245 |
cpu_physical_memory_reset_dirty(frame_base + step * minline, |
|
246 |
frame_base + step * maxline, VGA_DIRTY_FLAG); |
|
216 |
framebuffer_update_display(omap_lcd->state, |
|
217 |
frame_base, width, height, |
|
218 |
step, linesize, 0, |
|
219 |
omap_lcd->invalidate, |
|
220 |
draw_line, omap_lcd->palette, |
|
221 |
&first, &last); |
|
222 |
if (first >= 0) { |
|
223 |
dpy_update(omap_lcd->state, 0, first, width, last - first + 1); |
|
247 | 224 |
} |
225 |
omap_lcd->invalidate = 0; |
|
248 | 226 |
} |
249 | 227 |
|
250 | 228 |
static int ppm_save(const char *filename, uint8_t *data, |
... | ... | |
336 | 314 |
return; |
337 | 315 |
} |
338 | 316 |
|
339 |
if (s->dma->src == imif) { |
|
340 |
/* Framebuffers are in SRAM */ |
|
341 |
s->dma->phys_framebuffer[0] = s->imif_base + |
|
342 |
s->dma->src_f1_top - OMAP_IMIF_BASE; |
|
343 |
|
|
344 |
s->dma->phys_framebuffer[1] = s->imif_base + |
|
345 |
s->dma->src_f2_top - OMAP_IMIF_BASE; |
|
346 |
} else { |
|
347 |
/* Framebuffers are in RAM */ |
|
348 |
s->dma->phys_framebuffer[0] = s->emiff_base + |
|
349 |
s->dma->src_f1_top - OMAP_EMIFF_BASE; |
|
350 |
|
|
351 |
s->dma->phys_framebuffer[1] = s->emiff_base + |
|
352 |
s->dma->src_f2_top - OMAP_EMIFF_BASE; |
|
353 |
} |
|
317 |
s->dma->phys_framebuffer[0] = s->dma->src_f1_top; |
|
318 |
s->dma->phys_framebuffer[1] = s->dma->src_f2_top; |
|
354 | 319 |
|
355 | 320 |
if (s->plm != 2 && !s->palette_done) { |
356 |
memcpy(s->palette, phys_ram_base + |
|
357 |
s->dma->phys_framebuffer[s->dma->current_frame], 0x200); |
|
321 |
cpu_physical_memory_read( |
|
322 |
s->dma->phys_framebuffer[s->dma->current_frame], |
|
323 |
(void *)s->palette, 0x200); |
|
358 | 324 |
s->palette_done = 1; |
359 | 325 |
omap_lcd_interrupts(s); |
360 | 326 |
} |
b/hw/pl110.c | ||
---|---|---|
10 | 10 |
#include "hw.h" |
11 | 11 |
#include "primecell.h" |
12 | 12 |
#include "console.h" |
13 |
#include "framebuffer.h" |
|
13 | 14 |
|
14 | 15 |
#define PL110_CR_EN 0x001 |
15 | 16 |
#define PL110_CR_BGR 0x100 |
... | ... | |
61 | 62 |
|
62 | 63 |
#include "pixel_ops.h" |
63 | 64 |
|
64 |
typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int); |
|
65 |
|
|
66 | 65 |
#define BITS 8 |
67 | 66 |
#include "pl110_template.h" |
68 | 67 |
#define BITS 15 |
... | ... | |
84 | 83 |
pl110_state *s = (pl110_state *)opaque; |
85 | 84 |
drawfn* fntable; |
86 | 85 |
drawfn fn; |
87 |
uint32_t *pallette; |
|
88 |
uint32_t addr; |
|
89 |
uint32_t base; |
|
90 | 86 |
int dest_width; |
91 | 87 |
int src_width; |
92 |
uint8_t *dest; |
|
93 |
uint8_t *src; |
|
94 |
int first, last = 0; |
|
95 |
int dirty, new_dirty; |
|
96 |
int i; |
|
97 | 88 |
int bpp_offset; |
89 |
int first; |
|
90 |
int last; |
|
98 | 91 |
|
99 | 92 |
if (!pl110_enabled(s)) |
100 | 93 |
return; |
... | ... | |
159 | 152 |
break; |
160 | 153 |
} |
161 | 154 |
dest_width *= s->cols; |
162 |
pallette = s->pallette; |
|
163 |
base = s->upbase; |
|
164 |
/* HACK: Arm aliases physical memory at 0x80000000. */ |
|
165 |
if (base > 0x80000000) |
|
166 |
base -= 0x80000000; |
|
167 |
src = phys_ram_base + base; |
|
168 |
dest = ds_get_data(s->ds); |
|
169 |
first = -1; |
|
170 |
addr = base; |
|
171 |
|
|
172 |
dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); |
|
173 |
new_dirty = dirty; |
|
174 |
for (i = 0; i < s->rows; i++) { |
|
175 |
if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) { |
|
176 |
uint32_t tmp; |
|
177 |
new_dirty = 0; |
|
178 |
for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) { |
|
179 |
new_dirty |= cpu_physical_memory_get_dirty(addr + tmp, |
|
180 |
VGA_DIRTY_FLAG); |
|
181 |
} |
|
182 |
} |
|
183 |
|
|
184 |
if (dirty || new_dirty || s->invalidate) { |
|
185 |
fn(pallette, dest, src, s->cols); |
|
186 |
if (first == -1) |
|
187 |
first = i; |
|
188 |
last = i; |
|
189 |
} |
|
190 |
dirty = new_dirty; |
|
191 |
addr += src_width; |
|
192 |
dest += dest_width; |
|
193 |
src += src_width; |
|
155 |
first = 0; |
|
156 |
framebuffer_update_display(s->ds, |
|
157 |
s->upbase, s->cols, s->rows, |
|
158 |
src_width, dest_width, 0, |
|
159 |
s->invalidate, |
|
160 |
fn, s->pallette, |
|
161 |
&first, &last); |
|
162 |
if (first >= 0) { |
|
163 |
dpy_update(s->ds, 0, first, s->cols, last - first + 1); |
|
194 | 164 |
} |
195 |
if (first < 0) |
|
196 |
return; |
|
197 |
|
|
198 | 165 |
s->invalidate = 0; |
199 |
cpu_physical_memory_reset_dirty(base + first * src_width, |
|
200 |
base + (last + 1) * src_width, |
|
201 |
VGA_DIRTY_FLAG); |
|
202 |
dpy_update(s->ds, 0, first, s->cols, last - first + 1); |
|
203 | 166 |
} |
204 | 167 |
|
205 | 168 |
static void pl110_invalidate_display(void * opaque) |
b/hw/pl110_template.h | ||
---|---|---|
115 | 115 |
#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y) |
116 | 116 |
#define FN_8(y) FN_4(0, y) FN_4(4, y) |
117 | 117 |
|
118 |
static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
118 |
static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
119 | 119 |
{ |
120 |
uint32_t *pallette = opaque; |
|
120 | 121 |
uint32_t data; |
121 | 122 |
while (width > 0) { |
122 | 123 |
data = *(uint32_t *)src; |
... | ... | |
142 | 143 |
} |
143 | 144 |
} |
144 | 145 |
|
145 |
static void glue(pl110_draw_line2_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
146 |
static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
146 | 147 |
{ |
148 |
uint32_t *pallette = opaque; |
|
147 | 149 |
uint32_t data; |
148 | 150 |
while (width > 0) { |
149 | 151 |
data = *(uint32_t *)src; |
... | ... | |
169 | 171 |
} |
170 | 172 |
} |
171 | 173 |
|
172 |
static void glue(pl110_draw_line4_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
174 |
static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
173 | 175 |
{ |
176 |
uint32_t *pallette = opaque; |
|
174 | 177 |
uint32_t data; |
175 | 178 |
while (width > 0) { |
176 | 179 |
data = *(uint32_t *)src; |
... | ... | |
196 | 199 |
} |
197 | 200 |
} |
198 | 201 |
|
199 |
static void glue(pl110_draw_line8_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
202 |
static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
200 | 203 |
{ |
204 |
uint32_t *pallette = opaque; |
|
201 | 205 |
uint32_t data; |
202 | 206 |
while (width > 0) { |
203 | 207 |
data = *(uint32_t *)src; |
... | ... | |
219 | 223 |
} |
220 | 224 |
} |
221 | 225 |
|
222 |
static void glue(pl110_draw_line16_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
226 |
static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
223 | 227 |
{ |
224 | 228 |
uint32_t data; |
225 | 229 |
unsigned int r, g, b; |
... | ... | |
265 | 269 |
} |
266 | 270 |
} |
267 | 271 |
|
268 |
static void glue(pl110_draw_line32_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width)
|
|
272 |
static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
|
|
269 | 273 |
{ |
270 | 274 |
uint32_t data; |
271 | 275 |
unsigned int r, g, b; |
b/hw/pxa2xx_lcd.c | ||
---|---|---|
13 | 13 |
#include "pixel_ops.h" |
14 | 14 |
/* FIXME: For graphic_rotate. Should probably be done in common code. */ |
15 | 15 |
#include "sysemu.h" |
16 |
|
|
17 |
typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int, int); |
|
16 |
#include "framebuffer.h" |
|
18 | 17 |
|
19 | 18 |
struct pxa2xx_lcdc_s { |
20 | 19 |
qemu_irq irq; |
... | ... | |
56 | 55 |
int up; |
57 | 56 |
uint8_t palette[1024]; |
58 | 57 |
uint8_t pbuffer[1024]; |
59 |
void (*redraw)(struct pxa2xx_lcdc_s *s, uint8_t *fb,
|
|
58 |
void (*redraw)(struct pxa2xx_lcdc_s *s, target_phys_addr_t addr,
|
|
60 | 59 |
int *miny, int *maxy); |
61 | 60 |
|
62 | 61 |
target_phys_addr_t descriptor; |
... | ... | |
669 | 668 |
} |
670 | 669 |
|
671 | 670 |
static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s, |
672 |
uint8_t *fb, int *miny, int *maxy)
|
|
671 |
target_phys_addr_t addr, int *miny, int *maxy)
|
|
673 | 672 |
{ |
674 |
int y, src_width, dest_width, dirty[2]; |
|
675 |
uint8_t *src, *dest; |
|
676 |
ram_addr_t x, addr, new_addr, start, end; |
|
673 |
int src_width, dest_width; |
|
677 | 674 |
drawfn fn = 0; |
678 | 675 |
if (s->dest_width) |
679 | 676 |
fn = s->line_fn[s->transp][s->bpp]; |
680 | 677 |
if (!fn) |
681 | 678 |
return; |
682 | 679 |
|
683 |
src = fb; |
|
684 | 680 |
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ |
685 | 681 |
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) |
686 | 682 |
src_width *= 3; |
... | ... | |
689 | 685 |
else if (s->bpp > pxa_lcdc_8bpp) |
690 | 686 |
src_width *= 2; |
691 | 687 |
|
692 |
dest = ds_get_data(s->ds); |
|
693 | 688 |
dest_width = s->xres * s->dest_width; |
694 |
|
|
695 |
addr = (ram_addr_t) (fb - phys_ram_base); |
|
696 |
start = addr + s->yres * src_width; |
|
697 |
end = addr; |
|
698 |
dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); |
|
699 |
for (y = 0; y < s->yres; y ++) { |
|
700 |
new_addr = addr + src_width; |
|
701 |
for (x = addr + TARGET_PAGE_SIZE; x < new_addr; |
|
702 |
x += TARGET_PAGE_SIZE) { |
|
703 |
dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); |
|
704 |
dirty[0] |= dirty[1]; |
|
705 |
} |
|
706 |
if (dirty[0] || s->invalidated) { |
|
707 |
fn((uint32_t *) s->dma_ch[0].palette, |
|
708 |
dest, src, s->xres, s->dest_width); |
|
709 |
if (addr < start) |
|
710 |
start = addr; |
|
711 |
end = new_addr; |
|
712 |
if (y < *miny) |
|
713 |
*miny = y; |
|
714 |
if (y >= *maxy) |
|
715 |
*maxy = y + 1; |
|
716 |
} |
|
717 |
addr = new_addr; |
|
718 |
dirty[0] = dirty[1]; |
|
719 |
src += src_width; |
|
720 |
dest += dest_width; |
|
721 |
} |
|
722 |
|
|
723 |
if (end > start) |
|
724 |
cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG); |
|
689 |
*miny = 0; |
|
690 |
framebuffer_update_display(s->ds, |
|
691 |
addr, s->xres, s->yres, |
|
692 |
src_width, dest_width, s->dest_width, |
|
693 |
s->invalidated, |
|
694 |
fn, s->dma_ch[0].palette, miny, maxy); |
|
725 | 695 |
} |
726 | 696 |
|
727 | 697 |
static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s, |
728 |
uint8_t *fb, int *miny, int *maxy)
|
|
698 |
target_phys_addr_t addr, int *miny, int *maxy)
|
|
729 | 699 |
{ |
730 |
int y, src_width, dest_width, dirty[2]; |
|
731 |
uint8_t *src, *dest; |
|
732 |
ram_addr_t x, addr, new_addr, start, end; |
|
700 |
int src_width, dest_width; |
|
733 | 701 |
drawfn fn = 0; |
734 | 702 |
if (s->dest_width) |
735 | 703 |
fn = s->line_fn[s->transp][s->bpp]; |
736 | 704 |
if (!fn) |
737 | 705 |
return; |
738 | 706 |
|
739 |
src = fb; |
|
740 | 707 |
src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ |
741 | 708 |
if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) |
742 | 709 |
src_width *= 3; |
... | ... | |
746 | 713 |
src_width *= 2; |
747 | 714 |
|
748 | 715 |
dest_width = s->yres * s->dest_width; |
749 |
dest = ds_get_data(s->ds) + dest_width * (s->xres - 1); |
|
750 |
|
|
751 |
addr = (ram_addr_t) (fb - phys_ram_base); |
|
752 |
start = addr + s->yres * src_width; |
|
753 |
end = addr; |
|
754 |
x = addr + TARGET_PAGE_SIZE; |
|
755 |
dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG); |
|
756 |
for (y = 0; y < s->yres; y ++) { |
|
757 |
new_addr = addr + src_width; |
|
758 |
for (; x < new_addr; x += TARGET_PAGE_SIZE) { |
|
759 |
dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); |
|
760 |
dirty[0] |= dirty[1]; |
|
761 |
} |
|
762 |
if (dirty[0] || s->invalidated) { |
|
763 |
fn((uint32_t *) s->dma_ch[0].palette, |
|
764 |
dest, src, s->xres, -dest_width); |
|
765 |
if (addr < start) |
|
766 |
start = addr; |
|
767 |
end = new_addr; |
|
768 |
if (y < *miny) |
|
769 |
*miny = y; |
|
770 |
if (y >= *maxy) |
|
771 |
*maxy = y + 1; |
|
772 |
} |
|
773 |
addr = new_addr; |
|
774 |
dirty[0] = dirty[1]; |
|
775 |
src += src_width; |
|
776 |
dest += s->dest_width; |
|
777 |
} |
|
778 |
|
|
779 |
if (end > start) |
|
780 |
cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG); |
|
716 |
*miny = 0; |
|
717 |
framebuffer_update_display(s->ds, |
|
718 |
addr, s->xres, s->yres, |
|
719 |
src_width, s->dest_width, -dest_width, |
|
720 |
s->invalidated, |
|
721 |
fn, s->dma_ch[0].palette, |
|
722 |
miny, maxy); |
|
781 | 723 |
} |
782 | 724 |
|
783 | 725 |
static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s) |
... | ... | |
803 | 745 |
static void pxa2xx_update_display(void *opaque) |
804 | 746 |
{ |
805 | 747 |
struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque; |
806 |
uint8_t *fb; |
|
807 | 748 |
target_phys_addr_t fbptr; |
808 | 749 |
int miny, maxy; |
809 | 750 |
int ch; |
... | ... | |
829 | 770 |
pxa2xx_dma_ber_set(s, ch); |
830 | 771 |
continue; |
831 | 772 |
} |
832 |
fbptr -= PXA2XX_SDRAM_BASE; |
|
833 |
fb = phys_ram_base + fbptr; |
|
834 | 773 |
|
835 | 774 |
if (s->dma_ch[ch].command & LDCMD_PAL) { |
836 |
memcpy(s->dma_ch[ch].pbuffer, fb,
|
|
837 |
MAX(LDCMD_LENGTH(s->dma_ch[ch].command),
|
|
838 |
sizeof(s->dma_ch[ch].pbuffer)));
|
|
775 |
cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer,
|
|
776 |
MAX(LDCMD_LENGTH(s->dma_ch[ch].command), |
|
777 |
sizeof(s->dma_ch[ch].pbuffer))); |
|
839 | 778 |
pxa2xx_palette_parse(s, ch, s->bpp); |
840 | 779 |
} else { |
841 | 780 |
/* Do we need to reparse palette */ |
... | ... | |
845 | 784 |
/* ACK frame start */ |
846 | 785 |
pxa2xx_dma_sof_set(s, ch); |
847 | 786 |
|
848 |
s->dma_ch[ch].redraw(s, fb, &miny, &maxy); |
|
787 |
s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy);
|
|
849 | 788 |
s->invalidated = 0; |
850 | 789 |
|
851 | 790 |
/* ACK frame completed */ |
... | ... | |
859 | 798 |
s->status[0] |= LCSR0_LDD; |
860 | 799 |
} |
861 | 800 |
|
862 |
if (s->orientation) |
|
863 |
dpy_update(s->ds, miny, 0, maxy, s->xres); |
|
864 |
else |
|
865 |
dpy_update(s->ds, 0, miny, s->xres, maxy); |
|
801 |
if (miny >= 0) { |
|
802 |
if (s->orientation) |
|
803 |
dpy_update(s->ds, miny, 0, maxy, s->xres); |
|
804 |
else |
|
805 |
dpy_update(s->ds, 0, miny, s->xres, maxy); |
|
806 |
} |
|
866 | 807 |
pxa2xx_lcdc_int_update(s); |
867 | 808 |
|
868 | 809 |
qemu_irq_raise(s->vsync_cb); |
b/hw/pxa2xx_template.h | ||
---|---|---|
30 | 30 |
#define FN_2(x) FN(x + 1) FN(x) |
31 | 31 |
#define FN_4(x) FN_2(x + 2) FN_2(x) |
32 | 32 |
|
33 |
static void glue(pxa2xx_draw_line2_, BITS)(uint32_t *palette,
|
|
33 |
static void glue(pxa2xx_draw_line2_, BITS)(void *opaque,
|
|
34 | 34 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
35 | 35 |
{ |
36 |
uint32_t *palette = opaque; |
|
36 | 37 |
uint32_t data; |
37 | 38 |
while (width > 0) { |
38 | 39 |
data = *(uint32_t *) src; |
... | ... | |
54 | 55 |
} |
55 | 56 |
} |
56 | 57 |
|
57 |
static void glue(pxa2xx_draw_line4_, BITS)(uint32_t *palette,
|
|
58 |
static void glue(pxa2xx_draw_line4_, BITS)(void *opaque,
|
|
58 | 59 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
59 | 60 |
{ |
61 |
uint32_t *palette = opaque; |
|
60 | 62 |
uint32_t data; |
61 | 63 |
while (width > 0) { |
62 | 64 |
data = *(uint32_t *) src; |
... | ... | |
78 | 80 |
} |
79 | 81 |
} |
80 | 82 |
|
81 |
static void glue(pxa2xx_draw_line8_, BITS)(uint32_t *palette,
|
|
83 |
static void glue(pxa2xx_draw_line8_, BITS)(void *opaque,
|
|
82 | 84 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
83 | 85 |
{ |
86 |
uint32_t *palette = opaque; |
|
84 | 87 |
uint32_t data; |
85 | 88 |
while (width > 0) { |
86 | 89 |
data = *(uint32_t *) src; |
... | ... | |
102 | 105 |
} |
103 | 106 |
} |
104 | 107 |
|
105 |
static void glue(pxa2xx_draw_line16_, BITS)(uint32_t *palette,
|
|
108 |
static void glue(pxa2xx_draw_line16_, BITS)(void *opaque,
|
|
106 | 109 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
107 | 110 |
{ |
108 | 111 |
uint32_t data; |
... | ... | |
130 | 133 |
} |
131 | 134 |
} |
132 | 135 |
|
133 |
static void glue(pxa2xx_draw_line16t_, BITS)(uint32_t *palette,
|
|
136 |
static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque,
|
|
134 | 137 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
135 | 138 |
{ |
136 | 139 |
uint32_t data; |
... | ... | |
166 | 169 |
} |
167 | 170 |
} |
168 | 171 |
|
169 |
static void glue(pxa2xx_draw_line18_, BITS)(uint32_t *palette,
|
|
172 |
static void glue(pxa2xx_draw_line18_, BITS)(void *opaque,
|
|
170 | 173 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
171 | 174 |
{ |
172 | 175 |
uint32_t data; |
... | ... | |
188 | 191 |
} |
189 | 192 |
|
190 | 193 |
/* The wicked packed format */ |
191 |
static void glue(pxa2xx_draw_line18p_, BITS)(uint32_t *palette,
|
|
194 |
static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque,
|
|
192 | 195 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
193 | 196 |
{ |
194 | 197 |
uint32_t data[3]; |
... | ... | |
236 | 239 |
} |
237 | 240 |
} |
238 | 241 |
|
239 |
static void glue(pxa2xx_draw_line19_, BITS)(uint32_t *palette,
|
|
242 |
static void glue(pxa2xx_draw_line19_, BITS)(void *opaque,
|
|
240 | 243 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
241 | 244 |
{ |
242 | 245 |
uint32_t data; |
... | ... | |
262 | 265 |
} |
263 | 266 |
|
264 | 267 |
/* The wicked packed format */ |
265 |
static void glue(pxa2xx_draw_line19p_, BITS)(uint32_t *palette,
|
|
268 |
static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque,
|
|
266 | 269 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
267 | 270 |
{ |
268 | 271 |
uint32_t data[3]; |
... | ... | |
326 | 329 |
} |
327 | 330 |
} |
328 | 331 |
|
329 |
static void glue(pxa2xx_draw_line24_, BITS)(uint32_t *palette,
|
|
332 |
static void glue(pxa2xx_draw_line24_, BITS)(void *opaque,
|
|
330 | 333 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
331 | 334 |
{ |
332 | 335 |
uint32_t data; |
... | ... | |
347 | 350 |
} |
348 | 351 |
} |
349 | 352 |
|
350 |
static void glue(pxa2xx_draw_line24t_, BITS)(uint32_t *palette,
|
|
353 |
static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque,
|
|
351 | 354 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
352 | 355 |
{ |
353 | 356 |
uint32_t data; |
... | ... | |
372 | 375 |
} |
373 | 376 |
} |
374 | 377 |
|
375 |
static void glue(pxa2xx_draw_line25_, BITS)(uint32_t *palette,
|
|
378 |
static void glue(pxa2xx_draw_line25_, BITS)(void *opaque,
|
|
376 | 379 |
uint8_t *dest, const uint8_t *src, int width, int deststep) |
377 | 380 |
{ |
378 | 381 |
uint32_t data; |
Also available in: Unified diff