diff --git a/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc b/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc index 910f5c85d..ecc00c949 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc @@ -46,9 +46,11 @@ static inline uint32_t to_phys(uint32_t addr) static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info, - unsigned long width, unsigned long height, + unsigned long &width, unsigned long &height, unsigned long depth, bool verbose) { + bool choose_highest_resolution_mode = ((width == 0) || (height == 0)); + uint16_t ret = 0; if (verbose) @@ -72,10 +74,22 @@ static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info mode_info->y_resolution, mode_info->bits_per_pixel); - if (mode_info->x_resolution == width && - mode_info->y_resolution == height && - mode_info->bits_per_pixel == depth) - ret = *MODE_PTR(off); + if (choose_highest_resolution_mode) { + if ((mode_info->bits_per_pixel == depth) && + ((mode_info->x_resolution > width) || + ((mode_info->x_resolution == width) && + (mode_info->y_resolution > height)))) { + + width = mode_info->x_resolution; + height = mode_info->y_resolution; + ret = *MODE_PTR(off); + } + } else { + if (mode_info->x_resolution == width && + mode_info->y_resolution == height && + mode_info->bits_per_pixel == depth) + ret = *MODE_PTR(off); + } } #undef MODE_PTR @@ -85,6 +99,19 @@ static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info if (verbose) PWRN("Searching in default vesa modes"); + if (choose_highest_resolution_mode) { + /* + * We did not find any mode for the given color depth so far. + * Default to 1024x768 for now. + */ + ret = get_default_vesa_mode(1024, 768, depth); + if (ret != 0) { + width = 1024; + height = 768; + } + return ret; + } + return get_default_vesa_mode(width, height, depth); } @@ -124,52 +151,7 @@ int Framebuffer_drv::map_io_mem(addr_t base, size_t size, bool write_combined, } -int Framebuffer_drv::use_current_mode() -{ - mb_vbe_ctrl_t *ctrl_info; - mb_vbe_mode_t *mode_info; - - /* set location of data types */ - ctrl_info = reinterpret_cast(X86emu::x86_mem.data_addr() - + VESA_CTRL_OFFS); - mode_info = reinterpret_cast(X86emu::x86_mem.data_addr() - + VESA_MODE_OFFS); - - /* retrieve controller information */ - if (X86emu::x86emu_cmd(VBE_CONTROL_FUNC, 0, 0, VESA_CTRL_OFFS) != VBE_SUPPORTED) { - PWRN("VBE Bios not present"); - return -1; - } - - /* retrieve current video mode */ - uint16_t vesa_mode = 0; - if (X86emu::x86emu_cmd(VBE_GMODE_FUNC, 0, 0, 0, &vesa_mode) != VBE_SUPPORTED) { - PWRN("VBE Bios not present"); - return -1; - } - vesa_mode &= 0x3fff; - - /* retrieve framebuffer info for current mode */ - if (X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, vesa_mode, VESA_MODE_OFFS) != VBE_SUPPORTED) { - PWRN("VBE Info function failed"); - return -2; - } - - if (!io_mem_cap.valid()) { - printf("Found: physical frame buffer at 0x%08x size: 0x%08x\n", - mode_info->phys_base, - ctrl_info->total_memory << 16); - - void *fb; - map_io_mem(mode_info->phys_base, ctrl_info->total_memory << 16, true, - &fb, 0, &io_mem_cap); - } - - return 0; -} - - -int Framebuffer_drv::set_mode(unsigned long width, unsigned long height, +int Framebuffer_drv::set_mode(unsigned long &width, unsigned long &height, unsigned long mode) { mb_vbe_ctrl_t *ctrl_info; @@ -195,7 +177,8 @@ int Framebuffer_drv::set_mode(unsigned long width, unsigned long height, /* retrieve vesa mode hex value */ if (!(vesa_mode = get_vesa_mode(ctrl_info, mode_info, width, height, mode, verbose))) { PWRN("graphics mode %lux%lu@%lu not found", width, height, mode); - get_vesa_mode(ctrl_info, mode_info, 0, 0, 0, true); + /* print available modes */ + get_vesa_mode(ctrl_info, mode_info, width, height, mode, true); return -2; } @@ -220,7 +203,8 @@ int Framebuffer_drv::set_mode(unsigned long width, unsigned long height, if (X86emu::x86emu_cmd(VBE_INFO_FUNC, 0, vesa_mode, VESA_MODE_OFFS) != VBE_SUPPORTED || (mode_info->mode_attributes & 0x91) != 0x91) { PWRN("graphics mode %lux%lu@%lu not supported", width, height, mode); - get_vesa_mode(ctrl_info, mode_info, 0, 0, 0, true); + /* print available modes */ + get_vesa_mode(ctrl_info, mode_info, width, height, mode, true); return -4; } diff --git a/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h b/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h index 459cc2076..3f60a12bd 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h +++ b/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h @@ -35,12 +35,14 @@ namespace Framebuffer_drv { /** * Set video, initialize framebuffer dataspace * + * If either 'width' or 'height' is 0, the mode with the highest resolution + * for the given color depth is chosen and 'width' and 'height' are updated + * accordingly. + * * \return 0 on success, * non-zero otherwise */ - int set_mode(unsigned long width, unsigned long height, unsigned long mode); - - int use_current_mode(); + int set_mode(unsigned long &width, unsigned long &height, unsigned long mode); /** * Map given device memory, return out_addr (map address) diff --git a/repos/libports/src/drivers/framebuffer/vesa/main.cc b/repos/libports/src/drivers/framebuffer/vesa/main.cc index 84d9a0dbb..a07a64357 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/main.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/main.cc @@ -209,23 +209,19 @@ namespace Framebuffer { Session_component *_create_session(const char *args) override { - unsigned long scr_width = session_arg("width", args, "fb_width", 1024), - scr_height = session_arg("height", args, "fb_height", 768), - scr_mode = session_arg("depth", args, "fb_mode", 16); - bool buffered = config_attribute("buffered"); - bool use_current_mode = config_attribute("preinit"); + unsigned long scr_width = session_arg("width", args, "fb_width", 0), + scr_height = session_arg("height", args, "fb_height", 0), + scr_mode = session_arg("depth", args, "fb_mode", 16); + bool buffered = config_attribute("buffered"); - if (use_current_mode) { - if (Framebuffer_drv::use_current_mode()) { - PWRN("Could not use preinitialized VESA mode"); - throw Root::Invalid_args(); - } - } else if (Framebuffer_drv::set_mode(scr_width, scr_height, scr_mode)) { + if (Framebuffer_drv::set_mode(scr_width, scr_height, scr_mode) != 0) { PWRN("Could not set vesa mode %lux%lu@%lu", scr_width, scr_height, scr_mode); throw Root::Invalid_args(); } + printf("Using video mode: %lu x %lu x %lu\n", scr_width, scr_height, scr_mode); + return new (md_alloc()) Session_component(scr_width, scr_height, scr_mode, Framebuffer_drv::hw_framebuffer(), buffered);