djgpp.c

00001 /*----------------------------------------------------------------
00002  * amesa.c -- Allegro-Mesa interfacing
00003  *----------------------------------------------------------------
00004  *  This is the interface module for use AllegroGL with Mesa using the AMesa driver.
00005  */
00006 #include <string.h>
00007 
00008 #include <GL/gl.h>
00009 #include <GL/amesa.h>
00010 
00011 #include <allegro.h>
00012 #include <allegro/internal/aintern.h>
00013 
00014 #include "alleggl.h"
00015 #include "allglint.h"
00016 #include "glvtable.h"
00017 
00018 
00019 static void allegro_gl_amesa_exit(BITMAP *bmp);
00020 static void __allegro_gl_init_texture_read_format(void);
00021 
00022 #ifdef GFX_OPENGL_FULLSCREEN
00023 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int color_depth);
00024 
00025 GFX_DRIVER gfx_allegro_gl_fullscreen =
00026 {
00027    GFX_OPENGL_FULLSCREEN,
00028    empty_string,
00029    empty_string,
00030    "AllegroGL Fullscreen (AMesa)",
00031    allegro_gl_amesa_fullscreen_init,
00032    allegro_gl_amesa_exit,
00033    NULL,
00034    NULL,               //_xwin_vsync,
00035    NULL,
00036    NULL, NULL, NULL,
00037    allegro_gl_create_video_bitmap,
00038    allegro_gl_destroy_video_bitmap,
00039    NULL, NULL,                  /* No show/request video bitmaps */
00040    NULL, NULL,
00041    allegro_gl_set_mouse_sprite,
00042    allegro_gl_show_mouse,
00043    allegro_gl_hide_mouse,
00044    allegro_gl_move_mouse,
00045    NULL,
00046    NULL, NULL,
00047    NULL,                        /* No fetch_mode_list */
00048    0, 0,
00049    0,
00050    0, 0,
00051    0,
00052    0,
00053    FALSE                        /* Windowed mode */
00054 };
00055 #endif /* GFX_OPENGL_FULLSCREEN */
00056 
00057 
00058 #ifdef GFX_OPENGL_WINDOWED
00059 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int color_depth);
00060 
00061 GFX_DRIVER gfx_allegro_gl_windowed =
00062 {
00063    GFX_OPENGL_WINDOWED,
00064    empty_string,
00065    empty_string,
00066    "AllegroGL Windowed (AMesa)",
00067    allegro_gl_amesa_windowed_init,
00068    allegro_gl_amesa_exit,
00069    NULL,
00070    NULL,               //_xwin_vsync,
00071    NULL,
00072    NULL, NULL, NULL,
00073    allegro_gl_create_video_bitmap,
00074    allegro_gl_destroy_video_bitmap,
00075    NULL, NULL,                  /* No show/request video bitmaps */
00076    NULL, NULL,
00077    allegro_gl_set_mouse_sprite,
00078    allegro_gl_show_mouse,
00079    allegro_gl_hide_mouse,
00080    allegro_gl_move_mouse,
00081    NULL,
00082    NULL, NULL,
00083    NULL,                        /* No fetch_mode_list */
00084    0, 0,
00085    0,
00086    0, 0,
00087    0,
00088    0,
00089    TRUE                         /* Windowed mode */
00090 };
00091 #endif /* GFX_OPENGL_WINDOWED */
00092 
00093 
00094 
00095 static int allegro_gl_amesa_create_window (int fullscreen);
00096 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv, int w, int h, int depth);
00097 
00098 struct AMESA_DATA {
00099     int          fullscreen;
00100     AMesaVisual  visual;
00101     AMesaBuffer  buffer;
00102     AMesaContext context;
00103 } AMESA_DATA;
00104 
00105 static struct AMESA_DATA _amesa;
00106 static struct allegro_gl_driver allegro_gl_amesa;
00107 
00108 static BITMAP* subscreen = NULL;                 /* Sub_bitmap of the virtual screen */
00109 static BITMAP* saved_screen = NULL;              /* Saves screen address */
00110 
00111 GFX_DRIVER *amesa_gfx_driver = NULL;
00112 
00113 static GFX_VTABLE allegro_gl_generic_vtable;
00114 static GFX_VTABLE *old_vtable;
00115 
00116 
00117 
00118 /* allegro_gl_amesa_create_screen:
00119  *  Creates screen bitmap.
00120  */
00121 static BITMAP *allegro_gl_amesa_create_screen(int w, int h, int vw, int vh, int depth, int fullscreen)
00122 {
00123     int _keyboard_was_installed = FALSE;
00124     int _mouse_was_installed = FALSE;
00125     GFX_VTABLE vtable, *pvtable;
00126 
00127     pvtable = &vtable;
00128     
00129     if (keyboard_driver) {
00130         _keyboard_was_installed = TRUE;
00131         remove_keyboard();
00132         TRACE("* Note * amesa_create_screen: Removing Keyboard...\n");
00133     }
00134     
00135     if (mouse_driver) {
00136         _mouse_was_installed = TRUE;
00137         remove_mouse();
00138         TRACE("* Note * amesa_create_screen: Removing Mouse...\n");
00139     }
00140     
00141     if ((w == 0) && (h == 0)) {
00142         w = 640;
00143         h = 480;
00144     }
00145 
00146     if ((vw > w) || (vh > h)) {
00147         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00148              get_config_text ("OpenGL drivers do not support virtual screens"));
00149         return NULL;
00150     }
00151 
00152     allegro_gl_display_info.w = w;
00153     allegro_gl_display_info.h = h;
00154 
00155     if (allegro_gl_amesa_create_window(fullscreen)) {
00156         if (fullscreen) {
00157             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00158                       get_config_text ("Unable to switch in AMesa fullscreen"));
00159         }
00160         else {
00161             ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00162                       get_config_text ("Unable to create AMesa window"));
00163         }
00164         return NULL;
00165     }
00166 
00167     /* If pixel format is Allegro compatible, set up Allegro correctly. */
00168 
00169     if (fullscreen) {
00170 #ifdef GFX_OPENGL_FULLSCREEN
00171         allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_fullscreen, w, h, allegro_gl_display_info.colour_depth);
00172 #endif
00173     }
00174     else {
00175 #ifdef GFX_OPENGL_WINDOWED
00176         allegro_gl_screen = allegro_gl_amesa_create_screen_bitmap (&gfx_allegro_gl_windowed, w, h, allegro_gl_display_info.colour_depth);
00177 #endif
00178     }
00179 
00180     if (!allegro_gl_screen) {
00181         ustrzcpy (allegro_error, ALLEGRO_ERROR_SIZE,
00182                   get_config_text ("Error creating screen bitmap"));
00183         return NULL;
00184     }
00185     
00186     __allegro_gl_valid_context = TRUE;
00187     __allegro_gl_driver = &allegro_gl_amesa;
00188     LOCK_DATA(&_amesa, sizeof(AMESA_DATA));
00189     LOCK_DATA(__allegro_gl_driver, sizeof(struct allegro_gl_driver));
00190 
00191     /* save the old vtable and create a copy */
00192     old_vtable = allegro_gl_screen->vtable;
00193     memcpy(&allegro_gl_generic_vtable, allegro_gl_screen->vtable,
00194            sizeof(GFX_VTABLE));
00195     allegro_gl_screen->vtable = &allegro_gl_generic_vtable;
00196 
00197     /* The generic driver does not use the glvtable (since it already uses
00198      * 'pure' Allegro gfx functions. However it needs the AGL-specific
00199      * draw_glyph method. 
00200      * Hence this hack : we call __allegro_gl__glvtable_update_vtable with
00201      * 'pvtable' as a parameter since we do not want the regular
00202      * allegro_gl_screen->vtable to be crushed.
00203      */
00204     __allegro_gl__glvtable_update_vtable(&pvtable);
00205     allegro_gl_screen->vtable->draw_glyph = pvtable->draw_glyph;
00206     memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE));
00207     allegro_gl_screen->vtable = &_screen_vtable;
00208     __allegro_gl_init_screen_mode();
00209 
00210     /* Print out OpenGL version info */
00211     TRACE("\n\nOpenGL Version: %s\nVendor: %s\nRenderer: %s\n",
00212           (const char*)glGetString(GL_VERSION),
00213           (const char*)glGetString(GL_VENDOR),
00214           (const char*)glGetString(GL_RENDERER));
00215     
00216     /* Prints out OpenGL extensions info and activates needed extensions */
00217     __allegro_gl_manage_extensions();
00218     __allegro_gl_init_texture_read_format();    
00219 
00220     if (_keyboard_was_installed) {
00221         install_keyboard();
00222         TRACE("* Note * amesa_create_screen: Installing Keyboard...\n");
00223     }
00224 
00225     if (_mouse_was_installed) {
00226         install_mouse();
00227         TRACE("* Note * amesa_create_screen: Installing Mouse...\n");
00228     }
00229     
00230     /* XXX <rohannessian> Maybe we should leave this for autodetection? */
00231     gfx_capabilities |= GFX_HW_CURSOR;
00232 
00233     allegro_gl_info.is_mesa_driver = TRUE;
00234     _amesa.fullscreen = fullscreen;
00235     return allegro_gl_screen;
00236 }
00237 
00238 
00239 
00240 #ifdef GFX_OPENGL_WINDOWED
00241 /* allegro_gl_amesa_windowed_init:
00242  *  Creates screen bitmap for windowed driver.
00243  */
00244 static BITMAP *allegro_gl_amesa_windowed_init(int w, int h, int vw, int vh, int depth)
00245 {
00246     return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, FALSE);
00247 }
00248 #endif
00249 
00250 
00251 
00252 #ifdef GFX_OPENGL_FULLSCREEN
00253 /* allegro_gl_amesa_fullscreen_init:
00254  *  Creates screen bitmap for fullscreen driver.
00255  */
00256 static BITMAP *allegro_gl_amesa_fullscreen_init(int w, int h, int vw, int vh, int depth)
00257 {
00258     return allegro_gl_amesa_create_screen(w, h, vw, vh, depth, TRUE);
00259 }
00260 #endif
00261 
00262 
00263 
00264 /* allegro_gl_amesa_exit:
00265  *  Shuts down the driver (shared between windowed and full-screen)
00266  */
00267 static void allegro_gl_amesa_exit(BITMAP *bmp)
00268 {
00269     /* Restore the screen to its intial value */
00270     screen = saved_screen;
00271     if (subscreen)
00272        destroy_bitmap(subscreen);
00273 
00274     amesa_gfx_driver->exit(screen);
00275    
00276     AMesaMakeCurrent(_amesa.context, NULL);
00277     AMesaDestroyVisual(_amesa.visual);
00278     AMesaDestroyBuffer(_amesa.buffer);
00279     AMesaDestroyContext(_amesa.context);
00280     
00281     __allegro_gl_valid_context = FALSE;
00282 }
00283 
00284 
00285 
00286 static void amesa_choose_gfx_mode(_DRIVER_INFO *driver_info, int *w, int *h,
00287                                   int *colour_depth)
00288 {
00289     GFX_MODE_LIST *mode_list;
00290     GFX_MODE *mode;
00291     int i;
00292 
00293     TRACE("* Note * amesa_choose_gfx_mode: GFX driver : %s\n",
00294           ((GFX_DRIVER*)driver_info->driver)->ascii_name);
00295 
00296     /* Try to find a mode which resolution and color depth are higher or
00297      * equal to those requested
00298      */
00299     mode_list = get_gfx_mode_list(driver_info->id);
00300 
00301     if (mode_list) {
00302         TRACE("* Note * amesa_choose_gfx_mode: %i modes\n",
00303               mode_list->num_modes);
00304 
00305         mode = mode_list->mode;
00306 
00307         for (i = 0; i < mode_list->num_modes; i++) {
00308             TRACE("Mode %i : %ix%i %i bpp\n", i, mode->width, mode->height,
00309                    mode->bpp);
00310             if ((mode->width >= *w) && (mode->height >= *h) &&
00311                 (mode->bpp >= *colour_depth)) {
00312                 break;
00313             }
00314             if (mode->width) {
00315                 mode++;
00316             }
00317         }
00318         if ((mode->width) && (mode->height) && (mode->bpp)) {
00319             allegro_gl_display_info.w = *w = mode->width;
00320             allegro_gl_display_info.h = *h = mode->height;
00321             allegro_gl_display_info.colour_depth = *colour_depth = mode->bpp;
00322         }
00323         TRACE("Best Mode : %ix%i %i bpp\n", *w, *h, *colour_depth);
00324         destroy_gfx_mode_list(mode_list);
00325     }
00326     else {
00327         TRACE("** Warning ** amesa_choose_gfx_mode: Can not list modes...\n"
00328               "Trying %ix%i %i bpp anyway\n", *w, *h, *colour_depth);
00329     }
00330 }
00331 
00332 
00333 
00334 /* amesa_set_gfx_mode :
00335  * A light version of set_gfx_mode since when this function is reached we are
00336  * ALREADY in set_gfx_mode. No need to initialize some parameters.
00337  * Moreover we must choose our driver in saved_gfx_drivers and set the real
00338  * gfx driver (i.e. the GFX_OPENGL one) the right way.
00339  */
00340 static int amesa_set_gfx_mode(int fullscreen)
00341 {
00342     extern void blit_end();
00343     _DRIVER_INFO *driver_list;
00344     int tried = FALSE;
00345     char buf[512], tmp[64];
00346     int c, n;
00347     int card = GFX_AUTODETECT;
00348     int w = allegro_gl_display_info.w;
00349     int h = allegro_gl_display_info.h;
00350     int check_mode = TRUE, require_window = FALSE;
00351 
00352     driver_list = saved_gfx_drivers();
00353 
00354     if (!fullscreen)
00355         require_window = TRUE;
00356 
00357     /* try the drivers that are listed in the config file */
00358     for (n=-2; n<255; n++) {
00359         switch (n) {
00360 
00361             case -2:
00362                 /* example: gfx_card_640x480x16 = */
00363                 usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h,
00364                          _color_depth);
00365                 break;
00366 
00367             case -1:
00368                 /* example: gfx_card_24bpp = */
00369                 usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp),
00370                          _color_depth);
00371                 break;
00372 
00373             case 0:
00374                 /* example: gfx_card = */
00375                 ustrcpy(buf, uconvert_ascii("gfx_card", tmp));
00376                 break;
00377 
00378             default:
00379                 /* example: gfx_card1 = */
00380                 usprintf(buf, uconvert_ascii("gfx_card%d", tmp), n);
00381             break;
00382         }
00383         card = get_config_id(uconvert_ascii("graphics", tmp), buf,
00384                              GFX_AUTODETECT);
00385 
00386         if (card != GFX_AUTODETECT) {
00387 
00388             for (c=0; driver_list[c].driver; c++) {
00389                 if (driver_list[c].id == card) {
00390                     amesa_gfx_driver = driver_list[c].driver;
00391                     
00392                     if (check_mode) {
00393                         if ( ((require_window) && (!amesa_gfx_driver->windowed))
00394                          || ((!require_window)
00395                           && (amesa_gfx_driver->windowed))) {
00396 
00397                             amesa_gfx_driver = NULL;
00398                             continue;
00399                         }
00400                     }
00401                     break;
00402                 }
00403             }
00404 
00405             if (amesa_gfx_driver) {
00406                 tried = TRUE;
00407                 amesa_gfx_driver->name = amesa_gfx_driver->desc
00408                                 = get_config_text(amesa_gfx_driver->ascii_name);
00409                 
00410                 amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
00411                 
00412                 screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
00413                 if (screen) {
00414                     break;
00415                 }
00416                 else {
00417                     amesa_gfx_driver = NULL;
00418                 }
00419             }
00420         }
00421         else {
00422             if (n > 1) {
00423                 break;
00424             }
00425         }
00426     }
00427 
00428     if (!tried) {
00429         for (c=0; driver_list[c].driver; c++) {
00430 
00431             if (driver_list[c].autodetect) {
00432                 
00433                 amesa_gfx_driver = driver_list[c].driver;
00434                 if (check_mode) {
00435                     if (((require_window) && (!amesa_gfx_driver->windowed)) ||
00436                        ((!require_window) && (amesa_gfx_driver->windowed)))
00437                         continue;
00438                 }
00439 
00440                 amesa_gfx_driver->name = amesa_gfx_driver->desc
00441                                 = get_config_text(amesa_gfx_driver->ascii_name);
00442 
00443                 amesa_choose_gfx_mode(&driver_list[c], &w, &h, &_color_depth);
00444 
00445                 screen = amesa_gfx_driver->init(w, h, 0, 0, _color_depth);
00446 
00447                 if (screen) {
00448                     break;
00449                 }
00450             }
00451         }
00452     }
00453 
00454     if (!screen) {
00455         amesa_gfx_driver = NULL;
00456         return -1;
00457     }
00458 
00459     LOCK_DATA(amesa_gfx_driver, sizeof(GFX_DRIVER));
00460     _register_switch_bitmap(screen, NULL);
00461 
00462     return 0;
00463 }
00464 
00465 
00466 
00467 /* create_window:
00468  *  Based on Bernhard Tschirren AMesa GLUT code.
00469  */
00470 static int allegro_gl_amesa_create_window (int fullscreen)
00471 {
00472     if (!allegro_gl_display_info.colour_depth)
00473         allegro_gl_display_info.colour_depth = _color_depth;
00474 
00475     set_color_depth(allegro_gl_display_info.colour_depth);
00476 
00477     if (amesa_set_gfx_mode(fullscreen)) {
00478         TRACE("** ERROR ** amesa_create_window: Unable to set a gfx mode!\n");
00479         return 1;
00480     }
00481 
00482     _amesa.visual  = AMesaCreateVisual(allegro_gl_display_info.doublebuffered,
00483                     allegro_gl_display_info.colour_depth,
00484                     GL_TRUE,                /* RGBA Mode */
00485                     allegro_gl_display_info.depth_size,
00486                     allegro_gl_display_info.stencil_size,
00487                     allegro_gl_display_info.accum_size.rgba.r,
00488                     allegro_gl_display_info.accum_size.rgba.g,
00489                     allegro_gl_display_info.accum_size.rgba.b,
00490                     allegro_gl_display_info.accum_size.rgba.a
00491                     );
00492     if (!_amesa.visual) {
00493         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00494               "Visual\n");
00495         return 1;
00496     }
00497 
00498     _amesa.context = AMesaCreateContext(_amesa.visual, NULL);
00499     if (!_amesa.context) {
00500         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00501               "Context\n");
00502         AMesaDestroyVisual(_amesa.visual);
00503         return 1;
00504     }
00505 
00506     if ((screen->w != allegro_gl_display_info.w)
00507      || (screen->h != allegro_gl_display_info.h)) {
00508 
00509         subscreen = create_sub_bitmap(screen, 0, 0,
00510                           allegro_gl_display_info.w, allegro_gl_display_info.h);
00511 
00512         _amesa.buffer = AMesaCreateBuffer(_amesa.visual, subscreen);
00513 
00514         TRACE("** Note ** amesa_create_window: Screen : %ix%i %i bpp\n",
00515               ubscreen->w, subscreen->h, bitmap_color_depth(subscreen));
00516     }
00517     else {
00518         _amesa.buffer = AMesaCreateBuffer(_amesa.visual, screen);
00519     }
00520 
00521     if (!_amesa.buffer) {
00522         AMesaDestroyContext(_amesa.context);
00523         AMesaDestroyVisual(_amesa.visual);
00524         TRACE("** ERROR ** amesa_create_window: Unable to create AMesa "
00525               "Buffer\n");
00526         return 1;
00527     }
00528 
00529     if (!AMesaMakeCurrent(_amesa.context, _amesa.buffer)) {
00530         AMesaDestroyContext(_amesa.context);
00531         AMesaDestroyVisual(_amesa.visual);
00532         AMesaDestroyBuffer(_amesa.buffer);
00533         TRACE("** ERROR ** amesa_create_window: Unable to make context "
00534               "current\n");
00535         return 1;
00536     }
00537 
00538     saved_screen = screen;
00539     return 0;
00540 }
00541 
00542 
00543 
00544 static BITMAP *allegro_gl_amesa_create_screen_bitmap (GFX_DRIVER *drv,
00545                                                       int w, int h, int depth)
00546 {
00547     drv->w = w;
00548     drv->h = h;
00549     drv->linear        = amesa_gfx_driver->linear;
00550     drv->bank_size     = amesa_gfx_driver->bank_size;
00551     drv->bank_gran     = amesa_gfx_driver->bank_gran;
00552     drv->vid_mem       = amesa_gfx_driver->vid_mem;
00553     drv->vid_phys_base = amesa_gfx_driver->vid_phys_base;
00554 
00555     return AMesaGetColorBuffer(_amesa.buffer, AMESA_ACTIVE);
00556 }
00557 
00558 
00559 
00560 static void __allegro_gl_init_texture_read_format(void)
00561 {
00562     /* 8 bpp (true color mode) */
00563     __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00564 
00565     /* 15 bpp */
00566     if (_rgb_r_shift_15 > _rgb_b_shift_15) {
00567         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
00568         if (_rgb_r_shift_15 == 10) {
00569             __allegro_gl_texture_components[1] = GL_BGRA;
00570         }
00571     }
00572     else {
00573         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_1_5_5_5_REV;
00574     }
00575 
00576     /* 16 bpp */
00577     if (_rgb_r_shift_16 > _rgb_b_shift_16) {
00578         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
00579     }
00580     else {
00581         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5_REV;
00582     }
00583 
00584     /* 24 bpp */
00585     __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00586 
00587     /* 32 bpp */
00588     if (_rgb_r_shift_32 > _rgb_b_shift_32) {
00589         __allegro_gl_texture_read_format[4] = GL_UNSIGNED_INT_8_8_8_8_REV;
00590         if (_rgb_r_shift_32 == 16) {
00591             __allegro_gl_texture_components[4] = GL_BGRA;
00592         }
00593     }
00594     else {
00595         __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
00596     }
00597 }
00598 
00599 
00600 
00601 /******************************/
00602 /* AllegroGL driver functions */
00603 /******************************/
00604 
00605 /* flip:
00606  *  Does a page flip / double buffer copy / whatever it really is.
00607  */
00608 static void amesa_flip (void)
00609 {
00610     AMesaSwapBuffers (_amesa.buffer);
00611 }
00612 
00613 
00614 
00615 /* gl_on, gl_off:
00616  *  Switches to/from GL mode.
00617  */
00618 static void amesa_gl_on (void)
00619 {
00620 }
00621 
00622 
00623 
00624 static void amesa_gl_off (void)
00625 {
00626 }
00627 
00628 
00629 
00630 /*****************/
00631 /* Driver struct */
00632 /*****************/
00633 
00634 static struct allegro_gl_driver allegro_gl_amesa = {
00635     amesa_flip,
00636     amesa_gl_on,
00637     amesa_gl_off
00638 };
00639 

Generated on Mon Apr 3 18:20:12 2006 for AllegroGL by  doxygen 1.4.6