#include "vga_regs.h"
+#ifndef V3_CONFIG_DEBUG_VGA
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
+#define DEBUG_MEM_DATA 0
+#define DEBUG_DEEP_MEM 0
+#define DEBUG_DEEP_RENDER 0
+
+
#define MEM_REGION_START 0xa0000
#define MEM_REGION_END 0xc0000
#define MEM_REGION_NUM_PAGES (((MEM_REGION_END)-(MEM_REGION_START))/4096)
#define MAP_SIZE 65536
#define MAP_NUM 4
-#define UPDATES_PER_RENDER 100
typedef uint8_t *vga_map; // points to MAP_SIZE data
#define VGA_FONT_WIDTH 8
#define VGA_MAX_FONT_HEIGHT 32
+struct vga_render_model {
+ uint32_t model; // composite the following
+
+#define VGA_DRIVEN_PERIODIC_RENDERING 0x1 // render after n GPU updates
+#define CONSOLE_ADVISORY_RENDERING 0x2 // ask console if we should render following an update
+#define CONSOLE_DRIVEN_RENDERING 0x4 // have console tell us when to render
+
+ uint32_t updates_before_render; // defaults to the following
+
+#define DEFAULT_UPDATES_BEFORE_RENDER 1000
+};
+
struct vga_misc_regs {
/* Read: 0x3cc; Write: 0x3c2 */
struct vga_misc_out_reg vga_misc_out;
struct vga_internal {
struct vm_device *dev;
-
+
bool passthrough;
bool skip_next_passthrough_out; // for word access
struct v3_frame_buffer_spec target_spec;
v3_graphics_console_t host_cons;
+ struct vga_render_model render_model;
uint32_t updates_since_render;
}
+
static void find_text_attr_start(struct vga_internal *vga, void **data)
{
uint32_t offset;
}
+static void find_graphics_data_starting_offset(struct vga_internal *vga, uint32_t *offset)
+{
+
+ *offset = vga->vga_crt_controller.vga_start_address_high;
+ *offset <<= 8;
+ *offset += vga->vga_crt_controller.vga_start_address_low;
+}
+
+
+static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode)
+{
+ if (vga->vga_graphics_controller.vga_graphics_mode.c256) {
+ *mode=C256_SHIFT;
+ } else {
+ if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) {
+ *mode=PACKED_SHIFT;
+ } else {
+ *mode=PLANAR_SHIFT;
+ }
+ }
+}
+
+
static void find_graphics_res(struct vga_internal *vga, uint32_t *width, uint32_t *height)
{
uint32_t vert_lsb, vert_msb;
+ (vga->vga_crt_controller.vga_overflow.vertical_disp_enable_end8);
*height = ( (vert_msb << 8) + vert_lsb + 1) ; // pixels high (scanlines)
+
+ // At this point we have the resolution in dot clocks across and scanlines top-to-bottom
+ // This is usually the resolution in pixels, but it can be monkeyed with
+ // at least in the following ways
+
+ // vga sequencer dot clock divide by two
+ if (vga->vga_sequencer.vga_clocking_mode.dot_clock) {
+ *width/=2;
+ *height/=2;
+ }
+
+ // crt_controller.max_row_scan.double_scan => each row twice for 200=>400
+ if (vga->vga_crt_controller.vga_max_row_scan.double_scan) {
+ *height/=2;
+ }
+
+ // crt_controller.crt_mode_control.count_by_two => pixels twice as wide as normal
+ if (vga->vga_crt_controller.vga_crt_mode_control.count_by_two) {
+ *width /= 2;
+ }
+
+ // crt_controller.crt_mode_control.horizontal_retrace_select => pixels twice as tall as normal
+ if (vga->vga_crt_controller.vga_crt_mode_control.horizontal_retrace_select) {
+ *height /= 2;
+ }
}
}
-static void find_shift_mode(struct vga_internal *vga, shift_mode_t *mode)
-{
- if (vga->vga_graphics_controller.vga_graphics_mode.c256) {
- *mode=C256_SHIFT;
- } else {
- if (vga->vga_graphics_controller.vga_graphics_mode.shift_reg_mode) {
- *mode=PACKED_SHIFT;
- } else {
- *mode=PLANAR_SHIFT;
- }
- }
-}
-
static void dac_lookup_24bit_color(struct vga_internal *vga,
uint8_t entry,
uint8_t *red,
find_graphics_cursor_pos(vga,&cur_x,&cur_y);
+ find_graphics_data_starting_offset(vga,&offset);
+
fw = spec->width;
fh = spec->height;
PrintDebug("vga: attempting graphics render (%s): graphics_res=(%u,%u), fb_res=(%u,%u), "
- "fb=0x%p (16 color mode)\n",
+ "fb=0x%p offset=0x%x\n",
sm == PLANAR_SHIFT ? "planar shift" :
sm == PACKED_SHIFT ? "packed shift" :
sm == C256_SHIFT ? "color256 shift" : "UNKNOWN",
- gw,gh,fw,fh, fb);
+ gw,gh,fw,fh,fb,offset);
// First we need to clip to what we can actually show
rgw = gw < fw ? gw : fw;
- rgh = gh < fh ? gh : gw;
+ rgh = gh < fh ? gh : fh;
if (gw%8) {
PrintError("vga: warning: graphics width is not a multiple of 8\n");
}
- offset=0; // do we always start at zero in the map?
+
// Now we scan across by row
for (fy=0;fy<gh;fy++) {
for (fx=0;fx<gw;
fx += (sm==C256_SHIFT ? 4 : 8) , offset++ ) {
- // if any of these pixels are in the renger region
+ // if any of these pixels are in the rendger region
if (fy < rgh && fx < rgw) {
// assemble all 4 or 8 pixels
case PLANAR_SHIFT:
for (p=0;p<8;p++) {
pb[p]=
- ( db[0] >> 7) |
- ( db[1] >> 6) |
- ( db[2] >> 5) |
- ( db[3] >> 4) ;
+ (( db[0] >> 7) & 0x1) |
+ (( db[1] >> 6) & 0x2) |
+ (( db[2] >> 5) & 0x4) |
+ (( db[3] >> 4) & 0x8) ;
for (m=0;m<4;m++) {
db[m] <<= 1;
// first 4 pixels use planes 0 and 2
for (p=0;p<4;p++) {
pb[p] =
- ( db[2] >> 4) |
- ( db[0] >> 6) ;
+ ((db[2] >> 4) & 0xc) |
+ ((db[0] >> 6) & 0x3) ;
db[2] <<= 2;
db[0] <<= 2;
}
// next 4 pixels use planes 1 and 3
for (p=4;p<8;p++) {
pb[p] =
- ( db[3] >> 4) |
- ( db[1] >> 6) ;
+ ((db[3] >> 4) & 0xc) |
+ ((db[1] >> 6) & 0x3) ;
db[3] <<= 2;
db[1] <<= 2;
}
for (p=0;p< (sm==C256_SHIFT ? 4 : 8);p++) {
// find its color
- find_24bit_color(vga,db[p],&r,&g,&b);
+ find_24bit_color(vga,pb[p],&r,&g,&b);
// find its position in the framebuffer;
pixel = fb + (((fx + p) + (fy*spec->width)) * spec->bytes_per_pixel);
rtw = tw < fw/cw ? tw : fw/cw;
rth = th < fh/ch ? th : fh/ch;
-
+ PrintDebug("\n");
// Now let's scan by char across the whole thing
for (y=0;y<th;y++) {
ca = *attr;
a.val = ca;
+ PrintDebug("%c",ct);
+
// find the character's font bitmap (one byte per row)
find_text_font_start(vga,(void**)&font,
extended_fontset(vga) ? a.foreground_intensity_or_font_select : 0 );
}
}
+static void render_black(struct vga_internal *vga, void *fb)
+{
+ struct v3_frame_buffer_spec *s;
+
+ s=&(vga->target_spec);
+
+ memset(fb,0,s->height*s->width*s->bytes_per_pixel);
+}
+
static void render_maps(struct vga_internal *vga, void *fb)
{
s=&(vga->target_spec);
- if (fb && s->height>=768 && s->width>=1024 && !(vga->updates_since_render % 100)) {
+ if (fb && s->height>=768 && s->width>=1024 ) {
// we draw the maps next, each being a 256x256 block appearing 32 pixels below the display block
uint8_t m;
uint32_t x,y;
}
}
+static int render_core(struct vga_internal *vga)
+{
+ void *fb;
+
+ PrintDebug("vga: render on update %u\n",vga->updates_since_render);
+
+ fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
+
+ if (!(vga->vga_sequencer.vga_clocking_mode.screen_off)) {
+ if (vga->vga_attribute_controller.vga_attribute_mode_control.graphics) {
+ render_graphics(vga,fb);
+ } else {
+ render_text(vga,fb);
+ render_text_cursor(vga,fb);
+ }
+ } else {
+ render_black(vga,fb);
+ }
+
+ if (0) { render_test(vga,fb); }
+
+ // always render maps for now
+ render_maps(vga,fb);
+
+ v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
+
+ vga->updates_since_render=0;
+
+ return 0;
+
+}
+
static int render(struct vga_internal *vga)
{
- void *fb;
-
vga->updates_since_render++;
- if (vga->updates_since_render%100) {
- // skip render
+
+ if (vga->host_cons) {
+ int do_render=0;
+
+ if ((vga->render_model.model & VGA_DRIVEN_PERIODIC_RENDERING)
+ &&
+ (vga->updates_since_render > vga->render_model.updates_before_render)) {
+ PrintDebug("vga: render due to periodic\n");
+
+ do_render = 1;
+ }
+
+ if ((vga->render_model.model & CONSOLE_ADVISORY_RENDERING)
+ &&
+ (v3_graphics_console_inform_update(vga->host_cons) > 0) ) {
+
+ PrintDebug("vga: render due to advisory\n");
+
+ do_render = 1;
+ }
+
+ // note that CONSOLE_DRIVEN_RENDERING is handled via the render_callback() function
+
+ if (do_render) {
+ return render_core(vga);
+ } else {
return 0;
+ }
}
+ return 0;
+
+}
- if (vga->host_cons && v3_graphics_console_inform_update(vga->host_cons)>0) {
-
- fb = v3_graphics_console_get_frame_buffer_data_rw(vga->host_cons,&(vga->target_spec));
-
- if (vga->vga_graphics_controller.vga_misc.graphics_mode) {
- render_graphics(vga,fb);
- } else {
- render_text(vga,fb);
- render_text_cursor(vga,fb);
- }
-
- if (0) { render_test(vga,fb); }
- render_maps(vga,fb);
+static int render_callback(v3_graphics_console_t cons,
+ void *priv)
+{
+ struct vga_internal *vga = (struct vga_internal *) priv;
+
+ PrintDebug("vga: render due to callback\n");
- v3_graphics_console_release_frame_buffer_data_rw(vga->host_cons);
- }
+ return render_core(vga);
+}
- return 0;
+static int update_callback(v3_graphics_console_t cons,
+ void *priv)
+{
+ struct vga_internal *vga = (struct vga_internal *) priv;
+
+ return vga->updates_since_render>0;
}
+
static void get_mem_region(struct vga_internal *vga, uint64_t *mem_start, uint64_t *mem_end)
{
switch (vga->vga_graphics_controller.vga_misc.memory_map) {
size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
if (vga->vga_sequencer.vga_mem_mode.odd_even) {
- return (guest_addr-mem_start) % size;
+ // NOT odd/even mode
+ return (guest_addr-mem_start) % size;
} else {
// odd/even mode
- return ((guest_addr-mem_start) >> 1 ) % size;
+ return ((guest_addr-mem_start) >> 1 ) % size;
}
}
uint8_t mm = vga->vga_sequencer.vga_map_mask.val;
if (vga->vga_sequencer.vga_mem_mode.odd_even) {
- return mm;
+ // NOT odd/even mode
+ return mm;
} else {
- if (guest_addr & 0x1) {
- return mm & 0xa; // 0x1010
- } else {
- return mm & 0x5; // 0x0101
- }
+ // odd/even mode
+ if (guest_addr & 0x1) {
+ return mm & 0xa; // 0x1010
+ } else {
+ return mm & 0x5; // 0x0101
+ }
}
}
static uint8_t find_increment_write(struct vga_internal *vga, addr_t new_guest_addr)
{
- if (vga->vga_sequencer.vga_mem_mode.odd_even) {
- return 1;
- } else {
- return !(new_guest_addr & 0x1);
- }
+ if (vga->vga_sequencer.vga_mem_mode.odd_even) {
+ // NOT odd/even mode
+ return 1;
+ } else {
+ return !(new_guest_addr & 0x1);
+ }
}
struct vm_device *dev = (struct vm_device *)priv_data;
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
- PrintDebug("vga: memory write: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
+ PrintDebug("vga: memory write: guest_addr=0x%p len=%u write_mode=%d\n",(void*)guest_addr, length,
+ vga->vga_graphics_controller.vga_graphics_mode.write_mode);
if (vga->passthrough) {
PrintDebug("vga: passthrough write to 0x%p\n", V3_VAddr((void*)guest_addr));
memcpy(V3_VAddr((void*)guest_addr),src,length);
}
-#if 0
+#if DEBUG_MEM_DATA
int i;
PrintDebug("vga: data written was 0x");
for (i=0;i<length;i++) {
offset = find_offset_write(vga, guest_addr);
+#if DEBUG_DEEP_MEM
PrintDebug("vga: mode 0 write, offset=0x%llx, ror=%u, func=%u\n", offset,ror,func);
+#endif
for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
// now for each map
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask;
uint8_t mm = find_map_write(vga,guest_addr+i);
- //PrintDebug("vga: write i=%u, mm=0x%x, offset=0x%x\n",i,(unsigned int)mm,(unsigned int)offset);
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: write i=%u, mm=0x%x, bm=0x%x sr=0x%x esr=0x%x offset=0x%x\n",i,(unsigned int)mm,(unsigned int)bm, (unsigned int)sr, (unsigned int)esr,(unsigned int)offset);
+#endif
- for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, bm>>=1, mm>>=1) {
+ for (mapnum=0;mapnum<4;mapnum++, sr>>=1, esr>>=1, mm>>=1) {
vga_map map = vga->map[mapnum];
uint8_t data = ((uint8_t *)src)[i];
uint8_t latchval = vga->latch[mapnum];
-
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: raw data=0x%x\n",data);
+#endif
// rotate data right
- data = (data>>ror) | data<<(8-ror);
-
+ if (ror) {
+ data = (data>>ror) | (data<<(8-ror));
+ }
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: data after ror=0x%x\n",data);
+#endif
// use SR bit if ESR is on for this map
- if (esr & 0x1) {
- data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
+ if (esr & 0x1) {
+ data = (sr&0x1) * -1;
+
}
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: data after esrr=0x%x\n",data);
+#endif
+
// Apply function
switch (func) {
case 0: // NOP
data ^= latchval;
break;
}
-
- // mux between latch and alu output
- if (bm & 0x1) {
- // use alu output, which is in data
- } else {
- // use latch value
- data=latchval;
- }
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: data after func=0x%x\n",data);
+#endif
+
+ // mux between the data byte and the latch byte on
+ // a per-bit basis
+ data = (bm & data) | ((~bm) & latchval);
+
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: data after bm mux=0x%x\n",data);
+#endif
// selective write
if (mm & 0x1) {
// write to this map
- //PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: write map %u offset 0x%p map=0x%p pointer=0x%p\n",mapnum,(void*)offset,map,&(map[offset]));
+#endif
map[offset] = data;
} else {
// skip this map
uint64_t offset = find_offset_write(vga,guest_addr);
+#if DEBUG_DEEP_MEM
PrintDebug("vga: mode 1 write, offset=0x%llx\n", offset);
+#endif
for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
offset = find_offset_write(vga, guest_addr);
+#if DEBUG_DEEP_MEM
PrintDebug("vga: mode 2 write, offset=0x%llx, func=%u\n", offset,func);
+#endif
for (i=0;i<length;i++,offset+=find_increment_write(vga,guest_addr+i)) {
// now for each map
uint8_t latchval = vga->latch[mapnum];
// expand relevant bit to 8 bit
- // it's basically esr=1, sr=bit from write
- data = (uint8_t)(((sint8_t)(((data>>mapnum)&0x1)<<7))>>7);
-
+ // it's basically esr=1, sr=bit from mode 0 write
+ data = ((data>>mapnum)&0x1) * -1;
+
// Apply function
switch (func) {
case 0: // NOP
data ^= latchval;
break;
}
-
+
// mux between latch and alu output
- if (bm & 0x1) {
- // use alu output, which is in data
- } else {
- // use latch value
- data=latchval;
- }
+ data = (bm & data) | ((~bm) & latchval);
// selective write
if (mm & 0x1) {
// now for each map
uint8_t data = ((uint8_t *)src)[i];
- data = (data>>ror) | data<<(8-ror);
+ if (ror) {
+ data = (data>>ror) | (data<<(8-ror));
+ }
uint8_t bm = vga->vga_graphics_controller.vga_bit_mask & data;
uint8_t sr = vga->vga_graphics_controller.vga_set_reset.val & 0xf;
vga_map map = vga->map[mapnum];
uint8_t latchval = vga->latch[mapnum];
- data = (uint8_t)((((sint8_t)(sr&0x1))<<7)>>7); // expand sr bit
-
-
+ // expand SR bit
+ data = (sr&0x1) * -1;
+
// mux between latch and alu output
- if (bm & 0x1) {
- // use alu output, which is in data
- } else {
- // use latch value
- data=latchval;
- }
+ data = (bm & data) | ((~bm) & latchval);
// selective write
if (mm & 0x1) {
size=(mem_end-mem_start > 65536 ? 65536 : (mem_end-mem_start));
- if (!vga->vga_sequencer.vga_mem_mode.chain4) {
- return (guest_addr-mem_start) % size;
- } else {
- // chain4 mode
- return ((guest_addr - mem_start) >> 2) % size;
+ if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
+ // odd/even mode takes priority
+ return ((guest_addr-mem_start) >> 1 ) % size;
+ }
+
+ if (vga->vga_sequencer.vga_mem_mode.chain4) {
+ // otherwise chain4 if it's on
+ return ((guest_addr - mem_start) >> 2) % size;
+ }
+
+ // and what you would expect if neither are on
+ return (guest_addr-mem_start) % size;
+}
+
+// Given this address
+// which specific map should we write into?
+// Note that unlike with find_map_write, here we are looking
+// for a single map number, not a bit vector of maps to be selected
+static uint8_t find_map_read(struct vga_internal *vga, addr_t guest_addr)
+{
+ uint64_t mem_start, mem_end;
+
+ mem_start=mem_end=0;
+
+ get_mem_region(vga, &mem_start, &mem_end);
+
+ if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
+ // odd-even mode
+ // last bit tells us map 0 or 1
+ return (guest_addr-mem_start) & 0x1;
+ }
+
+ if (vga->vga_sequencer.vga_mem_mode.chain4) {
+ // otherwise chain4 if it's on
+ // last two bits
+ return (guest_addr - mem_start) & 0x3;
}
+
+ // and what you would expect if neither are on
+ // note that it's not the same as a write!
+ return vga->vga_graphics_controller.vga_read_map_select.map_select;
}
static uint8_t find_increment_read(struct vga_internal *vga, addr_t new_guest_addr)
{
- if (vga->vga_sequencer.vga_mem_mode.chain4) {
- return !(new_guest_addr & 0x3);
- } else {
- return 1;
- }
+ if (!vga->vga_sequencer.vga_mem_mode.odd_even) {
+ // odd-even mode
+ return !(new_guest_addr & 0x1);
+ }
+
+ if (vga->vga_sequencer.vga_mem_mode.chain4) {
+ return !(new_guest_addr & 0x3);
+ }
+ return 1;
}
struct vga_internal *vga = (struct vga_internal *) dev->private_data;
- PrintDebug("vga: memory read: guest_addr=0x%p len=%u\n",(void*)guest_addr, length);
+ PrintDebug("vga: memory read: guest_addr=0x%p len=%u read_mode=%d\n",(void*)guest_addr, length,
+ vga->vga_graphics_controller.vga_graphics_mode.read_mode);
switch (vga->vga_graphics_controller.vga_graphics_mode.read_mode) {
case 0: {
/* 0 - a byte from ONE of the 4 planes is returned;
- which plane is determined by Read Map Select (Read Map Select Register (Index 04h)) */
+ which plane is determined by Read Map Select (Read Map Select Register (Index 04h))
+ OR by odd/even chaining OR by chain4 chaining
+ */
uint8_t mapnum;
uint64_t offset;
+ uint32_t i;
+
+ offset = find_offset_read(vga,guest_addr);
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: mode 0 read, offset=0x%llx\n",offset);
+#endif
+ for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
+
+ mapnum = find_map_read(vga,guest_addr+i);
+
+ ((uint8_t*)dst)[i] = *(vga->map[mapnum]+offset);
+
+ vga->latch[mapnum] = *(vga->map[mapnum]+offset);
- if (vga->vga_sequencer.vga_mem_mode.chain4) {
- uint32_t i;
- offset = find_offset_read(vga,guest_addr);
- // address bytes select the map
- for (i=0;i<length;i++,offset+=find_increment_read(vga,guest_addr+i)) {
- mapnum = (guest_addr+i) % 4;
- ((uint8_t*)dst)[i] = vga->latch[mapnum] = *(vga->map[mapnum]+offset);
- }
- } else {
- mapnum = vga->vga_graphics_controller.vga_read_map_select.map_select;
- offset = find_offset_read(vga,guest_addr);
-
- if (offset>=65536) {
- PrintError("vga: read to offset=%llu map=%u (%u bytes)\n",offset,mapnum,length);
- }
-
- memcpy(dst,(vga->map[mapnum])+offset,length);
-
- // load the latches with the last item read
- for (mapnum=0;mapnum<4;mapnum++) {
- vga->latch[mapnum] = vga->map[mapnum][offset+length-1];
- }
}
+
}
break;
uint8_t bits;
offset = find_offset_read(vga,guest_addr);
+
+#if DEBUG_DEEP_MEM
+ PrintDebug("vga: mode 1 read, offset=0x%llx, cc=0x%x, dc-0x%x\n",offset,cc,dc);
+#endif
+
for (i=0;i<length;i++,offset++) {
vga_map map;
}
-#if 0
+#if DEBUG_MEM_DATA
int i;
PrintDebug("vga: data read is 0x");
for (i=0;i<length;i++) {
static int init_vga(struct vga_internal *vga)
{
- // TODO: startup spec of register contents, if any
- PrintError("vga: init_vga is UNIMPLEMTED\n");
- return 0;
+ // TODO: startup spec of register contents, if any
+ vga->vga_misc.vga_input_stat1.val = 0x1; // display enable, not in retrace
+
+ return 0;
}
static int free_vga(struct vga_internal *vga)
memset(vga, 0, sizeof(struct vga_internal));
+ vga->render_model.model = CONSOLE_DRIVEN_RENDERING | VGA_DRIVEN_PERIODIC_RENDERING;
+ vga->render_model.updates_before_render = DEFAULT_UPDATES_BEFORE_RENDER;
+
if (passthrough && strcasecmp(passthrough,"enable")==0) {
PrintDebug("vga: enabling passthrough\n");
vga->passthrough=true;
PrintDebug("vga: response: %u by %u by %u with %u bpc and r,g,b at %u, %u, %u\n", vga->target_spec.width, vga->target_spec.height, vga->target_spec.bytes_per_pixel, vga->target_spec.bits_per_channel, vga->target_spec.red_offset, vga->target_spec.green_offset, vga->target_spec.blue_offset);
}
- }
+
+ if (vga->render_model.model & CONSOLE_DRIVEN_RENDERING) {
+ V3_Print("vga: enabling console-driven rendering\n");
+ if (v3_graphics_console_register_render_request(vga->host_cons, render_callback, vga)!=0) {
+ PrintError("vga: cannot enable console-driven rendering\n");
+ free_vga(vga);
+ return -1;
+ }
+ }
+
+ V3_Print("vga: enabling console inquiry for updates\n");
+ if (v3_graphics_console_register_update_inquire(vga->host_cons, update_callback, vga)!=0) {
+ PrintError("vga: cannot enable console inquiry for updates\n");
+ free_vga(vga);
+ return -1;
+ }
+ }
if (!vga->passthrough && !vga->host_cons) {
V3_Print("vga: neither passthrough nor host console are enabled - no way to display anything!\n");
// Now allocate the maps
for (i=0;i<MAP_NUM;i++) {
- vga->map[i] = (vga_map) V3_VAddr((void*)V3_AllocPages(MAP_SIZE/4096));
- if (!(vga->map[i])) {
+ void *temp;
+
+ temp = (void*)V3_AllocPages(MAP_SIZE/4096);
+ if (!temp) {
PrintError("vga: cannot allocate maps\n");
free_vga(vga);
return -1;
}
+
+ vga->map[i] = (vga_map) V3_VAddr(temp);
+
memset(vga->map[i],0,MAP_SIZE);
}