--- trunk/src/devices/dev_fb.c 2007/10/08 16:19:37 22 +++ trunk/src/devices/dev_fb.c 2007/10/08 16:20:58 32 @@ -25,16 +25,16 @@ * SUCH DAMAGE. * * - * $Id: dev_fb.c,v 1.116 2006/02/05 10:26:36 debug Exp $ + * $Id: dev_fb.c,v 1.127 2006/10/22 04:20:53 debug Exp $ * * Generic framebuffer device. * * DECstation VFB01 monochrome framebuffer, 1024x864 * DECstation VFB02 8-bit color framebuffer, 1024x864 * DECstation Maxine, 1024x768 8-bit color - * HPC (mips, arm, ..) framebuffer * Playstation 2 (24-bit color) - * generic (any resolution, several bit depths possible) + * Generic (any resolution, several bit depths possible, useful for + * testmachines) * * * TODO: This should actually be independent of X11, but that @@ -62,7 +62,7 @@ #endif -#define FB_TICK_SHIFT 18 +#define FB_TICK_SHIFT 19 /* #define FB_DEBUG */ @@ -104,11 +104,23 @@ } +static void set_title(struct vfb_data *d) +{ + snprintf(d->title, sizeof(d->title),"GXemul: %ix%ix%i %s framebuffer", + d->visible_xsize, d->visible_ysize, d->bit_depth, d->name); + d->title[sizeof(d->title)-1] = '\0'; +} + + /* * dev_fb_resize(): * * Resize a framebuffer window. (This functionality is probably a bit buggy, * because I didn't think of including it from the start.) + * + * SUPER-IMPORTANT: Anyone who resizes a framebuffer by calling this function + * must also clear all dyntrans address translations manually, in all cpus + * which might have access to the framebuffer! */ void dev_fb_resize(struct vfb_data *d, int new_xsize, int new_ysize) { @@ -121,6 +133,11 @@ return; } + if (new_xsize < 10 || new_ysize < 10) { + fatal("dev_fb_resize(): size too small.\n"); + exit(1); + } + new_bytes_per_line = new_xsize * d->bit_depth / 8; size = new_ysize * new_bytes_per_line; @@ -163,9 +180,15 @@ d->x11_xsize = d->xsize / d->vfb_scaledown; d->x11_ysize = d->ysize / d->vfb_scaledown; + memory_device_update_data(d->memory, d, d->framebuffer); + + set_title(d); + #ifdef WITH_X11 - if (d->fb_window != NULL) + if (d->fb_window != NULL) { x11_fb_resize(d->fb_window, new_xsize, new_ysize); + x11_set_standard_properties(d->fb_window, d->title); + } #endif } @@ -195,10 +218,6 @@ } #endif - if (d->fb_window != NULL) - console_set_framebuffer_mouse(cursor_x, cursor_y, - d->fb_window->fb_number); - /* debug("dev_fb_setcursor(%i,%i, size %i,%i, on=%i)\n", cursor_x, cursor_y, cursor_xsize, cursor_ysize, on); */ } @@ -211,7 +230,7 @@ * block copy/fill. * * If fillflag is non-zero, then fill_[rgb] should contain the color - * with which to fill. + * with which to fill. (In 8-bit mode, only fill_r is used.) * * If fillflag is zero, copy mode is used, and from_[xy] should contain * the offset on the framebuffer where we should copy from. @@ -222,7 +241,7 @@ int fill_g, int fill_b, int x1, int y1, int x2, int y2, int from_x, int from_y) { - int y; + int x, y; long from_ofs, dest_ofs, linelen; if (fillflag) @@ -245,22 +264,23 @@ if (fillflag) { for (y=y1; y<=y2; y++) { if (y>=0 && yysize) { - int x; - char buf[8192 * 3]; - if (d->bit_depth == 24) + unsigned char *buf = + d->framebuffer + dest_ofs; + + if (d->bit_depth == 24) { for (x=0; xbit_depth == 8) { + memset(buf, fill_r, linelen); + } else { + fatal("Unimplemented bit-depth (%i)" + " for fb fill\n", d->bit_depth); + exit(1); } - - memmove(d->framebuffer + dest_ofs, buf, - linelen); } dest_ofs += d->bytes_per_line; @@ -268,12 +288,16 @@ } else { from_ofs = d->bytes_per_line * from_y + (d->bit_depth/8) * from_x; - for (y=y1; y<=y2; y++) { - if (y>=0 && yysize) - memmove(d->framebuffer + dest_ofs, - d->framebuffer + from_ofs, linelen); - + if (y >= 0 && y < d->ysize) { + if (from_y >= 0 && from_y < d->ysize) + memmove(d->framebuffer + dest_ofs, + d->framebuffer + from_ofs, linelen); + else + memset(d->framebuffer + dest_ofs, + 0, linelen); + } + from_y ++; from_ofs += d->bytes_per_line; dest_ofs += d->bytes_per_line; } @@ -384,11 +408,7 @@ #endif /* WITH_X11 */ -/* - * dev_fb_tick(): - * - */ -void dev_fb_tick(struct cpu *cpu, void *extra) +DEVICE_TICK(fb) { struct vfb_data *d = extra; #ifdef WITH_X11 @@ -513,7 +533,10 @@ #endif if (d->update_x2 != -1) { - int y, addr, addr2, q = d->vfb_scaledown; +#ifdef WITH_X11 + int y; +#endif + int addr, addr2, q = d->vfb_scaledown; if (d->update_x1 >= d->visible_xsize) d->update_x1 = d->visible_xsize - 1; @@ -585,9 +608,6 @@ } -/* - * dev_fb_access(): - */ DEVICE_ACCESS(fb) { struct vfb_data *d = extra; @@ -712,7 +732,8 @@ * * VFB_DEC_VFB01, _VFB02, and VFB_DEC_MAXINE are DECstation specific. * - * If type is VFB_HPC, then color encoding differs from the generic case. + * VFB_HPC is like generic, but the color encoding is done as on HPCmips + * and Dreamcast. * * If bit_depth = -15 (note the minus sign), then a special hack is used for * the Playstation Portable's 5-bit R, 5-bit G, 5-bit B. @@ -725,7 +746,6 @@ size_t size, nlen; int flags; int reverse_start = 0; - char title[400]; char *name2; d = malloc(sizeof(struct vfb_data)); @@ -740,6 +760,7 @@ reverse_start = 1; } + d->memory = mem; d->vfb_type = vfb_type; /* Defaults: */ @@ -818,20 +839,14 @@ d->update_x2 = d->update_y2 = -1; } - /* Don't set the title to include the size of the framebuffer for - VGA, since then the resolution might change during runtime. */ - if (strcmp(name, "VGA") == 0) - snprintf(title, sizeof(title),"GXemul: %s framebuffer", name); - else - snprintf(title, sizeof(title),"GXemul: %ix%ix%i %s framebuffer", - d->visible_xsize, d->visible_ysize, d->bit_depth, name); - title[sizeof(title)-1] = '\0'; + d->name = strdup(name); + set_title(d); #ifdef WITH_X11 if (machine->use_x11) { int i = 0; d->fb_window = x11_fb_init(d->x11_xsize, d->x11_ysize, - title, machine->x11_scaledown, machine); + d->title, machine->x11_scaledown, machine); switch (d->fb_window->x11_screen_depth) { case 15: i = 2; break; case 16: i = 4; break; @@ -863,7 +878,7 @@ memory_device_register(mem, name2, baseaddr, size, dev_fb_access, d, flags, d->framebuffer); - machine_add_tickfunction(machine, dev_fb_tick, d, FB_TICK_SHIFT); + machine_add_tickfunction(machine, dev_fb_tick, d, FB_TICK_SHIFT, 0.0); return d; }