2 * Framebuffer device helper routines
4 * Copyright (c) 2009 CodeSourcery
5 * Written by Paul Brook <paul@codesourcery.com>
7 * This code is licensed under the GNU GPLv2.
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.
19 #include "framebuffer.h"
21 /* Render an image from a shared memory framebuffer. */
23 void framebuffer_update_display(
25 MemoryRegion
*address_space
,
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. */
35 int *first_row
, /* Input and output. */
36 int *last_row
/* Output only */)
38 target_phys_addr_t src_len
;
46 MemoryRegionSection mem_section
;
51 src_len
= src_width
* rows
;
53 mem_section
= memory_region_find(address_space
, base
, src_len
);
54 if (mem_section
.size
!= src_len
|| !memory_region_is_ram(mem_section
.mr
)) {
59 assert(mem_section
.offset_within_address_space
== base
);
61 memory_region_sync_dirty_bitmap(mem
);
62 src_base
= cpu_physical_memory_map(base
, &src_len
, 0);
63 /* If we can't map the framebuffer then bail. We could try harder,
64 but it's not really worth it as dirty flag tracking will probably
65 already have failed above. */
68 if (src_len
!= src_width
* rows
) {
69 cpu_physical_memory_unmap(src_base
, src_len
, 0, 0);
73 dest
= ds_get_data(ds
);
74 if (dest_col_pitch
< 0)
75 dest
-= dest_col_pitch
* (cols
- 1);
76 if (dest_row_pitch
< 0) {
77 dest
-= dest_row_pitch
* (rows
- 1);
80 addr
= mem_section
.offset_within_region
;
82 addr
+= i
* src_width
;
84 dest
+= i
* dest_row_pitch
;
86 for (; i
< rows
; i
++) {
87 target_phys_addr_t dirty_offset
;
90 while (addr
+ dirty_offset
< TARGET_PAGE_ALIGN(addr
+ src_width
)) {
91 dirty
|= memory_region_get_dirty(mem
, addr
+ dirty_offset
,
93 dirty_offset
+= TARGET_PAGE_SIZE
;
96 if (dirty
|| invalidate
) {
97 fn(opaque
, dest
, src
, cols
, dest_col_pitch
);
104 dest
+= dest_row_pitch
;
106 cpu_physical_memory_unmap(src_base
, src_len
, 0, 0);
110 memory_region_reset_dirty(mem
, mem_section
.offset_within_region
, src_len
,