1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Windows OpenGL display driver
12  *
13  *      By Milan Mimica.
14  *      Based on AllegroGL Windows display driver.
15  *
16  */
17 
18 #if 0
19 /* Raw input */
20 #define _WIN32_WINNT 0x0501
21 #ifndef WINVER
22 #define WINVER 0x0501
23 #endif
24 #endif
25 
26 #include <windows.h>
27 
28 #include "allegro5/allegro.h"
29 #include "allegro5/allegro_opengl.h"
30 #include "allegro5/system.h"
31 #include "allegro5/internal/aintern.h"
32 #include "allegro5/internal/aintern_bitmap.h"
33 #include "allegro5/internal/aintern_opengl.h"
34 #include "allegro5/internal/aintern_vector.h"
35 #include "allegro5/internal/aintern_wclipboard.h"
36 #include "allegro5/platform/aintwin.h"
37 #include "allegro5/internal/aintern_wunicode.h"
38 
39 #include "wgl.h"
40 
41 #include <process.h>
42 
43 ALLEGRO_DEBUG_CHANNEL("display")
44 
45 static ALLEGRO_DISPLAY_INTERFACE vt;
46 
47 /* Forward declarations: */
48 static void display_thread_proc(void *arg);
49 static void destroy_display_internals(ALLEGRO_DISPLAY_WGL *wgl_disp);
50 static bool wgl_acknowledge_resize(ALLEGRO_DISPLAY *d);
51 
52 /* Prevents switching to desktop resolution when destroying the display. Used
53    on full screen resize. */
54 static bool _wgl_do_not_change_display_mode = false;
55 
56 /*
57  * These parameters cannot be gotten by the display thread because
58  * they're thread local. We get them in the calling thread first.
59  */
60 typedef struct WGL_DISPLAY_PARAMETERS {
61    ALLEGRO_DISPLAY_WGL *display;
62    volatile bool init_failed;
63    HANDLE AckEvent;
64    int window_x, window_y;
65    /* Not owned. */
66    const char* window_title;
67 } WGL_DISPLAY_PARAMETERS;
68 
is_wgl_extension_supported(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,const char * extension,HDC dc)69 static bool is_wgl_extension_supported(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, const char *extension, HDC dc)
70 {
71    int ret;
72 
73    /* XXX deprecated in OpenGL 3.0 */
74    if (!glGetString(GL_EXTENSIONS))
75       return false;
76    if (!_wglGetExtensionsStringARB)
77       return false;
78 
79    ret = _al_ogl_look_for_an_extension(extension,
80          (const GLubyte*)_wglGetExtensionsStringARB(dc));
81 
82    return ret;
83 }
84 
85 
init_temp_context(HWND wnd)86 static HGLRC init_temp_context(HWND wnd)
87 {
88    PIXELFORMATDESCRIPTOR pfd;
89    int pf;
90    HDC dc;
91    HGLRC glrc;
92 
93    dc = GetDC(wnd);
94 
95    memset(&pfd, 0, sizeof(pfd));
96    pfd.nSize = sizeof(pfd);
97    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL
98               | PFD_DOUBLEBUFFER_DONTCARE | PFD_STEREO_DONTCARE;
99    pfd.iPixelType = PFD_TYPE_RGBA;
100    pfd.iLayerType = PFD_MAIN_PLANE;
101    pfd.cColorBits = 32;
102 
103    pf = ChoosePixelFormat(dc, &pfd);
104    if (!pf) {
105       ALLEGRO_ERROR("Unable to chose a temporary pixel format. %s\n",
106         _al_win_last_error());
107       return NULL;
108    }
109 
110    memset(&pfd, 0, sizeof(pfd));
111    if (!SetPixelFormat(dc, pf, &pfd)) {
112       ALLEGRO_ERROR("Unable to set a temporary pixel format. %s\n",
113         _al_win_last_error());
114       return NULL;
115    }
116 
117    glrc = wglCreateContext(dc);
118    if (!glrc) {
119       ALLEGRO_ERROR("Unable to create a render context. %s\n",
120         _al_win_last_error());
121       return NULL;
122    }
123 
124    if (!wglMakeCurrent(dc, glrc)) {
125       ALLEGRO_ERROR("Unable to set the render context as current. %s\n",
126         _al_win_last_error());
127       wglDeleteContext(glrc);
128       return NULL;
129    }
130 
131    return glrc;
132 }
133 
134 
135 static _ALLEGRO_wglGetPixelFormatAttribivARB_t _wglGetPixelFormatAttribivARB = NULL;
136 static _ALLEGRO_wglGetPixelFormatAttribivEXT_t _wglGetPixelFormatAttribivEXT = NULL;
137 
init_pixel_format_extensions(void)138 static bool init_pixel_format_extensions(void)
139 {
140    /* Load the ARB_p_f symbol - Note, we shouldn't use the extension
141     * mechanism here, because it hasn't been initialized yet!
142     */
143    _wglGetPixelFormatAttribivARB =
144       (_ALLEGRO_wglGetPixelFormatAttribivARB_t)wglGetProcAddress("wglGetPixelFormatAttribivARB");
145    _wglGetPixelFormatAttribivEXT =
146       (_ALLEGRO_wglGetPixelFormatAttribivEXT_t)wglGetProcAddress("wglGetPixelFormatAttribivEXT");
147 
148    if (!_wglGetPixelFormatAttribivARB && !_wglGetPixelFormatAttribivEXT) {
149       ALLEGRO_ERROR("WGL_ARB/EXT_pf not supported.\n");
150       return false;
151    }
152 
153    return true;
154 }
155 
156 
157 static _ALLEGRO_wglCreateContextAttribsARB_t _wglCreateContextAttribsARB = NULL;
158 
init_context_creation_extensions(void)159 static bool init_context_creation_extensions(void)
160 {
161    _wglCreateContextAttribsARB =
162       (_ALLEGRO_wglCreateContextAttribsARB_t)wglGetProcAddress("wglCreateContextAttribsARB");
163 
164    if (!_wglCreateContextAttribsARB) {
165       ALLEGRO_ERROR("wglCreateContextAttribs not supported!\n");
166       return false;
167    }
168 
169    return true;
170 }
171 
172 
get_pixel_formats_count_old(HDC dc)173 static int get_pixel_formats_count_old(HDC dc)
174 {
175    PIXELFORMATDESCRIPTOR pfd;
176    int ret;
177 
178    ret = DescribePixelFormat(dc, 1, sizeof(pfd), &pfd);
179    if (!ret) {
180       ALLEGRO_ERROR("DescribePixelFormat failed! %s\n",
181                      _al_win_last_error());
182    }
183 
184    return ret;
185 }
186 
187 
get_pixel_formats_count_ext(HDC dc)188 static int get_pixel_formats_count_ext(HDC dc)
189 {
190    int attrib[1];
191    int value[1];
192 
193    attrib[0] = WGL_NUMBER_PIXEL_FORMATS_ARB;
194    if ((_wglGetPixelFormatAttribivARB(dc, 0, 0, 1, attrib, value) == GL_FALSE)
195     && (_wglGetPixelFormatAttribivEXT(dc, 0, 0, 1, attrib, value) == GL_FALSE)) {
196         ALLEGRO_ERROR("WGL_ARB/EXT_pixel_format use failed! %s\n",
197                        _al_win_last_error());
198    }
199 
200    return value[0];
201 }
202 
203 
display_pixel_format(ALLEGRO_EXTRA_DISPLAY_SETTINGS * eds)204 static void display_pixel_format(ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds)
205 {
206    ALLEGRO_INFO("Accelerated: %s\n", eds->settings[ALLEGRO_RENDER_METHOD] ? "yes" : "no");
207    ALLEGRO_INFO("Single-buffer: %s\n", eds->settings[ALLEGRO_SINGLE_BUFFER] ? "yes" : "no");
208    if (eds->settings[ALLEGRO_SWAP_METHOD] > 0)
209       ALLEGRO_INFO("Swap method: %s\n", eds->settings[ALLEGRO_SWAP_METHOD] == 2 ? "flip" : "copy");
210    else
211       ALLEGRO_INFO("Swap method: undefined\n");
212    ALLEGRO_INFO("Color format: r%i g%i b%i a%i, %i bit\n",
213       eds->settings[ALLEGRO_RED_SIZE],
214       eds->settings[ALLEGRO_GREEN_SIZE],
215       eds->settings[ALLEGRO_BLUE_SIZE],
216       eds->settings[ALLEGRO_ALPHA_SIZE],
217       eds->settings[ALLEGRO_COLOR_SIZE]);
218    ALLEGRO_INFO("Depth buffer: %i bits\n", eds->settings[ALLEGRO_DEPTH_SIZE]);
219    ALLEGRO_INFO("Sample buffers: %s\n", eds->settings[ALLEGRO_SAMPLE_BUFFERS] ? "yes" : "no");
220    ALLEGRO_INFO("Samples: %i\n", eds->settings[ALLEGRO_SAMPLES]);
221 }
222 
223 
decode_pixel_format_old(PIXELFORMATDESCRIPTOR * pfd,ALLEGRO_EXTRA_DISPLAY_SETTINGS * eds)224 static int decode_pixel_format_old(PIXELFORMATDESCRIPTOR *pfd,
225                                    ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds)
226 {
227    ALLEGRO_INFO("Decoding:\n");
228 
229 	/* Not interested if it doesn't support OpenGL and RGBA */
230    if (!(pfd->dwFlags & PFD_SUPPORT_OPENGL)) {
231       ALLEGRO_INFO("OpenGL Unsupported\n");
232       return false;
233    }
234    if (pfd->iPixelType != PFD_TYPE_RGBA) {
235       ALLEGRO_INFO("Not RGBA mode\n");
236       return false;
237    }
238 
239    /* hardware acceleration */
240    if (((pfd->dwFlags & PFD_GENERIC_ACCELERATED) && (pfd->dwFlags & PFD_GENERIC_FORMAT))
241    || (!(pfd->dwFlags & PFD_GENERIC_ACCELERATED) && !(pfd->dwFlags & PFD_GENERIC_FORMAT)))
242       eds->settings[ALLEGRO_RENDER_METHOD] = 1;
243    else
244       eds->settings[ALLEGRO_RENDER_METHOD] = 0;
245 
246    /* Depths of colour buffers */
247    eds->settings[ALLEGRO_RED_SIZE] = pfd->cRedBits;
248    eds->settings[ALLEGRO_GREEN_SIZE] = pfd->cGreenBits;
249    eds->settings[ALLEGRO_BLUE_SIZE] = pfd->cBlueBits;
250    eds->settings[ALLEGRO_ALPHA_SIZE] = pfd->cAlphaBits;
251 
252    /* Depths of accumulation buffer */
253    eds->settings[ALLEGRO_ACC_RED_SIZE] = pfd->cAccumRedBits;
254    eds->settings[ALLEGRO_ACC_GREEN_SIZE] = pfd->cAccumGreenBits;
255    eds->settings[ALLEGRO_ACC_BLUE_SIZE] = pfd->cAccumBlueBits;
256    eds->settings[ALLEGRO_ACC_ALPHA_SIZE] = pfd->cAccumAlphaBits;
257 
258    /* Miscellaneous settings */
259    eds->settings[ALLEGRO_SINGLE_BUFFER] = !(pfd->dwFlags & PFD_DOUBLEBUFFER);
260    eds->settings[ALLEGRO_DEPTH_SIZE] = pfd->cDepthBits;
261    eds->settings[ALLEGRO_STENCIL_SIZE] = pfd->cStencilBits;
262    eds->settings[ALLEGRO_COLOR_SIZE] = pfd->cColorBits;
263    eds->settings[ALLEGRO_STEREO] = pfd->dwFlags & PFD_STEREO;
264    eds->settings[ALLEGRO_AUX_BUFFERS] = pfd->cAuxBuffers;
265 
266    /* These are the component shifts. */
267    eds->settings[ALLEGRO_RED_SHIFT] = pfd->cRedShift;
268    eds->settings[ALLEGRO_GREEN_SHIFT] = pfd->cGreenShift;
269    eds->settings[ALLEGRO_BLUE_SHIFT] = pfd->cBlueShift;
270    eds->settings[ALLEGRO_ALPHA_SHIFT] = pfd->cAlphaShift;
271 
272    /* Multisampling isn't supported under Windows if we don't also use
273     * WGL_ARB_pixel_format or WGL_EXT_pixel_format.
274     */
275    eds->settings[ALLEGRO_SAMPLE_BUFFERS] = 0;
276    eds->settings[ALLEGRO_SAMPLES] = 0;
277 
278    /* Swap method can't be detected without WGL_ARB_pixel_format or
279     * WGL_EXT_pixel_format
280     */
281    eds->settings[ALLEGRO_SWAP_METHOD] = 0;
282 
283    /* Float depth/color isn't supported under Windows if we don't also use
284     * AGL_ARB_pixel_format or WGL_EXT_pixel_format.
285     */
286    eds->settings[ALLEGRO_FLOAT_COLOR] = 0;
287    eds->settings[ALLEGRO_FLOAT_DEPTH] = 0;
288 
289    // FIXME
290 
291    eds->settings[ALLEGRO_COMPATIBLE_DISPLAY] = 1;
292 
293    return true;
294 }
295 
296 
decode_pixel_format_attrib(ALLEGRO_EXTRA_DISPLAY_SETTINGS * eds,int num_attribs,const int * attrib,const int * value)297 static bool decode_pixel_format_attrib(ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds, int num_attribs,
298                                       const int *attrib, const int *value)
299 {
300    int i;
301 
302    ALLEGRO_INFO("Decoding:\n");
303 
304    eds->settings[ALLEGRO_SAMPLES] = 0;
305    eds->settings[ALLEGRO_SAMPLE_BUFFERS] = 0;
306    eds->settings[ALLEGRO_FLOAT_DEPTH] = 0;
307    eds->settings[ALLEGRO_FLOAT_COLOR] = 0;
308    eds->settings[ALLEGRO_COMPATIBLE_DISPLAY] = 1;
309 
310    for (i = 0; i < num_attribs; i++) {
311       /* Not interested if it doesn't support OpenGL or window drawing or RGBA. */
312       if (attrib[i] == WGL_SUPPORT_OPENGL_ARB && value[i] == 0) {
313          ALLEGRO_INFO("OpenGL Unsupported\n");
314          return false;
315       }
316       else if (attrib[i] == WGL_DRAW_TO_WINDOW_ARB && value[i] == 0) {
317          ALLEGRO_INFO("Can't draw to window\n");
318          return false;
319       }
320       else if (attrib[i] == WGL_PIXEL_TYPE_ARB
321          && (value[i] != WGL_TYPE_RGBA_ARB && value[i] != WGL_TYPE_RGBA_FLOAT_ARB)) {
322          ALLEGRO_INFO("Not RGBA mode\n");
323          return false;
324       }
325       /* hardware acceleration */
326       else if (attrib[i] == WGL_ACCELERATION_ARB) {
327          eds->settings[ALLEGRO_RENDER_METHOD] = (value[i] == WGL_NO_ACCELERATION_ARB) ? 0 : 1;
328       }
329       /* Depths of colour buffers */
330       else if (attrib[i] == WGL_RED_BITS_ARB) {
331          eds->settings[ALLEGRO_RED_SIZE] = value[i];
332       }
333       else if (attrib[i] == WGL_GREEN_BITS_ARB) {
334          eds->settings[ALLEGRO_GREEN_SIZE] = value[i];
335       }
336       else if (attrib[i] == WGL_BLUE_BITS_ARB) {
337          eds->settings[ALLEGRO_BLUE_SIZE] = value[i];
338       }
339       else if (attrib[i] == WGL_ALPHA_BITS_ARB) {
340          eds->settings[ALLEGRO_ALPHA_SIZE] = value[i];
341       }
342       /* Shift of color components */
343       else if (attrib[i] == WGL_RED_SHIFT_ARB) {
344          eds->settings[ALLEGRO_RED_SHIFT] = value[i];
345       }
346       else if (attrib[i] == WGL_GREEN_SHIFT_ARB) {
347          eds->settings[ALLEGRO_GREEN_SHIFT] = value[i];
348       }
349       else if (attrib[i] == WGL_BLUE_SHIFT_ARB) {
350          eds->settings[ALLEGRO_BLUE_SHIFT] = value[i];
351       }
352       else if (attrib[i] == WGL_ALPHA_SHIFT_ARB) {
353          eds->settings[ALLEGRO_ALPHA_SHIFT] = value[i];
354       }
355       /* Miscellaneous settings */
356       else if (attrib[i] == WGL_DOUBLE_BUFFER_ARB) {
357          eds->settings[ALLEGRO_SINGLE_BUFFER] = !(value[i]);
358       }
359       else if (attrib[i] == WGL_SWAP_METHOD_ARB) {
360          if (value[i] == WGL_SWAP_UNDEFINED_ARB)
361             eds->settings[ALLEGRO_SWAP_METHOD] = 0;
362          else if (value[i] == WGL_SWAP_COPY_ARB)
363             eds->settings[ALLEGRO_SWAP_METHOD] = 1;
364          else if (value[i] == WGL_SWAP_EXCHANGE_ARB)
365             eds->settings[ALLEGRO_SWAP_METHOD] = 2;
366       }
367 
368       else if (attrib[i] == WGL_STEREO_ARB) {
369          eds->settings[ALLEGRO_STEREO] = value[i];
370       }
371       else if (attrib[i] == WGL_AUX_BUFFERS_ARB) {
372          eds->settings[ALLEGRO_AUX_BUFFERS] = value[i];
373       }
374       else if (attrib[i] == WGL_STENCIL_BITS_ARB) {
375          eds->settings[ALLEGRO_STENCIL_SIZE] = value[i];
376       }
377       /* Depths of accumulation buffer */
378       else if (attrib[i] == WGL_ACCUM_RED_BITS_ARB) {
379          eds->settings[ALLEGRO_ACC_RED_SIZE] = value[i];
380       }
381       else if (attrib[i] == WGL_ACCUM_GREEN_BITS_ARB) {
382          eds->settings[ALLEGRO_ACC_GREEN_SIZE] = value[i];
383       }
384       else if (attrib[i] == WGL_ACCUM_BLUE_BITS_ARB) {
385          eds->settings[ALLEGRO_ACC_BLUE_SIZE] = value[i];
386       }
387       else if (attrib[i] == WGL_ACCUM_ALPHA_BITS_ARB) {
388          eds->settings[ALLEGRO_ACC_ALPHA_SIZE] = value[i];
389       }
390 
391       else if (attrib[i] == WGL_DEPTH_BITS_ARB) {
392          eds->settings[ALLEGRO_DEPTH_SIZE] = value[i];
393       }
394       else if (attrib[i] == WGL_COLOR_BITS_ARB) {
395          eds->settings[ALLEGRO_COLOR_SIZE] = value[i];
396       }
397       /* Multisampling bits */
398       else if (attrib[i] == WGL_SAMPLE_BUFFERS_ARB) {
399          eds->settings[ALLEGRO_SAMPLE_BUFFERS] = value[i];
400       }
401       else if (attrib[i] == WGL_SAMPLES_ARB) {
402          eds->settings[ALLEGRO_SAMPLES] = value[i];
403       }
404       /* Float color */
405       if (attrib[i] == WGL_PIXEL_TYPE_ARB && value[i] == WGL_TYPE_RGBA_FLOAT_ARB) {
406          eds->settings[ALLEGRO_FLOAT_COLOR] = true;
407       }
408       /* Float depth */
409       else if (attrib[i] == WGL_DEPTH_FLOAT_EXT) {
410          eds->settings[ALLEGRO_FLOAT_DEPTH] = value[i];
411       }
412    }
413 
414    return true;
415 }
416 
417 
read_pixel_format_old(int fmt,HDC dc)418 static ALLEGRO_EXTRA_DISPLAY_SETTINGS* read_pixel_format_old(int fmt, HDC dc)
419 {
420    ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = NULL;
421    PIXELFORMATDESCRIPTOR pfd;
422    int result;
423 
424    result = DescribePixelFormat(dc, fmt+1, sizeof(pfd), &pfd);
425    if (!result) {
426       ALLEGRO_WARN("DescribePixelFormat() failed. %s\n", _al_win_last_error());
427       return NULL;
428    }
429 
430    eds = al_calloc(1, sizeof *eds);
431    if (!decode_pixel_format_old(&pfd, eds)) {
432       al_free(eds);
433       return NULL;
434    }
435 
436    return eds;
437 }
438 
439 
read_pixel_format_ext(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,int fmt,HDC dc)440 static ALLEGRO_EXTRA_DISPLAY_SETTINGS* read_pixel_format_ext(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, int fmt, HDC dc)
441 {
442    ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = NULL;
443 
444    /* Note: Even though we use te ARB suffix, all those enums are compatible
445     * with EXT_pixel_format.
446     */
447    int attrib[] = {
448       WGL_SUPPORT_OPENGL_ARB,
449       WGL_DRAW_TO_WINDOW_ARB,
450       WGL_PIXEL_TYPE_ARB,
451       WGL_ACCELERATION_ARB,
452       WGL_DOUBLE_BUFFER_ARB,
453       WGL_DEPTH_BITS_ARB,
454       WGL_SWAP_METHOD_ARB,
455       WGL_COLOR_BITS_ARB,
456       WGL_RED_BITS_ARB,
457       WGL_GREEN_BITS_ARB,
458       WGL_BLUE_BITS_ARB,
459       WGL_ALPHA_BITS_ARB,
460       WGL_RED_SHIFT_ARB,
461       WGL_GREEN_SHIFT_ARB,
462       WGL_BLUE_SHIFT_ARB,
463       WGL_ALPHA_SHIFT_ARB,
464       WGL_STENCIL_BITS_ARB,
465       WGL_STEREO_ARB,
466       WGL_ACCUM_BITS_ARB,
467       WGL_ACCUM_RED_BITS_ARB,
468       WGL_ACCUM_GREEN_BITS_ARB,
469       WGL_ACCUM_BLUE_BITS_ARB,
470       WGL_ACCUM_ALPHA_BITS_ARB,
471       WGL_AUX_BUFFERS_ARB,
472 
473       /* The following are used by extensions that add to WGL_pixel_format.
474        * If WGL_p_f isn't supported though, we can't use the (then invalid)
475        * enums. We can't use any magic number either, so we settle for
476        * replicating one. The pixel format decoder
477        * (decode_pixel_format_attrib()) doesn't care about duplicates.
478        */
479       WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLE_BUFFERS_ARB */
480       WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_SAMPLES_ARB        */
481       WGL_AUX_BUFFERS_ARB, /* placeholder for WGL_DEPTH_FLOAT_EXT    */
482    };
483 
484    const int num_attribs = sizeof(attrib) / sizeof(attrib[0]);
485    int *value = (int*)al_malloc(sizeof(int) * num_attribs);
486    int ret;
487 
488    if (!value)
489       return NULL;
490 
491    /* If multisampling is supported, query for it. */
492    if (is_wgl_extension_supported(_wglGetExtensionsStringARB, "WGL_ARB_multisample", dc)) {
493       attrib[num_attribs - 3] = WGL_SAMPLE_BUFFERS_ARB;
494       attrib[num_attribs - 2] = WGL_SAMPLES_ARB;
495    }
496    if (is_wgl_extension_supported(_wglGetExtensionsStringARB, "WGL_EXT_depth_float", dc)) {
497       attrib[num_attribs - 1] = WGL_DEPTH_FLOAT_EXT;
498    }
499 
500    /* Get the pf attributes */
501    if (_wglGetPixelFormatAttribivARB) {
502       ret = _wglGetPixelFormatAttribivARB(dc, fmt+1, 0, num_attribs, attrib, value);
503    }
504    else if (_wglGetPixelFormatAttribivEXT) {
505       ret = _wglGetPixelFormatAttribivEXT(dc, fmt+1, 0, num_attribs, attrib, value);
506    }
507    else {
508       ret = 0;
509    }
510 
511    if (!ret) {
512       ALLEGRO_ERROR("wglGetPixelFormatAttrib failed! %s\n", _al_win_last_error());
513       al_free(value);
514       return NULL;
515    }
516 
517    eds = al_calloc(1, sizeof *eds);
518    if (!decode_pixel_format_attrib(eds, num_attribs, attrib, value)) {
519       al_free(eds);
520       eds = NULL;
521    }
522 
523    al_free(value);
524 
525    /* Hack: for some reason this happens for me under Wine. */
526    if (eds &&
527       eds->settings[ALLEGRO_RED_SHIFT] == 0 &&
528          eds->settings[ALLEGRO_GREEN_SHIFT] == 0 &&
529          eds->settings[ALLEGRO_BLUE_SHIFT] == 0 &&
530          eds->settings[ALLEGRO_ALPHA_SHIFT] == 0) {
531       eds->settings[ALLEGRO_RED_SHIFT] = 0;
532       eds->settings[ALLEGRO_GREEN_SHIFT] = 8;
533       eds->settings[ALLEGRO_BLUE_SHIFT] = 16;
534       eds->settings[ALLEGRO_ALPHA_SHIFT] = 24;
535    }
536 
537    return eds;
538 }
539 
540 
change_display_mode(ALLEGRO_DISPLAY * d)541 static bool change_display_mode(ALLEGRO_DISPLAY *d)
542 {
543    DEVMODE dm;
544    DEVMODE fallback_dm;
545    DISPLAY_DEVICE dd;
546    TCHAR* dev_name = NULL;
547    int i, modeswitch, result;
548    int fallback_dm_valid = 0;
549    int bpp;
550    int adapter = al_get_new_display_adapter();
551 
552    if (adapter >= 0) {
553       memset(&dd, 0, sizeof(dd));
554       dd.cb = sizeof(dd);
555       if (EnumDisplayDevices(NULL, adapter, &dd, 0) == false)
556          return false;
557       dev_name = dd.DeviceName;
558    }
559 
560    memset(&fallback_dm, 0, sizeof(fallback_dm));
561    memset(&dm, 0, sizeof(dm));
562    dm.dmSize = sizeof(DEVMODE);
563 
564    bpp = d->extra_settings.settings[ALLEGRO_COLOR_SIZE];
565    if (!bpp)
566       bpp = 32;
567 
568    i = 0;
569    do {
570       modeswitch = EnumDisplaySettings(dev_name, i, &dm);
571       if (!modeswitch)
572          break;
573 
574       if ((dm.dmPelsWidth  == (unsigned) d->w)
575          && (dm.dmPelsHeight == (unsigned) d->h)
576          && (dm.dmBitsPerPel == (unsigned) bpp)
577          && (dm.dmDisplayFrequency != (unsigned) d->refresh_rate))
578       {
579          /* Keep it as fallback if refresh rate request could not
580           * be satisfied. Try to get as close to 60Hz as possible though,
581           * it's a bit better for a fallback than just blindly picking
582           * something like 47Hz or 200Hz.
583           */
584          if (!fallback_dm_valid) {
585             fallback_dm = dm;
586             fallback_dm_valid = 1;
587          }
588          else if (dm.dmDisplayFrequency >= 60) {
589             if (dm.dmDisplayFrequency < fallback_dm.dmDisplayFrequency) {
590                 fallback_dm = dm;
591             }
592          }
593       }
594       i++;
595    }
596    while ((dm.dmPelsWidth  != (unsigned) d->w)
597        || (dm.dmPelsHeight != (unsigned) d->h)
598        || (dm.dmBitsPerPel != (unsigned) bpp)
599        || (dm.dmDisplayFrequency != (unsigned) d->refresh_rate));
600 
601    if (!modeswitch && !fallback_dm_valid) {
602       ALLEGRO_ERROR("Mode not found.\n");
603       return false;
604    }
605 
606    if (!modeswitch && fallback_dm_valid)
607       dm = fallback_dm;
608 
609    dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
610    result = ChangeDisplaySettingsEx(dev_name, &dm, NULL, CDS_FULLSCREEN, 0);
611 
612    d->refresh_rate = dm.dmDisplayFrequency;
613 
614    if (result != DISP_CHANGE_SUCCESSFUL) {
615       ALLEGRO_ERROR("Unable to set mode. %s\n", _al_win_last_error());
616       return false;
617    }
618 
619    ALLEGRO_INFO("Mode seccessfuly set.\n");
620    return true;
621 }
622 
623 
init_ogl_context_ex(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,HDC dc,bool fc,int major,int minor)624 static HGLRC init_ogl_context_ex(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, HDC dc, bool fc, int major, int minor)
625 {
626    HWND testwnd = NULL;
627    HDC testdc   = NULL;
628    HGLRC testrc = NULL;
629    HGLRC old_rc = NULL;
630    HDC old_dc   = NULL;
631    HGLRC glrc   = NULL;
632 
633    testwnd = _al_win_create_hidden_window();
634    if (!testwnd)
635       return NULL;
636 
637    old_rc = wglGetCurrentContext();
638    old_dc = wglGetCurrentDC();
639 
640    testdc = GetDC(testwnd);
641    testrc = init_temp_context(testwnd);
642    if (!testrc)
643       goto bail;
644 
645    if (is_wgl_extension_supported(_wglGetExtensionsStringARB, "WGL_ARB_create_context", testdc)) {
646       int attrib[] = {WGL_CONTEXT_MAJOR_VERSION_ARB, major,
647                       WGL_CONTEXT_MINOR_VERSION_ARB, minor,
648                       WGL_CONTEXT_FLAGS_ARB, 0,
649                       0};
650       if (fc)
651          attrib[5] = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
652       if (!init_context_creation_extensions())
653          goto bail;
654       /* TODO: we could use the context sharing feature */
655       glrc = _wglCreateContextAttribsARB(dc, 0, attrib);
656    }
657    else
658       goto bail;
659 
660 bail:
661    wglMakeCurrent(NULL, NULL);
662    if (testrc) {
663       wglDeleteContext(testrc);
664    }
665 
666    wglMakeCurrent(old_dc, old_rc);
667 
668    _wglCreateContextAttribsARB = NULL;
669 
670    if (testwnd) {
671       ReleaseDC(testwnd, testdc);
672       DestroyWindow(testwnd);
673    }
674 
675    return glrc;
676 }
677 
678 
get_available_pixel_formats_ext(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,int * count)679 static ALLEGRO_EXTRA_DISPLAY_SETTINGS** get_available_pixel_formats_ext(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, int *count)
680 {
681    HWND testwnd = NULL;
682    HDC testdc   = NULL;
683    HGLRC testrc = NULL;
684    HGLRC old_rc = NULL;
685    HDC old_dc   = NULL;
686    ALLEGRO_EXTRA_DISPLAY_SETTINGS **eds_list = NULL;
687    ALLEGRO_EXTRA_DISPLAY_SETTINGS *ref;
688    int maxindex;
689    int i, j;
690 
691    *count = 0;
692    ref =  _al_get_new_display_settings();
693 
694    /* We need to create a dummy window with a pixel format to get the
695     * list of valid PFDs
696     */
697    testwnd = _al_win_create_hidden_window();
698    if (!testwnd)
699       return false;
700 
701    old_rc = wglGetCurrentContext();
702    old_dc = wglGetCurrentDC();
703 
704    testdc = GetDC(testwnd);
705    testrc = init_temp_context(testwnd);
706    if (!testrc)
707       goto bail;
708 
709    if (!is_wgl_extension_supported(_wglGetExtensionsStringARB, "WGL_ARB_pixel_format", testdc) &&
710        !is_wgl_extension_supported(_wglGetExtensionsStringARB, "WGL_EXT_pixel_format", testdc)) {
711       ALLEGRO_ERROR("WGL_ARB/EXT_pf not supported.\n");
712       goto bail;
713   }
714 
715    if (!init_pixel_format_extensions())
716       goto bail;
717 
718    maxindex = get_pixel_formats_count_ext(testdc);
719    if (maxindex < 1)
720       goto bail;
721 
722    ALLEGRO_INFO("Got %i visuals.\n", maxindex);
723 
724    eds_list = al_calloc(maxindex, sizeof(*eds_list));
725    if (!eds_list)
726       goto bail;
727 
728    for (j = i = 0; i < maxindex; i++) {
729       ALLEGRO_INFO("-- \n");
730       ALLEGRO_INFO("Decoding visual no. %i...\n", i+1);
731       eds_list[j] = read_pixel_format_ext(_wglGetExtensionsStringARB, i, testdc);
732       if (!eds_list[j])
733          continue;
734       // Fill vsync setting here and enable/disable it after display creation
735       eds_list[j]->settings[ALLEGRO_VSYNC] = ref->settings[ALLEGRO_VSYNC];
736       display_pixel_format(eds_list[j]);
737       eds_list[j]->score = _al_score_display_settings(eds_list[j], ref);
738       if (eds_list[j]->score == -1) {
739          al_free(eds_list[j]);
740          eds_list[j] = NULL;
741          continue;
742       }
743       /* In WinAPI first index is 1 ::) */
744       eds_list[j]->index = i+1;
745       j++;
746    }
747 
748    ALLEGRO_INFO("%i visuals are good enough.\n", j);
749    *count = j;
750 
751 bail:
752    wglMakeCurrent(NULL, NULL);
753    if (testrc) {
754       wglDeleteContext(testrc);
755    }
756 
757    wglMakeCurrent(old_dc, old_rc);
758 
759    _wglGetPixelFormatAttribivARB = NULL;
760    _wglGetPixelFormatAttribivEXT = NULL;
761 
762    if (testwnd) {
763       ReleaseDC(testwnd, testdc);
764       DestroyWindow(testwnd);
765    }
766 
767    return eds_list;
768 }
769 
770 
get_available_pixel_formats_old(int * count,HDC dc)771 static ALLEGRO_EXTRA_DISPLAY_SETTINGS** get_available_pixel_formats_old(int *count, HDC dc)
772 {
773    ALLEGRO_EXTRA_DISPLAY_SETTINGS **eds_list = NULL;
774    ALLEGRO_EXTRA_DISPLAY_SETTINGS *ref;
775    int maxindex;
776    int i, j;
777 
778    *count = 0;
779    ref =  _al_get_new_display_settings();
780 
781    maxindex = get_pixel_formats_count_old(dc);
782    if (maxindex < 1)
783       return NULL;
784 
785    ALLEGRO_INFO("Got %i visuals.\n", maxindex);
786 
787    eds_list = al_calloc(maxindex, sizeof(*eds_list));
788    if (!eds_list)
789       return NULL;
790 
791    for (j = i = 0; i < maxindex; i++) {
792       ALLEGRO_INFO("-- \n");
793       ALLEGRO_INFO("Decoding visual no. %i...\n", i+1);
794       eds_list[j] = read_pixel_format_old(i, dc);
795       if (!eds_list[j])
796          continue;
797 #ifdef DEBUGMODE
798       display_pixel_format(eds_list[j]);
799 #endif
800       eds_list[j]->score = _al_score_display_settings(eds_list[j], ref);
801       if (eds_list[j]->score == -1) {
802          al_free(eds_list[j]);
803          eds_list[j] = NULL;
804          continue;
805       }
806       /* In WinAPI first index is 1 ::) */
807       eds_list[j]->index = i+1;
808       j++;
809    }
810 
811    ALLEGRO_INFO("%i visuals are good enough.\n", j);
812    *count = j;
813 
814    return eds_list;
815 }
816 
817 
select_pixel_format(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,ALLEGRO_DISPLAY_WGL * d,HDC dc)818 static bool select_pixel_format(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, ALLEGRO_DISPLAY_WGL *d, HDC dc)
819 {
820    ALLEGRO_EXTRA_DISPLAY_SETTINGS **eds = NULL;
821    ALLEGRO_CONFIG *sys_cfg = al_get_system_config();
822    int eds_count = 0;
823    int i;
824    bool force_old = false;
825    const char *selection_mode;
826 
827    selection_mode = al_get_config_value(sys_cfg, "graphics",
828                        "config_selection");
829    if (selection_mode && selection_mode[0] != '\0') {
830       if (!_al_stricmp(selection_mode, "old")) {
831          ALLEGRO_INFO("Forcing OLD visual selection method.\n");
832          force_old = true;
833       }
834       else if (!_al_stricmp(selection_mode, "new"))
835          force_old = false;
836    }
837 
838    if (!force_old)
839       eds = get_available_pixel_formats_ext(_wglGetExtensionsStringARB, &eds_count);
840    if (!eds)
841       eds = get_available_pixel_formats_old(&eds_count, dc);
842 
843    if (!eds || !eds_count) {
844       ALLEGRO_ERROR("Didn't find any suitable pixel format!\n");
845       return false;
846    }
847 
848    qsort(eds, eds_count, sizeof(eds[0]), _al_display_settings_sorter);
849 
850    for (i = 0; i < eds_count ; i++) {
851       if (SetPixelFormat(d->dc, eds[i]->index, NULL)) {
852          ALLEGRO_INFO("Chose visual no. %i\n\n", eds[i]->index);
853          display_pixel_format(eds[i]);
854          break;
855       }
856       else {
857          ALLEGRO_WARN("Unable to set pixel format! %s\n", _al_win_last_error());
858          ALLEGRO_WARN("Trying next one.\n");
859       }
860    }
861 
862    if (i == eds_count) {
863       ALLEGRO_ERROR("Unable to set any pixel format! %s\n", _al_win_last_error());
864       for (i = 0; i < eds_count; i++)
865          al_free(eds[i]);
866       al_free(eds);
867       return false;
868    }
869 
870    memcpy(&d->win_display.display.extra_settings, eds[i], sizeof(ALLEGRO_EXTRA_DISPLAY_SETTINGS));
871 
872    for (i = 0; i < eds_count; i++)
873       al_free(eds[i]);
874    if (eds)
875       al_free(eds);
876 
877    return true;
878 }
879 
create_display_internals(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,ALLEGRO_DISPLAY_WGL * wgl_disp)880 static bool create_display_internals(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, ALLEGRO_DISPLAY_WGL *wgl_disp)
881 {
882    ALLEGRO_DISPLAY     *disp     = (void*)wgl_disp;
883    ALLEGRO_DISPLAY_WIN *win_disp = (void*)wgl_disp;
884    WGL_DISPLAY_PARAMETERS ndp;
885    int window_x, window_y;
886    int major, minor;
887 
888    /* The window is created in a separate thread so we need to pass this
889     * TLS on
890     */
891    al_get_new_window_position(&window_x, &window_y);
892    ndp.window_x = window_x;
893    ndp.window_y = window_y;
894    ndp.window_title = al_get_new_window_title();
895 
896    /* _beginthread closes the handle automatically. */
897    ndp.display = wgl_disp;
898    ndp.init_failed = true;
899    ndp.AckEvent = CreateEvent(NULL, false, false, NULL);
900    _beginthread(display_thread_proc, 0, &ndp);
901 
902    /* Wait some _finite_ time (10 secs or so) for display thread to init, and
903     * give up if something horrible happened to it, unless we're in debug mode
904     * and we may have intentionally stopped the execution to analyze the code.
905     */
906 #ifdef DEBUGMODE
907    WaitForSingleObject(ndp.AckEvent, INFINITE);
908 #else
909    WaitForSingleObject(ndp.AckEvent, 10*1000);
910 #endif
911 
912    CloseHandle(ndp.AckEvent);
913 
914    if (ndp.init_failed) {
915       ALLEGRO_ERROR("Failed to create display.\n");
916       return false;
917    }
918 
919    /* WGL display lists cannot be shared with the API currently in use. */
920    disp->ogl_extras->is_shared = false;
921 
922    if (!select_pixel_format(_wglGetExtensionsStringARB, wgl_disp, wgl_disp->dc)) {
923       destroy_display_internals(wgl_disp);
924       return false;
925    }
926 
927    major = al_get_new_display_option(ALLEGRO_OPENGL_MAJOR_VERSION, 0);
928    minor = al_get_new_display_option(ALLEGRO_OPENGL_MINOR_VERSION, 0);
929 
930    // TODO: request GLES context in GLES builds
931    if ((disp->flags & ALLEGRO_OPENGL_3_0) || major != 0) {
932       if (major == 0)
933          major = 3;
934       bool fc = (disp->flags & ALLEGRO_OPENGL_FORWARD_COMPATIBLE) != 0;
935       wgl_disp->glrc = init_ogl_context_ex(_wglGetExtensionsStringARB, wgl_disp->dc, fc, major,
936          minor);
937    }
938    else {
939       wgl_disp->glrc = wglCreateContext(wgl_disp->dc);
940    }
941 
942    if (!wgl_disp->glrc) {
943       ALLEGRO_ERROR("Unable to create a render context! %s\n", _al_win_last_error());
944       destroy_display_internals(wgl_disp);
945       return false;
946    }
947 
948    /* make the context the current one */
949    if (!wglMakeCurrent(wgl_disp->dc, wgl_disp->glrc)) {
950       ALLEGRO_ERROR("Unable to make the context current! %s\n", _al_win_last_error());
951       destroy_display_internals(wgl_disp);
952       return false;
953    }
954 
955    _al_ogl_manage_extensions(disp);
956    _al_ogl_set_extensions(disp->ogl_extras->extension_api);
957 
958    if (disp->ogl_extras->ogl_info.version < _ALLEGRO_OPENGL_VERSION_1_2) {
959       ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds = _al_get_new_display_settings();
960       if (eds->required & (1<<ALLEGRO_COMPATIBLE_DISPLAY)) {
961          ALLEGRO_WARN("Allegro requires at least OpenGL version 1.2 to work.\n");
962          destroy_display_internals(wgl_disp);
963          return false;
964       }
965       disp->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY] = 0;
966    }
967 
968    /* Fill in the display settings for opengl major and minor versions...*/
969    const int v = disp->ogl_extras->ogl_info.version;
970    disp->extra_settings.settings[ALLEGRO_OPENGL_MAJOR_VERSION] = (v >> 24) & 0xFF;
971    disp->extra_settings.settings[ALLEGRO_OPENGL_MINOR_VERSION] = (v >> 16) & 0xFF;
972 
973    /* Try to enable or disable vsync as requested */
974    /* NOTE: my drivers claim I don't have WGL_EXT_swap_control
975     * (according to al_have_opengl_extension), but wglSwapIntervalEXT
976     * does get loaded, so just check for that.
977     */
978    if (wglSwapIntervalEXT) {
979       if (disp->extra_settings.settings[ALLEGRO_VSYNC] == 1) {
980          wglSwapIntervalEXT(1);
981       }
982       else if (disp->extra_settings.settings[ALLEGRO_VSYNC] == 2) {
983          wglSwapIntervalEXT(0);
984       }
985    }
986 
987    win_disp->mouse_selected_hcursor = 0;
988    win_disp->mouse_cursor_shown = false;
989    win_disp->can_acknowledge = false;
990 
991    _al_win_grab_input(win_disp);
992 
993    if (disp->extra_settings.settings[ALLEGRO_COMPATIBLE_DISPLAY])
994       _al_ogl_setup_gl(disp);
995 
996    return true;
997 }
998 
999 
wgl_create_display(int w,int h)1000 static ALLEGRO_DISPLAY* wgl_create_display(int w, int h)
1001 {
1002    ALLEGRO_SYSTEM_WIN *system = (ALLEGRO_SYSTEM_WIN *)al_get_system_driver();
1003    ALLEGRO_DISPLAY_WGL **add;
1004    ALLEGRO_DISPLAY_WGL *wgl_display = al_calloc(1, sizeof *wgl_display);
1005    ALLEGRO_DISPLAY *ogl_display = (void*)wgl_display;
1006    ALLEGRO_DISPLAY     *display     = (void*)ogl_display;
1007    ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)display;
1008 
1009    win_disp->adapter = _al_win_determine_adapter();
1010 
1011    display->w = w;
1012    display->h = h;
1013    display->refresh_rate = al_get_new_display_refresh_rate();
1014    display->flags = al_get_new_display_flags();
1015 #ifdef ALLEGRO_CFG_OPENGLES2
1016    display->flags |= ALLEGRO_PROGRAMMABLE_PIPELINE;
1017 #endif
1018 #ifdef ALLEGRO_CFG_OPENGLES
1019    display->flags |= ALLEGRO_OPENGL_ES_PROFILE;
1020 #endif
1021    display->vt = &vt;
1022 
1023    display->ogl_extras = al_calloc(1, sizeof(ALLEGRO_OGL_EXTRAS));
1024 
1025    _ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB
1026       = (_ALLEGRO_wglGetExtensionsStringARB_t)wglGetProcAddress("wglGetExtensionsStringARB");
1027    if (!create_display_internals(_wglGetExtensionsStringARB, wgl_display)) {
1028       al_free(display->ogl_extras);
1029       al_free(display);
1030       return NULL;
1031    }
1032 
1033    /* Print out OpenGL version info */
1034    ALLEGRO_INFO("OpenGL Version: %s\n", (const char*)glGetString(GL_VERSION));
1035    ALLEGRO_INFO("Vendor: %s\n", (const char*)glGetString(GL_VENDOR));
1036    ALLEGRO_INFO("Renderer: %s\n\n", (const char*)glGetString(GL_RENDERER));
1037 
1038    /* Add ourself to the list of displays. */
1039    add = _al_vector_alloc_back(&system->system.displays);
1040    *add = wgl_display;
1041 
1042    /* Each display is an event source. */
1043    _al_event_source_init(&display->es);
1044 
1045    _al_win_set_system_mouse_cursor(display, ALLEGRO_SYSTEM_MOUSE_CURSOR_ARROW);
1046    _al_win_show_mouse_cursor(display);
1047 
1048    _al_win_post_create_window(display);
1049 
1050    return display;
1051 }
1052 
1053 
destroy_display_internals(ALLEGRO_DISPLAY_WGL * wgl_disp)1054 static void destroy_display_internals(ALLEGRO_DISPLAY_WGL *wgl_disp)
1055 {
1056    ALLEGRO_DISPLAY *disp = (ALLEGRO_DISPLAY *)wgl_disp;
1057    ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)wgl_disp;
1058 
1059    /* We need to convert all our bitmaps to display independent (memory)
1060     * bitmaps because WGL driver doesn't support sharing of resources. */
1061    while (disp->bitmaps._size > 0) {
1062       ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&disp->bitmaps);
1063       ALLEGRO_BITMAP *bmp = *bptr;
1064       _al_convert_to_memory_bitmap(bmp);
1065    }
1066 
1067    if (disp->ogl_extras->backbuffer)
1068       _al_ogl_destroy_backbuffer(disp->ogl_extras->backbuffer);
1069    disp->ogl_extras->backbuffer = NULL;
1070 
1071    _al_ogl_unmanage_extensions(disp);
1072 
1073    PostMessage(win_disp->window, _al_win_msg_suicide, (WPARAM)win_disp, 0);
1074 
1075    while (!win_disp->thread_ended)
1076       al_rest(0.001);
1077 
1078    if (wgl_disp->glrc) {
1079       wglDeleteContext(wgl_disp->glrc);
1080       wgl_disp->glrc = NULL;
1081    }
1082    if (wgl_disp->dc) {
1083       ReleaseDC(win_disp->window, wgl_disp->dc);
1084       wgl_disp->dc = NULL;
1085    }
1086 
1087    if (disp->flags & ALLEGRO_FULLSCREEN && !_wgl_do_not_change_display_mode) {
1088       ChangeDisplaySettings(NULL, 0);
1089    }
1090 
1091    if (win_disp->window) {
1092       DestroyWindow(win_disp->window);
1093       win_disp->window = NULL;
1094    }
1095 }
1096 
1097 
wgl_destroy_display(ALLEGRO_DISPLAY * disp)1098 static void wgl_destroy_display(ALLEGRO_DISPLAY *disp)
1099 {
1100    ALLEGRO_SYSTEM_WIN *system = (ALLEGRO_SYSTEM_WIN *)al_get_system_driver();
1101    ALLEGRO_DISPLAY_WGL *wgl_disp = (ALLEGRO_DISPLAY_WGL *)disp;
1102    ALLEGRO_DISPLAY *old_disp = al_get_current_display();
1103 
1104    if (old_disp != disp)
1105       _al_set_current_display_only(disp);
1106 
1107    if (system->mouse_grab_display == disp)
1108       system->mouse_grab_display = NULL;
1109 
1110    _al_win_destroy_display_icons(disp);
1111 
1112    destroy_display_internals(wgl_disp);
1113    _al_event_source_free(&disp->es);
1114    _al_vector_find_and_delete(&system->system.displays, &disp);
1115 
1116    _al_vector_free(&disp->bitmaps);
1117    _al_vector_free(&((ALLEGRO_DISPLAY_WIN*) disp)->msg_callbacks);
1118    al_free(disp->ogl_extras);
1119 
1120    if (old_disp != disp)
1121       _al_set_current_display_only(old_disp);
1122 
1123    al_free(disp->vertex_cache);
1124    al_free(wgl_disp);
1125 }
1126 
1127 
wgl_set_current_display(ALLEGRO_DISPLAY * d)1128 static bool wgl_set_current_display(ALLEGRO_DISPLAY *d)
1129 {
1130    ALLEGRO_DISPLAY_WGL *wgl_disp = (ALLEGRO_DISPLAY_WGL *)d;
1131    HGLRC current_glrc;
1132 
1133    current_glrc = wglGetCurrentContext();
1134 
1135    if (!current_glrc || (current_glrc && current_glrc != wgl_disp->glrc)) {
1136       /* make the context the current one */
1137       if (!wglMakeCurrent(wgl_disp->dc, wgl_disp->glrc)) {
1138          ALLEGRO_ERROR("Unable to make the context current! %s\n",
1139                         _al_win_last_error());
1140          return false;
1141       }
1142 
1143       _al_ogl_set_extensions(d->ogl_extras->extension_api);
1144    }
1145 
1146    _al_ogl_update_render_state(d);
1147 
1148    return true;
1149 }
1150 
1151 
wgl_unset_current_display(ALLEGRO_DISPLAY * d)1152 static void wgl_unset_current_display(ALLEGRO_DISPLAY *d)
1153 {
1154    (void)d;
1155 
1156    if (!wglMakeCurrent(NULL, NULL)) {
1157       ALLEGRO_ERROR("Unable unset the current context! %s\n", _al_win_last_error());
1158    }
1159 }
1160 
1161 
1162 /*
1163  * The window must be created in the same thread that
1164  * runs the message loop.
1165  */
display_thread_proc(void * arg)1166 static void display_thread_proc(void *arg)
1167 {
1168    WGL_DISPLAY_PARAMETERS *ndp = arg;
1169    ALLEGRO_DISPLAY *disp = (ALLEGRO_DISPLAY*)ndp->display;
1170    ALLEGRO_DISPLAY_WGL *wgl_disp = (void*)disp;
1171    ALLEGRO_DISPLAY_WIN *win_disp = (void*)disp;
1172    MSG msg;
1173 
1174    /* So that we can call the functions using TLS from this thread. */
1175    al_set_new_display_flags(disp->flags);
1176    al_set_new_window_position(ndp->window_x, ndp->window_y);
1177    al_set_new_window_title(ndp->window_title);
1178 
1179    if (disp->flags & ALLEGRO_FULLSCREEN) {
1180       if (!change_display_mode(disp)) {
1181          win_disp->thread_ended = true;
1182          destroy_display_internals(wgl_disp);
1183          SetEvent(ndp->AckEvent);
1184          return;
1185       }
1186    }
1187    else if (disp->flags & ALLEGRO_FULLSCREEN_WINDOW) {
1188       ALLEGRO_MONITOR_INFO mi;
1189       int adapter = win_disp->adapter;
1190       al_get_monitor_info(adapter, &mi);
1191 
1192       win_disp->toggle_w = disp->w;
1193       win_disp->toggle_h = disp->h;
1194 
1195       disp->w = mi.x2 - mi.x1;
1196       disp->h = mi.y2 - mi.y1;
1197 
1198       disp->refresh_rate = al_get_monitor_refresh_rate(adapter);
1199    }
1200    else {
1201       int adapter = win_disp->adapter;
1202       win_disp->toggle_w = disp->w;
1203       win_disp->toggle_h = disp->h;
1204 
1205       disp->refresh_rate = al_get_monitor_refresh_rate(adapter);
1206    }
1207 
1208    win_disp->window = _al_win_create_window(disp, disp->w, disp->h, disp->flags);
1209 
1210    if (!win_disp->window) {
1211       win_disp->thread_ended = true;
1212       destroy_display_internals(wgl_disp);
1213       SetEvent(ndp->AckEvent);
1214       return;
1215    }
1216 
1217    /* FIXME: can't _al_win_create_window() do this? */
1218    if ((disp->flags & ALLEGRO_FULLSCREEN) ||
1219          (disp->flags & ALLEGRO_FULLSCREEN_WINDOW)) {
1220       RECT rect;
1221       rect.left = 0;
1222       rect.right = disp->w;
1223       rect.top  = 0;
1224       rect.bottom = disp->h;
1225       SetWindowPos(win_disp->window, 0, rect.left, rect.top,
1226              rect.right - rect.left, rect.bottom - rect.top,
1227              SWP_NOZORDER | SWP_FRAMECHANGED);
1228    }
1229 
1230    if (disp->flags & ALLEGRO_FULLSCREEN_WINDOW) {
1231       bool frameless = true;
1232       _al_win_set_window_frameless(disp, win_disp->window, frameless);
1233    }
1234 
1235    /* Yep, the following is really needed sometimes. */
1236    /* ... Or is it now that we have dumped DInput? */
1237    /* <rohannessian> Win98/2k/XP's window forground rules don't let us
1238     * make our window the topmost window on launch. This causes issues on
1239     * full-screen apps, as DInput loses input focus on them.
1240     * We use this trick to force the window to be topmost, when switching
1241     * to full-screen only. Note that this only works for Win98 and greater.
1242     * Win95 will ignore our SystemParametersInfo() calls.
1243     *
1244     * See http://support.microsoft.com:80/support/kb/articles/Q97/9/25.asp
1245     * for details.
1246     */
1247    {
1248       DWORD lock_time;
1249       HWND wnd = win_disp->window;
1250 
1251 #define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000
1252 #define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001
1253       if (disp->flags & ALLEGRO_FULLSCREEN) {
1254          SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT,
1255                0, (LPVOID)&lock_time, 0);
1256          SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,
1257                0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
1258       }
1259 
1260       ShowWindow(wnd, SW_SHOWNORMAL);
1261       SetForegroundWindow(wnd);
1262       /* In some rare cases, it doesn't seem to work without the loop. And we
1263        * absolutely need this to succeed, else we trap the user in a
1264        * fullscreen window without input.
1265        */
1266       while (GetForegroundWindow() != wnd) {
1267          al_rest(0.01);
1268          SetForegroundWindow(wnd);
1269       }
1270       UpdateWindow(wnd);
1271 
1272       if (disp->flags & ALLEGRO_FULLSCREEN) {
1273          SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT,
1274               0, (LPVOID)&lock_time, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
1275       }
1276 #undef SPI_GETFOREGROUNDLOCKTIMEOUT
1277 #undef SPI_SETFOREGROUNDLOCKTIMEOUT
1278    }
1279 
1280 #if 0
1281    if (disp->flags & ALLEGRO_FULLSCREEN && al_is_mouse_installed()) {
1282       RAWINPUTDEVICE rid[1];
1283       rid[0].usUsagePage = 0x01;
1284       rid[0].usUsage = 0x02;
1285       rid[0].dwFlags = RIDEV_NOLEGACY;
1286       rid[0].hwndTarget = 0;
1287       if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == FALSE) {
1288           ALLEGRO_ERROR(
1289              "Failed to init mouse. %s\n", get_error_desc(GetLastError()));
1290       }
1291    }
1292 #endif
1293 
1294    /* get the device context of our window */
1295    wgl_disp->dc = GetDC(win_disp->window);
1296 
1297    win_disp->thread_ended = false;
1298    win_disp->end_thread = false;
1299    ndp->init_failed = false;
1300    SetEvent(ndp->AckEvent);
1301 
1302    while (!win_disp->end_thread) {
1303       /* get a message from the queue */
1304       if (GetMessage(&msg, NULL, 0, 0) != 0)
1305          DispatchMessage(&msg);
1306       else
1307          break;                 /* WM_QUIT received or error (GetMessage returned -1)  */
1308    }
1309 
1310    ALLEGRO_INFO("wgl display thread exits\n");
1311    win_disp->thread_ended = true;
1312 }
1313 
1314 
wgl_flip_display(ALLEGRO_DISPLAY * d)1315 static void wgl_flip_display(ALLEGRO_DISPLAY *d)
1316 {
1317    ALLEGRO_DISPLAY_WGL* disp = (ALLEGRO_DISPLAY_WGL*)d;
1318    glFlush();
1319    if (!d->extra_settings.settings[ALLEGRO_SINGLE_BUFFER])
1320       SwapBuffers(disp->dc);
1321 }
1322 
1323 
wgl_update_display_region(ALLEGRO_DISPLAY * d,int x,int y,int width,int height)1324 static void wgl_update_display_region(ALLEGRO_DISPLAY *d,
1325                                       int x, int y, int width, int height)
1326 {
1327    if (al_get_opengl_extension_list()->ALLEGRO_WGL_WIN_swap_hint) {
1328       /* FIXME: This is just a driver hint and there is no guarantee that the
1329        * contens of the front buffer outside the given rectangle will be preserved,
1330        * thus we should really return false here and do nothing. */
1331       ALLEGRO_DISPLAY_WGL* disp = (ALLEGRO_DISPLAY_WGL*)d;
1332       wglAddSwapHintRectWIN(x, y, width, height);
1333       glFlush();
1334       SwapBuffers(disp->dc);
1335       return;
1336    }
1337    wgl_flip_display(d);
1338 }
1339 
1340 
wgl_resize_helper(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB,ALLEGRO_DISPLAY * d,int width,int height)1341 static bool wgl_resize_helper(_ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB, ALLEGRO_DISPLAY *d, int width, int height)
1342 {
1343    ALLEGRO_DISPLAY_WGL *wgl_disp = (ALLEGRO_DISPLAY_WGL *)d;
1344    ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)d;
1345    int full_w, full_h;
1346    ALLEGRO_MONITOR_INFO mi;
1347    int adapter = al_get_new_display_adapter();
1348    if (adapter < 0)
1349       adapter = 0;
1350    al_get_monitor_info(adapter, &mi);
1351    full_w = mi.x2 - mi.x1;
1352    full_h = mi.y2 - mi.y1;
1353 
1354    if ((d->flags & ALLEGRO_FULLSCREEN_WINDOW) && (full_w != width || full_h != height)) {
1355       win_disp->toggle_w = width;
1356       win_disp->toggle_h = height;
1357       return true;
1358    }
1359 
1360    win_disp->can_acknowledge = false;
1361 
1362    if (d->flags & ALLEGRO_FULLSCREEN) {
1363       ALLEGRO_BITMAP *target_bmp;
1364       _AL_VECTOR disp_bmps;
1365       bool was_backbuffer = false;
1366       size_t i;
1367 
1368       target_bmp = al_get_target_bitmap();
1369       if (target_bmp && target_bmp->vt) {
1370          ALLEGRO_BITMAP_EXTRA_OPENGL *extra = target_bmp->parent ?
1371             target_bmp->parent->extra : target_bmp->extra;
1372          was_backbuffer = extra->is_backbuffer;
1373       }
1374 
1375       /* Remember display bitmaps. */
1376       _al_vector_init(&disp_bmps, sizeof(ALLEGRO_BITMAP*));
1377       for (i = 0; i < _al_vector_size(&d->bitmaps); i++) {
1378          ALLEGRO_BITMAP **dis = _al_vector_ref(&d->bitmaps, i);
1379          ALLEGRO_BITMAP **mem = _al_vector_alloc_back(&disp_bmps);
1380          *mem = *dis;
1381       }
1382 
1383       /* This flag prevents from switching to desktop resolution in between. */
1384       _wgl_do_not_change_display_mode = true;
1385       destroy_display_internals(wgl_disp);
1386       _wgl_do_not_change_display_mode = false;
1387 
1388       d->w = width;
1389       d->h = height;
1390       if(!create_display_internals(_wglGetExtensionsStringARB, wgl_disp))
1391          return false;
1392 
1393       /* We have a new backbuffer now. */
1394       if (was_backbuffer)
1395          al_set_target_bitmap(al_get_backbuffer(d));
1396 
1397       /* Reupload bitmaps. */
1398       while (_al_vector_is_nonempty(&disp_bmps)) {
1399          ALLEGRO_BITMAP **back = _al_vector_ref_back(&disp_bmps);
1400          _al_convert_to_display_bitmap(*back);
1401          _al_vector_delete_at(&disp_bmps, _al_vector_size(&disp_bmps) - 1);
1402       }
1403    }
1404    else {
1405       RECT win_size;
1406       WINDOWINFO wi;
1407 
1408       win_size.left = 0;
1409       win_size.top = 0;
1410       win_size.right = width;
1411       win_size.bottom = height;
1412 
1413       wi.cbSize = sizeof(WINDOWINFO);
1414       GetWindowInfo(win_disp->window, &wi);
1415 
1416       AdjustWindowRectEx(&win_size, wi.dwStyle, GetMenu(win_disp->window) ? TRUE : FALSE, wi.dwExStyle);
1417 
1418       if (!SetWindowPos(win_disp->window, HWND_TOP,
1419          0, 0,
1420          win_size.right - win_size.left,
1421          win_size.bottom - win_size.top,
1422          SWP_NOMOVE|SWP_NOZORDER))
1423             return false;
1424 
1425       d->w = width;
1426       d->h = height;
1427       if (!(d->flags & ALLEGRO_FULLSCREEN_WINDOW)) {
1428          win_disp->toggle_w = width;
1429          win_disp->toggle_h = height;
1430       }
1431    }
1432 
1433    return true;
1434 }
1435 
wgl_resize_display(ALLEGRO_DISPLAY * d,int width,int height)1436 static bool wgl_resize_display(ALLEGRO_DISPLAY *d, int width, int height)
1437 {
1438    ALLEGRO_DISPLAY_WIN *win_display = (ALLEGRO_DISPLAY_WIN *)d;
1439    int orig_w = d->w;
1440    int orig_h = d->h;
1441    bool ret;
1442 
1443    win_display->ignore_resize = true;
1444 
1445    _ALLEGRO_wglGetExtensionsStringARB_t _wglGetExtensionsStringARB
1446       = (_ALLEGRO_wglGetExtensionsStringARB_t)wglGetProcAddress("wglGetExtensionsStringARB");
1447    if (!wgl_resize_helper(_wglGetExtensionsStringARB, d, width, height)) {
1448       wgl_resize_helper(_wglGetExtensionsStringARB, d, orig_w, orig_h);
1449       ret = false;
1450    } else {
1451       ret = true;
1452       wgl_acknowledge_resize(d);
1453    }
1454 
1455    win_display->ignore_resize = false;
1456 
1457    return ret;
1458 }
1459 
wgl_acknowledge_resize(ALLEGRO_DISPLAY * d)1460 static bool wgl_acknowledge_resize(ALLEGRO_DISPLAY *d)
1461 {
1462    WINDOWINFO wi;
1463    ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)d;
1464    int w, h;
1465    ALLEGRO_STATE state;
1466 
1467    wi.cbSize = sizeof(WINDOWINFO);
1468    GetWindowInfo(win_disp->window, &wi);
1469    w = wi.rcClient.right - wi.rcClient.left;
1470    h = wi.rcClient.bottom - wi.rcClient.top;
1471 
1472    d->w = w;
1473    d->h = h;
1474 
1475    _al_ogl_setup_gl(d);
1476    _al_ogl_update_render_state(d);
1477 
1478    al_store_state(&state, ALLEGRO_STATE_DISPLAY | ALLEGRO_STATE_TARGET_BITMAP);
1479    al_set_target_backbuffer(d);
1480    al_set_clipping_rectangle(0, 0, w, h);
1481    al_restore_state(&state);
1482 
1483    return true;
1484 }
1485 
1486 
wgl_is_compatible_bitmap(ALLEGRO_DISPLAY * display,ALLEGRO_BITMAP * bitmap)1487 static bool wgl_is_compatible_bitmap(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *bitmap)
1488 {
1489    /* Note: WGL driver doesn't support sharing of resources between contexts,
1490     * thus all bitmaps are tied to the display which was current at the time
1491     * al_create_bitmap was called.
1492     */
1493    return display == _al_get_bitmap_display(bitmap);
1494 }
1495 
1496 
wgl_switch_in(ALLEGRO_DISPLAY * display)1497 static void wgl_switch_in(ALLEGRO_DISPLAY *display)
1498 {
1499    (void)display;
1500    /*
1501    ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)display;
1502 
1503    if (al_is_mouse_installed())
1504       al_set_mouse_range(win_disp->mouse_range_x1, win_disp->mouse_range_y1,
1505          win_disp->mouse_range_x2, win_disp->mouse_range_y2);
1506    */
1507 }
1508 
1509 
wgl_switch_out(ALLEGRO_DISPLAY * display)1510 static void wgl_switch_out(ALLEGRO_DISPLAY *display)
1511 {
1512    (void)display;
1513 }
1514 
1515 
wgl_set_window_position(ALLEGRO_DISPLAY * display,int x,int y)1516 static void wgl_set_window_position(ALLEGRO_DISPLAY *display, int x, int y)
1517 {
1518    _al_win_set_window_position(((ALLEGRO_DISPLAY_WIN *)display)->window, x, y);
1519 }
1520 
1521 
wgl_get_window_position(ALLEGRO_DISPLAY * display,int * x,int * y)1522 static void wgl_get_window_position(ALLEGRO_DISPLAY *display, int *x, int *y)
1523 {
1524    _al_win_get_window_position(((ALLEGRO_DISPLAY_WIN *)display)->window, x, y);
1525 }
1526 
1527 
1528 /* Obtain a reference to this driver. */
_al_display_wgl_driver(void)1529 ALLEGRO_DISPLAY_INTERFACE *_al_display_wgl_driver(void)
1530 {
1531    if (vt.create_display)
1532       return &vt;
1533 
1534    vt.create_display = wgl_create_display;
1535    vt.destroy_display = wgl_destroy_display;
1536    vt.resize_display = wgl_resize_display;
1537    vt.set_current_display = wgl_set_current_display;
1538    vt.unset_current_display = wgl_unset_current_display;
1539    vt.flip_display = wgl_flip_display;
1540    vt.update_display_region = wgl_update_display_region;
1541    vt.acknowledge_resize = wgl_acknowledge_resize;
1542    vt.create_bitmap = _al_ogl_create_bitmap;
1543    vt.get_backbuffer = _al_ogl_get_backbuffer;
1544    vt.set_target_bitmap = _al_ogl_set_target_bitmap;
1545    vt.is_compatible_bitmap = wgl_is_compatible_bitmap;
1546    vt.switch_in = wgl_switch_in;
1547    vt.switch_out = wgl_switch_out;
1548 
1549    vt.set_mouse_cursor = _al_win_set_mouse_cursor;
1550    vt.set_system_mouse_cursor = _al_win_set_system_mouse_cursor;
1551    vt.show_mouse_cursor = _al_win_show_mouse_cursor;
1552    vt.hide_mouse_cursor = _al_win_hide_mouse_cursor;
1553 
1554    vt.set_icons = _al_win_set_display_icons;
1555    vt.set_window_position = wgl_set_window_position;
1556    vt.get_window_position = wgl_get_window_position;
1557    vt.set_window_constraints = _al_win_set_window_constraints;
1558    vt.get_window_constraints = _al_win_get_window_constraints;
1559    vt.apply_window_constraints = _al_win_apply_window_constraints;
1560    vt.set_display_flag = _al_win_set_display_flag;
1561    vt.set_window_title = _al_win_set_window_title;
1562 
1563    vt.update_render_state = _al_ogl_update_render_state;
1564    _al_ogl_add_drawing_functions(&vt);
1565    _al_win_add_clipboard_functions(&vt);
1566 
1567    return &vt;
1568 }
1569 
_al_wgl_get_num_display_modes(int format,int refresh_rate,int flags)1570 int _al_wgl_get_num_display_modes(int format, int refresh_rate, int flags)
1571 {
1572    DEVMODE dm;
1573    int count = 0;
1574 
1575    /* FIXME: Ignoring format.
1576     * To get a list of pixel formats we have to create a window with a valid DC, which
1577     * would even require to change the video mode in fullscreen cases and we really
1578     * don't want to do that.
1579     */
1580    (void)format;
1581    (void)refresh_rate;
1582    (void)flags;
1583 
1584    memset(&dm, 0, sizeof(dm));
1585    dm.dmSize = sizeof(dm);
1586 
1587    while (EnumDisplaySettings(NULL, count, &dm) != false) {
1588       count++;
1589    }
1590 
1591    return count;
1592 }
1593 
1594 
_al_wgl_get_display_mode(int index,int format,int refresh_rate,int flags,ALLEGRO_DISPLAY_MODE * mode)1595 ALLEGRO_DISPLAY_MODE *_al_wgl_get_display_mode(int index, int format,
1596                                                int refresh_rate, int flags,
1597                                                ALLEGRO_DISPLAY_MODE *mode)
1598 {
1599    DEVMODE dm;
1600 
1601    /*
1602     * FIXME: see the comment in _al_wgl_get_num_display_modes
1603     */
1604    (void)format;
1605    (void)refresh_rate;
1606    (void)flags;
1607 
1608    memset(&dm, 0, sizeof(dm));
1609    dm.dmSize = sizeof(dm);
1610 
1611    if (!EnumDisplaySettings(NULL, index, &dm))
1612       return NULL;
1613 
1614    mode->width = dm.dmPelsWidth;
1615    mode->height = dm.dmPelsHeight;
1616    mode->refresh_rate = dm.dmDisplayFrequency;
1617    mode->format = format;
1618    switch (dm.dmBitsPerPel) {
1619       case 32:
1620          if (format == ALLEGRO_PIXEL_FORMAT_ANY)
1621             mode->format = ALLEGRO_PIXEL_FORMAT_ANY_32_WITH_ALPHA;
1622          else if (format == ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA)
1623             mode->format = ALLEGRO_PIXEL_FORMAT_ANY_32_NO_ALPHA;
1624          break;
1625       case 24:
1626          mode->format = ALLEGRO_PIXEL_FORMAT_ANY_24_NO_ALPHA;
1627          break;
1628       case 16:
1629          if (format == ALLEGRO_PIXEL_FORMAT_ANY)
1630             mode->format = ALLEGRO_PIXEL_FORMAT_ANY_16_WITH_ALPHA;
1631          else if(format == ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA)
1632             mode->format = ALLEGRO_PIXEL_FORMAT_ANY_16_NO_ALPHA;
1633          break;
1634       default:
1635          break;
1636    }
1637 
1638    return mode;
1639 }
1640 
1641 /* vi: set sts=3 sw=3 et: */
1642 
1643