FreeBASIC  0.91.0
gfx_driver_vesa_bnk.c
Go to the documentation of this file.
1 /* banked VESA gfx driver */
2 
3 #include "../fb_gfx.h"
4 #include "fb_gfx_dos.h"
5 
6 static int driver_init(char *title, int w, int h, int depth, int refresh_rate, int flags);
7 static void driver_exit(void);
8 static void driver_update(void);
9 static void end_of_driver_update(void);
10 static void fb_dos_vesa_set_bank_int(void);
11 static void fb_dos_vesa_set_bank_int_end(void);
12 extern void fb_dos_vesa_set_bank_pm(void);
13 extern void fb_dos_vesa_set_bank_pm_end(void);
14 
16 {
17  "VESA banked", /* char *name; */
18  driver_init, /* int (*init)(char *title, int w, int h, int depth, int refresh_rate, int flags); */
19  driver_exit, /* void (*exit)(void); */
20  fb_dos_lock, /* void (*lock)(void); */
21  fb_dos_unlock, /* void (*unlock)(void); */
22  fb_dos_set_palette, /* void (*set_palette)(int index, int r, int g, int b); */
23  fb_dos_vga_wait_vsync, /* void (*wait_vsync)(void); */
24  fb_dos_get_mouse, /* int (*get_mouse)(int *x, int *y, int *z, int *buttons, int *clip); */
25  fb_dos_set_mouse, /* void (*set_mouse)(int x, int y, int cursor, int clip); */
26  fb_dos_set_window_title, /* void (*set_window_title)(char *title); */
27  NULL, /* int (*set_window_pos)(int x, int y); */
28  fb_dos_vesa_fetch_modes, /* int *(*fetch_modes)(int depth, int *size); */
29  NULL, /* void (*flip)(void); */
30  NULL /* void (*poll_events)(void); */
31 };
32 
33 static int data_locked = FALSE;
34 static void (*fb_dos_vesa_set_bank)(void) = NULL;
35 static BLITTER *blitter = NULL;
36 static unsigned char *buffer = NULL;
37 
39 
40 static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags)
41 {
42  int depth = MAX(8, depth_arg);
43  int is_rgb = FALSE;
44  int bpp;
45 
46  fb_dos_detect();
48 
49  if (flags & DRIVER_OPENGL)
50  return -1;
51 
52  if (!fb_dos.vesa_ok)
53  return -1;
54 
55  if (fb_dos_vesa_set_mode(w, h, depth, FALSE))
56  return -1;
57 
59 
62  else
64 
65  refresh_rate = 60; /* FIXME */
66 
67  is_rgb = (depth > 8) && (fb_dos.vesa_mode_info.RedFieldPosition == 0);
68 
70  bpp = 15;
72  bpp = 16;
73  else
75 
76  if( depth != bpp || is_rgb )
77  {
78  blitter = fb_hGetBlitter(bpp, is_rgb);
79  if( !blitter )
80  return -1;
81 
83  if( !buffer )
84  return -1;
85  }
86  else
87  {
88  blitter = NULL;
89  buffer = NULL;
90  }
91 
94  fb_dos_lock_data( &blitter, sizeof(blitter) );
97  if( buffer )
98  {
99  fb_dos_lock_data( &buffer, sizeof(buffer) );
101  }
102  data_locked = TRUE;
103 
105  fb_dos.update_len = (unsigned int)end_of_driver_update - (unsigned int)driver_update;
107 
108  return fb_dos_init(title, w, h, depth, refresh_rate, flags);
109 }
110 
111 static void driver_exit(void)
112 {
113  if( data_locked )
114  {
117  fb_dos_unlock_data( &blitter, sizeof(blitter) );
120  data_locked = FALSE;
121  }
122 
123  if( buffer )
124  {
125  fb_dos_unlock_data( &buffer, sizeof(buffer) );
127  free( buffer );
128  buffer = NULL;
129  }
130 
131  fb_dos_exit();
132 }
133 
134 static void fb_dos_vesa_set_bank_int(void)
135 {
136  /* set write bank of window A based on fb_dos_vesa_bank_number */
137  fb_dos.regs.x.ax = 0x4F05;
138  fb_dos.regs.x.bx = 0;
140  __dpmi_int(0x10, &fb_dos.regs);
141 }
142 static void fb_dos_vesa_set_bank_int_end(void) { }
143 
144 static void driver_update(void)
145 {
146  int curr_bank = -1;
147  unsigned char *memory_buffer;
148  unsigned char *framebuffer;
149  int framebuffer_start;
150  int bank_size;
151  int bank_granularity;
152  int bank_add;
153  int todo;
154  int copy_size;
155  int y1, y2;
156 
157  if( blitter )
158  {
160  framebuffer = buffer;
161  }
162  else
163  {
164  framebuffer = __fb_gfx->framebuffer;
165  }
166 
167  bank_size = fb_dos.vesa_mode_info.WinSize * 1024;
168  bank_granularity = fb_dos.vesa_mode_info.WinGranularity * 1024;
169  bank_add = bank_size / bank_granularity;
170 
171  for (y1 = 0; y1 < fb_dos.h; y1++) {
172  if (__fb_gfx->dirty[y1]) {
173  for (y2 = fb_dos.h - 1; !__fb_gfx->dirty[y2]; y2--)
174  ;
175 
176  fb_dos_vesa_bank_number = (y1 * __fb_gfx->pitch) / bank_granularity;
177 
178  framebuffer_start = fb_dos_vesa_bank_number * bank_granularity;
179 
180  todo = ((y2 + 1) * __fb_gfx->pitch) - framebuffer_start;
181 
182  memory_buffer = framebuffer + framebuffer_start;
183 
184  while (todo > 0) {
185  /* select the appropriate bank */
186  if (curr_bank != fb_dos_vesa_bank_number) {
187  curr_bank = fb_dos_vesa_bank_number;
188 
190  }
191 
192  /* how much can we copy in one go? */
193  if (todo > bank_size)
194  copy_size = bank_size;
195  else
196  copy_size = todo;
197 
198  /* copy a bank of data to the screen */
199  dosmemput(memory_buffer, copy_size, 0xA0000);
200 
201  /* move on to the next bank of data */
202  todo -= copy_size;
203  memory_buffer += copy_size;
204  fb_dos_vesa_bank_number += bank_add;
205  }
206 
207  break;
208  }
209  }
210 }
211 static void end_of_driver_update(void) { /* do not remove */ }