AllegroGL: win.c Source File

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

# win.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 #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(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