@@ -62,7 +62,16 @@ void framebuffer_update_display(
assert(mem);
assert(mem_section.offset_within_address_space == base);
- memory_region_sync_dirty_bitmap(mem);
+ if (memory_region_is_logging(mem) & (1 << DIRTY_MEMORY_VGA)) {
+ memory_region_sync_dirty_bitmap(mem);
+ if (invalidate) {
+ memory_region_reset_dirty(mem, mem_section.offset_within_region,
+ src_len, DIRTY_MEMORY_VGA);
+ }
+ } else {
+ invalidate = true;
+ }
+
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
@@ -88,9 +97,13 @@ void framebuffer_update_display(
dest += i * dest_row_pitch;
for (; i < rows; i++) {
- dirty = memory_region_get_dirty(mem, addr, src_width,
- DIRTY_MEMORY_VGA);
- if (dirty || invalidate) {
+ if (invalidate) {
+ dirty = true;
+ } else {
+ dirty = memory_region_test_and_clear_dirty(mem, addr, src_width,
+ DIRTY_MEMORY_VGA);
+ }
+ if (dirty) {
fn(opaque, dest, src, cols, dest_col_pitch);
if (first == -1)
first = i;
@@ -104,8 +117,6 @@ void framebuffer_update_display(
if (first < 0) {
goto out;
}
- memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len,
- DIRTY_MEMORY_VGA);
*first_row = first;
*last_row = last;
out:
framebuffer.c expects DIRTY_MEMORY_VGA logging to be always on, but that will not be the case soon. Because framebuffer.c computes the memory region on the fly for every update (with memory_region_find), it cannot enable/disable logging by itself. Instead, always treat updates as invalidations if dirty logging is not enabled, assuming that the board will enable logging on the RAM region that includes the framebuffer. To simplify the code, replace memory_region_get_dirty with memory_region_test_and_clear_dirty. Then memory_region_reset_dirty is only needed in the invalidate case. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hw/display/framebuffer.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-)