|
|
1.1 ! root 1: /* ! 2: * Framebuffer device helper routines ! 3: * ! 4: * Copyright (c) 2009 CodeSourcery ! 5: * Written by Paul Brook <[email protected]> ! 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: first = -1; ! 82: addr = pd; ! 83: ! 84: addr += i * src_width; ! 85: src += i * src_width; ! 86: dest += i * dest_row_pitch; ! 87: ! 88: for (; i < rows; i++) { ! 89: target_phys_addr_t dirty_offset; ! 90: dirty = 0; ! 91: dirty_offset = 0; ! 92: while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) { ! 93: dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset, ! 94: VGA_DIRTY_FLAG); ! 95: dirty_offset += TARGET_PAGE_SIZE; ! 96: } ! 97: ! 98: if (dirty || invalidate) { ! 99: fn(opaque, dest, src, cols, dest_col_pitch); ! 100: if (first == -1) ! 101: first = i; ! 102: last = i; ! 103: } ! 104: addr += src_width; ! 105: src += src_width; ! 106: dest += dest_row_pitch; ! 107: } ! 108: cpu_physical_memory_unmap(src_base, src_len, 0, 0); ! 109: if (first < 0) { ! 110: return; ! 111: } ! 112: cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG); ! 113: *first_row = first; ! 114: *last_row = last; ! 115: return; ! 116: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.