vbe mode query
authorJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 2 May 2018 21:28:27 +0000 (00:28 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Wed, 2 May 2018 21:28:27 +0000 (00:28 +0300)
Makefile
src/kmain.c
src/test/vbetest.c
src/video.c
src/video.h

index fb282f3..23c8eaf 100644 (file)
--- 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
index 645c87e..339d3e0 100644 (file)
@@ -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)) {
index 1525bd8..177eac3 100644 (file)
@@ -1,3 +1,4 @@
+#include <stdio.h>
 #include <string.h>
 #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<nmodes; i++) {
+               if(video_mode_info(i, &vi) == -1) {
+                       continue;
+               }
+               printf(" %04x: %dx%d %d bpp (%d%d%d)\n", vi.mode, vi.width, vi.height, vi.bpp,
+                               vi.rbits, vi.gbits, vi.bbits);
+       }
+
+       if(!(framebuf = set_video_mode(find_video_mode(640, 480, 16)))) {
                return -1;
        }
 
index 277dcbd..58b764b 100644 (file)
@@ -32,8 +32,11 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
         ((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, &regs);
 }
 
-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; i<mode_count; i++) {
+               inf = vbe_get_mode_info(modes[i] | VBE_MODE_LFB);
+               if(!inf || inf->xres != 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;
+}
index bbeb224..3e4626d 100644 (file)
@@ -18,8 +18,24 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #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);