SDL 2.0
SDL_DirectFB_modes.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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;
50
51 mode.w = width;
52 mode.h = height;
53 mode.refresh_rate = 0;
54 mode.driverdata = NULL;
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{
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
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
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
149{
151 IDirectFBDisplayLayer *layer = NULL;
152 SDL_VideoDisplay display;
153 DFB_DisplayData *dispdata = NULL;
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);
269 return;
270}
271
272void
274{
276 DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
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
291 CheckSetDisplayMode(_this, display, dispdata, &mode);
293 CheckSetDisplayMode(_this, display, dispdata, &mode);
295 CheckSetDisplayMode(_this, display, dispdata, &mode);
297 CheckSetDisplayMode(_this, display, dispdata, &mode);
299 CheckSetDisplayMode(_this, display, dispdata, &mode);
300 }
301
302 SDL_DFB_FREE(data.modelist);
303error:
304 return;
305}
306
307int
309{
310 /*
311 * FIXME: video mode switch is currently broken for 1.2.0
312 *
313 */
314
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));
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
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
390 DirectFB_SetDisplayMode(_this, display, &tmode);
391
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: */
void DirectFB_SetContext(_THIS, SDL_Window *window)
void DirectFB_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
void DirectFB_InitModes(_THIS)
int DirectFB_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
void DirectFB_QuitModes(_THIS)
#define SDL_DFB_ERR(x...)
#define SDL_DFB_CHECKERR(x...)
#define SDL_DFB_FREE(x)
#define SDL_DFB_ALLOC_CLEAR(r, s)
#define SDL_DFB_CHECK(x...)
#define SDL_DFB_LOG(x...)
#define SDL_DFB_DEVICEDATA(dev)
#define SDL_DFB_CALLOC(r, n, s)
#define SDL_DFB_RELEASE(x)
#define DFB_MAX_SCREENS
DFBSurfacePixelFormat DirectFB_SDLToDFBPixelFormat(Uint32 format)
Uint32 DirectFB_DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat)
#define _THIS
#define SDL_GetDesktopDisplayMode
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
GLenum mode
GLenum GLuint GLint GLint layer
@ SDL_PIXELFORMAT_INDEX8
Definition: SDL_pixels.h:186
@ SDL_PIXELFORMAT_RGB24
Definition: SDL_pixels.h:230
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:236
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
@ SDL_PIXELFORMAT_RGB565
Definition: SDL_pixels.h:224
@ SDL_PIXELFORMAT_UNKNOWN
Definition: SDL_pixels.h:173
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:1089
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:603
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:751
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:167
EGLConfig config
Definition: eglext.h:433
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
The structure that defines a display mode.
Definition: SDL_video.h:54
Uint32 format
Definition: SDL_video.h:55
SDL_VideoDisplay * displays
Definition: SDL_sysvideo.h:316
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:131
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:132
The type used to identify a window.
Definition: SDL_sysvideo.h:74
SDL_Renderer * screen