00001
00002
00003
00004
00005
00006
00007
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,
00038 NULL,
00039 NULL, NULL, NULL,
00040 allegro_gl_create_video_bitmap,
00041 allegro_gl_destroy_video_bitmap,
00042 NULL, NULL,
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,
00051 0, 0,
00052 0,
00053 0, 0,
00054 0,
00055 0,
00056 FALSE
00057 };
00058 #endif
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,
00074 NULL,
00075 NULL, NULL, NULL,
00076 allegro_gl_create_video_bitmap,
00077 allegro_gl_destroy_video_bitmap,
00078 NULL, NULL,
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,
00087 0, 0,
00088 0,
00089 0, 0,
00090 0,
00091 0,
00092 TRUE
00093 };
00094 #endif
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;
00112 static BITMAP* saved_screen = NULL;
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
00122
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
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
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
00201
00202
00203
00204
00205
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
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
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
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
00245
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
00257
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
00268
00269
00270 static void allegro_gl_amesa_exit(BITMAP *bmp)
00271 {
00272
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
00300
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
00338
00339
00340
00341
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
00361 for (n=-2; n<255; n++) {
00362 switch (n) {
00363
00364 case -2:
00365
00366 usprintf(buf, uconvert_ascii("gfx_card_%dx%dx%d", tmp), w, h,
00367 _color_depth);
00368 break;
00369
00370 case -1:
00371
00372 usprintf(buf, uconvert_ascii("gfx_card_%dbpp", tmp),
00373 _color_depth);
00374 break;
00375
00376 case 0:
00377
00378 ustrcpy(buf, uconvert_ascii("gfx_card", tmp));
00379 break;
00380
00381 default:
00382
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
00471
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,
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
00566 __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00567
00568
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
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
00588 __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00589
00590
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
00606
00607
00608
00609
00610
00611 static void amesa_flip (void)
00612 {
00613 AMesaSwapBuffers (_amesa.buffer);
00614 }
00615
00616
00617
00618
00619
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
00635
00636
00637 static struct allegro_gl_driver allegro_gl_amesa = {
00638 amesa_flip,
00639 amesa_gl_on,
00640 amesa_gl_off
00641 };
00642