Commit eee0b8367b01ff1bbe6159212a8d33ff587fc200
1 parent
b9652ca3
TCX 24 bit model support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2710 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
232 additions
and
15 deletions
hw/sun4m.c
... | ... | @@ -234,8 +234,12 @@ static void sun4m_hw_init(const struct hwdef *hwdef, int ram_size, |
234 | 234 | dma = sparc32_dma_init(hwdef->dma_base, slavio_irq[hwdef->esp_irq], |
235 | 235 | slavio_irq[hwdef->le_irq], iommu); |
236 | 236 | |
237 | + if (graphic_depth != 8 && graphic_depth != 24) { | |
238 | + fprintf(stderr, "qemu: Unsupported depth: %d\n", graphic_depth); | |
239 | + exit (1); | |
240 | + } | |
237 | 241 | tcx_init(ds, hwdef->tcx_base, phys_ram_base + ram_size, ram_size, |
238 | - hwdef->vram_size, graphic_width, graphic_height); | |
242 | + hwdef->vram_size, graphic_width, graphic_height, graphic_depth); | |
239 | 243 | if (nd_table[0].vlan) { |
240 | 244 | if (nd_table[0].model == NULL |
241 | 245 | || strcmp(nd_table[0].model, "lance") == 0) { | ... | ... |
hw/tcx.c
... | ... | @@ -31,14 +31,16 @@ typedef struct TCXState { |
31 | 31 | uint32_t addr; |
32 | 32 | DisplayState *ds; |
33 | 33 | uint8_t *vram; |
34 | - ram_addr_t vram_offset; | |
35 | - uint16_t width, height; | |
34 | + uint32_t *vram24, *cplane; | |
35 | + ram_addr_t vram_offset, vram24_offset, cplane_offset; | |
36 | + uint16_t width, height, depth; | |
36 | 37 | uint8_t r[256], g[256], b[256]; |
37 | 38 | uint32_t palette[256]; |
38 | 39 | uint8_t dac_index, dac_state; |
39 | 40 | } TCXState; |
40 | 41 | |
41 | 42 | static void tcx_screen_dump(void *opaque, const char *filename); |
43 | +static void tcx24_screen_dump(void *opaque, const char *filename); | |
42 | 44 | |
43 | 45 | /* XXX: unify with vga draw line functions */ |
44 | 46 | static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b) |
... | ... | @@ -121,6 +123,57 @@ static void tcx_draw_line8(TCXState *s1, uint8_t *d, |
121 | 123 | } |
122 | 124 | } |
123 | 125 | |
126 | +static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d, | |
127 | + const uint8_t *s, int width, | |
128 | + const uint32_t *cplane, | |
129 | + const uint32_t *s24) | |
130 | +{ | |
131 | + int x; | |
132 | + uint8_t val; | |
133 | + uint32_t *p = (uint32_t *)d; | |
134 | + uint32_t dval; | |
135 | + | |
136 | + for(x = 0; x < width; x++, s++, s24++) { | |
137 | + if ((bswap32(*cplane++) & 0xff000000) == 0x03000000) { // 24-bit direct | |
138 | + dval = bswap32(*s24) & 0x00ffffff; | |
139 | + } else { | |
140 | + val = *s; | |
141 | + dval = s1->palette[val]; | |
142 | + } | |
143 | + *p++ = dval; | |
144 | + } | |
145 | +} | |
146 | + | |
147 | +static inline int check_dirty(TCXState *ts, ram_addr_t page, ram_addr_t page24, | |
148 | + ram_addr_t cpage) | |
149 | +{ | |
150 | + int ret; | |
151 | + unsigned int off; | |
152 | + | |
153 | + ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG); | |
154 | + for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) { | |
155 | + ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG); | |
156 | + ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG); | |
157 | + } | |
158 | + return ret; | |
159 | +} | |
160 | + | |
161 | +static inline void reset_dirty(TCXState *ts, ram_addr_t page_min, | |
162 | + ram_addr_t page_max, ram_addr_t page24, | |
163 | + ram_addr_t cpage) | |
164 | +{ | |
165 | + cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE, | |
166 | + VGA_DIRTY_FLAG); | |
167 | + page_min -= ts->vram_offset; | |
168 | + page_max -= ts->vram_offset; | |
169 | + cpu_physical_memory_reset_dirty(page24 + page_min * 4, | |
170 | + page24 + page_max * 4 + TARGET_PAGE_SIZE, | |
171 | + VGA_DIRTY_FLAG); | |
172 | + cpu_physical_memory_reset_dirty(cpage + page_min * 4, | |
173 | + cpage + page_max * 4 + TARGET_PAGE_SIZE, | |
174 | + VGA_DIRTY_FLAG); | |
175 | +} | |
176 | + | |
124 | 177 | /* Fixed line length 1024 allows us to do nice tricks not possible on |
125 | 178 | VGA... */ |
126 | 179 | static void tcx_update_display(void *opaque) |
... | ... | @@ -201,6 +254,82 @@ static void tcx_update_display(void *opaque) |
201 | 254 | } |
202 | 255 | } |
203 | 256 | |
257 | +static void tcx24_update_display(void *opaque) | |
258 | +{ | |
259 | + TCXState *ts = opaque; | |
260 | + ram_addr_t page, page_min, page_max, cpage, page24; | |
261 | + int y, y_start, dd, ds; | |
262 | + uint8_t *d, *s; | |
263 | + uint32_t *cptr, *s24; | |
264 | + | |
265 | + if (ts->ds->depth != 32) | |
266 | + return; | |
267 | + page = ts->vram_offset; | |
268 | + page24 = ts->vram24_offset; | |
269 | + cpage = ts->cplane_offset; | |
270 | + y_start = -1; | |
271 | + page_min = 0xffffffff; | |
272 | + page_max = 0; | |
273 | + d = ts->ds->data; | |
274 | + s = ts->vram; | |
275 | + s24 = ts->vram24; | |
276 | + cptr = ts->cplane; | |
277 | + dd = ts->ds->linesize; | |
278 | + ds = 1024; | |
279 | + | |
280 | + for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE, | |
281 | + page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) { | |
282 | + if (check_dirty(ts, page, page24, cpage)) { | |
283 | + if (y_start < 0) | |
284 | + y_start = y; | |
285 | + if (page < page_min) | |
286 | + page_min = page; | |
287 | + if (page > page_max) | |
288 | + page_max = page; | |
289 | + tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); | |
290 | + d += dd; | |
291 | + s += ds; | |
292 | + cptr += ds; | |
293 | + s24 += ds; | |
294 | + tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); | |
295 | + d += dd; | |
296 | + s += ds; | |
297 | + cptr += ds; | |
298 | + s24 += ds; | |
299 | + tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); | |
300 | + d += dd; | |
301 | + s += ds; | |
302 | + cptr += ds; | |
303 | + s24 += ds; | |
304 | + tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); | |
305 | + d += dd; | |
306 | + s += ds; | |
307 | + cptr += ds; | |
308 | + s24 += ds; | |
309 | + } else { | |
310 | + if (y_start >= 0) { | |
311 | + /* flush to display */ | |
312 | + dpy_update(ts->ds, 0, y_start, | |
313 | + ts->width, y - y_start); | |
314 | + y_start = -1; | |
315 | + } | |
316 | + d += dd * 4; | |
317 | + s += ds * 4; | |
318 | + cptr += ds * 4; | |
319 | + s24 += ds * 4; | |
320 | + } | |
321 | + } | |
322 | + if (y_start >= 0) { | |
323 | + /* flush to display */ | |
324 | + dpy_update(ts->ds, 0, y_start, | |
325 | + ts->width, y - y_start); | |
326 | + } | |
327 | + /* reset modified pages */ | |
328 | + if (page_min <= page_max) { | |
329 | + reset_dirty(ts, page_min, page_max, page24, cpage); | |
330 | + } | |
331 | +} | |
332 | + | |
204 | 333 | static void tcx_invalidate_display(void *opaque) |
205 | 334 | { |
206 | 335 | TCXState *s = opaque; |
... | ... | @@ -211,14 +340,29 @@ static void tcx_invalidate_display(void *opaque) |
211 | 340 | } |
212 | 341 | } |
213 | 342 | |
343 | +static void tcx24_invalidate_display(void *opaque) | |
344 | +{ | |
345 | + TCXState *s = opaque; | |
346 | + int i; | |
347 | + | |
348 | + tcx_invalidate_display(s); | |
349 | + for (i = 0; i < MAXX*MAXY * 4; i += TARGET_PAGE_SIZE) { | |
350 | + cpu_physical_memory_set_dirty(s->vram24_offset + i); | |
351 | + cpu_physical_memory_set_dirty(s->cplane_offset + i); | |
352 | + } | |
353 | +} | |
354 | + | |
214 | 355 | static void tcx_save(QEMUFile *f, void *opaque) |
215 | 356 | { |
216 | 357 | TCXState *s = opaque; |
217 | 358 | |
218 | 359 | qemu_put_be32s(f, (uint32_t *)&s->addr); |
219 | 360 | qemu_put_be32s(f, (uint32_t *)&s->vram); |
361 | + qemu_put_be32s(f, (uint32_t *)&s->vram24); | |
362 | + qemu_put_be32s(f, (uint32_t *)&s->cplane); | |
220 | 363 | qemu_put_be16s(f, (uint16_t *)&s->height); |
221 | 364 | qemu_put_be16s(f, (uint16_t *)&s->width); |
365 | + qemu_put_be16s(f, (uint16_t *)&s->depth); | |
222 | 366 | qemu_put_buffer(f, s->r, 256); |
223 | 367 | qemu_put_buffer(f, s->g, 256); |
224 | 368 | qemu_put_buffer(f, s->b, 256); |
... | ... | @@ -230,13 +374,16 @@ static int tcx_load(QEMUFile *f, void *opaque, int version_id) |
230 | 374 | { |
231 | 375 | TCXState *s = opaque; |
232 | 376 | |
233 | - if (version_id != 1) | |
377 | + if (version_id != 2) | |
234 | 378 | return -EINVAL; |
235 | 379 | |
236 | 380 | qemu_get_be32s(f, (uint32_t *)&s->addr); |
237 | 381 | qemu_get_be32s(f, (uint32_t *)&s->vram); |
382 | + qemu_get_be32s(f, (uint32_t *)&s->vram24); | |
383 | + qemu_get_be32s(f, (uint32_t *)&s->cplane); | |
238 | 384 | qemu_get_be16s(f, (uint16_t *)&s->height); |
239 | 385 | qemu_get_be16s(f, (uint16_t *)&s->width); |
386 | + qemu_get_be16s(f, (uint16_t *)&s->depth); | |
240 | 387 | qemu_get_buffer(f, s->r, 256); |
241 | 388 | qemu_get_buffer(f, s->g, 256); |
242 | 389 | qemu_get_buffer(f, s->b, 256); |
... | ... | @@ -259,8 +406,8 @@ static void tcx_reset(void *opaque) |
259 | 406 | s->r[255] = s->g[255] = s->b[255] = 255; |
260 | 407 | update_palette_entries(s, 0, 256); |
261 | 408 | memset(s->vram, 0, MAXX*MAXY); |
262 | - cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY, | |
263 | - VGA_DIRTY_FLAG); | |
409 | + cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + | |
410 | + MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG); | |
264 | 411 | s->dac_index = 0; |
265 | 412 | s->dac_state = 0; |
266 | 413 | } |
... | ... | @@ -321,27 +468,54 @@ static CPUWriteMemoryFunc *tcx_dac_write[3] = { |
321 | 468 | }; |
322 | 469 | |
323 | 470 | void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, |
324 | - unsigned long vram_offset, int vram_size, int width, int height) | |
471 | + unsigned long vram_offset, int vram_size, int width, int height, | |
472 | + int depth) | |
325 | 473 | { |
326 | 474 | TCXState *s; |
327 | 475 | int io_memory; |
476 | + int size; | |
328 | 477 | |
329 | 478 | s = qemu_mallocz(sizeof(TCXState)); |
330 | 479 | if (!s) |
331 | 480 | return; |
332 | 481 | s->ds = ds; |
333 | 482 | s->addr = addr; |
334 | - s->vram = vram_base; | |
335 | 483 | s->vram_offset = vram_offset; |
336 | 484 | s->width = width; |
337 | 485 | s->height = height; |
486 | + s->depth = depth; | |
487 | + | |
488 | + // 8-bit plane | |
489 | + s->vram = vram_base; | |
490 | + size = vram_size; | |
491 | + cpu_register_physical_memory(addr + 0x00800000, size, vram_offset); | |
492 | + vram_offset += size; | |
493 | + vram_base += size; | |
338 | 494 | |
339 | - cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset); | |
340 | 495 | io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s); |
341 | - cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory); | |
496 | + cpu_register_physical_memory(addr + 0x00200000, TCX_DAC_NREGS, io_memory); | |
497 | + | |
498 | + if (depth == 24) { | |
499 | + // 24-bit plane | |
500 | + size = vram_size * 4; | |
501 | + s->vram24 = (uint32_t *)vram_base; | |
502 | + s->vram24_offset = vram_offset; | |
503 | + cpu_register_physical_memory(addr + 0x02000000, size, vram_offset); | |
504 | + vram_offset += size; | |
505 | + vram_base += size; | |
506 | + | |
507 | + // Control plane | |
508 | + size = vram_size * 4; | |
509 | + s->cplane = (uint32_t *)vram_base; | |
510 | + s->cplane_offset = vram_offset; | |
511 | + cpu_register_physical_memory(addr + 0x0a000000, size, vram_offset); | |
512 | + graphic_console_init(s->ds, tcx24_update_display, tcx24_invalidate_display, | |
513 | + tcx24_screen_dump, s); | |
514 | + } else { | |
515 | + graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display, | |
516 | + tcx_screen_dump, s); | |
517 | + } | |
342 | 518 | |
343 | - graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display, | |
344 | - tcx_screen_dump, s); | |
345 | 519 | register_savevm("tcx", addr, 1, tcx_save, tcx_load, s); |
346 | 520 | qemu_register_reset(tcx_reset, s); |
347 | 521 | tcx_reset(s); |
... | ... | @@ -375,5 +549,38 @@ static void tcx_screen_dump(void *opaque, const char *filename) |
375 | 549 | return; |
376 | 550 | } |
377 | 551 | |
552 | +static void tcx24_screen_dump(void *opaque, const char *filename) | |
553 | +{ | |
554 | + TCXState *s = opaque; | |
555 | + FILE *f; | |
556 | + uint8_t *d, *d1, v; | |
557 | + uint32_t *s24, *cptr, dval; | |
558 | + int y, x; | |
378 | 559 | |
379 | - | |
560 | + f = fopen(filename, "wb"); | |
561 | + if (!f) | |
562 | + return; | |
563 | + fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255); | |
564 | + d1 = s->vram; | |
565 | + s24 = s->vram24; | |
566 | + cptr = s->cplane; | |
567 | + for(y = 0; y < s->height; y++) { | |
568 | + d = d1; | |
569 | + for(x = 0; x < s->width; x++, d++, s24++) { | |
570 | + if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct | |
571 | + dval = *s24 & 0x00ffffff; | |
572 | + fputc((dval >> 16) & 0xff, f); | |
573 | + fputc((dval >> 8) & 0xff, f); | |
574 | + fputc(dval & 0xff, f); | |
575 | + } else { | |
576 | + v = *d; | |
577 | + fputc(s->r[v], f); | |
578 | + fputc(s->g[v], f); | |
579 | + fputc(s->b[v], f); | |
580 | + } | |
581 | + } | |
582 | + d1 += MAXX; | |
583 | + } | |
584 | + fclose(f); | |
585 | + return; | |
586 | +} | ... | ... |
vl.c
... | ... | @@ -159,11 +159,12 @@ int vmsvga_enabled = 0; |
159 | 159 | #ifdef TARGET_SPARC |
160 | 160 | int graphic_width = 1024; |
161 | 161 | int graphic_height = 768; |
162 | +int graphic_depth = 8; | |
162 | 163 | #else |
163 | 164 | int graphic_width = 800; |
164 | 165 | int graphic_height = 600; |
165 | -#endif | |
166 | 166 | int graphic_depth = 15; |
167 | +#endif | |
167 | 168 | int full_screen = 0; |
168 | 169 | int no_frame = 0; |
169 | 170 | int no_quit = 0; | ... | ... |
vl.h
... | ... | @@ -889,7 +889,11 @@ extern struct soundhw soundhw[]; |
889 | 889 | |
890 | 890 | /* vga.c */ |
891 | 891 | |
892 | +#ifndef TARGET_SPARC | |
892 | 893 | #define VGA_RAM_SIZE (8192 * 1024) |
894 | +#else | |
895 | +#define VGA_RAM_SIZE (9 * 1024 * 1024) | |
896 | +#endif | |
893 | 897 | |
894 | 898 | struct DisplayState { |
895 | 899 | uint8_t *data; |
... | ... | @@ -1206,7 +1210,8 @@ static inline void sparc_iommu_memory_write(void *opaque, |
1206 | 1210 | |
1207 | 1211 | /* tcx.c */ |
1208 | 1212 | void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, |
1209 | - unsigned long vram_offset, int vram_size, int width, int height); | |
1213 | + unsigned long vram_offset, int vram_size, int width, int height, | |
1214 | + int depth); | |
1210 | 1215 | |
1211 | 1216 | /* slavio_intctl.c */ |
1212 | 1217 | void pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu); | ... | ... |