AllegroGL 0.4.4
|
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 #include <string.h> 00005 #include <allegro.h> 00006 #include <allegro/internal/aintern.h> 00007 00008 00009 #include "alleggl.h" 00010 #include "glvtable.h" 00011 #include "allglint.h" 00012 00013 00014 static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h, 00015 int color_depth); 00016 static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h, 00017 int color_depth); 00018 static void allegro_gl_win_exit(struct BITMAP *b); 00019 static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void); 00020 00021 static struct allegro_gl_driver allegro_gl_win; 00022 00023 #define PREFIX_I "agl-win INFO: " 00024 #define PREFIX_W "agl-win WARNING: " 00025 #define PREFIX_E "agl-win ERROR: " 00026 00027 00028 static BITMAP *allegro_gl_screen = NULL; 00029 00030 00031 /* Windowed mode driver */ 00032 GFX_DRIVER gfx_allegro_gl_windowed = { 00033 GFX_OPENGL_WINDOWED, 00034 EMPTY_STRING, 00035 EMPTY_STRING, 00036 "AllegroGL Windowed (Win32)", 00037 allegro_gl_win_init_windowed, 00038 allegro_gl_win_exit, 00039 NULL, /* scrolling not implemented */ 00040 NULL, /* vsync, may use for flip? */ 00041 NULL, /* No h/w pallete, not using indexed mode */ 00042 NULL, NULL, /* Still no scrolling */ 00043 NULL, /* No triple buffering */ 00044 allegro_gl_create_video_bitmap, 00045 allegro_gl_destroy_video_bitmap, 00046 NULL, NULL, /* No show/request video bitmaps */ 00047 NULL, NULL, /* No system bitmaps */ 00048 allegro_gl_set_mouse_sprite, 00049 allegro_gl_show_mouse, 00050 allegro_gl_hide_mouse, 00051 allegro_gl_move_mouse, 00052 allegro_gl_drawing_mode, 00053 NULL, NULL, /* No video state stuff */ 00054 allegro_gl_set_blender_mode, 00055 NULL, /* No fetch_mode_list */ 00056 0,0, /* physical (not virtual!) screen size */ 00057 0, /* true if video memory is linear */ 00058 0, /* bank size, in bytes */ 00059 0, /* bank granularity, in bytes */ 00060 0, /* video memory size, in bytes */ 00061 0, /* physical address of video memory */ 00062 TRUE /* Windowed mode */ 00063 }; 00064 00065 00066 /* Fullscreen driver */ 00067 GFX_DRIVER gfx_allegro_gl_fullscreen = { 00068 GFX_OPENGL_FULLSCREEN, 00069 EMPTY_STRING, 00070 EMPTY_STRING, 00071 "AllegroGL Fullscreen (Win32)", 00072 allegro_gl_win_init_fullscreen, 00073 allegro_gl_win_exit, 00074 NULL, /* scrolling not implemented */ 00075 NULL, /* vsync, may use for flip? */ 00076 NULL, /* No h/w pallete, not using indexed mode */ 00077 NULL, NULL, /* Still no scrolling */ 00078 NULL, /* No triple buffering */ 00079 allegro_gl_create_video_bitmap, 00080 allegro_gl_destroy_video_bitmap, 00081 NULL, NULL, /* No show/request video bitmaps */ 00082 NULL, NULL, /* No system bitmaps */ 00083 allegro_gl_set_mouse_sprite, 00084 allegro_gl_show_mouse, 00085 allegro_gl_hide_mouse, 00086 allegro_gl_move_mouse, 00087 allegro_gl_drawing_mode, 00088 NULL, NULL, /* No video state stuff */ 00089 allegro_gl_set_blender_mode, 00090 allegro_gl_win_fetch_mode_list, /* fetch_mode_list */ 00091 0,0, /* physical (not virtual!) screen size */ 00092 0, /* true if video memory is linear */ 00093 0, /* bank size, in bytes */ 00094 0, /* bank granularity, in bytes */ 00095 0, /* video memory size, in bytes */ 00096 0, /* physical address of video memory */ 00097 FALSE /* Windowed mode */ 00098 }; 00099 00100 00101 /* XXX <rohannessian> We should move those variable definitions into a struct, 00102 * for when multiple windows end up being supported. 00103 */ 00104 00105 /* Device Context used for the Allegro window. Note that only one window 00106 * is supported, so only onyl HDC is needed. This is shared by the AGL 00107 * extension code. 00108 */ 00109 HDC __allegro_gl_hdc = NULL; 00110 00111 /* Render Context used by AllegroGL, once screen mode was set. Note that only 00112 * a single window is supported. 00113 */ 00114 static HGLRC allegro_glrc = NULL; 00115 00116 /* Full-screen flag, for the current context. */ 00117 static int fullscreen = 0; 00118 00119 /* Current window handle */ 00120 static HWND wnd = NULL; 00121 00122 /* If AGL was initialized */ 00123 static int initialized = 0; 00124 00125 /* XXX <rohannessian> Put those globals as function parameters */ 00126 /* Note - these globals should really end up as parameters to functions. 00127 */ 00128 static DWORD style_saved, exstyle_saved; 00129 static DEVMODE dm_saved; 00130 static int test_windows_created = 0; 00131 static int new_w = 0, new_h = 0; 00132 00133 static PIXELFORMATDESCRIPTOR pfd = { 00134 sizeof(PIXELFORMATDESCRIPTOR), /* size of this pfd */ 00135 1, /* version number */ 00136 PFD_DRAW_TO_WINDOW /* support window */ 00137 | PFD_SUPPORT_OPENGL /* support OpenGL */ 00138 | PFD_DOUBLEBUFFER, /* double buffered */ 00139 PFD_TYPE_RGBA, /* RGBA type */ 00140 24, /* 24-bit color depth */ 00141 0, 0, 0, 0, 0, 0, /* color bits ignored */ 00142 0, /* no alpha buffer */ 00143 0, /* shift bit ignored */ 00144 0, /* no accumulation buffer */ 00145 0, 0, 0, 0, /* accum bits ignored */ 00146 0, /* z-buffer */ 00147 0, /* no stencil buffer */ 00148 0, /* no auxiliary buffer */ 00149 PFD_MAIN_PLANE, /* main layer */ 00150 0, /* reserved */ 00151 0, 0, 0 /* layer masks ignored */ 00152 }; 00153 00154 00155 00156 /* Logs a Win32 error/warning message in the log file. 00157 */ 00158 static void log_win32_msg(const char *prefix, const char *func, 00159 const char *error_msg, DWORD err) { 00160 00161 char *err_msg = NULL; 00162 BOOL free_msg = TRUE; 00163 00164 /* Get the formatting error string from Windows. Note that only the 00165 * bottom 14 bits matter - the rest are reserved for various library 00166 * IDs and type of error. 00167 */ 00168 if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER 00169 | FORMAT_MESSAGE_FROM_SYSTEM 00170 | FORMAT_MESSAGE_IGNORE_INSERTS, 00171 NULL, err & 0x3FFF, 00172 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 00173 (LPTSTR) &err_msg, 0, NULL)) { 00174 err_msg = "(Unable to decode error code) "; 00175 free_msg = FALSE; 00176 } 00177 00178 /* Remove two trailing characters */ 00179 if (err_msg && strlen(err_msg) > 1) 00180 *(err_msg + strlen(err_msg) - 2) = '\0'; 00181 00182 TRACE("%s%s(): %s %s (0x%08lx)\n", prefix, func, 00183 error_msg ? error_msg : "", 00184 err_msg ? err_msg : "(null)", 00185 (unsigned long)err); 00186 00187 if (free_msg) { 00188 LocalFree(err_msg); 00189 } 00190 00191 return; 00192 } 00193 00194 00195 00196 /* Logs an error */ 00197 static void log_win32_error(const char *func, const char *error_msg, 00198 DWORD err) { 00199 log_win32_msg(PREFIX_E, func, error_msg, err); 00200 } 00201 00202 00203 00204 /* Logs a warning */ 00205 static void log_win32_warning(const char *func, const char *error_msg, 00206 DWORD err) { 00207 log_win32_msg(PREFIX_W, func, error_msg, err); 00208 } 00209 00210 00211 00212 /* Logs a note */ 00213 static void log_win32_note(const char *func, const char *error_msg, DWORD err) { 00214 log_win32_msg(PREFIX_I, func, error_msg, err); 00215 } 00216 00217 00218 00219 /* Define the AllegroGL Test window class */ 00220 #define ALLEGROGL_TEST_WINDOW_CLASS "AllegroGLTestWindow" 00221 00222 00223 /* Registers the test window 00224 * Returns 0 on success, non-zero on failure. 00225 */ 00226 static int register_test_window() 00227 { 00228 WNDCLASS wc; 00229 00230 memset(&wc, 0, sizeof(wc)); 00231 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 00232 wc.lpfnWndProc = DefWindowProc; 00233 wc.hInstance = GetModuleHandle(NULL); 00234 wc.hIcon = LoadIcon(GetModuleHandle(NULL), IDI_APPLICATION); 00235 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 00236 wc.lpszClassName = ALLEGROGL_TEST_WINDOW_CLASS; 00237 00238 if (!RegisterClass(&wc)) { 00239 DWORD err = GetLastError(); 00240 00241 if (err != ERROR_CLASS_ALREADY_EXISTS) { 00242 log_win32_error("register_test_window", 00243 "Unable to register the window class!", err); 00244 return -1; 00245 } 00246 } 00247 00248 return 0; 00249 } 00250 00251 00252 00253 00254 /* Creates the test window. 00255 * The window class must have already been registered. 00256 * Returns the window handle, or NULL on failure. 00257 */ 00258 static HWND create_test_window() 00259 { 00260 HWND wnd = CreateWindow(ALLEGROGL_TEST_WINDOW_CLASS, 00261 "AllegroGL Test Window", 00262 WS_POPUP | WS_CLIPCHILDREN, 00263 0, 0, new_w, new_h, 00264 NULL, NULL, 00265 GetModuleHandle(NULL), 00266 NULL); 00267 00268 if (!wnd) { 00269 log_win32_error("create_test_window", 00270 "Unable to create a test window!", GetLastError()); 00271 return NULL; 00272 } 00273 00274 test_windows_created++; 00275 return wnd; 00276 } 00277 00278 00279 00280 /* Print the pixel format info */ 00281 static void print_pixel_format(struct allegro_gl_display_info *dinfo) { 00282 00283 if (!dinfo) { 00284 return; 00285 } 00286 00287 TRACE(PREFIX_I "Acceleration: %s\n", ((dinfo->rmethod == 0) ? "No" 00288 : ((dinfo->rmethod == 1) ? "Yes" : "Unknown"))); 00289 TRACE(PREFIX_I "RGBA: %i.%i.%i.%i\n", dinfo->pixel_size.rgba.r, 00290 dinfo->pixel_size.rgba.g, dinfo->pixel_size.rgba.b, 00291 dinfo->pixel_size.rgba.a); 00292 00293 TRACE(PREFIX_I "Accum: %i.%i.%i.%i\n", dinfo->accum_size.rgba.r, 00294 dinfo->accum_size.rgba.g, dinfo->accum_size.rgba.b, 00295 dinfo->accum_size.rgba.a); 00296 00297 TRACE(PREFIX_I "DblBuf: %i Zbuf: %i Stereo: %i Aux: %i Stencil: %i\n", 00298 dinfo->doublebuffered, dinfo->depth_size, dinfo->stereo, 00299 dinfo->aux_buffers, dinfo->stencil_size); 00300 00301 TRACE(PREFIX_I "Shift: %i.%i.%i.%i\n", dinfo->r_shift, dinfo->g_shift, 00302 dinfo->b_shift, dinfo->a_shift); 00303 00304 TRACE(PREFIX_I "Sample Buffers: %i Samples: %i\n", 00305 dinfo->sample_buffers, dinfo->samples); 00306 00307 TRACE(PREFIX_I "Decoded bpp: %i\n", dinfo->colour_depth); 00308 } 00309 00310 00311 00312 /* Decodes the pixel format into an agl_display_info struct and logs the pixel 00313 * format in the trace file. 00314 */ 00315 static int decode_pixel_format(PIXELFORMATDESCRIPTOR * pfd, HDC hdc, int format, 00316 struct allegro_gl_display_info *dinfo, 00317 int desktop_depth) 00318 { 00319 TRACE(PREFIX_I "Decoding: \n"); 00320 /* Not interested if it doesn't support OpenGL and RGBA */ 00321 if (!(pfd->dwFlags & PFD_SUPPORT_OPENGL)) { 00322 TRACE(PREFIX_I "OpenGL Unsupported\n"); 00323 return -1; 00324 } 00325 if (pfd->iPixelType != PFD_TYPE_RGBA) { 00326 TRACE(PREFIX_I "Not RGBA mode\n"); 00327 return -1; 00328 } 00329 00330 if ((pfd->cColorBits != desktop_depth) 00331 && (pfd->cColorBits != 32 || desktop_depth < 24)) { 00332 TRACE(PREFIX_I "Current color depth != " 00333 "pixel format color depth\n"); 00334 //return -1; /* XXX <rohannessian> Why is this a bad thing? */ 00335 } 00336 00337 00338 /* hardware acceleration */ 00339 if (((pfd->dwFlags & PFD_GENERIC_ACCELERATED) 00340 && (pfd->dwFlags & PFD_GENERIC_FORMAT)) 00341 || (!(pfd->dwFlags & PFD_GENERIC_ACCELERATED) 00342 && !(pfd->dwFlags & PFD_GENERIC_FORMAT))) 00343 dinfo->rmethod = 1; 00344 else 00345 dinfo->rmethod = 0; 00346 00347 00348 /* Depths of colour buffers */ 00349 dinfo->pixel_size.rgba.r = pfd->cRedBits; 00350 dinfo->pixel_size.rgba.g = pfd->cGreenBits; 00351 dinfo->pixel_size.rgba.b = pfd->cBlueBits; 00352 dinfo->pixel_size.rgba.a = pfd->cAlphaBits; 00353 00354 /* Depths of accumulation buffer */ 00355 dinfo->accum_size.rgba.r = pfd->cAccumRedBits; 00356 dinfo->accum_size.rgba.g = pfd->cAccumGreenBits; 00357 dinfo->accum_size.rgba.b = pfd->cAccumBlueBits; 00358 dinfo->accum_size.rgba.a = pfd->cAccumAlphaBits; 00359 00360 /* Miscellaneous settings */ 00361 dinfo->doublebuffered = pfd->dwFlags & PFD_DOUBLEBUFFER; 00362 dinfo->stereo = pfd->dwFlags & PFD_STEREO; 00363 dinfo->aux_buffers = pfd->cAuxBuffers; 00364 dinfo->depth_size = pfd->cDepthBits; 00365 dinfo->stencil_size = pfd->cStencilBits; 00366 00367 /* These are the component shifts, like Allegro's _rgb_*_shift_*. */ 00368 dinfo->r_shift = pfd->cRedShift; 00369 dinfo->g_shift = pfd->cGreenShift; 00370 dinfo->b_shift = pfd->cBlueShift; 00371 dinfo->a_shift = pfd->cAlphaShift; 00372 00373 /* Multisampling isn't supported under Windows if we don't also use 00374 * WGL_ARB_pixel_format or WGL_EXT_pixel_format. 00375 */ 00376 dinfo->sample_buffers = 0; 00377 dinfo->samples = 0; 00378 00379 /* Float depth/color isn't supported under Windows if we don't also use 00380 * AGL_ARB_pixel_format or WGL_EXT_pixel_format. 00381 */ 00382 dinfo->float_color = 0; 00383 dinfo->float_depth = 0; 00384 00385 /* This bit is the same as the X code, setting some things based on 00386 * what we've read out of the PFD. */ 00387 dinfo->colour_depth = 0; 00388 if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) { 00389 if (dinfo->pixel_size.rgba.g == 5) 00390 dinfo->colour_depth = 15; 00391 if (dinfo->pixel_size.rgba.g == 6) 00392 dinfo->colour_depth = 16; 00393 } 00394 if (dinfo->pixel_size.rgba.r == 8 00395 && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) { 00396 if (dinfo->pixel_size.rgba.a == 8) 00397 dinfo->colour_depth = 32; 00398 else 00399 dinfo->colour_depth = 24; 00400 } 00401 00402 00403 dinfo->allegro_format = (dinfo->colour_depth != 0) 00404 && (dinfo->g_shift == dinfo->pixel_size.rgba.b) 00405 && (dinfo->r_shift * dinfo->b_shift == 0) 00406 && (dinfo->r_shift + dinfo->b_shift == 00407 dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g); 00408 00409 return 0; 00410 } 00411 00412 00413 00414 /* Decodes the pixel format into an agl_display_info struct and logs the pixel 00415 * format in the trace file. 00416 */ 00417 static int decode_pixel_format_attrib(struct allegro_gl_display_info *dinfo, 00418 int num_attribs, const int *attrib, const int *value, 00419 int desktop_depth) { 00420 int i; 00421 00422 TRACE(PREFIX_I "Decoding: \n"); 00423 00424 dinfo->samples = 0; 00425 dinfo->sample_buffers = 0; 00426 dinfo->float_depth = 0; 00427 dinfo->float_color = 0; 00428 00429 for (i = 0; i < num_attribs; i++) { 00430 00431 /* Not interested if it doesn't support OpenGL or window drawing or 00432 * RGBA. 00433 */ 00434 if (attrib[i] == WGL_SUPPORT_OPENGL_ARB && value[i] == 0) { 00435 TRACE(PREFIX_I "OpenGL Unsupported\n"); 00436 return -1; 00437 } 00438 else if (attrib[i] == WGL_DRAW_TO_WINDOW_ARB && value[i] == 0) { 00439 TRACE(PREFIX_I "Can't draw to window\n"); 00440 return -1; 00441 } 00442 else if (attrib[i] == WGL_PIXEL_TYPE_ARB && 00443 (value[i] != WGL_TYPE_RGBA_ARB 00444 && value[i] != WGL_TYPE_RGBA_FLOAT_ARB)) { 00445 TRACE(PREFIX_I "Not RGBA mode\n"); 00446 return -1; 00447 } 00448 /* Check for color depth matching */ 00449 else if (attrib[i] == WGL_COLOR_BITS_ARB) { 00450 if ((value[i] != desktop_depth) 00451 && (value[i] != 32 || desktop_depth < 24)) { 00452 TRACE(PREFIX_I "Current color depth != " 00453 "pixel format color depth\n"); 00454 //return -1; /* XXX <rohannessian> Why is this a bad thing? */ 00455 } 00456 } 00457 /* hardware acceleration */ 00458 else if (attrib[i] == WGL_ACCELERATION_ARB) { 00459 dinfo->rmethod = (value[i] == WGL_NO_ACCELERATION_ARB) ? 0 : 1; 00460 } 00461 /* Depths of colour buffers */ 00462 else if (attrib[i] == WGL_RED_BITS_ARB) { 00463 dinfo->pixel_size.rgba.r = value[i]; 00464 } 00465 else if (attrib[i] == WGL_GREEN_BITS_ARB) { 00466 dinfo->pixel_size.rgba.g = value[i]; 00467 } 00468 else if (attrib[i] == WGL_BLUE_BITS_ARB) { 00469 dinfo->pixel_size.rgba.b = value[i]; 00470 } 00471 else if (attrib[i] == WGL_ALPHA_BITS_ARB) { 00472 dinfo->pixel_size.rgba.a = value[i]; 00473 } 00474 /* Shift of color components */ 00475 else if (attrib[i] == WGL_RED_SHIFT_ARB) { 00476 dinfo->r_shift = value[i]; 00477 } 00478 else if (attrib[i] == WGL_GREEN_SHIFT_ARB) { 00479 dinfo->g_shift = value[i]; 00480 } 00481 else if (attrib[i] == WGL_BLUE_SHIFT_ARB) { 00482 dinfo->b_shift = value[i]; 00483 } 00484 else if (attrib[i] == WGL_ALPHA_SHIFT_ARB) { 00485 dinfo->a_shift = value[i]; 00486 } 00487 00488 /* Depths of accumulation buffer */ 00489 else if (attrib[i] == WGL_ACCUM_RED_BITS_ARB) { 00490 dinfo->accum_size.rgba.r = value[i]; 00491 } 00492 else if (attrib[i] == WGL_ACCUM_GREEN_BITS_ARB) { 00493 dinfo->accum_size.rgba.g = value[i]; 00494 } 00495 else if (attrib[i] == WGL_ACCUM_BLUE_BITS_ARB) { 00496 dinfo->accum_size.rgba.b = value[i]; 00497 } 00498 else if (attrib[i] == WGL_ACCUM_ALPHA_BITS_ARB) { 00499 dinfo->accum_size.rgba.a = value[i]; 00500 } 00501 /* Miscellaneous settings */ 00502 else if (attrib[i] == WGL_DOUBLE_BUFFER_ARB) { 00503 dinfo->doublebuffered = value[i]; 00504 } 00505 else if (attrib[i] == WGL_STEREO_ARB) { 00506 dinfo->stereo = value[i]; 00507 } 00508 else if (attrib[i] == WGL_AUX_BUFFERS_ARB) { 00509 dinfo->aux_buffers = value[i]; 00510 } 00511 else if (attrib[i] == WGL_DEPTH_BITS_ARB) { 00512 dinfo->depth_size = value[i]; 00513 } 00514 else if (attrib[i] == WGL_STENCIL_BITS_ARB) { 00515 dinfo->stencil_size = value[i]; 00516 } 00517 /* Multisampling bits */ 00518 else if (attrib[i] == WGL_SAMPLE_BUFFERS_ARB) { 00519 dinfo->sample_buffers = value[i]; 00520 } 00521 else if (attrib[i] == WGL_SAMPLES_ARB) { 00522 dinfo->samples = value[i]; 00523 } 00524 /* Float color */ 00525 if (attrib[i] == WGL_PIXEL_TYPE_ARB 00526 && value[i] == WGL_TYPE_RGBA_FLOAT_ARB) { 00527 dinfo->float_color = TRUE; 00528 } 00529 /* Float depth */ 00530 else if (attrib[i] == WGL_DEPTH_FLOAT_EXT) { 00531 dinfo->float_depth = value[i]; 00532 } 00533 } 00534 00535 /* This bit is the same as the X code, setting some things based on 00536 * what we've read out of the PFD. */ 00537 dinfo->colour_depth = 0; 00538 if (dinfo->pixel_size.rgba.r == 5 && dinfo->pixel_size.rgba.b == 5) { 00539 if (dinfo->pixel_size.rgba.g == 5) 00540 dinfo->colour_depth = 15; 00541 if (dinfo->pixel_size.rgba.g == 6) 00542 dinfo->colour_depth = 16; 00543 } 00544 if (dinfo->pixel_size.rgba.r == 8 00545 && dinfo->pixel_size.rgba.g == 8 && dinfo->pixel_size.rgba.b == 8) { 00546 if (dinfo->pixel_size.rgba.a == 8) 00547 dinfo->colour_depth = 32; 00548 else 00549 dinfo->colour_depth = 24; 00550 } 00551 00552 dinfo->allegro_format = (dinfo->colour_depth != 0) 00553 && (dinfo->g_shift == dinfo->pixel_size.rgba.b) 00554 && (dinfo->r_shift * dinfo->b_shift == 0) 00555 && (dinfo->r_shift + dinfo->b_shift == 00556 dinfo->pixel_size.rgba.b + dinfo->pixel_size.rgba.g); 00557 00558 return 0; 00559 } 00560 00561 00562 00563 typedef struct format_t { 00564 int score; 00565 int format; 00566 } format_t; 00567 00568 00569 00570 /* Helper function for sorting pixel formats by score */ 00571 static int select_pixel_format_sorter(const void *p0, const void *p1) { 00572 format_t *f0 = (format_t*)p0; 00573 format_t *f1 = (format_t*)p1; 00574 00575 if (f0->score == f1->score) { 00576 return 0; 00577 } 00578 else if (f0->score > f1->score) { 00579 return -1; 00580 } 00581 else { 00582 return 1; 00583 } 00584 } 00585 00586 00587 00588 /* Describes the pixel format and assigns it a score */ 00589 int describe_pixel_format_old(HDC dc, int fmt, int desktop_depth, 00590 format_t *formats, int *num_formats, 00591 struct allegro_gl_display_info *pdinfo) { 00592 00593 struct allegro_gl_display_info dinfo; 00594 PIXELFORMATDESCRIPTOR pfd; 00595 int score = -1; 00596 00597 int result = DescribePixelFormat(dc, fmt, sizeof(pfd), &pfd); 00598 00599 /* Remember old settings */ 00600 if (pdinfo) { 00601 dinfo = *pdinfo; 00602 } 00603 00604 if (!result) { 00605 log_win32_warning("describe_pixel_format_old", 00606 "DescribePixelFormat() failed!", GetLastError()); 00607 return -1; 00608 } 00609 00610 result = !decode_pixel_format(&pfd, dc, fmt, &dinfo, desktop_depth); 00611 00612 if (result) { 00613 print_pixel_format(&dinfo); 00614 score = __allegro_gl_score_config(fmt, &dinfo); 00615 } 00616 00617 if (score < 0) { 00618 return -1; /* Reject non-compliant pixel formats */ 00619 } 00620 00621 if (formats && num_formats) { 00622 formats[*num_formats].score = score; 00623 formats[*num_formats].format = fmt; 00624 (*num_formats)++; 00625 } 00626 00627 if (pdinfo) { 00628 *pdinfo = dinfo; 00629 } 00630 00631 return 0; 00632 } 00633 00634 00635 00636 static AGL_GetPixelFormatAttribivARB_t __wglGetPixelFormatAttribivARB = NULL; 00637 static AGL_GetPixelFormatAttribivEXT_t __wglGetPixelFormatAttribivEXT = NULL; 00638 00639 00640 00641 /* Describes the pixel format and assigns it a score */ 00642 int describe_pixel_format_new(HDC dc, int fmt, int desktop_depth, 00643 format_t *formats, int *num_formats, 00644 struct allegro_gl_display_info *pdinfo) { 00645 00646 struct allegro_gl_display_info dinfo; 00647 int score = -1; 00648 00649 /* Note: Even though we use te ARB suffix, all those enums are compatible 00650 * with EXT_pixel_format. 00651 */ 00652 int attrib[] = { 00653 WGL_SUPPORT_OPENGL_ARB, 00654 WGL_DRAW_TO_WINDOW_ARB, 00655 WGL_PIXEL_TYPE_ARB, 00656 WGL_ACCELERATION_ARB, 00657 WGL_DOUBLE_BUFFER_ARB, 00658 WGL_DEPTH_BITS_ARB, 00659 WGL_COLOR_BITS_ARB, 00660 WGL_RED_BITS_ARB, 00661 WGL_GREEN_BITS_ARB, 00662 WGL_BLUE_BITS_ARB, 00663 WGL_ALPHA_BITS_ARB, 00664 WGL_RED_SHIFT_ARB, 00665 WGL_GREEN_SHIFT_ARB, 00666 WGL_BLUE_SHIFT_ARB, 00667 WGL_ALPHA_SHIFT_ARB, 00668 WGL_STENCIL_BITS_ARB, 00669 WGL_STEREO_ARB, 00670 WGL_ACCUM_BITS_ARB, 00671 WGL_ACCUM_RED_BITS_ARB, 00672 WGL_ACCUM_GREEN_BITS_ARB, 00673 WGL_ACCUM_BLUE_BITS_ARB, 00674 WGL_ACCUM_ALPHA_BITS_ARB, 00675 WGL_AUX_BUFFERS_ARB, 00676 00677 /* The following are used by extensions that add to WGL_pixel_format. 00678 * If WGL_p_f isn't supported though, we can't use the (then invalid) 00679 * enums. We can't use any magic number either, so we settle for 00680 * replicating one. The pixel format decoder 00681 * (decode_pixel_format_attrib()) doesn't care about duplicates. 00682 */ 00683 WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLE_BUFFERS_ARB */ 00684 WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLES_ARB */ 00685 WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_DEPTH_FLOAT_EXT */ 00686 }; 00687 00688 const int num_attribs = sizeof(attrib) / sizeof(attrib[0]); 00689 int *value = (int*)malloc(sizeof(int) * num_attribs); 00690 int result; 00691 BOOL ret; 00692 int old_valid = __allegro_gl_valid_context; 00693 00694 /* Can't allocate mem? */ 00695 if (!value) { 00696 TRACE(PREFIX_E "describe_pixel_format_new(): Unable to allocate " 00697 "memory for pixel format descriptor!\n"); 00698 return -1; 00699 } 00700 00701 /* Remember old settings */ 00702 if (pdinfo) { 00703 dinfo = *pdinfo; 00704 } 00705 00706 00707 /* If multisampling is supported, query for it. Note - we need to tell 00708 * allegro_gl_is_extension_supported() that we have a valid context, 00709 * even though AGL is not initialized yet. 00710 */ 00711 __allegro_gl_valid_context = 1; 00712 if (allegro_gl_is_extension_supported("WGL_ARB_multisample")) { 00713 attrib[num_attribs - 3] = WGL_SAMPLE_BUFFERS_ARB; 00714 attrib[num_attribs - 2] = WGL_SAMPLES_ARB; 00715 } 00716 if (allegro_gl_is_extension_supported("WGL_EXT_depth_float")) { 00717 attrib[num_attribs - 1] = WGL_DEPTH_FLOAT_EXT; 00718 } 00719 __allegro_gl_valid_context = old_valid; 00720 00721 00722 /* Get the pf attributes */ 00723 if (__wglGetPixelFormatAttribivARB) { 00724 ret = __wglGetPixelFormatAttribivARB(dc, fmt, 0, num_attribs, 00725 attrib, value); 00726 } 00727 else if (__wglGetPixelFormatAttribivEXT) { 00728 ret = __wglGetPixelFormatAttribivEXT(dc, fmt, 0, num_attribs, 00729 attrib, value); 00730 } 00731 else { 00732 ret = 0; 00733 } 00734 00735 /* wglGetPixelFormatAttrib() failed? Abort and revert to old path */ 00736 if (!ret) { 00737 log_win32_error("describe_pixel_format_new", 00738 "wglGetPixelFormatAttrib failed!", GetLastError()); 00739 free(value); 00740 return -1; 00741 } 00742 00743 /* Convert to AllegroGL format for scoring */ 00744 result = !decode_pixel_format_attrib(&dinfo, num_attribs, attrib, value, 00745 desktop_depth); 00746 free(value); 00747 00748 if (result) { 00749 print_pixel_format(&dinfo); 00750 score = __allegro_gl_score_config(fmt, &dinfo); 00751 } 00752 00753 if (score < 0) { 00754 return 0; /* Reject non-compliant pixel formats */ 00755 } 00756 00757 if (formats && num_formats) { 00758 formats[*num_formats].score = score; 00759 formats[*num_formats].format = fmt; 00760 (*num_formats)++; 00761 } 00762 00763 if (pdinfo) { 00764 *pdinfo = dinfo; 00765 } 00766 00767 return 0; 00768 } 00769 00770 00771 00772 /* Returns the number of pixel formats we should investigate */ 00773 int get_num_pixel_formats(HDC dc, int *new_pf_code) { 00774 00775 /* DescribePixelFormat() returns maximum pixel format index in the old 00776 * code. wglGetPixelFormatAttribivARB() does it in the new code. 00777 */ 00778 if (new_pf_code && *new_pf_code) { 00779 int attrib[1]; 00780 int value[1]; 00781 00782 TRACE(PREFIX_I "get_num_pixel_formats(): Attempting to use WGL_pf.\n"); 00783 attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB; 00784 if ((__wglGetPixelFormatAttribivARB 00785 && __wglGetPixelFormatAttribivARB(dc, 0, 0, 1, attrib, value) 00786 == GL_FALSE) 00787 || (__wglGetPixelFormatAttribivEXT 00788 && __wglGetPixelFormatAttribivEXT(dc, 0, 0, 1, attrib, value) 00789 == GL_FALSE)) { 00790 log_win32_note("get_num_pixel_formats", 00791 "WGL_ARB/EXT_pixel_format use failed!", GetLastError()); 00792 *new_pf_code = 0; 00793 } 00794 else { 00795 return value[0]; 00796 } 00797 } 00798 00799 if (!new_pf_code || !*new_pf_code) { 00800 PIXELFORMATDESCRIPTOR pfd; 00801 int ret; 00802 00803 TRACE(PREFIX_I "get_num_pixel_formats(): Using DescribePixelFormat.\n"); 00804 ret = DescribePixelFormat(dc, 1, sizeof(pfd), &pfd); 00805 00806 if (!ret) { 00807 log_win32_error("get_num_pixel_formats", 00808 "DescribePixelFormat failed!", GetLastError()); 00809 } 00810 00811 return ret; 00812 } 00813 00814 return 0; 00815 } 00816 00817 00818 00819 /* Pick the best matching pixel format */ 00820 static int select_pixel_format(PIXELFORMATDESCRIPTOR * pfd) 00821 { 00822 int i; 00823 int result, maxindex; 00824 int desktop_depth; 00825 00826 HWND testwnd = NULL; 00827 HDC testdc = NULL; 00828 HGLRC testrc = NULL; 00829 00830 format_t *format = NULL; 00831 int num_formats = 0; 00832 int new_pf_code = 0; 00833 00834 00835 __allegro_gl_reset_scorer(); 00836 00837 /* Read again the desktop depth */ 00838 desktop_depth = desktop_color_depth(); 00839 00840 if (register_test_window() < 0) { 00841 return 0; 00842 } 00843 00844 testwnd = create_test_window(); 00845 00846 if (!testwnd) { 00847 return 0; 00848 } 00849 00850 testdc = GetDC(testwnd); 00851 00852 /* Check if we can support new pixel format code */ 00853 TRACE(PREFIX_I "select_pixel_format(): Trying to set up temporary RC\n"); 00854 { 00855 HDC old_dc = __allegro_gl_hdc; 00856 int old_valid = __allegro_gl_valid_context; 00857 PIXELFORMATDESCRIPTOR pfd; 00858 int pf; 00859 00860 new_pf_code = 0; 00861 00862 /* We need to create a dummy window with a pixel format to get the 00863 * list of valid PFDs 00864 */ 00865 memset(&pfd, 0, sizeof(pfd)); 00866 pfd.nSize = sizeof(pfd); 00867 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL 00868 | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE; 00869 pfd.iPixelType = PFD_TYPE_RGBA; 00870 pfd.iLayerType = PFD_MAIN_PLANE; 00871 pfd.cColorBits = 32; 00872 00873 TRACE(PREFIX_I "select_pixel_format(): ChoosePixelFormat()\n"); 00874 pf = ChoosePixelFormat(testdc, &pfd); 00875 00876 if (!pf) { 00877 log_win32_warning("select_pixel_format", 00878 "Unable to chose a temporary pixel format!", 00879 GetLastError()); 00880 goto fail_pf; 00881 } 00882 00883 /* Set up a GL context there */ 00884 TRACE(PREFIX_I "select_pixel_format(): SetPixelFormat()\n"); 00885 memset(&pfd, 0, sizeof(pfd)); 00886 if (!SetPixelFormat(testdc, pf, &pfd)) { 00887 log_win32_warning("select_pixel_format", 00888 "Unable to set a temporary pixel format!", 00889 GetLastError()); 00890 goto fail_pf; 00891 } 00892 00893 TRACE(PREFIX_I "select_pixel_format(): CreateContext()\n"); 00894 testrc = wglCreateContext(testdc); 00895 00896 if (!testrc) { 00897 log_win32_warning("select_pixel_format", 00898 "Unable to create a render context!", 00899 GetLastError()); 00900 goto fail_pf; 00901 } 00902 00903 TRACE(PREFIX_I "select_pixel_format(): MakeCurrent()\n"); 00904 if (!wglMakeCurrent(testdc, testrc)) { 00905 log_win32_warning("select_pixel_format", 00906 "Unable to set the render context as current!", 00907 GetLastError()); 00908 goto fail_pf; 00909 } 00910 00911 __allegro_gl_hdc = testdc; 00912 __allegro_gl_valid_context = TRUE; 00913 00914 00915 /* This is a workaround for a bug in old NVidia drivers. We need to 00916 * call wglGetExtensionsStringARB() for it to properly initialize. 00917 */ 00918 TRACE(PREFIX_I "select_pixel_format(): GetExtensionsStringARB()\n"); 00919 if (strstr((AL_CONST char*)glGetString(GL_VENDOR), "NVIDIA")) { 00920 AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL; 00921 00922 __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t) 00923 wglGetProcAddress("wglGetExtensionsStringARB"); 00924 00925 TRACE(PREFIX_I "select_pixel_format(): Querying for " 00926 "WGL_ARB_extension_string\n"); 00927 00928 if (__wglGetExtensionsStringARB) { 00929 TRACE(PREFIX_I "select_pixel_format(): Calling " 00930 "__wglGetExtensionsStringARB\n"); 00931 __wglGetExtensionsStringARB(testdc); 00932 } 00933 } 00934 00935 00936 /* Check that we support ARB/EXT_pixel_format */ 00937 if (!allegro_gl_is_extension_supported("WGL_ARB_pixel_format") 00938 && !allegro_gl_is_extension_supported("WGL_EXT_pixel_format")) { 00939 TRACE(PREFIX_I "select_pixel_format(): WGL_ARB/EXT_pf unsupported.\n"); 00940 goto fail_pf; 00941 } 00942 00943 /* Load the ARB_p_f symbol - Note, we shouldn't use the AGL extension 00944 * mechanism here, because AGL hasn't been initialized yet! 00945 */ 00946 TRACE(PREFIX_I "select_pixel_format(): GetProcAddress()\n"); 00947 __wglGetPixelFormatAttribivARB = (AGL_GetPixelFormatAttribivARB_t) 00948 wglGetProcAddress("wglGetPixelFormatAttribivARB"); 00949 __wglGetPixelFormatAttribivEXT = (AGL_GetPixelFormatAttribivEXT_t) 00950 wglGetProcAddress("wglGetPixelFormatAttribivEXT"); 00951 00952 if (!__wglGetPixelFormatAttribivARB 00953 && !__wglGetPixelFormatAttribivEXT) { 00954 TRACE(PREFIX_E "select_pixel_format(): WGL_ARB/EXT_pf not " 00955 "correctly supported!\n"); 00956 goto fail_pf; 00957 } 00958 00959 new_pf_code = 1; 00960 goto exit_pf; 00961 00962 fail_pf: 00963 wglMakeCurrent(NULL, NULL); 00964 if (testrc) { 00965 wglDeleteContext(testrc); 00966 } 00967 testrc = NULL; 00968 00969 __wglGetPixelFormatAttribivARB = NULL; 00970 __wglGetPixelFormatAttribivEXT = NULL; 00971 exit_pf: 00972 __allegro_gl_hdc = old_dc; 00973 __allegro_gl_valid_context = old_valid; 00974 } 00975 00976 maxindex = get_num_pixel_formats(testdc, &new_pf_code); 00977 00978 /* Check if using the new pf code failed. Likely due to driver bug. 00979 * maxindex is still valid though, so we can continue. 00980 */ 00981 if (!new_pf_code && testrc) { 00982 TRACE(PREFIX_W "select_pixel_format(): WGL_ARB_pf call failed - " 00983 "reverted to plain old WGL.\n"); 00984 wglMakeCurrent(NULL, NULL); 00985 wglDeleteContext(testrc); 00986 testrc = NULL; 00987 __wglGetPixelFormatAttribivARB = NULL; 00988 __wglGetPixelFormatAttribivEXT = NULL; 00989 } 00990 00991 TRACE(PREFIX_I "select_pixel_format(): %i formats.\n", maxindex); 00992 00993 if (maxindex < 1) { 00994 TRACE(PREFIX_E "select_pixel_format(): Didn't find any pixel " 00995 "formats at all!\n"); 00996 goto bail; 00997 } 00998 00999 format = malloc((maxindex + 1) * sizeof(format_t)); 01000 01001 if (!format) { 01002 TRACE(PREFIX_E "select_pixel_format(): Unable to allocate memory for " 01003 "pixel format scores!\n"); 01004 goto bail; 01005 } 01006 01007 /* First, pixel formats are sorted by decreasing order */ 01008 TRACE(PREFIX_I "select_pixel_format(): Testing pixel formats:\n"); 01009 for (i = 1; i <= maxindex; i++) { 01010 01011 int use_old = !new_pf_code; 01012 01013 TRACE(PREFIX_I "Format %i:\n", i); 01014 01015 if (new_pf_code) { 01016 if (describe_pixel_format_new(testdc, i, desktop_depth, 01017 format, &num_formats, NULL) < 0) { 01018 TRACE(PREFIX_W "select_pixel_format(): Wasn't able to use " 01019 "WGL_PixelFormat - reverting to old WGL code.\n"); 01020 use_old = 1; 01021 } 01022 } 01023 01024 if (use_old) { 01025 if (describe_pixel_format_old(testdc, i, desktop_depth, 01026 format, &num_formats, NULL) < 0) { 01027 TRACE(PREFIX_W "select_pixel_format(): Unable to rely on " 01028 "unextended WGL to describe this pixelformat.\n"); 01029 } 01030 } 01031 } 01032 01033 if (new_pf_code) { 01034 wglMakeCurrent(NULL, NULL); 01035 wglDeleteContext(testrc); 01036 testrc = NULL; 01037 } 01038 if (testwnd) { 01039 ReleaseDC(testwnd, testdc); 01040 testdc = NULL; 01041 DestroyWindow(testwnd); 01042 testwnd = NULL; 01043 } 01044 01045 if (num_formats < 1) { 01046 TRACE(PREFIX_E "select_pixel_format(): Didn't find any available " 01047 "pixel formats!\n"); 01048 goto bail; 01049 } 01050 01051 qsort(format, num_formats, sizeof(format_t), select_pixel_format_sorter); 01052 01053 01054 /* Sorted pixel formats are tested until one of them succeeds to 01055 * make a GL context current */ 01056 for (i = 0; i < num_formats ; i++) { 01057 HGLRC rc; 01058 01059 /* Recreate our test windows */ 01060 testwnd = create_test_window(); 01061 testdc = GetDC(testwnd); 01062 01063 if (SetPixelFormat(testdc, format[i].format, pfd)) { 01064 rc = wglCreateContext(testdc); 01065 if (!rc) { 01066 TRACE(PREFIX_I "select_pixel_format(): Unable to create RC!\n"); 01067 } 01068 else { 01069 if (wglMakeCurrent(testdc, rc)) { 01070 wglMakeCurrent(NULL, NULL); 01071 wglDeleteContext(rc); 01072 rc = NULL; 01073 01074 TRACE(PREFIX_I "select_pixel_format(): Best config is: %i" 01075 "\n", format[i].format); 01076 01077 /* XXX <rohannessian> DescribePixelFormat may fail on 01078 * extended pixel format (WGL_ARB_p_f) 01079 */ 01080 if (!DescribePixelFormat(testdc, format[i].format, 01081 sizeof *pfd, pfd)) { 01082 TRACE(PREFIX_E "Cannot describe this pixel format\n"); 01083 ReleaseDC(testwnd, testdc); 01084 DestroyWindow(testwnd); 01085 testdc = NULL; 01086 testwnd = NULL; 01087 continue; 01088 } 01089 01090 ReleaseDC(testwnd, testdc); 01091 DestroyWindow(testwnd); 01092 01093 result = format[i].format; 01094 01095 free(format); 01096 return result; 01097 } 01098 else { 01099 wglMakeCurrent(NULL, NULL); 01100 wglDeleteContext(rc); 01101 rc = NULL; 01102 log_win32_warning("select_pixel_format", 01103 "Couldn't make the temporary render context " 01104 "current for the this pixel format.", 01105 GetLastError()); 01106 } 01107 } 01108 } 01109 else { 01110 log_win32_note("select_pixel_format", 01111 "Unable to set pixel format!", GetLastError()); 01112 } 01113 01114 ReleaseDC(testwnd, testdc); 01115 DestroyWindow(testwnd); 01116 testdc = NULL; 01117 testwnd = NULL; 01118 } 01119 01120 TRACE(PREFIX_E "select_pixel_format(): All modes have failed...\n"); 01121 bail: 01122 if (format) { 01123 free(format); 01124 } 01125 if (new_pf_code) { 01126 wglMakeCurrent(NULL, NULL); 01127 if (testrc) { 01128 wglDeleteContext(testrc); 01129 } 01130 } 01131 if (testwnd) { 01132 ReleaseDC(testwnd, testdc); 01133 DestroyWindow(testwnd); 01134 } 01135 01136 return 0; 01137 } 01138 01139 01140 01141 static void allegrogl_init_window(int w, int h, DWORD style, DWORD exstyle) 01142 { 01143 RECT rect; 01144 01145 #define req __allegro_gl_required_settings 01146 #define sug __allegro_gl_suggested_settings 01147 01148 int x = 32, y = 32; 01149 01150 if (req & AGL_WINDOW_X || sug & AGL_WINDOW_X) 01151 x = allegro_gl_display_info.x; 01152 if (req & AGL_WINDOW_Y || sug & AGL_WINDOW_Y) 01153 y = allegro_gl_display_info.y; 01154 01155 #undef req 01156 #undef sug 01157 01158 if (!fullscreen) { 01159 rect.left = x; 01160 rect.right = x + w; 01161 rect.top = y; 01162 rect.bottom = y + h; 01163 } 01164 else { 01165 rect.left = 0; 01166 rect.right = w; 01167 rect.top = 0; 01168 rect.bottom = h; 01169 } 01170 01171 /* save original Allegro styles */ 01172 style_saved = GetWindowLong(wnd, GWL_STYLE); 01173 exstyle_saved = GetWindowLong(wnd, GWL_EXSTYLE); 01174 01175 /* set custom AllegroGL style */ 01176 SetWindowLong(wnd, GWL_STYLE, style); 01177 SetWindowLong(wnd, GWL_EXSTYLE, exstyle); 01178 01179 if (!fullscreen) { 01180 AdjustWindowRectEx(&rect, style, FALSE, exstyle); 01181 } 01182 01183 /* make the changes visible */ 01184 SetWindowPos(wnd, 0, rect.left, rect.top, 01185 rect.right - rect.left, rect.bottom - rect.top, 01186 SWP_NOZORDER | SWP_FRAMECHANGED); 01187 01188 return; 01189 } 01190 01191 01192 01193 static BITMAP *allegro_gl_create_screen (GFX_DRIVER *drv, int w, int h, 01194 int depth) 01195 { 01196 BITMAP *bmp; 01197 int is_linear = drv->linear; 01198 01199 drv->linear = 1; 01200 bmp = _make_bitmap (w, h, 0, drv, depth, 0); 01201 01202 if (!bmp) { 01203 return NULL; 01204 } 01205 01206 bmp->id = BMP_ID_VIDEO | 1000; 01207 drv->linear = is_linear; 01208 01209 drv->w = w; 01210 drv->h = h; 01211 01212 return bmp; 01213 } 01214 01215 01216 static LRESULT CALLBACK dummy_wnd_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam) 01217 { 01218 return DefWindowProc(wnd, message, wparam, lparam); 01219 } 01220 01221 static HWND dummy_wnd; 01222 01223 static void dummy_window(void) 01224 { 01225 WNDCLASS wnd_class; 01226 01227 wnd_class.style = CS_HREDRAW | CS_VREDRAW; 01228 wnd_class.lpfnWndProc = dummy_wnd_proc; 01229 wnd_class.cbClsExtra = 0; 01230 wnd_class.cbWndExtra = 0; 01231 wnd_class.hInstance = GetModuleHandle(NULL); 01232 wnd_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); 01233 wnd_class.hCursor = LoadCursor(NULL, IDC_ARROW); 01234 wnd_class.hbrBackground = NULL; 01235 wnd_class.lpszMenuName = NULL; 01236 wnd_class.lpszClassName = "allegro focus"; 01237 01238 RegisterClass(&wnd_class); 01239 01240 dummy_wnd = CreateWindow("allegro focus", "Allegro", WS_POPUP | WS_VISIBLE, 01241 0, 0, 200, 200, 01242 NULL, NULL, GetModuleHandle(NULL), NULL); 01243 01244 ShowWindow(dummy_wnd, SW_SHOWNORMAL); 01245 SetForegroundWindow(dummy_wnd); 01246 } 01247 01248 static void remove_dummy_window(void) 01249 { 01250 DestroyWindow(dummy_wnd); 01251 UnregisterClass("allegro focus", GetModuleHandle(NULL)); 01252 } 01253 01254 01255 static BITMAP *allegro_gl_win_init(int w, int h, int v_w, int v_h) 01256 { 01257 static int first_time = 1; 01258 01259 DWORD style=0, exstyle=0; 01260 int refresh_rate = _refresh_rate_request; 01261 int desktop_depth; 01262 int pf=0; 01263 01264 new_w = w; 01265 new_h = h; 01266 01267 /* virtual screen are not supported */ 01268 if ((v_w != 0 && v_w != w) || (v_h != 0 && v_h != h)) { 01269 TRACE(PREFIX_E "win_init(): Virtual screens are not supported in " 01270 "AllegroGL!\n"); 01271 return NULL; 01272 } 01273 01274 /* Fill in missing color depth info */ 01275 __allegro_gl_fill_in_info(); 01276 01277 /* Be sure the current desktop color depth is at least 15bpp */ 01278 /* We may want to change this, so try to set a better depth, or 01279 to at least report an error somehow */ 01280 desktop_depth = desktop_color_depth(); 01281 01282 if (desktop_depth < 15) 01283 return NULL; 01284 01285 TRACE(PREFIX_I "win_init(): Requested color depth: %i " 01286 "Desktop color depth: %i\n", allegro_gl_display_info.colour_depth, 01287 desktop_depth); 01288 01289 /* In the moment the main window is destroyed, Allegro loses focus, and 01290 * focus can only be returned by actual user input under Windows XP. So 01291 * we need to create a dummy window which retains focus for us, until 01292 * the new window is up. 01293 */ 01294 if (fullscreen) dummy_window(); 01295 01296 /* Need to set the w and h driver members at this point to avoid assertion 01297 * failure in set_mouse_range() when win_set_window() is called. 01298 */ 01299 if (fullscreen) { 01300 gfx_allegro_gl_fullscreen.w = w; 01301 gfx_allegro_gl_fullscreen.h = h; 01302 } 01303 else { 01304 gfx_allegro_gl_windowed.w = w; 01305 gfx_allegro_gl_windowed.h = h; 01306 } 01307 01308 /* request a fresh new window from Allegro... */ 01309 /* Set a NULL window to get Allegro to generate a new HWND. This is needed 01310 * because we can only set the pixel format once per window. Thus, calling 01311 * set_gfx_mode() multiple times will fail without this code. 01312 */ 01313 if (!first_time) { 01314 win_set_window(NULL); 01315 } 01316 first_time = 0; 01317 01318 /* ...and retrieve its handle */ 01319 wnd = win_get_window(); 01320 if (!wnd) 01321 return NULL; 01322 01323 /* set up the AllegroGL window */ 01324 if (fullscreen) { 01325 style = WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS; 01326 exstyle = WS_EX_APPWINDOW | WS_EX_TOPMOST; 01327 } 01328 else { 01329 style = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN 01330 | WS_CLIPSIBLINGS; 01331 exstyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; 01332 } 01333 01334 TRACE(PREFIX_I "win_init(): Setting up window.\n"); 01335 allegrogl_init_window(w, h, style, exstyle); 01336 01337 __allegro_gl_hdc = GetDC(wnd); /* get the device context of our window */ 01338 if (!__allegro_gl_hdc) { 01339 goto Error; 01340 } 01341 01342 TRACE(PREFIX_I "win_init(): Driver selected fullscreen: %s\n", 01343 fullscreen ? "Yes" : "No"); 01344 01345 if (fullscreen) 01346 { 01347 DEVMODE dm; 01348 DEVMODE fallback_dm; 01349 int fallback_dm_valid = 0; 01350 01351 int bpp_to_check[] = {16, 32, 24, 15, 0}; 01352 int bpp_checked[] = {0, 0, 0, 0, 0}; 01353 int bpp_index = 0; 01354 int i, j, result, modeswitch, done = 0; 01355 01356 for (j = 0; j < 4; j++) 01357 { 01358 if (bpp_to_check[j] == allegro_gl_get(AGL_COLOR_DEPTH)) 01359 { 01360 bpp_index = j; 01361 break; 01362 } 01363 } 01364 01365 dm.dmSize = sizeof(DEVMODE); 01366 dm_saved.dmSize = sizeof(DEVMODE); 01367 01368 /* Save old mode */ 01369 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm_saved); 01370 dm.dmBitsPerPel = desktop_depth; /* Go around Win95's bug */ 01371 01372 do 01373 { 01374 if (!bpp_to_check[bpp_index]) 01375 { 01376 TRACE(PREFIX_E "win_init(): No more color depths to test.\n" 01377 "\tUnable to find appropriate full screen mode and pixel " 01378 "format.\n"); 01379 goto Error; 01380 } 01381 01382 TRACE(PREFIX_I "win_init(): Testing color depth: %i\n", 01383 bpp_to_check[bpp_index]); 01384 01385 memset(&dm, 0, sizeof(DEVMODE)); 01386 dm.dmSize = sizeof(DEVMODE); 01387 01388 i = 0; 01389 do 01390 { 01391 modeswitch = EnumDisplaySettings(NULL, i, &dm); 01392 if (!modeswitch) 01393 break; 01394 01395 if ((dm.dmPelsWidth == (unsigned) w) 01396 && (dm.dmPelsHeight == (unsigned) h) 01397 && (dm.dmBitsPerPel == (unsigned) bpp_to_check[bpp_index]) 01398 && (dm.dmDisplayFrequency != (unsigned) refresh_rate)) { 01399 /* Keep it as fallback if refresh rate request could not 01400 * be satisfied. Try to get as close to 60Hz as possible though, 01401 * it's a bit better for a fallback than just blindly picking 01402 * something like 47Hz or 200Hz. 01403 */ 01404 if (!fallback_dm_valid) { 01405 fallback_dm = dm; 01406 fallback_dm_valid = 1; 01407 } 01408 else if (dm.dmDisplayFrequency >= 60) { 01409 if (dm.dmDisplayFrequency < fallback_dm.dmDisplayFrequency) { 01410 fallback_dm = dm; 01411 } 01412 } 01413 } 01414 01415 i++; 01416 } 01417 while ((dm.dmPelsWidth != (unsigned) w) 01418 || (dm.dmPelsHeight != (unsigned) h) 01419 || (dm.dmBitsPerPel != (unsigned) bpp_to_check[bpp_index]) 01420 || (dm.dmDisplayFrequency != (unsigned) refresh_rate)); 01421 01422 if (!modeswitch && !fallback_dm_valid) { 01423 TRACE(PREFIX_I "win_init(): Unable to set mode, continuing " 01424 "with next color depth\n"); 01425 } 01426 else { 01427 if (!modeswitch && fallback_dm_valid) 01428 dm = fallback_dm; 01429 01430 TRACE(PREFIX_I "win_init(): bpp_to_check[bpp_index] = %i\n", 01431 bpp_to_check[bpp_index]); 01432 TRACE(PREFIX_I "win_init(): dm.dmBitsPerPel = %i\n", 01433 (int)dm.dmBitsPerPel); 01434 01435 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL 01436 | DM_DISPLAYFREQUENCY; 01437 01438 result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); 01439 01440 if (result == DISP_CHANGE_SUCCESSFUL) 01441 { 01442 TRACE(PREFIX_I "win_init(): Setting pixel format.\n"); 01443 pf = select_pixel_format(&pfd); 01444 if (pf) { 01445 TRACE(PREFIX_I "mode found\n"); 01446 _set_current_refresh_rate(dm.dmDisplayFrequency); 01447 done = 1; 01448 } 01449 else { 01450 TRACE(PREFIX_I "win_init(): Couldn't find compatible " 01451 "GL context. Trying another screen mode.\n"); 01452 } 01453 } 01454 } 01455 01456 fallback_dm_valid = 0; 01457 bpp_checked[bpp_index] = 1; 01458 01459 bpp_index = 0; 01460 while (bpp_checked[bpp_index]) { 01461 bpp_index++; 01462 } 01463 } while (!done); 01464 } 01465 else { 01466 DEVMODE dm; 01467 01468 memset(&dm, 0, sizeof(DEVMODE)); 01469 dm.dmSize = sizeof(DEVMODE); 01470 if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm) != 0) { 01471 _set_current_refresh_rate(dm.dmDisplayFrequency); 01472 } 01473 } 01474 01475 if (!fullscreen) { 01476 TRACE(PREFIX_I "win_init(): Setting pixel format.\n"); 01477 pf = select_pixel_format(&pfd); 01478 if (pf == 0) 01479 goto Error; 01480 } 01481 01482 /* set the pixel format */ 01483 if (!SetPixelFormat(__allegro_gl_hdc, pf, &pfd)) { 01484 log_win32_error("win_init", 01485 "Unable to set pixel format.", 01486 GetLastError()); 01487 goto Error; 01488 } 01489 01490 /* create an OpenGL context */ 01491 allegro_glrc = wglCreateContext(__allegro_gl_hdc); 01492 01493 if (!allegro_glrc) { /* make the context the current one */ 01494 log_win32_error("win_init", 01495 "Unable to create a render context!", 01496 GetLastError()); 01497 goto Error; 01498 } 01499 if (!wglMakeCurrent(__allegro_gl_hdc, allegro_glrc)) { 01500 log_win32_error("win_init", 01501 "Unable to make the context current!", 01502 GetLastError()); 01503 goto Error; 01504 } 01505 01506 01507 if (__wglGetPixelFormatAttribivARB || __wglGetPixelFormatAttribivEXT) { 01508 describe_pixel_format_new(__allegro_gl_hdc, pf, desktop_depth, 01509 NULL, NULL, &allegro_gl_display_info); 01510 } 01511 else { 01512 describe_pixel_format_old(__allegro_gl_hdc, pf, desktop_depth, 01513 NULL, NULL, &allegro_gl_display_info); 01514 } 01515 01516 01517 __allegro_gl_set_allegro_image_format(FALSE); 01518 set_color_depth(allegro_gl_display_info.colour_depth); 01519 allegro_gl_display_info.w = w; 01520 allegro_gl_display_info.h = h; 01521 01522 01523 /* <rohannessian> Win98/2k/XP's window forground rules don't let us 01524 * make our window the topmost window on launch. This causes issues on 01525 * full-screen apps, as DInput loses input focus on them. 01526 * We use this trick to force the window to be topmost, when switching 01527 * to full-screen only. Note that this only works for Win98 and greater. 01528 * Win95 will ignore our SystemParametersInfo() calls. 01529 * 01530 * See http://support.microsoft.com:80/support/kb/articles/Q97/9/25.asp 01531 * for details. 01532 */ 01533 { 01534 DWORD lock_time; 01535 01536 #define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000 01537 #define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001 01538 if (fullscreen) { 01539 SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 01540 0, (LPVOID)&lock_time, 0); 01541 SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 01542 0, (LPVOID)0, 01543 SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); 01544 } 01545 01546 ShowWindow(wnd, SW_SHOWNORMAL); 01547 SetForegroundWindow(wnd); 01548 /* In some rare cases, it doesn't seem to work without the loop. And we 01549 * absolutely need this to succeed, else we trap the user in a 01550 * fullscreen window without input. 01551 */ 01552 while (GetForegroundWindow() != wnd) { 01553 rest(100); 01554 SetForegroundWindow(wnd); 01555 } 01556 UpdateWindow(wnd); 01557 01558 if (fullscreen) { 01559 SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 01560 0, (LPVOID)lock_time, 01561 SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE); 01562 } 01563 #undef SPI_GETFOREGROUNDLOCKTIMEOUT 01564 #undef SPI_SETFOREGROUNDLOCKTIMEOUT 01565 } 01566 01567 win_grab_input(); 01568 01569 if (fullscreen) { 01570 allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_fullscreen, 01571 w, h, allegro_gl_get(AGL_COLOR_DEPTH)); 01572 } 01573 else { 01574 allegro_gl_screen= allegro_gl_create_screen(&gfx_allegro_gl_windowed, 01575 w, h, allegro_gl_get(AGL_COLOR_DEPTH)); 01576 } 01577 01578 if (!allegro_gl_screen) { 01579 ChangeDisplaySettings(NULL, 0); 01580 goto Error; 01581 } 01582 01583 01584 TRACE(PREFIX_I "win_init(): GLScreen: %ix%ix%i\n", 01585 w, h, allegro_gl_get(AGL_COLOR_DEPTH)); 01586 01587 allegro_gl_screen->id |= BMP_ID_VIDEO | BMP_ID_MASK; 01588 01589 __allegro_gl_valid_context = TRUE; 01590 __allegro_gl_driver = &allegro_gl_win; 01591 initialized = 1; 01592 01593 /* Print out OpenGL version info */ 01594 TRACE(PREFIX_I "OpenGL Version: %s\n", (AL_CONST char*)glGetString(GL_VERSION)); 01595 TRACE(PREFIX_I "Vendor: %s\n", (AL_CONST char*)glGetString(GL_VENDOR)); 01596 TRACE(PREFIX_I "Renderer: %s\n\n", (AL_CONST char*)glGetString(GL_RENDERER)); 01597 01598 /* Detect if the GL driver is based on Mesa */ 01599 allegro_gl_info.is_mesa_driver = FALSE; 01600 if (strstr((AL_CONST char*)glGetString(GL_VERSION),"Mesa")) { 01601 AGL_LOG(1, "OpenGL driver based on Mesa\n"); 01602 allegro_gl_info.is_mesa_driver = TRUE; 01603 } 01604 01605 /* init the GL extensions */ 01606 __allegro_gl_manage_extensions(); 01607 01608 /* Update screen vtable in order to use AGL's */ 01609 __allegro_gl__glvtable_update_vtable(&allegro_gl_screen->vtable); 01610 memcpy(&_screen_vtable, allegro_gl_screen->vtable, sizeof(GFX_VTABLE)); 01611 allegro_gl_screen->vtable = &_screen_vtable; 01612 01613 /* Print out WGL extension info */ 01614 if (wglGetExtensionsStringARB) { 01615 AGL_LOG(1, "WGL Extensions :\n"); 01616 #if LOGLEVEL >= 1 01617 __allegro_gl_print_extensions((AL_CONST char*)wglGetExtensionsStringARB(wglGetCurrentDC())); 01618 #endif 01619 } 01620 else { 01621 TRACE(PREFIX_I "win_init(): No WGL Extensions available\n"); 01622 } 01623 01624 gfx_capabilities |= GFX_HW_CURSOR; 01625 01626 /* Initialize a reasonable viewport. Those should be OpenGL defaults, 01627 * but some drivers don't implement this correctly. 01628 */ 01629 glViewport(0, 0, SCREEN_W, SCREEN_H); 01630 glMatrixMode(GL_PROJECTION); 01631 glLoadIdentity(); 01632 glMatrixMode(GL_MODELVIEW); 01633 glLoadIdentity(); 01634 01635 if (allegro_gl_extensions_GL.ARB_multisample) { 01636 /* Workaround some "special" drivers that do not export the extension 01637 * once it was promoted to core.*/ 01638 if (allegro_gl_opengl_version() >= 1.3) 01639 glSampleCoverage(1.0, GL_FALSE); 01640 else 01641 glSampleCoverageARB(1.0, GL_FALSE); 01642 } 01643 01644 /* Set up some variables that some GL drivers omit */ 01645 glBindTexture(GL_TEXTURE_2D, 0); 01646 01647 screen = allegro_gl_screen; 01648 01649 if (fullscreen) 01650 remove_dummy_window(); 01651 01652 return allegro_gl_screen; 01653 01654 Error: 01655 if (allegro_glrc) { 01656 wglDeleteContext(allegro_glrc); 01657 } 01658 if (__allegro_gl_hdc) { 01659 ReleaseDC(wnd, __allegro_gl_hdc); 01660 } 01661 __allegro_gl_hdc = NULL; 01662 ChangeDisplaySettings(NULL, 0); 01663 allegro_gl_win_exit(NULL); 01664 01665 return NULL; 01666 } 01667 01668 01669 01670 static BITMAP *allegro_gl_win_init_windowed(int w, int h, int v_w, int v_h, 01671 int color_depth) 01672 { 01673 fullscreen = 0; 01674 return allegro_gl_win_init(w, h, v_w, v_h); 01675 } 01676 01677 01678 01679 static BITMAP *allegro_gl_win_init_fullscreen(int w, int h, int v_w, int v_h, 01680 int color_depth) 01681 { 01682 fullscreen = 1; 01683 return allegro_gl_win_init(w, h, v_w, v_h); 01684 } 01685 01686 01687 01688 static void allegro_gl_win_exit(struct BITMAP *b) 01689 { 01690 /* XXX <rohannessian> For some reason, uncommenting this line will blank 01691 * out the log file. 01692 */ 01693 //TRACE(PREFIX_I "allegro_gl_win_exit: Shutting down.\n"); 01694 __allegro_gl_unmanage_extensions(); 01695 01696 if (allegro_glrc) { 01697 wglDeleteContext(allegro_glrc); 01698 allegro_glrc = NULL; 01699 } 01700 01701 if (__allegro_gl_hdc) { 01702 ReleaseDC(wnd, __allegro_gl_hdc); 01703 __allegro_gl_hdc = NULL; 01704 } 01705 01706 if (fullscreen && initialized) { 01707 /* Restore screen */ 01708 ChangeDisplaySettings(NULL, 0); 01709 _set_current_refresh_rate(0); 01710 } 01711 initialized = 0; 01712 01713 /* Note: Allegro will destroy screen (== allegro_gl_screen), 01714 * so don't destroy it here. 01715 */ 01716 //destroy_bitmap(allegro_gl_screen); 01717 allegro_gl_screen = NULL; 01718 01719 /* hide the window */ 01720 system_driver->restore_console_state(); 01721 01722 /* restore original Allegro styles */ 01723 SetWindowLong(wnd, GWL_STYLE, style_saved); 01724 SetWindowLong(wnd, GWL_EXSTYLE, exstyle_saved); 01725 SetWindowPos(wnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER 01726 | SWP_FRAMECHANGED); 01727 01728 __allegro_gl_valid_context = FALSE; 01729 01730 return; 01731 } 01732 01733 01734 /* 01735 Returns TRUE is dm doesn't match any mode in mode_list, FALSE otherwise. 01736 */ 01737 static int is_mode_entry_unique(GFX_MODE_LIST *mode_list, DEVMODE *dm) { 01738 int i; 01739 01740 for (i = 0; i < mode_list->num_modes; ++i) { 01741 if (mode_list->mode[i].width == (int)dm->dmPelsWidth 01742 && mode_list->mode[i].height == (int)dm->dmPelsHeight 01743 && mode_list->mode[i].bpp == (int)dm->dmBitsPerPel) 01744 return FALSE; 01745 } 01746 01747 return TRUE; 01748 } 01749 01750 01751 01752 /* Returns a list of valid video modes */ 01753 static GFX_MODE_LIST* allegro_gl_win_fetch_mode_list(void) 01754 { 01755 int c, modes_count; 01756 GFX_MODE_LIST *mode_list; 01757 DEVMODE dm; 01758 01759 dm.dmSize = sizeof(DEVMODE); 01760 01761 /* Allocate space for mode list. */ 01762 mode_list = malloc(sizeof(GFX_MODE_LIST)); 01763 if (!mode_list) { 01764 return NULL; 01765 } 01766 01767 /* Allocate and fill the first mode in case EnumDisplaySettings fails at 01768 * first call. 01769 */ 01770 mode_list->mode = malloc(sizeof(GFX_MODE)); 01771 if (!mode_list->mode) { 01772 free(mode_list); 01773 return NULL; 01774 } 01775 mode_list->mode[0].width = 0; 01776 mode_list->mode[0].height = 0; 01777 mode_list->mode[0].bpp = 0; 01778 mode_list->num_modes = 0; 01779 01780 modes_count = 0; 01781 c = 0; 01782 while (EnumDisplaySettings(NULL, c, &dm)) { 01783 mode_list->mode = realloc(mode_list->mode, 01784 sizeof(GFX_MODE) * (modes_count + 2)); 01785 if (!mode_list->mode) { 01786 free(mode_list); 01787 return NULL; 01788 } 01789 01790 /* Filter modes with bpp lower than 9, and those which are already 01791 * in there. 01792 */ 01793 if (dm.dmBitsPerPel > 8 && is_mode_entry_unique(mode_list, &dm)) { 01794 mode_list->mode[modes_count].width = dm.dmPelsWidth; 01795 mode_list->mode[modes_count].height = dm.dmPelsHeight; 01796 mode_list->mode[modes_count].bpp = dm.dmBitsPerPel; 01797 ++modes_count; 01798 mode_list->mode[modes_count].width = 0; 01799 mode_list->mode[modes_count].height = 0; 01800 mode_list->mode[modes_count].bpp = 0; 01801 mode_list->num_modes = modes_count; 01802 } 01803 ++c; 01804 }; 01805 01806 return mode_list; 01807 } 01808 01809 01810 01811 01812 /* AllegroGL driver routines */ 01813 01814 static void flip(void) 01815 { 01816 SwapBuffers(__allegro_gl_hdc); 01817 } 01818 01819 01820 01821 static void gl_on(void) 01822 { 01823 return; 01824 } 01825 01826 01827 01828 static void gl_off(void) 01829 { 01830 return; 01831 } 01832 01833 01834 01835 /* AllegroGL driver */ 01836 01837 static struct allegro_gl_driver allegro_gl_win = { 01838 flip, gl_on, gl_off, NULL 01839 }; 01840