cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_windowsmodes.c (9938B)


      1/*
      2  Simple DirectMedia Layer
      3  Copyright (C) 1997-2014 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_internal.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
     32static SDL_bool
     33WIN_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	data->ScaleX = 1.0f;
     54	data->ScaleY = 1.0f;
     55
     56    /* Fill in the mode information */
     57    mode->format = SDL_PIXELFORMAT_UNKNOWN;
     58    mode->w = devmode.dmPelsWidth;
     59    mode->h = devmode.dmPelsHeight;
     60    mode->refresh_rate = devmode.dmDisplayFrequency;
     61    mode->driverdata = data;
     62
     63    if (index == ENUM_CURRENT_SETTINGS
     64        && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
     65        char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
     66        LPBITMAPINFO bmi;
     67        HBITMAP hbm;
     68		int logical_width = GetDeviceCaps( hdc, HORZRES );
     69		int logical_height = GetDeviceCaps( hdc, VERTRES );
     70
     71		data->ScaleX = (float)logical_width / devmode.dmPelsWidth;
     72		data->ScaleY = (float)logical_height / devmode.dmPelsHeight;
     73		mode->w = logical_width;
     74		mode->h = logical_height;
     75
     76        SDL_zero(bmi_data);
     77        bmi = (LPBITMAPINFO) bmi_data;
     78        bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     79
     80        hbm = CreateCompatibleBitmap(hdc, 1, 1);
     81        GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
     82        GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
     83        DeleteObject(hbm);
     84        DeleteDC(hdc);
     85        if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
     86            switch (*(Uint32 *) bmi->bmiColors) {
     87            case 0x00FF0000:
     88                mode->format = SDL_PIXELFORMAT_RGB888;
     89                break;
     90            case 0x000000FF:
     91                mode->format = SDL_PIXELFORMAT_BGR888;
     92                break;
     93            case 0xF800:
     94                mode->format = SDL_PIXELFORMAT_RGB565;
     95                break;
     96            case 0x7C00:
     97                mode->format = SDL_PIXELFORMAT_RGB555;
     98                break;
     99            }
    100        } else if (bmi->bmiHeader.biBitCount == 8) {
    101            mode->format = SDL_PIXELFORMAT_INDEX8;
    102        } else if (bmi->bmiHeader.biBitCount == 4) {
    103            mode->format = SDL_PIXELFORMAT_INDEX4LSB;
    104        }
    105	} else {
    106        /* FIXME: Can we tell what this will be? */
    107        if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
    108            switch (devmode.dmBitsPerPel) {
    109            case 32:
    110                mode->format = SDL_PIXELFORMAT_RGB888;
    111                break;
    112            case 24:
    113                mode->format = SDL_PIXELFORMAT_RGB24;
    114                break;
    115            case 16:
    116                mode->format = SDL_PIXELFORMAT_RGB565;
    117                break;
    118            case 15:
    119                mode->format = SDL_PIXELFORMAT_RGB555;
    120                break;
    121            case 8:
    122                mode->format = SDL_PIXELFORMAT_INDEX8;
    123                break;
    124            case 4:
    125                mode->format = SDL_PIXELFORMAT_INDEX4LSB;
    126                break;
    127            }
    128        }
    129    }
    130    return SDL_TRUE;
    131}
    132
    133static SDL_bool
    134WIN_AddDisplay(LPTSTR DeviceName)
    135{
    136    SDL_VideoDisplay display;
    137    SDL_DisplayData *displaydata;
    138    SDL_DisplayMode mode;
    139    DISPLAY_DEVICE device;
    140
    141#ifdef DEBUG_MODES
    142    printf("Display: %s\n", WIN_StringToUTF8(DeviceName));
    143#endif
    144    if (!WIN_GetDisplayMode(DeviceName, ENUM_CURRENT_SETTINGS, &mode)) {
    145        return SDL_FALSE;
    146    }
    147
    148    displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
    149    if (!displaydata) {
    150        return SDL_FALSE;
    151    }
    152    SDL_memcpy(displaydata->DeviceName, DeviceName,
    153               sizeof(displaydata->DeviceName));
    154
    155    SDL_zero(display);
    156    device.cb = sizeof(device);
    157    if (EnumDisplayDevices(DeviceName, 0, &device, 0)) {
    158        display.name = WIN_StringToUTF8(device.DeviceString);
    159    }
    160    display.desktop_mode = mode;
    161    display.current_mode = mode;
    162    display.driverdata = displaydata;
    163    SDL_AddVideoDisplay(&display);
    164    SDL_free(display.name);
    165    return SDL_TRUE;
    166}
    167
    168int
    169WIN_InitModes(_THIS)
    170{
    171    int pass;
    172    DWORD i, j, count;
    173    DISPLAY_DEVICE device;
    174
    175    device.cb = sizeof(device);
    176
    177    /* Get the primary display in the first pass */
    178    for (pass = 0; pass < 2; ++pass) {
    179        for (i = 0; ; ++i) {
    180            TCHAR DeviceName[32];
    181
    182            if (!EnumDisplayDevices(NULL, i, &device, 0)) {
    183                break;
    184            }
    185            if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
    186                continue;
    187            }
    188            if (pass == 0) {
    189                if (!(device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
    190                    continue;
    191                }
    192            } else {
    193                if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
    194                    continue;
    195                }
    196            }
    197            SDL_memcpy(DeviceName, device.DeviceName, sizeof(DeviceName));
    198#ifdef DEBUG_MODES
    199            printf("Device: %s\n", WIN_StringToUTF8(DeviceName));
    200#endif
    201            count = 0;
    202            for (j = 0; ; ++j) {
    203                if (!EnumDisplayDevices(DeviceName, j, &device, 0)) {
    204                    break;
    205                }
    206                if (!(device.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) {
    207                    continue;
    208                }
    209                if (pass == 0) {
    210                    if (!(device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) {
    211                        continue;
    212                    }
    213                } else {
    214                    if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
    215                        continue;
    216                    }
    217                }
    218                count += WIN_AddDisplay(device.DeviceName);
    219            }
    220            if (count == 0) {
    221                WIN_AddDisplay(DeviceName);
    222            }
    223        }
    224    }
    225    if (_this->num_displays == 0) {
    226        return SDL_SetError("No displays available");
    227    }
    228    return 0;
    229}
    230
    231int
    232WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
    233{
    234    SDL_DisplayModeData *data = (SDL_DisplayModeData *) display->current_mode.driverdata;
    235
    236    rect->x = (int)SDL_ceil(data->DeviceMode.dmPosition.x * data->ScaleX);
    237    rect->y = (int)SDL_ceil(data->DeviceMode.dmPosition.y * data->ScaleY);
    238    rect->w = (int)SDL_ceil(data->DeviceMode.dmPelsWidth * data->ScaleX);
    239    rect->h = (int)SDL_ceil(data->DeviceMode.dmPelsHeight * data->ScaleY);
    240
    241    return 0;
    242}
    243
    244void
    245WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
    246{
    247    SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
    248    DWORD i;
    249    SDL_DisplayMode mode;
    250
    251    for (i = 0;; ++i) {
    252        if (!WIN_GetDisplayMode(data->DeviceName, i, &mode)) {
    253            break;
    254        }
    255        if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
    256            /* We don't support palettized modes now */
    257            SDL_free(mode.driverdata);
    258            continue;
    259        }
    260        if (mode.format != SDL_PIXELFORMAT_UNKNOWN) {
    261            if (!SDL_AddDisplayMode(display, &mode)) {
    262                SDL_free(mode.driverdata);
    263            }
    264        } else {
    265            SDL_free(mode.driverdata);
    266        }
    267    }
    268}
    269
    270int
    271WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
    272{
    273    SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
    274    SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
    275    LONG status;
    276
    277    if (mode->driverdata == display->desktop_mode.driverdata) {
    278        status = ChangeDisplaySettingsEx(displaydata->DeviceName, NULL, NULL, 0, NULL);
    279    } else {
    280        status = ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode, NULL, CDS_FULLSCREEN, NULL);
    281    }
    282    if (status != DISP_CHANGE_SUCCESSFUL) {
    283        const char *reason = "Unknown reason";
    284        switch (status) {
    285        case DISP_CHANGE_BADFLAGS:
    286            reason = "DISP_CHANGE_BADFLAGS";
    287            break;
    288        case DISP_CHANGE_BADMODE:
    289            reason = "DISP_CHANGE_BADMODE";
    290            break;
    291        case DISP_CHANGE_BADPARAM:
    292            reason = "DISP_CHANGE_BADPARAM";
    293            break;
    294        case DISP_CHANGE_FAILED:
    295            reason = "DISP_CHANGE_FAILED";
    296            break;
    297        }
    298        return SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
    299    }
    300    EnumDisplaySettings(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode);
    301    return 0;
    302}
    303
    304void
    305WIN_QuitModes(_THIS)
    306{
    307    /* All fullscreen windows should have restored modes by now */
    308}
    309
    310#endif /* SDL_VIDEO_DRIVER_WINDOWS */
    311
    312/* vi: set ts=4 sw=4 expandtab: */