src/video/windows/SDL_windowsmodes.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 30 Oct 2012 18:59:56 -0700
changeset 6620 62fe18dc6841
parent 6430 48d519500f7e
child 6793 c8d1036975b7
permissions -rw-r--r--
Added Windows message box implementation, but it needs a little work on layout.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINDOWS
    24 
    25 #include "SDL_windowsvideo.h"
    26 
    27 /* Windows CE compatibility */
    28 #ifndef CDS_FULLSCREEN
    29 #define CDS_FULLSCREEN 0
    30 #endif
    31 
    32 static SDL_bool
    33 WIN_GetDisplayMode(LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
    34 {
    35     SDL_DisplayModeData *data;
    36     DEVMODE devmode;
    37     HDC hdc;
    38 
    39     devmode.dmSize = sizeof(devmode);
    40     devmode.dmDriverExtra = 0;
    41     if (!EnumDisplaySettings(deviceName, index, &devmode)) {
    42         return SDL_FALSE;
    43     }
    44 
    45     data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
    46     if (!data) {
    47         return SDL_FALSE;
    48     }
    49     data->DeviceMode = devmode;
    50     data->DeviceMode.dmFields =
    51         (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
    52          DM_DISPLAYFLAGS);
    53 
    54     /* Fill in the mode information */
    55     mode->format = SDL_PIXELFORMAT_UNKNOWN;
    56     mode->w = devmode.dmPelsWidth;
    57     mode->h = devmode.dmPelsHeight;
    58     mode->refresh_rate = devmode.dmDisplayFrequency;
    59     mode->driverdata = data;
    60 
    61     if (index == ENUM_CURRENT_SETTINGS
    62         && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
    63         char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
    64         LPBITMAPINFO bmi;
    65         HBITMAP hbm;
    66 
    67         SDL_zero(bmi_data);
    68         bmi = (LPBITMAPINFO) bmi_data;
    69         bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    70 
    71         hbm = CreateCompatibleBitmap(hdc, 1, 1);
    72         GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
    73         GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
    74         DeleteObject(hbm);
    75         DeleteDC(hdc);
    76         if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
    77             switch (*(Uint32 *) bmi->bmiColors) {
    78             case 0x00FF0000:
    79                 mode->format = SDL_PIXELFORMAT_RGB888;
    80                 break;
    81             case 0x000000FF:
    82                 mode->format = SDL_PIXELFORMAT_BGR888;
    83                 break;
    84             case 0xF800:
    85                 mode->format = SDL_PIXELFORMAT_RGB565;
    86                 break;
    87             case 0x7C00:
    88                 mode->format = SDL_PIXELFORMAT_RGB555;
    89                 break;
    90             }
    91         } else if (bmi->bmiHeader.biBitCount == 8) {
    92             mode->format = SDL_PIXELFORMAT_INDEX8;
    93         } else if (bmi->bmiHeader.biBitCount == 4) {
    94             mode->format = SDL_PIXELFORMAT_INDEX4LSB;
    95         }
    96     } else {
    97         /* FIXME: Can we tell what this will be? */
    98         if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
    99             switch (devmode.dmBitsPerPel) {
   100             case 32:
   101                 mode->format = SDL_PIXELFORMAT_RGB888;
   102                 break;
   103             case 24:
   104                 mode->format = SDL_PIXELFORMAT_RGB24;
   105                 break;
   106             case 16:
   107                 mode->format = SDL_PIXELFORMAT_RGB565;
   108                 break;
   109             case 15:
   110                 mode->format = SDL_PIXELFORMAT_RGB555;
   111                 break;
   112             case 8:
   113                 mode->format = SDL_PIXELFORMAT_INDEX8;
   114                 break;
   115             case 4:
   116                 mode->format = SDL_PIXELFORMAT_INDEX4LSB;
   117                 break;
   118             }
   119         }
   120     }
   121     return SDL_TRUE;
   122 }
   123 
   124 static SDL_bool
   125 WIN_AddDisplay(LPTSTR DeviceName)
   126 {
   127     SDL_VideoDisplay display;
   128     SDL_DisplayData *displaydata;
   129     SDL_DisplayMode mode;
   130 
   131 #ifdef DEBUG_MODES
   132     printf("Display: %s\n", WIN_StringToUTF8(DeviceName));
   133 #endif
   134     if (!WIN_GetDisplayMode(DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
   135         return SDL_FALSE;
   136     }
   137 
   138     displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
   139     if (!displaydata) {
   140         return SDL_FALSE;
   141     }
   142     SDL_memcpy(displaydata->DeviceName, DeviceName,
   143                sizeof(displaydata->DeviceName));
   144 
   145     SDL_zero(display);
   146     display.desktop_mode = mode;
   147     display.current_mode = mode;
   148     display.driverdata = displaydata;
   149     SDL_AddVideoDisplay(&display);
   150     return SDL_TRUE;
   151 }
   152 
   153 int
   154 WIN_InitModes(_THIS)
   155 {
   156     int pass;
   157     DWORD i, j, count;
   158     DISPLAY_DEVICE device;
   159 
   160     device.cb = sizeof(device);
   161 
   162     /* Get the primary display in the first pass */
   163     for (pass = 0; pass < 2; ++pass) {
   164         for (i = 0; ; ++i) {
   165             TCHAR DeviceName[32];
   166 
   167             if (!EnumDisplayDevices(NULL, i, &device, 0)) {
   168                 break;
   169             }
   170             if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
   171                 continue;
   172             }
   173             if (pass == 0) {
   174                 if (!(device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
   175                     continue;
   176                 }
   177             } else {
   178                 if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
   179                     continue;
   180                 }
   181             }
   182             SDL_memcpy(DeviceName, device.DeviceName, sizeof(DeviceName));
   183 #ifdef DEBUG_MODES
   184             printf("Device: %s\n", WIN_StringToUTF8(DeviceName));
   185 #endif
   186             count = 0;
   187             for (j = 0; ; ++j) {
   188                 if (!EnumDisplayDevices(DeviceName, j, &device, 0)) {
   189                     break;
   190                 }
   191                 if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
   192                     continue;
   193                 }
   194                 if (pass == 0) {
   195                     if (!(device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
   196                         continue;
   197                     }
   198                 } else {
   199                     if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
   200                         continue;
   201                     }
   202                 }
   203                 count += WIN_AddDisplay(device.DeviceName);
   204             }
   205             if (count == 0) {
   206                 WIN_AddDisplay(DeviceName);
   207             }
   208         }
   209     }
   210     if (_this->num_displays == 0) {
   211         SDL_SetError("No displays available");
   212         return -1;
   213     }
   214     return 0;
   215 }
   216 
   217 int
   218 WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
   219 {
   220     SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata;
   221 
   222     rect->x = (int)data->DeviceMode.dmPosition.x;
   223     rect->y = (int)data->DeviceMode.dmPosition.y;
   224     rect->w = data->DeviceMode.dmPelsWidth;
   225     rect->h = data->DeviceMode.dmPelsHeight;
   226 
   227     return 0;
   228 }
   229 
   230 void
   231 WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
   232 {
   233     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   234     DWORD i;
   235     SDL_DisplayMode mode;
   236 
   237     for (i = 0;; ++i) {
   238         if (!WIN_GetDisplayMode(data->DeviceName, i, &mode)) {
   239             break;
   240         }
   241         if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
   242             /* We don't support palettized modes now */
   243             continue;
   244         }
   245         if (mode.format != SDL_PIXELFORMAT_UNKNOWN) {
   246             if (!SDL_AddDisplayMode(display, &mode)) {
   247                 SDL_free(mode.driverdata);
   248             }
   249         }
   250     }
   251 }
   252 
   253 int
   254 WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   255 {
   256     SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
   257     SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
   258     LONG status;
   259 
   260     status =
   261         ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode,
   262                                 NULL, CDS_FULLSCREEN, NULL);
   263     if (status != DISP_CHANGE_SUCCESSFUL) {
   264         const char *reason = "Unknown reason";
   265         switch (status) {
   266         case DISP_CHANGE_BADFLAGS:
   267             reason = "DISP_CHANGE_BADFLAGS";
   268             break;
   269         case DISP_CHANGE_BADMODE:
   270             reason = "DISP_CHANGE_BADMODE";
   271             break;
   272         case DISP_CHANGE_BADPARAM:
   273             reason = "DISP_CHANGE_BADPARAM";
   274             break;
   275         case DISP_CHANGE_FAILED:
   276             reason = "DISP_CHANGE_FAILED";
   277             break;
   278         }
   279         SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
   280         return -1;
   281     }
   282     EnumDisplaySettings(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode);
   283     return 0;
   284 }
   285 
   286 void
   287 WIN_QuitModes(_THIS)
   288 {
   289     /* All fullscreen windows should have restored modes by now */
   290 }
   291 
   292 #endif /* SDL_VIDEO_DRIVER_WINDOWS */
   293 
   294 /* vi: set ts=4 sw=4 expandtab: */