Main Page | Modules | File List | Globals | Related Pages

win.c

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

Generated on Wed Jun 30 23:59:52 2004 for AllegroGL by doxygen 1.3.5