djgpp.c

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

Generated on Sun Nov 11 15:52:55 2007 for AllegroGL by  doxygen 1.5.2