X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=drv_vbe.c;h=69c89eb54c9b43008aa6df74b73b98d75972b4b4;hb=75aa7ef609cbda625e6c19bc07acf744eb3bfc5a;hp=59ec306b92e63924a35fd8bd8ccd8456c981e97f;hpb=898a618bf25182f1e3b456303c3c2613c170856e;p=vidsys diff --git a/drv_vbe.c b/drv_vbe.c index 59ec306..69c89eb 100644 --- a/drv_vbe.c +++ b/drv_vbe.c @@ -4,6 +4,7 @@ #include "vidsys.h" #include "drv.h" #include "vbe.h" +#include "vga.h" #include "cdpmi.h" #define farptr_to_linear(rmaddr) \ @@ -11,18 +12,29 @@ static int init(void); static void cleanup(void); +static struct vid_modeinfo *find_mode(int mode); static int setmode(int mode); static int getmode(void); static const char *memsize_str(long sz); static int get_mode_info(int mode, struct vbe_mode_info *mi); +static int setwin(int wid, int pos); static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi); static unsigned int calc_mask(int nbits, int pos); +static void pack(uint32_t *pix, int r, int g, int b); +static void unpack(uint32_t pix, int *r, int *g, int *b); +static void clear(uint32_t color); +static void blitfb_lfb(void *fb, int pitch); +static void blitfb_banked(void *fb, int pitch); +static void flip(int vsync); + static struct vid_driver drv; static struct vid_drvops drvops = {init, cleanup, setmode, getmode}; static unsigned int vbe_ver; static int cur_mode; +static struct vid_modeinfo *cur_mi; +static int cur_pgsize; void vid_register_vbe(void) @@ -46,6 +58,7 @@ static int init(void) struct vid_modeinfo modeinf; cur_mode = -1; + cur_mi = 0; vbe = dpmi_lowbuf(); bufseg = (intptr_t)vbe >> 4; @@ -55,7 +68,7 @@ static int init(void) regs.eax = 0x4f00; regs.es = bufseg; dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) { + if((regs.eax & 0xffff) != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) { fprintf(stderr, "failed to get VBE controller information\n"); return -1; } @@ -114,24 +127,48 @@ static void cleanup(void) drv.num_modes = 0; } +static struct vid_modeinfo *find_mode(int mode) +{ + int i; + for(i=0; ilfb) { + mode |= VBE_MODE_LFB; + } + +retry: regs.eax = 0x4f02; - regs.ebx = mode | VBE_MODE_LFB; + regs.ebx = mode; dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f) { - regs.eax = 0x4f02; - regs.ebx = mode; - dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f) { - return -1; + if((regs.eax & 0xffff) != 0x4f) { + if(mode & VBE_MODE_LFB) { + mode &= ~VBE_MODE_LFB; + goto retry; } - cur_mode = mode; + return -1; + } + cur_mode = mode; + + if(!(cur_mi = minf)) return 0; + + cur_pgsize = minf->height * minf->pitch; + + if(mode & VBE_MODE_LFB) { + minf->ops.blitfb = blitfb_lfb; } else { - cur_mode = mode | VBE_MODE_LFB; + minf->ops.blitfb = blitfb_banked; } return 0; } @@ -169,7 +206,7 @@ static int get_mode_info(int mode, struct vbe_mode_info *mi) regs.ecx = mode; regs.es = bufseg; dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f) { + if((regs.eax & 0xffff) != 0x4f) { return -1; } @@ -177,8 +214,23 @@ static int get_mode_info(int mode, struct vbe_mode_info *mi) return 0; } +static int setwin(int wid, int pos) +{ + struct dpmi_regs regs = {0}; + + regs.eax = 0x4f05; + regs.ebx = wid; + regs.edx = pos; + dpmi_rmint(0x10, ®s); + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi) { + static int gran_shift; static const struct { int width, height, bpp; } stdmode[] = { {640, 400, 8}, /* 100h */ {640, 480, 8}, /* 101h */ @@ -235,6 +287,26 @@ static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info mi->pitch = vbemi->scanline_bytes; mi->win_size = vbemi->win_size; mi->win_gran = vbemi->win_gran; + + gran_shift = 0; + mi->win_step = 1; + if(mi->win_gran > 0 && mi->win_gran < 64) { + int gran = mi->win_gran; + while(gran < 64) { + gran_shift++; + gran <<= 1; + } + mi->win_step = 1 << gran_shift; + } + + mi->ops.pack = pack; + mi->ops.unpack = unpack; + mi->ops.setpal = vga_setpal; + mi->ops.getpal = vga_getpal; + mi->ops.vsync = vga_vsync; + mi->ops.clear = clear; + mi->ops.blitfb = 0; + mi->ops.flip = flip; return 0; } @@ -248,3 +320,61 @@ static unsigned int calc_mask(int nbits, int pos) } return mask << pos; } + + +static void pack(uint32_t *pix, int r, int g, int b) +{ + *pix = (((uint32_t)r << cur_mi->rshift) & cur_mi->rmask) | + (((uint32_t)g << cur_mi->gshift) & cur_mi->gmask) | + (((uint32_t)b << cur_mi->bshift) & cur_mi->bmask); +} + +static void unpack(uint32_t pix, int *r, int *g, int *b) +{ + *r = (pix & cur_mi->rmask) >> cur_mi->rshift; + *g = (pix & cur_mi->gmask) >> cur_mi->gshift; + *b = (pix & cur_mi->bmask) >> cur_mi->bshift; +} + +static void clear(uint32_t color) +{ +} + +static void blitfb_lfb(void *fb, int pitch) +{ + int i; + unsigned char *dest, *src; + + dest = vid_vmem; + src = fb; + + for(i=0; iheight; i++) { + memcpy(dest, src, cur_mi->pitch); + dest += cur_mi->pitch; + src += pitch; + } +} + +static void blitfb_banked(void *fb, int pitch) +{ + int sz, offs, pending; + unsigned char *pptr = fb; + + /* assume initial window offset at 0 */ + offs = 0; + pending = cur_pgsize; + while(pending > 0) { + sz = pending > 65536 ? 65536 : pending; + memcpy((void*)0xa0000, pptr, sz); + pptr += sz; + pending -= sz; + offs += cur_mi->win_step; + setwin(0, offs); + } + setwin(0, 0); +} + +static void flip(int vsync) +{ + /* TODO */ +}