src/video/windows/SDL_windowsmodes.c
author Sam Lantinga
Tue, 08 Feb 2011 16:50:51 -0800
changeset 5229 c015d3e63631
parent 5149 be02be2ea897
child 5250 f908e06b3c96
permissions -rw-r--r--
Fixed setting the texture unit, still doesn't work.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_windowsvideo.h"
    25 
    26 /* Windows CE compatibility */
    27 #ifndef CDS_FULLSCREEN
    28 #define CDS_FULLSCREEN 0
    29 #endif
    30 
    31 static SDL_bool
    32 WIN_GetDisplayMode(LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
    33 {
    34     SDL_DisplayModeData *data;
    35     DEVMODE devmode;
    36 #ifndef _WIN32_WCE
    37     HDC hdc;
    38 #endif
    39 
    40     devmode.dmSize = sizeof(devmode);
    41     devmode.dmDriverExtra = 0;
    42     if (!EnumDisplaySettings(deviceName, index, &devmode)) {
    43         return SDL_FALSE;
    44     }
    45 
    46     data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
    47     if (!data) {
    48         return SDL_FALSE;
    49     }
    50     data->DeviceMode = devmode;
    51     data->DeviceMode.dmFields =
    52         (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
    53          DM_DISPLAYFLAGS);
    54 
    55     /* Fill in the mode information */
    56     mode->format = SDL_PIXELFORMAT_UNKNOWN;
    57     mode->w = devmode.dmPelsWidth;
    58     mode->h = devmode.dmPelsHeight;
    59     mode->refresh_rate = devmode.dmDisplayFrequency;
    60     mode->driverdata = data;
    61 #ifdef _WIN32_WCE
    62     /* In WinCE EnumDisplaySettings(ENUM_CURRENT_SETTINGS) doesn't take the user defined orientation
    63        into account but GetSystemMetrics does. */
    64     if (index == ENUM_CURRENT_SETTINGS) {
    65         mode->w = GetSystemMetrics(SM_CXSCREEN);
    66         mode->h = GetSystemMetrics(SM_CYSCREEN);
    67     }
    68 #endif
    69 
    70 /* WinCE has no GetDIBits, therefore we can't use it to get the display format */
    71 #ifndef _WIN32_WCE
    72     if (index == ENUM_CURRENT_SETTINGS
    73         && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
    74         char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
    75         LPBITMAPINFO bmi;
    76         HBITMAP hbm;
    77 
    78         SDL_zero(bmi_data);
    79         bmi = (LPBITMAPINFO) bmi_data;
    80         bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    81 
    82         hbm = CreateCompatibleBitmap(hdc, 1, 1);
    83         GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
    84         GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
    85         DeleteObject(hbm);
    86         DeleteDC(hdc);
    87         if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
    88             switch (*(Uint32 *) bmi->bmiColors) {
    89             case 0x00FF0000:
    90                 mode->format = SDL_PIXELFORMAT_RGB888;
    91                 break;
    92             case 0x000000FF:
    93                 mode->format = SDL_PIXELFORMAT_BGR888;
    94                 break;
    95             case 0xF800:
    96                 mode->format = SDL_PIXELFORMAT_RGB565;
    97                 break;
    98             case 0x7C00:
    99                 mode->format = SDL_PIXELFORMAT_RGB555;
   100                 break;
   101             }
   102         } else if (bmi->bmiHeader.biBitCount == 8) {
   103             mode->format = SDL_PIXELFORMAT_INDEX8;
   104         } else if (bmi->bmiHeader.biBitCount == 4) {
   105             mode->format = SDL_PIXELFORMAT_INDEX4LSB;
   106         }
   107     } else
   108 #endif /* _WIN32_WCE */
   109     {
   110         /* FIXME: Can we tell what this will be? */
   111         if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
   112             switch (devmode.dmBitsPerPel) {
   113             case 32:
   114                 mode->format = SDL_PIXELFORMAT_RGB888;
   115                 break;
   116             case 24:
   117                 mode->format = SDL_PIXELFORMAT_RGB24;
   118                 break;
   119             case 16:
   120                 mode->format = SDL_PIXELFORMAT_RGB565;
   121                 break;
   122             case 15:
   123                 mode->format = SDL_PIXELFORMAT_RGB555;
   124                 break;
   125             case 8:
   126                 mode->format = SDL_PIXELFORMAT_INDEX8;
   127                 break;
   128             case 4:
   129                 mode->format = SDL_PIXELFORMAT_INDEX4LSB;
   130                 break;
   131             }
   132         }
   133     }
   134     if (SDL_ISPIXELFORMAT_INDEXED(mode->format)) {
   135         /* We don't support palettized modes now */
   136         return SDL_FALSE;
   137     }
   138     return SDL_TRUE;
   139 }
   140 
   141 static SDL_bool
   142 WIN_AddDisplay(LPTSTR DeviceName)
   143 {
   144     SDL_VideoDisplay display;
   145     SDL_DisplayData *displaydata;
   146     SDL_DisplayMode mode;
   147 
   148 #ifdef DEBUG_MODES
   149     printf("Display: %s\n", WIN_StringToUTF8(DeviceName));
   150 #endif
   151     if (!WIN_GetDisplayMode(DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
   152         return SDL_FALSE;
   153     }
   154 
   155     displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
   156     if (!displaydata) {
   157         return SDL_FALSE;
   158     }
   159     SDL_memcpy(displaydata->DeviceName, DeviceName,
   160                sizeof(displaydata->DeviceName));
   161 
   162     SDL_zero(display);
   163     display.desktop_mode = mode;
   164     display.current_mode = mode;
   165     display.driverdata = displaydata;
   166     SDL_AddVideoDisplay(&display);
   167     return SDL_TRUE;
   168 }
   169 
   170 int
   171 WIN_InitModes(_THIS)
   172 {
   173     DWORD i, j, count;
   174     DISPLAY_DEVICE device;
   175 
   176     device.cb = sizeof(device);
   177     for (i = 0;; ++i) {
   178         TCHAR DeviceName[32];
   179 
   180         if (!EnumDisplayDevices(NULL, i, &device, 0)) {
   181             break;
   182         }
   183         if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
   184             continue;
   185         }
   186         SDL_memcpy(DeviceName, device.DeviceName, sizeof(DeviceName));
   187 #ifdef DEBUG_MODES
   188         printf("Device: %s\n", WIN_StringToUTF8(DeviceName));
   189 #endif
   190         count = 0;
   191         for (j = 0;; ++j) {
   192             if (!EnumDisplayDevices(DeviceName, j, &device, 0)) {
   193                 break;
   194             }
   195             if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
   196                 continue;
   197             }
   198             count += WIN_AddDisplay(device.DeviceName);
   199         }
   200         if (count == 0) {
   201             WIN_AddDisplay(DeviceName);
   202         }
   203     }
   204     if (_this->num_displays == 0) {
   205         SDL_SetError("No displays available");
   206         return -1;
   207     }
   208     return 0;
   209 }
   210 
   211 int
   212 WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
   213 {
   214     SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
   215 
   216 #ifdef _WIN32_WCE
   217     // WINCE: DEVMODE.dmPosition not found, or may be mingw32ce bug
   218     rect->x = 0;
   219     rect->y = 0;
   220     rect->w = display->windows->w;
   221     rect->h = display->windows->h;
   222 #else
   223     rect->x = (int)data->DeviceMode.dmPosition.x;
   224     rect->y = (int)data->DeviceMode.dmPosition.y;
   225     rect->w = data->DeviceMode.dmPelsWidth;
   226     rect->h = data->DeviceMode.dmPelsHeight;
   227 #endif
   228     return 0;
   229 }
   230 
   231 void
   232 WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
   233 {
   234     SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
   235     DWORD i;
   236     SDL_DisplayMode mode;
   237 
   238     for (i = 0;; ++i) {
   239         if (!WIN_GetDisplayMode(data->DeviceName, i, &mode)) {
   240             break;
   241         }
   242         if (mode.format != SDL_PIXELFORMAT_UNKNOWN) {
   243             if (!SDL_AddDisplayMode(display, &mode)) {
   244                 SDL_free(mode.driverdata);
   245             }
   246         }
   247     }
   248 }
   249 
   250 int
   251 WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
   252 {
   253     SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
   254     SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
   255     LONG status;
   256 
   257 #ifdef _WIN32_WCE
   258     /* TODO: implement correctly.
   259        On my Asus MyPAL, if I execute the code below
   260        I get DISP_CHANGE_BADFLAGS and the Titlebar of the fullscreen window stays
   261        visible ... (SDL_RaiseWindow() would fix that one) */
   262     return 0;
   263 #endif
   264 
   265     status =
   266         ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode,
   267                                 NULL, CDS_FULLSCREEN, NULL);
   268     if (status == DISP_CHANGE_SUCCESSFUL) {
   269         return 0;
   270     } else {
   271         const char *reason = "Unknown reason";
   272         switch (status) {
   273         case DISP_CHANGE_BADFLAGS:
   274             reason = "DISP_CHANGE_BADFLAGS";
   275             break;
   276         case DISP_CHANGE_BADMODE:
   277             reason = "DISP_CHANGE_BADMODE";
   278             break;
   279         case DISP_CHANGE_BADPARAM:
   280             reason = "DISP_CHANGE_BADPARAM";
   281             break;
   282         case DISP_CHANGE_FAILED:
   283             reason = "DISP_CHANGE_FAILED";
   284             break;
   285         }
   286         SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
   287         return -1;
   288     }
   289 }
   290 
   291 void
   292 WIN_QuitModes(_THIS)
   293 {
   294     ChangeDisplaySettingsEx(NULL, NULL, NULL, 0, NULL);
   295 }
   296 
   297 /* vi: set ts=4 sw=4 expandtab: */