00001
00002
00003
00004
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,
00035 NULL,
00036 NULL, NULL, NULL,
00037 allegro_gl_create_video_bitmap,
00038 allegro_gl_destroy_video_bitmap,
00039 NULL, NULL,
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,
00048 0, 0,
00049 0,
00050 0, 0,
00051 0,
00052 0,
00053 FALSE
00054 };
00055 #endif
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,
00071 NULL,
00072 NULL, NULL, NULL,
00073 allegro_gl_create_video_bitmap,
00074 allegro_gl_destroy_video_bitmap,
00075 NULL, NULL,
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,
00084 0, 0,
00085 0,
00086 0, 0,
00087 0,
00088 0,
00089 TRUE
00090 };
00091 #endif
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;
00109 static BITMAP* saved_screen = NULL;
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
00119
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
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
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
00198
00199
00200
00201
00202
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
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
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
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
00242
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
00254
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
00265
00266
00267 static void allegro_gl_amesa_exit(BITMAP *bmp)
00268 {
00269
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
00297
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
00335
00336
00337
00338
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
00358 for (n=-2; n<255; n++) {
00359 switch (n) {
00360
00361 case -2:
00362
00363 usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h,
00364 _color_depth);
00365 break;
00366
00367 case -1:
00368
00369 usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp),
00370 _color_depth);
00371 break;
00372
00373 case 0:
00374
00375 ustrcpy(buf, uconvert_ascii("gfx_card", tmp));
00376 break;
00377
00378 default:
00379
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
00468
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,
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
00563 __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00564
00565
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
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
00585 __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00586
00587
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
00603
00604
00605
00606
00607
00608 static void amesa_flip (void)
00609 {
00610 AMesaSwapBuffers (_amesa.buffer);
00611 }
00612
00613
00614
00615
00616
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
00632
00633
00634 static struct allegro_gl_driver allegro_gl_amesa = {
00635 amesa_flip,
00636 amesa_gl_on,
00637 amesa_gl_off
00638 };
00639