summaryrefslogtreecommitdiff
path: root/Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c')
-rw-r--r--Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c414
1 files changed, 414 insertions, 0 deletions
diff --git a/Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c b/Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c
new file mode 100644
index 0000000..a3b8b45
--- /dev/null
+++ b/Source/external/SDL2/src/video/directfb/SDL_DirectFB_modes.c
@@ -0,0 +1,414 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_DIRECTFB
+
+#include "SDL_DirectFB_video.h"
+#include "SDL_DirectFB_modes.h"
+
+#define DFB_MAX_MODES 200
+
+struct screen_callback_t
+{
+ int numscreens;
+ DFBScreenID screenid[DFB_MAX_SCREENS];
+ DFBDisplayLayerID gralayer[DFB_MAX_SCREENS];
+ DFBDisplayLayerID vidlayer[DFB_MAX_SCREENS];
+ int aux; /* auxiliary integer for callbacks */
+};
+
+struct modes_callback_t
+{
+ int nummodes;
+ SDL_DisplayMode *modelist;
+};
+
+static DFBEnumerationResult
+EnumModesCallback(int width, int height, int bpp, void *data)
+{
+ struct modes_callback_t *modedata = (struct modes_callback_t *) data;
+ SDL_DisplayMode mode;
+
+ mode.w = width;
+ mode.h = height;
+ mode.refresh_rate = 0;
+ mode.driverdata = NULL;
+ mode.format = SDL_PIXELFORMAT_UNKNOWN;
+
+ if (modedata->nummodes < DFB_MAX_MODES) {
+ modedata->modelist[modedata->nummodes++] = mode;
+ }
+
+ return DFENUM_OK;
+}
+
+static DFBEnumerationResult
+EnumScreensCallback(DFBScreenID screen_id, DFBScreenDescription desc,
+ void *callbackdata)
+{
+ struct screen_callback_t *devdata = (struct screen_callback_t *) callbackdata;
+
+ devdata->screenid[devdata->numscreens++] = screen_id;
+ return DFENUM_OK;
+}
+
+static DFBEnumerationResult
+EnumLayersCallback(DFBDisplayLayerID layer_id, DFBDisplayLayerDescription desc,
+ void *callbackdata)
+{
+ struct screen_callback_t *devdata = (struct screen_callback_t *) callbackdata;
+
+ if (desc.caps & DLCAPS_SURFACE) {
+ if ((desc.type & DLTF_GRAPHICS) && (desc.type & DLTF_VIDEO)) {
+ if (devdata->vidlayer[devdata->aux] == -1)
+ devdata->vidlayer[devdata->aux] = layer_id;
+ } else if (desc.type & DLTF_GRAPHICS) {
+ if (devdata->gralayer[devdata->aux] == -1)
+ devdata->gralayer[devdata->aux] = layer_id;
+ }
+ }
+ return DFENUM_OK;
+}
+
+static void
+CheckSetDisplayMode(_THIS, SDL_VideoDisplay * display, DFB_DisplayData * data, SDL_DisplayMode * mode)
+{
+ SDL_DFB_DEVICEDATA(_this);
+ DFBDisplayLayerConfig config;
+ DFBDisplayLayerConfigFlags failed;
+
+ SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
+ DLSCL_ADMINISTRATIVE));
+ config.width = mode->w;
+ config.height = mode->h;
+ config.pixelformat = DirectFB_SDLToDFBPixelFormat(mode->format);
+ config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
+ if (devdata->use_yuv_underlays) {
+ config.flags |= DLCONF_OPTIONS;
+ config.options = DLOP_ALPHACHANNEL;
+ }
+ failed = 0;
+ data->layer->TestConfiguration(data->layer, &config, &failed);
+ SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
+ DLSCL_SHARED));
+ if (failed == 0)
+ {
+ SDL_AddDisplayMode(display, mode);
+ SDL_DFB_LOG("Mode %d x %d Added\n", mode->w, mode->h);
+ }
+ else
+ SDL_DFB_ERR("Mode %d x %d not available: %x\n", mode->w,
+ mode->h, failed);
+
+ return;
+ error:
+ return;
+}
+
+
+void
+DirectFB_SetContext(_THIS, SDL_Window *window)
+{
+#if (DFB_VERSION_ATLEAST(1,0,0))
+ /* FIXME: does not work on 1.0/1.2 with radeon driver
+ * the approach did work with the matrox driver
+ * This has simply no effect.
+ */
+
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
+
+ /* FIXME: should we handle the error */
+ if (dispdata->vidIDinuse)
+ SDL_DFB_CHECK(dispdata->vidlayer->SwitchContext(dispdata->vidlayer,
+ DFB_TRUE));
+#endif
+}
+
+void
+DirectFB_InitModes(_THIS)
+{
+ SDL_DFB_DEVICEDATA(_this);
+ IDirectFBDisplayLayer *layer = NULL;
+ SDL_VideoDisplay display;
+ DFB_DisplayData *dispdata = NULL;
+ SDL_DisplayMode mode;
+ DFBGraphicsDeviceDescription caps;
+ DFBDisplayLayerConfig dlc;
+ struct screen_callback_t *screencbdata;
+
+ int tcw[DFB_MAX_SCREENS];
+ int tch[DFB_MAX_SCREENS];
+ int i;
+ DFBResult ret;
+
+ SDL_DFB_ALLOC_CLEAR(screencbdata, sizeof(*screencbdata));
+
+ screencbdata->numscreens = 0;
+
+ for (i = 0; i < DFB_MAX_SCREENS; i++) {
+ screencbdata->gralayer[i] = -1;
+ screencbdata->vidlayer[i] = -1;
+ }
+
+ SDL_DFB_CHECKERR(devdata->dfb->EnumScreens(devdata->dfb, &EnumScreensCallback,
+ screencbdata));
+
+ for (i = 0; i < screencbdata->numscreens; i++) {
+ IDirectFBScreen *screen;
+
+ SDL_DFB_CHECKERR(devdata->dfb->GetScreen(devdata->dfb,
+ screencbdata->screenid
+ [i], &screen));
+
+ screencbdata->aux = i;
+ SDL_DFB_CHECKERR(screen->EnumDisplayLayers(screen, &EnumLayersCallback,
+ screencbdata));
+ screen->GetSize(screen, &tcw[i], &tch[i]);
+
+ screen->Release(screen);
+ }
+
+ /* Query card capabilities */
+
+ devdata->dfb->GetDeviceDescription(devdata->dfb, &caps);
+
+ for (i = 0; i < screencbdata->numscreens; i++) {
+ SDL_DFB_CHECKERR(devdata->dfb->GetDisplayLayer(devdata->dfb,
+ screencbdata->gralayer
+ [i], &layer));
+
+ SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer,
+ DLSCL_ADMINISTRATIVE));
+ layer->EnableCursor(layer, 1);
+ SDL_DFB_CHECKERR(layer->SetCursorOpacity(layer, 0xC0));
+
+ if (devdata->use_yuv_underlays) {
+ dlc.flags = DLCONF_PIXELFORMAT | DLCONF_OPTIONS;
+ dlc.pixelformat = DSPF_ARGB;
+ dlc.options = DLOP_ALPHACHANNEL;
+
+ ret = layer->SetConfiguration(layer, &dlc);
+ if (ret != DFB_OK) {
+ /* try AiRGB if the previous failed */
+ dlc.pixelformat = DSPF_AiRGB;
+ SDL_DFB_CHECKERR(layer->SetConfiguration(layer, &dlc));
+ }
+ }
+
+ /* Query layer configuration to determine the current mode and pixelformat */
+ dlc.flags = DLCONF_ALL;
+ SDL_DFB_CHECKERR(layer->GetConfiguration(layer, &dlc));
+
+ mode.format = DirectFB_DFBToSDLPixelFormat(dlc.pixelformat);
+
+ if (mode.format == SDL_PIXELFORMAT_UNKNOWN) {
+ SDL_DFB_ERR("Unknown dfb pixelformat %x !\n", dlc.pixelformat);
+ goto error;
+ }
+
+ mode.w = dlc.width;
+ mode.h = dlc.height;
+ mode.refresh_rate = 0;
+ mode.driverdata = NULL;
+
+ SDL_DFB_ALLOC_CLEAR(dispdata, sizeof(*dispdata));
+
+ dispdata->layer = layer;
+ dispdata->pixelformat = dlc.pixelformat;
+ dispdata->cw = tcw[i];
+ dispdata->ch = tch[i];
+
+ /* YUV - Video layer */
+
+ dispdata->vidID = screencbdata->vidlayer[i];
+ dispdata->vidIDinuse = 0;
+
+ SDL_zero(display);
+
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = dispdata;
+
+#if (DFB_VERSION_ATLEAST(1,2,0))
+ dlc.flags =
+ DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
+ DLCONF_OPTIONS;
+ ret = layer->SetConfiguration(layer, &dlc);
+#endif
+
+ SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer, DLSCL_SHARED));
+
+ SDL_AddVideoDisplay(&display);
+ }
+ SDL_DFB_FREE(screencbdata);
+ return;
+ error:
+ /* FIXME: Cleanup not complete, Free existing displays */
+ SDL_DFB_FREE(dispdata);
+ SDL_DFB_RELEASE(layer);
+ return;
+}
+
+void
+DirectFB_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
+{
+ SDL_DFB_DEVICEDATA(_this);
+ DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
+ SDL_DisplayMode mode;
+ struct modes_callback_t data;
+ int i;
+
+ data.nummodes = 0;
+ /* Enumerate the available fullscreen modes */
+ SDL_DFB_CALLOC(data.modelist, DFB_MAX_MODES, sizeof(SDL_DisplayMode));
+ SDL_DFB_CHECKERR(devdata->dfb->EnumVideoModes(devdata->dfb,
+ EnumModesCallback, &data));
+
+ for (i = 0; i < data.nummodes; ++i) {
+ mode = data.modelist[i];
+
+ mode.format = SDL_PIXELFORMAT_ARGB8888;
+ CheckSetDisplayMode(_this, display, dispdata, &mode);
+ mode.format = SDL_PIXELFORMAT_RGB888;
+ CheckSetDisplayMode(_this, display, dispdata, &mode);
+ mode.format = SDL_PIXELFORMAT_RGB24;
+ CheckSetDisplayMode(_this, display, dispdata, &mode);
+ mode.format = SDL_PIXELFORMAT_RGB565;
+ CheckSetDisplayMode(_this, display, dispdata, &mode);
+ mode.format = SDL_PIXELFORMAT_INDEX8;
+ CheckSetDisplayMode(_this, display, dispdata, &mode);
+ }
+
+ SDL_DFB_FREE(data.modelist);
+error:
+ return;
+}
+
+int
+DirectFB_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+ /*
+ * FIXME: video mode switch is currently broken for 1.2.0
+ *
+ */
+
+ SDL_DFB_DEVICEDATA(_this);
+ DFB_DisplayData *data = (DFB_DisplayData *) display->driverdata;
+ DFBDisplayLayerConfig config, rconfig;
+ DFBDisplayLayerConfigFlags fail = 0;
+
+ SDL_DFB_CHECKERR(data->layer->SetCooperativeLevel(data->layer,
+ DLSCL_ADMINISTRATIVE));
+
+ SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &config));
+ config.flags = DLCONF_WIDTH | DLCONF_HEIGHT;
+ if (mode->format != SDL_PIXELFORMAT_UNKNOWN) {
+ config.flags |= DLCONF_PIXELFORMAT;
+ config.pixelformat = DirectFB_SDLToDFBPixelFormat(mode->format);
+ data->pixelformat = config.pixelformat;
+ }
+ config.width = mode->w;
+ config.height = mode->h;
+
+ if (devdata->use_yuv_underlays) {
+ config.flags |= DLCONF_OPTIONS;
+ config.options = DLOP_ALPHACHANNEL;
+ }
+
+ data->layer->TestConfiguration(data->layer, &config, &fail);
+
+ if (fail &
+ (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT |
+ DLCONF_OPTIONS)) {
+ SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
+ mode->format);
+ return -1;
+ }
+
+ config.flags &= ~fail;
+ SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
+#if (DFB_VERSION_ATLEAST(1,2,0))
+ /* Need to call this twice ! */
+ SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
+#endif
+
+ /* Double check */
+ SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &rconfig));
+ SDL_DFB_CHECKERR(data->
+ layer->SetCooperativeLevel(data->layer, DLSCL_SHARED));
+
+ if ((config.width != rconfig.width) || (config.height != rconfig.height)
+ || ((mode->format != SDL_PIXELFORMAT_UNKNOWN)
+ && (config.pixelformat != rconfig.pixelformat))) {
+ SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
+ mode->format);
+ return -1;
+ }
+
+ data->pixelformat = rconfig.pixelformat;
+ data->cw = config.width;
+ data->ch = config.height;
+ display->current_mode = *mode;
+
+ return 0;
+ error:
+ return -1;
+}
+
+void
+DirectFB_QuitModes(_THIS)
+{
+ SDL_DisplayMode tmode;
+ int i;
+
+ for (i = 0; i < _this->num_displays; ++i) {
+ SDL_VideoDisplay *display = &_this->displays[i];
+ DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
+
+ SDL_GetDesktopDisplayMode(i, &tmode);
+ tmode.format = SDL_PIXELFORMAT_UNKNOWN;
+ DirectFB_SetDisplayMode(_this, display, &tmode);
+
+ SDL_GetDesktopDisplayMode(i, &tmode);
+ DirectFB_SetDisplayMode(_this, display, &tmode);
+
+ if (dispdata->layer) {
+ SDL_DFB_CHECK(dispdata->
+ layer->SetCooperativeLevel(dispdata->layer,
+ DLSCL_ADMINISTRATIVE));
+ SDL_DFB_CHECK(dispdata->
+ layer->SetCursorOpacity(dispdata->layer, 0x00));
+ SDL_DFB_CHECK(dispdata->
+ layer->SetCooperativeLevel(dispdata->layer,
+ DLSCL_SHARED));
+ }
+
+ SDL_DFB_RELEASE(dispdata->layer);
+ SDL_DFB_RELEASE(dispdata->vidlayer);
+
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
+
+/* vi: set ts=4 sw=4 expandtab: */