cscg22-gearboy

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

SDL_DirectFB_modes.c (13336B)


      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_DIRECTFB
     24
     25#include "SDL_DirectFB_video.h"
     26#include "SDL_DirectFB_modes.h"
     27
     28#define DFB_MAX_MODES 200
     29
     30struct screen_callback_t
     31{
     32    int numscreens;
     33    DFBScreenID screenid[DFB_MAX_SCREENS];
     34    DFBDisplayLayerID gralayer[DFB_MAX_SCREENS];
     35    DFBDisplayLayerID vidlayer[DFB_MAX_SCREENS];
     36    int aux;                    /* auxiliary integer for callbacks */
     37};
     38
     39struct modes_callback_t
     40{
     41    int nummodes;
     42    SDL_DisplayMode *modelist;
     43};
     44
     45static DFBEnumerationResult
     46EnumModesCallback(int width, int height, int bpp, void *data)
     47{
     48    struct modes_callback_t *modedata = (struct modes_callback_t *) data;
     49    SDL_DisplayMode mode;
     50
     51    mode.w = width;
     52    mode.h = height;
     53    mode.refresh_rate = 0;
     54    mode.driverdata = NULL;
     55    mode.format = SDL_PIXELFORMAT_UNKNOWN;
     56
     57    if (modedata->nummodes < DFB_MAX_MODES) {
     58        modedata->modelist[modedata->nummodes++] = mode;
     59    }
     60
     61    return DFENUM_OK;
     62}
     63
     64static DFBEnumerationResult
     65EnumScreensCallback(DFBScreenID screen_id, DFBScreenDescription desc,
     66          void *callbackdata)
     67{
     68    struct screen_callback_t *devdata = (struct screen_callback_t *) callbackdata;
     69
     70    devdata->screenid[devdata->numscreens++] = screen_id;
     71    return DFENUM_OK;
     72}
     73
     74static DFBEnumerationResult
     75EnumLayersCallback(DFBDisplayLayerID layer_id, DFBDisplayLayerDescription desc,
     76         void *callbackdata)
     77{
     78    struct screen_callback_t *devdata = (struct screen_callback_t *) callbackdata;
     79
     80    if (desc.caps & DLCAPS_SURFACE) {
     81        if ((desc.type & DLTF_GRAPHICS) && (desc.type & DLTF_VIDEO)) {
     82            if (devdata->vidlayer[devdata->aux] == -1)
     83                devdata->vidlayer[devdata->aux] = layer_id;
     84        } else if (desc.type & DLTF_GRAPHICS) {
     85            if (devdata->gralayer[devdata->aux] == -1)
     86                devdata->gralayer[devdata->aux] = layer_id;
     87        }
     88    }
     89    return DFENUM_OK;
     90}
     91
     92static void
     93CheckSetDisplayMode(_THIS, SDL_VideoDisplay * display, DFB_DisplayData * data, SDL_DisplayMode * mode)
     94{
     95    SDL_DFB_DEVICEDATA(_this);
     96    DFBDisplayLayerConfig config;
     97    DFBDisplayLayerConfigFlags failed;
     98
     99    SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
    100                                                      DLSCL_ADMINISTRATIVE));
    101    config.width = mode->w;
    102    config.height = mode->h;
    103    config.pixelformat = DirectFB_SDLToDFBPixelFormat(mode->format);
    104    config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
    105    if (devdata->use_yuv_underlays) {
    106        config.flags |= DLCONF_OPTIONS;
    107        config.options = DLOP_ALPHACHANNEL;
    108    }
    109    failed = 0;
    110    data->layer->TestConfiguration(data->layer, &config, &failed);
    111    SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
    112                                                      DLSCL_SHARED));
    113    if (failed == 0)
    114    {
    115        SDL_AddDisplayMode(display, mode);
    116        SDL_DFB_LOG("Mode %d x %d Added\n", mode->w, mode->h);
    117    }
    118    else
    119        SDL_DFB_ERR("Mode %d x %d not available: %x\n", mode->w,
    120                      mode->h, failed);
    121
    122    return;
    123  error:
    124    return;
    125}
    126
    127
    128void
    129DirectFB_SetContext(_THIS, SDL_Window *window)
    130{
    131#if (DFB_VERSION_ATLEAST(1,0,0))
    132    /* FIXME: does not work on 1.0/1.2 with radeon driver
    133     *        the approach did work with the matrox driver
    134     *        This has simply no effect.
    135     */
    136
    137    SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
    138    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
    139
    140    /* FIXME: should we handle the error */
    141    if (dispdata->vidIDinuse)
    142        SDL_DFB_CHECK(dispdata->vidlayer->SwitchContext(dispdata->vidlayer,
    143                                                           DFB_TRUE));
    144#endif
    145}
    146
    147void
    148DirectFB_InitModes(_THIS)
    149{
    150    SDL_DFB_DEVICEDATA(_this);
    151    IDirectFBDisplayLayer *layer = NULL;
    152    SDL_VideoDisplay display;
    153    DFB_DisplayData *dispdata = NULL;
    154    SDL_DisplayMode mode;
    155    DFBGraphicsDeviceDescription caps;
    156    DFBDisplayLayerConfig dlc;
    157    struct screen_callback_t *screencbdata;
    158
    159    int tcw[DFB_MAX_SCREENS];
    160    int tch[DFB_MAX_SCREENS];
    161    int i;
    162    DFBResult ret;
    163
    164    SDL_DFB_ALLOC_CLEAR(screencbdata, sizeof(*screencbdata));
    165
    166    screencbdata->numscreens = 0;
    167
    168    for (i = 0; i < DFB_MAX_SCREENS; i++) {
    169        screencbdata->gralayer[i] = -1;
    170        screencbdata->vidlayer[i] = -1;
    171    }
    172
    173    SDL_DFB_CHECKERR(devdata->dfb->EnumScreens(devdata->dfb, &EnumScreensCallback,
    174                                               screencbdata));
    175
    176    for (i = 0; i < screencbdata->numscreens; i++) {
    177        IDirectFBScreen *screen;
    178
    179        SDL_DFB_CHECKERR(devdata->dfb->GetScreen(devdata->dfb,
    180                                                 screencbdata->screenid
    181                                                 [i], &screen));
    182
    183        screencbdata->aux = i;
    184        SDL_DFB_CHECKERR(screen->EnumDisplayLayers(screen, &EnumLayersCallback,
    185                                                   screencbdata));
    186        screen->GetSize(screen, &tcw[i], &tch[i]);
    187
    188        screen->Release(screen);
    189    }
    190
    191    /* Query card capabilities */
    192
    193    devdata->dfb->GetDeviceDescription(devdata->dfb, &caps);
    194
    195    for (i = 0; i < screencbdata->numscreens; i++) {
    196        SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb,
    197                                                       screencbdata->gralayer
    198                                                       [i], &layer));
    199
    200        SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer,
    201                                                    DLSCL_ADMINISTRATIVE));
    202        layer->EnableCursor(layer, 1);
    203        SDL_DFB_CHECKERR(layer->SetCursorOpacity(layer, 0xC0));
    204
    205        if (devdata->use_yuv_underlays) {
    206            dlc.flags = DLCONF_PIXELFORMAT | DLCONF_OPTIONS;
    207            dlc.pixelformat = DSPF_ARGB;
    208            dlc.options = DLOP_ALPHACHANNEL;
    209
    210            ret = layer->SetConfiguration(layer, &dlc);
    211            if (ret != DFB_OK) {
    212                /* try AiRGB if the previous failed */
    213                dlc.pixelformat = DSPF_AiRGB;
    214                SDL_DFB_CHECKERR(layer->SetConfiguration(layer, &dlc));
    215            }
    216        }
    217
    218        /* Query layer configuration to determine the current mode and pixelformat */
    219        dlc.flags = DLCONF_ALL;
    220        SDL_DFB_CHECKERR(layer->GetConfiguration(layer, &dlc));
    221
    222        mode.format = DirectFB_DFBToSDLPixelFormat(dlc.pixelformat);
    223
    224        if (mode.format == SDL_PIXELFORMAT_UNKNOWN) {
    225            SDL_DFB_ERR("Unknown dfb pixelformat %x !\n", dlc.pixelformat);
    226            goto error;
    227        }
    228
    229        mode.w = dlc.width;
    230        mode.h = dlc.height;
    231        mode.refresh_rate = 0;
    232        mode.driverdata = NULL;
    233
    234        SDL_DFB_ALLOC_CLEAR(dispdata, sizeof(*dispdata));
    235
    236        dispdata->layer = layer;
    237        dispdata->pixelformat = dlc.pixelformat;
    238        dispdata->cw = tcw[i];
    239        dispdata->ch = tch[i];
    240
    241        /* YUV - Video layer */
    242
    243        dispdata->vidID = screencbdata->vidlayer[i];
    244        dispdata->vidIDinuse = 0;
    245
    246        SDL_zero(display);
    247
    248        display.desktop_mode = mode;
    249        display.current_mode = mode;
    250        display.driverdata = dispdata;
    251
    252#if (DFB_VERSION_ATLEAST(1,2,0))
    253        dlc.flags =
    254            DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
    255            DLCONF_OPTIONS;
    256        ret = layer->SetConfiguration(layer, &dlc);
    257#endif
    258
    259        SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer, DLSCL_SHARED));
    260
    261        SDL_AddVideoDisplay(&display);
    262    }
    263    SDL_DFB_FREE(screencbdata);
    264    return;
    265  error:
    266    /* FIXME: Cleanup not complete, Free existing displays */
    267    SDL_DFB_FREE(dispdata);
    268    SDL_DFB_RELEASE(layer);
    269    return;
    270}
    271
    272void
    273DirectFB_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
    274{
    275    SDL_DFB_DEVICEDATA(_this);
    276    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
    277    SDL_DisplayMode mode;
    278    struct modes_callback_t data;
    279    int i;
    280
    281    data.nummodes = 0;
    282    /* Enumerate the available fullscreen modes */
    283    SDL_DFB_CALLOC(data.modelist, DFB_MAX_MODES, sizeof(SDL_DisplayMode));
    284    SDL_DFB_CHECKERR(devdata->dfb->EnumVideoModes(devdata->dfb,
    285                                                  EnumModesCallback, &data));
    286
    287    for (i = 0; i < data.nummodes; ++i) {
    288        mode = data.modelist[i];
    289
    290        mode.format = SDL_PIXELFORMAT_ARGB8888;
    291        CheckSetDisplayMode(_this, display, dispdata, &mode);
    292        mode.format = SDL_PIXELFORMAT_RGB888;
    293        CheckSetDisplayMode(_this, display, dispdata, &mode);
    294        mode.format = SDL_PIXELFORMAT_RGB24;
    295        CheckSetDisplayMode(_this, display, dispdata, &mode);
    296        mode.format = SDL_PIXELFORMAT_RGB565;
    297        CheckSetDisplayMode(_this, display, dispdata, &mode);
    298        mode.format = SDL_PIXELFORMAT_INDEX8;
    299        CheckSetDisplayMode(_this, display, dispdata, &mode);
    300    }
    301
    302    SDL_DFB_FREE(data.modelist);
    303error:
    304    return;
    305}
    306
    307int
    308DirectFB_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
    309{
    310    /*
    311     * FIXME: video mode switch is currently broken for 1.2.0
    312     *
    313     */
    314
    315    SDL_DFB_DEVICEDATA(_this);
    316    DFB_DisplayData *data = (DFB_DisplayData *) display->driverdata;
    317    DFBDisplayLayerConfig config, rconfig;
    318    DFBDisplayLayerConfigFlags fail = 0;
    319
    320    SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
    321                                                      DLSCL_ADMINISTRATIVE));
    322
    323    SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &config));
    324    config.flags = DLCONF_WIDTH | DLCONF_HEIGHT;
    325    if (mode->format != SDL_PIXELFORMAT_UNKNOWN) {
    326        config.flags |= DLCONF_PIXELFORMAT;
    327        config.pixelformat = DirectFB_SDLToDFBPixelFormat(mode->format);
    328        data->pixelformat = config.pixelformat;
    329    }
    330    config.width = mode->w;
    331    config.height = mode->h;
    332
    333    if (devdata->use_yuv_underlays) {
    334        config.flags |= DLCONF_OPTIONS;
    335        config.options = DLOP_ALPHACHANNEL;
    336    }
    337
    338    data->layer->TestConfiguration(data->layer, &config, &fail);
    339
    340    if (fail &
    341        (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
    342         DLCONF_OPTIONS)) {
    343        SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
    344                    mode->format);
    345        return -1;
    346    }
    347
    348    config.flags &= ~fail;
    349    SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
    350#if (DFB_VERSION_ATLEAST(1,2,0))
    351    /* Need to call this twice ! */
    352    SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
    353#endif
    354
    355    /* Double check */
    356    SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &rconfig));
    357    SDL_DFB_CHECKERR(data->
    358                     layer->SetCooperativeLevel(data->layer, DLSCL_SHARED));
    359
    360    if ((config.width != rconfig.width) || (config.height != rconfig.height)
    361        || ((mode->format != SDL_PIXELFORMAT_UNKNOWN)
    362            && (config.pixelformat != rconfig.pixelformat))) {
    363        SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
    364                    mode->format);
    365        return -1;
    366    }
    367
    368    data->pixelformat = rconfig.pixelformat;
    369    data->cw = config.width;
    370    data->ch = config.height;
    371    display->current_mode = *mode;
    372
    373    return 0;
    374  error:
    375    return -1;
    376}
    377
    378void
    379DirectFB_QuitModes(_THIS)
    380{
    381    SDL_DisplayMode tmode;
    382    int i;
    383
    384    for (i = 0; i < _this->num_displays; ++i) {
    385        SDL_VideoDisplay *display = &_this->displays[i];
    386        DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
    387
    388        SDL_GetDesktopDisplayMode(i, &tmode);
    389        tmode.format = SDL_PIXELFORMAT_UNKNOWN;
    390        DirectFB_SetDisplayMode(_this, display, &tmode);
    391
    392        SDL_GetDesktopDisplayMode(i, &tmode);
    393        DirectFB_SetDisplayMode(_this, display, &tmode);
    394
    395        if (dispdata->layer) {
    396            SDL_DFB_CHECK(dispdata->
    397                          layer->SetCooperativeLevel(dispdata->layer,
    398                                                     DLSCL_ADMINISTRATIVE));
    399            SDL_DFB_CHECK(dispdata->
    400                          layer->SetCursorOpacity(dispdata->layer, 0x00));
    401            SDL_DFB_CHECK(dispdata->
    402                          layer->SetCooperativeLevel(dispdata->layer,
    403                                                     DLSCL_SHARED));
    404        }
    405
    406        SDL_DFB_RELEASE(dispdata->layer);
    407        SDL_DFB_RELEASE(dispdata->vidlayer);
    408
    409    }
    410}
    411
    412#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
    413
    414/* vi: set ts=4 sw=4 expandtab: */