src/video/directfb/SDL_DirectFB_modes.c
author Sam Lantinga
Fri, 27 Jan 2017 21:23:27 -0800
changeset 10861 71d8f9afb690
parent 10737 3406a0f8b041
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Fixed bug 3569 - GL_UpdateViewport leaves PROJECTION matrix selected

Tom Seddon

GL_ActivateRenderer may call GL_UpdateViewport, which leaves the GL_PROJECTION matrix selected. But after GL_ResetState, the GL_MODELVIEW matrix is selected, suggesting that's the intended default state.

It seems at least like these should be consistent. Presumably GL_UpdateViewport should be doing a glMatrixMode(GL_MODELVIEW) before it finishes.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2017 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);
   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: */