From 094e9170ca5f9b59443c171967cdc78f1c07044c Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Thu, 3 May 2018 00:28:27 +0300 Subject: [PATCH] vbe mode query --- Makefile | 4 +- src/kmain.c | 2 - src/test/vbetest.c | 16 ++++++- src/video.c | 128 ++++++++++++++++++++++++++++++++++++++-------------- src/video.h | 18 +++++++- 5 files changed, 128 insertions(+), 40 deletions(-) diff --git a/Makefile b/Makefile index fb282f3..23c8eaf 100644 --- a/Makefile +++ b/Makefile @@ -71,11 +71,11 @@ $(elf).sym: $(elf) .PHONY: run run: $(bin) - qemu-system-i386 -fda floppy.img -serial file:serial.log -vga std + qemu-system-i386 -fda floppy.img -serial file:serial.log .PHONY: debug debug: $(bin) $(elf).sym - qemu-system-i386 -fda floppy.img -serial file:serial.log -vga std -s -S + qemu-system-i386 -fda floppy.img -serial file:serial.log -s -S .PHONY: sym sym: $(elf).sym diff --git a/src/kmain.c b/src/kmain.c index 645c87e..339d3e0 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -60,9 +60,7 @@ void pcboot_main(void) break; case KB_F2: - set_video_mode(640, 480, 16); vbetest(); - set_vga_mode(3); break; } if(isprint(c)) { diff --git a/src/test/vbetest.c b/src/test/vbetest.c index 1525bd8..177eac3 100644 --- a/src/test/vbetest.c +++ b/src/test/vbetest.c @@ -1,3 +1,4 @@ +#include #include #include "video.h" #include "asmops.h" @@ -7,7 +8,20 @@ static uint16_t *framebuf; int vbetest(void) { - if(!(framebuf = set_video_mode(640, 480, 16))) { + int i, nmodes; + struct video_mode vi; + + nmodes = video_mode_count(); + printf("%d video modes found:\n", nmodes); + for(i=0; i. ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32)) +unsigned int color_mask(int nbits, int pos); static struct vbe_info *vbe_info; +static uint16_t *modes; +static int mode_count; static struct vbe_mode_info *mode_info; void set_vga_mode(int mode) @@ -45,59 +48,112 @@ void set_vga_mode(int mode) int86(0x10, ®s); } -void *set_video_mode(int xsz, int ysz, int bpp) +static int init_once(void) { int i; - static uint16_t *modes; - uint16_t best = 0; + static int done_init; + + if(done_init) { + return vbe_info && modes ? 0 : -1; + } + done_init = 1; /* check for VBE2 support and output some info */ - if(!vbe_info) { - if(!(vbe_info = vbe_get_info())) { - printf("VESA BIOS Extensions not available\n"); - return 0; - } + if(!(vbe_info = vbe_get_info())) { + printf("VESA BIOS Extensions not available\n"); + return -1; + } - printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff); - if(vbe_info->version < 0x200) { - printf("VBE >=2.0 not available. VBE 1.x support not implemented yet."); - return 0; - } + printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff); + if(vbe_info->version < 0x200) { + printf("VBE >=2.0 not available. VBE 1.x support not implemented yet."); + return -1; + } - printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr), - (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr)); - printf("Video memory: %dkb\n", vbe_info->total_mem << 6); + printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr), + (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr)); + printf("Video memory: %dkb\n", vbe_info->total_mem << 6); - modes = VBEPTR(vbe_info->vid_mode_ptr); - } + modes = VBEPTR(vbe_info->vid_mode_ptr); + mode_count = 0; for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */ if(modes[i] == 0xffff) { break; /* reached the end */ } + mode_count++; + } + return 0; +} + +void *set_video_mode(int mode) +{ + if(init_once() == -1) return 0; + if(mode < 0 || mode >= mode_count) return 0; + + if(!(mode_info = vbe_get_mode_info(mode))) { + return 0; + } + + if(vbe_set_mode(mode | VBE_MODE_LFB) == -1) { + printf("Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp); + return 0; + } + + return (void*)mode_info->fb_addr; +} - mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB); - if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) { +int find_video_mode(int xsz, int ysz, int bpp) +{ + int i; + uint16_t best = 0; + struct vbe_mode_info *inf; + + if(init_once() == -1) return -1; + + for(i=0; ixres != xsz || inf->yres != ysz) { continue; } - if(SAME_BPP(mode_info->bpp, bpp)) { + if(SAME_BPP(inf->bpp, bpp)) { best = modes[i]; } } - if(best) { - mode_info = vbe_get_mode_info(best); - } else { + if(!best) { printf("Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp); - return 0; + return -1; } + return best; +} - if(vbe_set_mode(best | VBE_MODE_LFB) == -1) { - printf("Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp); - return 0; - } +int video_mode_count(void) +{ + if(init_once() == -1) return 0; + return mode_count; +} - return (void*)mode_info->fb_addr; +int video_mode_info(int n, struct video_mode *vid) +{ + struct vbe_mode_info *inf; + + if(init_once() == -1) return -1; + + if(!(inf = vbe_get_mode_info(modes[n] | VBE_MODE_LFB))) { + return -1; + } + vid->mode = modes[n]; + vid->width = inf->xres; + vid->height = inf->yres; + vid->bpp = inf->bpp; + vid->rbits = inf->rmask_size; + vid->gbits = inf->gmask_size; + vid->bbits = inf->bmask_size; + vid->rmask = color_mask(inf->rmask_size, inf->rpos); + vid->gmask = color_mask(inf->gmask_size, inf->gpos); + vid->bmask = color_mask(inf->bmask_size, inf->bpos); + return 0; } int get_color_bits(int *rbits, int *gbits, int *bbits) @@ -113,13 +169,12 @@ int get_color_bits(int *rbits, int *gbits, int *bbits) int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask) { - static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff}; if(!mode_info) { return -1; } - *rmask = maskbits[mode_info->rmask_size] << mode_info->rpos; - *gmask = maskbits[mode_info->gmask_size] << mode_info->gpos; - *bmask = maskbits[mode_info->bmask_size] << mode_info->bpos; + *rmask = color_mask(mode_info->rmask_size, mode_info->rpos); + *gmask = color_mask(mode_info->gmask_size, mode_info->gpos); + *bmask = color_mask(mode_info->bmask_size, mode_info->bpos); return 0; } @@ -134,3 +189,8 @@ int get_color_shift(int *rshift, int *gshift, int *bshift) return 0; } +unsigned int color_mask(int nbits, int pos) +{ + static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff}; + return maskbits[nbits] << pos; +} diff --git a/src/video.h b/src/video.h index bbeb224..3e4626d 100644 --- a/src/video.h +++ b/src/video.h @@ -18,8 +18,24 @@ along with this program. If not, see . #ifndef VIDEO_H_ #define VIDEO_H_ +struct video_mode { + int mode; + int width, height; + int bpp; + int rbits, gbits, bbits; + unsigned int rmask, gmask, bmask; +}; + void set_vga_mode(int mode); -void *set_video_mode(int xsz, int ysz, int bpp); + +void *set_video_mode(int mode); +int find_video_mode(int xsz, int ysz, int bpp); + +int video_mode_count(void); +int video_mode_info(int n, struct video_mode *vid); + +int get_color_bits(int *rbits, int *gbits, int *bbits); +int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask); /* defined in video_asm.s */ void wait_vsync(void); -- 1.7.10.4