AllegroGL  0.4.4
djgpp.c
1 /* This code is (C) AllegroGL contributors, and double licensed under
2  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3  */
4 /*----------------------------------------------------------------
5  * amesa.c -- Allegro-Mesa interfacing
6  *----------------------------------------------------------------
7  * This is the interface module for use AllegroGL with Mesa using the AMesa driver.
8  */
9 #include <string.h>
10 
11 #include <GL/gl.h>
12 #include <GL/amesa.h>
13 
14 #include <allegro.h>
15 #include <allegro/internal/aintern.h>
16 
17 #include "alleggl.h"
18 #include "allglint.h"
19 #include "glvtable.h"
20 
21 
22 static void allegro_gl_amesa_exit(BITMAP *bmp);
23 static void __allegro_gl_init_texture_read_format(void);
24 
25 #ifdef GFX_OPENGL_FULLSCREEN
26 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int color_depth);
27 
28 GFX_DRIVER gfx_allegro_gl_fullscreen =
29 {
31  empty_string,
32  empty_string,
33  "AllegroGL Fullscreen (AMesa)",
34  allegro_gl_amesa_fullscreen_init,
35  allegro_gl_amesa_exit,
36  NULL,
37  NULL, //_xwin_vsync,
38  NULL,
39  NULL, NULL, NULL,
42  NULL, NULL, /* No show/request video bitmaps */
43  NULL, NULL,
44  allegro_gl_set_mouse_sprite,
45  allegro_gl_show_mouse,
46  allegro_gl_hide_mouse,
47  allegro_gl_move_mouse,
48  NULL,
49  NULL, NULL,
50  NULL, /* No fetch_mode_list */
51  0, 0,
52  0,
53  0, 0,
54  0,
55  0,
56  FALSE /* Windowed mode */
57 };
58 #endif /* GFX_OPENGL_FULLSCREEN */
59 
60 
61 #ifdef GFX_OPENGL_WINDOWED
62 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int color_depth);
63 
64 GFX_DRIVER gfx_allegro_gl_windowed =
65 {
67  empty_string,
68  empty_string,
69  "AllegroGL Windowed (AMesa)",
70  allegro_gl_amesa_windowed_init,
71  allegro_gl_amesa_exit,
72  NULL,
73  NULL, //_xwin_vsync,
74  NULL,
75  NULL, NULL, NULL,
78  NULL, NULL, /* No show/request video bitmaps */
79  NULL, NULL,
80  allegro_gl_set_mouse_sprite,
81  allegro_gl_show_mouse,
82  allegro_gl_hide_mouse,
83  allegro_gl_move_mouse,
84  NULL,
85  NULL, NULL,
86  NULL, /* No fetch_mode_list */
87  0, 0,
88  0,
89  0, 0,
90  0,
91  0,
92  TRUE /* Windowed mode */
93 };
94 #endif /* GFX_OPENGL_WINDOWED */
95 
96 
97 
98 static int allegro_gl_amesa_create_window (int fullscreen);
99 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv, int w, int h, int depth);
100 
101 struct AMESA_DATA {
102  int fullscreen;
103  AMesaVisual visual;
104  AMesaBuffer buffer;
105  AMesaContext context;
106 } AMESA_DATA;
107 
108 static struct AMESA_DATA _amesa;
109 static struct allegro_gl_driver allegro_gl_amesa;
110 
111 static BITMAP* subscreen = NULL; /* Sub_bitmap of the virtual screen */
112 static BITMAP* saved_screen = NULL; /* Saves screen address */
113 
114 GFX_DRIVER *amesa_gfx_driver = NULL;
115 
116 static GFX_VTABLE allegro_gl_generic_vtable;
117 static GFX_VTABLE *old_vtable;
118 
119 
120 
121 /* allegro_gl_amesa_create_screen:
122  * Creates screen bitmap.
123  */
124 static BITMAP *allegro_gl_amesa_create_screen(int w, int h, int vw, int vh, int depth, int fullscreen)
125 {
126  int _keyboard_was_installed = FALSE;
127  int _mouse_was_installed = FALSE;
128  GFX_VTABLE vtable, *pvtable;
129 
130  pvtable = &vtable;
131 
132  if (keyboard_driver) {
133  _keyboard_was_installed = TRUE;
134  remove_keyboard();
135  TRACE("* Note * amesa_create_screen: Removing Keyboard...\n");
136  }
137 
138  if (mouse_driver) {
139  _mouse_was_installed = TRUE;
140  remove_mouse();
141  TRACE("* Note * amesa_create_screen: Removing Mouse...\n");
142  }
143 
144  if ((w == 0) && (h == 0)) {
145  w = 640;
146  h = 480;
147  }
148 
149  if ((vw > w) || (vh > h)) {
150  ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
151  get_config_text ("OpenGL drivers do not support virtual screens"));
152  return NULL;
153  }
154 
155  allegro_gl_display_info.w = w;
156  allegro_gl_display_info.h = h;
157 
158  if (allegro_gl_amesa_create_window(fullscreen)) {
159  if (fullscreen) {
160  ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
161  get_config_text ("Unable to switch in AMesa fullscreen"));
162  }
163  else {
164  ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
165  get_config_text ("Unable to create AMesa window"));
166  }
167  return NULL;
168  }
169 
170  /* If pixel format is Allegro compatible, set up Allegro correctly. */
171 
172  if (fullscreen) {
173 #ifdef GFX_OPENGL_FULLSCREEN
174  allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_fullscreen, w, h, allegro_gl_display_info.colour_depth);
175 #endif
176  }
177  else {
178 #ifdef GFX_OPENGL_WINDOWED
179  allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_windowed, w, h, allegro_gl_display_info.colour_depth);
180 #endif
181  }
182 
183  if (!allegro_gl_screen) {
184  ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
185  get_config_text ("Error creating screen bitmap"));
186  return NULL;
187  }
188 
189  __allegro_gl_valid_context = TRUE;
190  __allegro_gl_driver = &allegro_gl_amesa;
191  LOCK_DATA(&_amesa, sizeof(AMESA_DATA));
192  LOCK_DATA(__allegro_gl_driver, sizeof(struct allegro_gl_driver));
193 
194  /* save the old vtable and create a copy */
195  old_vtable = allegro_gl_screen->vtable;
196  memcpy(&allegro_gl_generic_vtable, allegro_gl_screen->vtable,
197  sizeof(GFX_VTABLE));
198  allegro_gl_screen->vtable = &allegro_gl_generic_vtable;
199 
200  /* The generic driver does not use the glvtable (since it already uses
201  * 'pure' Allegro gfx functions. However it needs the AGL-specific
202  * draw_glyph method.
203  * Hence this hack : we call __allegro_gl__glvtable_update_vtable with
204  * 'pvtable' as a parameter since we do not want the regular
205  * allegro_gl_screen->vtable to be crushed.
206  */
207  __allegro_gl__glvtable_update_vtable(&pvtable);
208  allegro_gl_screen->vtable->draw_glyph = pvtable->draw_glyph;
209  memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
210  allegro_gl_screen->vtable = &_screen_vtable;
211  __allegro_gl_init_screen_mode();
212 
213  /* Print out OpenGL version info */
214  TRACE("\n\nOpenGL Version: %s\nVendor: %s\nRenderer: %s\n",
215  (const char*)glGetString(GL_VERSION),
216  (const char*)glGetString(GL_VENDOR),
217  (const char*)glGetString(GL_RENDERER));
218 
219  /* Prints out OpenGL extensions info and activates needed extensions */
220  __allegro_gl_manage_extensions();
221  __allegro_gl_init_texture_read_format();
222 
223  if (_keyboard_was_installed) {
224  install_keyboard();
225  TRACE("* Note * amesa_create_screen: Installing Keyboard...\n");
226  }
227 
228  if (_mouse_was_installed) {
229  install_mouse();
230  TRACE("* Note * amesa_create_screen: Installing Mouse...\n");
231  }
232 
233  /* XXX <rohannessian> Maybe we should leave this for autodetection? */
234  gfx_capabilities |= GFX_HW_CURSOR;
235 
236  allegro_gl_info.is_mesa_driver = TRUE;
237  _amesa.fullscreen = fullscreen;
238  return allegro_gl_screen;
239 }
240 
241 
242 
243 #ifdef GFX_OPENGL_WINDOWED
244 /* allegro_gl_amesa_windowed_init:
245  * Creates screen bitmap for windowed driver.
246  */
247 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int depth)
248 {
249  return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, FALSE);
250 }
251 #endif
252 
253 
254 
255 #ifdef GFX_OPENGL_FULLSCREEN
256 /* allegro_gl_amesa_fullscreen_init:
257  * Creates screen bitmap for fullscreen driver.
258  */
259 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int depth)
260 {
261  return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, TRUE);
262 }
263 #endif
264 
265 
266 
267 /* allegro_gl_amesa_exit:
268  * Shuts down the driver (shared between windowed and full-screen)
269  */
270 static void allegro_gl_amesa_exit(BITMAP *bmp)
271 {
272  /* Restore the screen to its intial value */
273  screen = saved_screen;
274  if (subscreen)
275  destroy_bitmap(subscreen);
276 
277  amesa_gfx_driver->exit(screen);
278 
279  AMesaMakeCurrent(_amesa.context, NULL);
280  AMesaDestroyVisual(_amesa.visual);
281  AMesaDestroyBuffer(_amesa.buffer);
282  AMesaDestroyContext(_amesa.context);
283 
284  __allegro_gl_valid_context = FALSE;
285 }
286 
287 
288 
289 static void amesa_choose_gfx_mode(_DRIVER_INFO *driver_info, int *w, int *h,
290  int *colour_depth)
291 {
292  GFX_MODE_LIST *mode_list;
293  GFX_MODE *mode;
294  int i;
295 
296  TRACE("* Note * amesa_choose_gfx_mode: GFX driver : %s\n",
297  ((GFX_DRIVER*)driver_info->driver)->ascii_name);
298 
299  /* Try to find a mode which resolution and color depth are higher or
300  * equal to those requested
301  */
302  mode_list = get_gfx_mode_list(driver_info->id);
303 
304  if (mode_list) {
305  TRACE("* Note * amesa_choose_gfx_mode: %i modes\n",
306  mode_list->num_modes);
307 
308  mode = mode_list->mode;
309 
310  for (i = 0; i < mode_list->num_modes; i++) {
311  TRACE("Mode %i : %ix%i %i bpp\n", i, mode->width, mode->height,
312  mode->bpp);
313  if ((mode->width >= *w) && (mode->height >= *h) &&
314  (mode->bpp >= *colour_depth)) {
315  break;
316  }
317  if (mode->width) {
318  mode++;
319  }
320  }
321  if ((mode->width) && (mode->height) && (mode->bpp)) {
322  allegro_gl_display_info.w = *w = mode->width;
323  allegro_gl_display_info.h = *h = mode->height;
324  allegro_gl_display_info.colour_depth = *colour_depth = mode->bpp;
325  }
326  TRACE("Best Mode : %ix%i %i bpp\n", *w, *h, *colour_depth);
327  destroy_gfx_mode_list(mode_list);
328  }
329  else {
330  TRACE("** Warning ** amesa_choose_gfx_mode: Can not list modes...\n"
331  "Trying %ix%i %i bpp anyway\n", *w, *h, *colour_depth);
332  }
333 }
334 
335 
336 
337 /* amesa_set_gfx_mode :
338  * A light version of set_gfx_mode since when this function is reached we are
339  * ALREADY in set_gfx_mode. No need to initialize some parameters.
340  * Moreover we must choose our driver in saved_gfx_drivers and set the real
341  * gfx driver (i.e. the GFX_OPENGL one) the right way.
342  */
343 static int amesa_set_gfx_mode(int fullscreen)
344 {
345  extern void blit_end();
346  _DRIVER_INFO *driver_list;
347  int tried = FALSE;
348  char buf[512], tmp[64];
349  int c, n;
350  int card = GFX_AUTODETECT;
351  int w = allegro_gl_display_info.w;
352  int h = allegro_gl_display_info.h;
353  int check_mode = TRUE, require_window = FALSE;
354 
355  driver_list = saved_gfx_drivers();
356 
357  if (!fullscreen)
358  require_window = TRUE;
359 
360  /* try the drivers that are listed in the config file */
361  for (n=-2; n<255; n++) {
362  switch (n) {
363 
364  case -2:
365  /* example: gfx_card_640x480x16 = */
366  usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h,
367  _color_depth);
368  break;
369 
370  case -1:
371  /* example: gfx_card_24bpp = */
372  usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp),
373  _color_depth);
374  break;
375 
376  case 0:
377  /* example: gfx_card = */
378  ustrcpy(buf, uconvert_ascii("gfx_card", tmp));
379  break;
380 
381  default:
382  /* example: gfx_card1 = */
383  usprintf(buf, uconvert_ascii("gfx_card%d", tmp), n);
384  break;
385  }
386  card = get_config_id(uconvert_ascii("graphics", tmp), buf,
387  GFX_AUTODETECT);
388 
389  if (card != GFX_AUTODETECT) {
390 
391  for (c=0; driver_list[c].driver; c++) {
392  if (driver_list[c].id == card) {
393  amesa_gfx_driver = driver_list[c].driver;
394 
395  if (check_mode) {
396  if ( ((require_window) && (!amesa_gfx_driver->windowed))
397  || ((!require_window)
398  && (amesa_gfx_driver->windowed))) {
399 
400  amesa_gfx_driver = NULL;
401  continue;
402  }
403  }
404  break;
405  }
406  }
407 
408  if (amesa_gfx_driver) {
409  tried = TRUE;
410  amesa_gfx_driver->name = amesa_gfx_driver->desc
411  = get_config_text(amesa_gfx_driver->ascii_name);
412 
413  amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
414 
415  screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
416  if (screen) {
417  break;
418  }
419  else {
420  amesa_gfx_driver = NULL;
421  }
422  }
423  }
424  else {
425  if (n > 1) {
426  break;
427  }
428  }
429  }
430 
431  if (!tried) {
432  for (c=0; driver_list[c].driver; c++) {
433 
434  if (driver_list[c].autodetect) {
435 
436  amesa_gfx_driver = driver_list[c].driver;
437  if (check_mode) {
438  if (((require_window) && (!amesa_gfx_driver->windowed)) ||
439  ((!require_window) && (amesa_gfx_driver->windowed)))
440  continue;
441  }
442 
443  amesa_gfx_driver->name = amesa_gfx_driver->desc
444  = get_config_text(amesa_gfx_driver->ascii_name);
445 
446  amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
447 
448  screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
449 
450  if (screen) {
451  break;
452  }
453  }
454  }
455  }
456 
457  if (!screen) {
458  amesa_gfx_driver = NULL;
459  return -1;
460  }
461 
462  LOCK_DATA(amesa_gfx_driver, sizeof(GFX_DRIVER));
463  _register_switch_bitmap(screen, NULL);
464 
465  return 0;
466 }
467 
468 
469 
470 /* create_window:
471  * Based on Bernhard Tschirren AMesa GLUT code.
472  */
473 static int allegro_gl_amesa_create_window (int fullscreen)
474 {
475  if (!allegro_gl_display_info.colour_depth)
476  allegro_gl_display_info.colour_depth = _color_depth;
477 
478  set_color_depth(allegro_gl_display_info.colour_depth);
479 
480  if (amesa_set_gfx_mode(fullscreen)) {
481  TRACE("** ERROR ** amesa_create_window: Unable to set a gfx mode!\n");
482  return 1;
483  }
484 
485  _amesa.visual = AMesaCreateVisual(allegro_gl_display_info.doublebuffered,
486  allegro_gl_display_info.colour_depth,
487  GL_TRUE, /* RGBA Mode */
488  allegro_gl_display_info.depth_size,
489  allegro_gl_display_info.stencil_size,
490  allegro_gl_display_info.accum_size.rgba.r,
491  allegro_gl_display_info.accum_size.rgba.g,
492  allegro_gl_display_info.accum_size.rgba.b,
493  allegro_gl_display_info.accum_size.rgba.a
494  );
495  if (!_amesa.visual) {
496  TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
497  "Visual\n");
498  return 1;
499  }
500 
501  _amesa.context = AMesaCreateContext(_amesa.visual, NULL);
502  if (!_amesa.context) {
503  TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
504  "Context\n");
505  AMesaDestroyVisual(_amesa.visual);
506  return 1;
507  }
508 
509  if ((screen->w != allegro_gl_display_info.w)
510  || (screen->h != allegro_gl_display_info.h)) {
511 
512  subscreen = create_sub_bitmap(screen, 0, 0,
513  allegro_gl_display_info.w, allegro_gl_display_info.h);
514 
515  _amesa.buffer = AMesaCreateBuffer(_amesa.visual, subscreen);
516 
517  TRACE("** Note ** amesa_create_window: Screen : %ix%i %i bpp\n",
518  ubscreen->w, subscreen->h, bitmap_color_depth(subscreen));
519  }
520  else {
521  _amesa.buffer = AMesaCreateBuffer(_amesa.visual, screen);
522  }
523 
524  if (!_amesa.buffer) {
525  AMesaDestroyContext(_amesa.context);
526  AMesaDestroyVisual(_amesa.visual);
527  TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
528  "Buffer\n");
529  return 1;
530  }
531 
532  if (!AMesaMakeCurrent(_amesa.context, _amesa.buffer)) {
533  AMesaDestroyContext(_amesa.context);
534  AMesaDestroyVisual(_amesa.visual);
535  AMesaDestroyBuffer(_amesa.buffer);
536  TRACE("** ERROR ** amesa_create_window: Unable to make context "
537  "current\n");
538  return 1;
539  }
540 
541  saved_screen = screen;
542  return 0;
543 }
544 
545 
546 
547 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv,
548  int w, int h, int depth)
549 {
550  drv->w = w;
551  drv->h = h;
552  drv->linear = amesa_gfx_driver->linear;
553  drv->bank_size = amesa_gfx_driver->bank_size;
554  drv->bank_gran = amesa_gfx_driver->bank_gran;
555  drv->vid_mem = amesa_gfx_driver->vid_mem;
556  drv->vid_phys_base = amesa_gfx_driver->vid_phys_base;
557 
558  return AMesaGetColorBuffer(_amesa.buffer, AMESA_ACTIVE);
559 }
560 
561 
562 
563 static void __allegro_gl_init_texture_read_format(void)
564 {
565  /* 8 bpp (true color mode) */
566  __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
567 
568  /* 15 bpp */
569  if (_rgb_r_shift_15 > _rgb_b_shift_15) {
570  __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
571  if (_rgb_r_shift_15 == 10) {
572  __allegro_gl_texture_components[1] = GL_BGRA;
573  }
574  }
575  else {
576  __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_1_5_5_5_REV;
577  }
578 
579  /* 16 bpp */
580  if (_rgb_r_shift_16 > _rgb_b_shift_16) {
581  __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
582  }
583  else {
584  __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5_REV;
585  }
586 
587  /* 24 bpp */
588  __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
589 
590  /* 32 bpp */
591  if (_rgb_r_shift_32 > _rgb_b_shift_32) {
592  __allegro_gl_texture_read_format[4] = GL_UNSIGNED_INT_8_8_8_8_REV;
593  if (_rgb_r_shift_32 == 16) {
594  __allegro_gl_texture_components[4] = GL_BGRA;
595  }
596  }
597  else {
598  __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
599  }
600 }
601 
602 
603 
604 /******************************/
605 /* AllegroGL driver functions */
606 /******************************/
607 
608 /* flip:
609  * Does a page flip / double buffer copy / whatever it really is.
610  */
611 static void amesa_flip (void)
612 {
613  AMesaSwapBuffers (_amesa.buffer);
614 }
615 
616 
617 
618 /* gl_on, gl_off:
619  * Switches to/from GL mode.
620  */
621 static void amesa_gl_on (void)
622 {
623 }
624 
625 
626 
627 static void amesa_gl_off (void)
628 {
629 }
630 
631 
632 
633 /*****************/
634 /* Driver struct */
635 /*****************/
636 
637 static struct allegro_gl_driver allegro_gl_amesa = {
638  amesa_flip,
639  amesa_gl_on,
640  amesa_gl_off
641 };
642 
#define GFX_OPENGL_FULLSCREEN
Fullscreen OpenGL graphics driver for Allegro.
Definition: alleggl.h:435
#define GFX_OPENGL_WINDOWED
Windowed OpenGL graphics driver for Allegro.
Definition: alleggl.h:433
void allegro_gl_destroy_video_bitmap(BITMAP *bmp)
destroy_video_bitmap() overload.
Definition: videovtb.c:308
Main header file for AllegroGL.
BITMAP * allegro_gl_screen
Direct-mode GL `screen&#39; bitmap.
Definition: alleggl.c:62
BITMAP * allegro_gl_create_video_bitmap(int w, int h)
create_video_bitmap() overload.
Definition: videovtb.c:344