sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_DirectFB_modes.c (13347B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 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 
     30 struct 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 
     39 struct modes_callback_t
     40 {
     41     int nummodes;
     42     SDL_DisplayMode *modelist;
     43 };
     44 
     45 static DFBEnumerationResult
     46 EnumModesCallback(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 
     64 static DFBEnumerationResult
     65 EnumScreensCallback(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 
     74 static DFBEnumerationResult
     75 EnumLayersCallback(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 
     92 static void
     93 CheckSetDisplayMode(_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 
    128 void
    129 DirectFB_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 
    147 void
    148 DirectFB_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, SDL_FALSE);
    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 
    272 void
    273 DirectFB_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);
    303 error:
    304     return;
    305 }
    306 
    307 int
    308 DirectFB_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 
    378 void
    379 DirectFB_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: */