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