comparison src/video/directfb/SDL_DirectFB_modes.c @ 2737:140a7edcf2bd

Date: Sun, 31 Aug 2008 17:53:59 +0200 From: Couriersud Subject: Re: Updated DirectFB driver for SDL1.3 attached is a patch which brings the directfb driver in line with current svn. In addition: * driver now is in line with the structure of the X11 driver. This adds a couple of files. * driver now supports relative mouse movements
author Sam Lantinga <slouken@libsdl.org>
date Sun, 31 Aug 2008 16:04:32 +0000
parents
children e759ad5e6f43
comparison
equal deleted inserted replaced
2736:ae653575d4af 2737:140a7edcf2bd
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22 #include "SDL_config.h"
23
24 #include "SDL_DirectFB_video.h"
25
26 #define DFB_MAX_MODES 200
27
28 struct scn_callback_t
29 {
30 int numscreens;
31 DFBScreenID screenid[DFB_MAX_SCREENS];
32 DFBDisplayLayerID gralayer[DFB_MAX_SCREENS];
33 DFBDisplayLayerID vidlayer[DFB_MAX_SCREENS];
34 int aux; /* auxiliary integer for callbacks */
35 };
36
37 struct modes_callback_t
38 {
39 int nummodes;
40 SDL_DisplayMode *modelist;
41 };
42
43 static int
44 DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat, Uint32 * fmt)
45 {
46 switch (pixelformat) {
47 case DSPF_ALUT44:
48 *fmt = SDL_PIXELFORMAT_INDEX4LSB;
49 break;
50 case DSPF_LUT8:
51 *fmt = SDL_PIXELFORMAT_INDEX8;
52 break;
53 case DSPF_RGB332:
54 *fmt = SDL_PIXELFORMAT_RGB332;
55 break;
56 case DSPF_ARGB4444:
57 *fmt = SDL_PIXELFORMAT_ARGB4444;
58 break;
59 case SDL_PIXELFORMAT_ARGB1555:
60 *fmt = SDL_PIXELFORMAT_ARGB1555;
61 break;
62 case DSPF_RGB16:
63 *fmt = SDL_PIXELFORMAT_RGB565;
64 break;
65 case DSPF_RGB24:
66 *fmt = SDL_PIXELFORMAT_RGB24;
67 break;
68 case DSPF_RGB32:
69 *fmt = SDL_PIXELFORMAT_RGB888;
70 break;
71 case DSPF_ARGB:
72 *fmt = SDL_PIXELFORMAT_ARGB8888;
73 break;
74 case DSPF_YV12:
75 *fmt = SDL_PIXELFORMAT_YV12;
76 break; /* Planar mode: Y + V + U (3 planes) */
77 case DSPF_I420:
78 *fmt = SDL_PIXELFORMAT_IYUV;
79 break; /* Planar mode: Y + U + V (3 planes) */
80 case DSPF_YUY2:
81 *fmt = SDL_PIXELFORMAT_YUY2;
82 break; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
83 case DSPF_UYVY:
84 *fmt = SDL_PIXELFORMAT_UYVY;
85 break; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
86 default:
87 return -1;
88 }
89 return 0;
90 }
91
92 static DFBSurfacePixelFormat
93 SDLToDFBPixelFormat(Uint32 format)
94 {
95 switch (format) {
96 case SDL_PIXELFORMAT_INDEX4LSB:
97 return DSPF_ALUT44;
98 case SDL_PIXELFORMAT_INDEX8:
99 return DSPF_LUT8;
100 case SDL_PIXELFORMAT_RGB332:
101 return DSPF_RGB332;
102 case SDL_PIXELFORMAT_RGB555:
103 return DSPF_ARGB1555;
104 case SDL_PIXELFORMAT_ARGB4444:
105 return DSPF_ARGB4444;
106 case SDL_PIXELFORMAT_ARGB1555:
107 return DSPF_ARGB1555;
108 case SDL_PIXELFORMAT_RGB565:
109 return DSPF_RGB16;
110 case SDL_PIXELFORMAT_RGB24:
111 return DSPF_RGB24;
112 case SDL_PIXELFORMAT_RGB888:
113 return DSPF_RGB32;
114 case SDL_PIXELFORMAT_ARGB8888:
115 return DSPF_ARGB;
116 case SDL_PIXELFORMAT_YV12:
117 return DSPF_YV12; /* Planar mode: Y + V + U (3 planes) */
118 case SDL_PIXELFORMAT_IYUV:
119 return DSPF_I420; /* Planar mode: Y + U + V (3 planes) */
120 case SDL_PIXELFORMAT_YUY2:
121 return DSPF_YUY2; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
122 case SDL_PIXELFORMAT_UYVY:
123 return DSPF_UYVY; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
124 case SDL_PIXELFORMAT_YVYU:
125 return DSPF_UNKNOWN; /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
126 case SDL_PIXELFORMAT_INDEX1LSB:
127 return DSPF_UNKNOWN;
128 case SDL_PIXELFORMAT_INDEX1MSB:
129 return DSPF_UNKNOWN;
130 case SDL_PIXELFORMAT_INDEX4MSB:
131 return DSPF_UNKNOWN;
132 case SDL_PIXELFORMAT_RGB444:
133 return DSPF_UNKNOWN;
134 case SDL_PIXELFORMAT_BGR24:
135 return DSPF_UNKNOWN;
136 case SDL_PIXELFORMAT_BGR888:
137 return DSPF_UNKNOWN;
138 case SDL_PIXELFORMAT_RGBA8888:
139 return DSPF_UNKNOWN;
140 case SDL_PIXELFORMAT_ABGR8888:
141 return DSPF_UNKNOWN;
142 case SDL_PIXELFORMAT_BGRA8888:
143 return DSPF_UNKNOWN;
144 case SDL_PIXELFORMAT_ARGB2101010:
145 return DSPF_UNKNOWN;
146 default:
147 return DSPF_UNKNOWN;
148 }
149 }
150
151 static DFBEnumerationResult
152 EnumModesCallback(int width, int height, int bpp, void *data)
153 {
154 struct modes_callback_t *modedata = (struct modes_callback_t *) data;
155 SDL_DisplayMode mode;
156
157 mode.w = width;
158 mode.h = height;
159 mode.refresh_rate = 0;
160 mode.driverdata = NULL;
161 mode.format = SDL_PIXELFORMAT_UNKNOWN;
162
163 if (modedata->nummodes < DFB_MAX_MODES) {
164 modedata->modelist[modedata->nummodes++] = mode;
165 }
166
167 SDL_DFB_DEBUG("w %d h %d bpp %d\n", width, height, bpp);
168 return DFENUM_OK;
169 }
170
171 static DFBEnumerationResult
172 cbScreens(DFBScreenID screen_id, DFBScreenDescription desc,
173 void *callbackdata)
174 {
175 struct scn_callback_t *devdata = (struct scn_callback_t *) callbackdata;
176
177 devdata->screenid[devdata->numscreens++] = screen_id;
178 return DFENUM_OK;
179 }
180
181 DFBEnumerationResult
182 cbLayers(DFBDisplayLayerID layer_id, DFBDisplayLayerDescription desc,
183 void *callbackdata)
184 {
185 struct scn_callback_t *devdata = (struct scn_callback_t *) callbackdata;
186
187 if (desc.caps & DLCAPS_SURFACE) {
188 if ((desc.type & DLTF_GRAPHICS) && (desc.type & DLTF_VIDEO)) {
189 if (devdata->vidlayer[devdata->aux] == -1)
190 devdata->vidlayer[devdata->aux] = layer_id;
191 } else if (desc.type & DLTF_GRAPHICS) {
192 if (devdata->gralayer[devdata->aux] == -1)
193 devdata->gralayer[devdata->aux] = layer_id;
194 }
195 }
196 return DFENUM_OK;
197 }
198
199 static void
200 CheckSetDisplayMode(_THIS, DFB_DisplayData * data, SDL_DisplayMode * mode)
201 {
202 SDL_DFB_DEVICEDATA(_this);
203 DFBDisplayLayerConfig config;
204 DFBDisplayLayerConfigFlags failed;
205 int ret;
206
207 SDL_DFB_CHECKERR(data->layer->
208 SetCooperativeLevel(data->layer, DLSCL_ADMINISTRATIVE));
209 config.width = mode->w;
210 config.height = mode->h;
211 config.pixelformat = SDLToDFBPixelFormat(mode->format);
212 config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
213 if (devdata->use_yuv_underlays) {
214 config.flags |= DLCONF_OPTIONS;
215 config.options = DLOP_ALPHACHANNEL;
216 }
217 failed = 0;
218 data->layer->TestConfiguration(data->layer, &config, &failed);
219 SDL_DFB_CHECKERR(data->layer->
220 SetCooperativeLevel(data->layer, DLSCL_SHARED));
221 if (failed == 0)
222 SDL_AddDisplayMode(_this->current_display, mode);
223 else
224 SDL_DFB_DEBUG("Mode %d x %d not available: %x\n", mode->w, mode->h,
225 failed);
226
227 return;
228 error:
229 return;
230 }
231
232 void
233 DirectFB_InitModes(_THIS)
234 {
235 SDL_DFB_DEVICEDATA(_this);
236 IDirectFBDisplayLayer *layer = NULL;
237 SDL_VideoDisplay display;
238 DFB_DisplayData *dispdata;
239 SDL_DisplayMode mode;
240 #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
241 DFBCardCapabilities caps;
242 #else
243 DFBGraphicsDeviceDescription caps;
244 #endif
245 DFBDisplayLayerConfig dlc;
246 struct scn_callback_t *screencbdata;
247
248 int tcw[DFB_MAX_SCREENS];
249 int tch[DFB_MAX_SCREENS];
250 int i;
251 DFBResult ret;
252
253 SDL_DFB_CALLOC(screencbdata, 1, sizeof(*screencbdata));
254
255 screencbdata->numscreens = 0;
256
257 for (i = 0; i < DFB_MAX_SCREENS; i++) {
258 screencbdata->gralayer[i] = -1;
259 screencbdata->vidlayer[i] = -1;
260 }
261
262 SDL_DFB_CHECKERR(devdata->dfb->
263 EnumScreens(devdata->dfb, &cbScreens, screencbdata));
264
265 for (i = 0; i < screencbdata->numscreens; i++) {
266 IDirectFBScreen *screen;
267
268 SDL_DFB_CHECKERR(devdata->dfb->
269 GetScreen(devdata->dfb, screencbdata->screenid[i],
270 &screen));
271
272 screencbdata->aux = i;
273 SDL_DFB_CHECKERR(screen->
274 EnumDisplayLayers(screen, &cbLayers, screencbdata));
275 #if (DIRECTFB_MAJOR_VERSION >= 1)
276 screen->GetSize(screen, &tcw[i], &tch[i]);
277 #else
278 /* FIXME: this is only used to center windows
279 * Should be done otherwise, e.g. get surface from layer
280 */
281 tcw[i] = 800;
282 tch[i] = 600;
283 #endif
284 screen->Release(screen);
285 }
286
287 /* Query card capabilities */
288
289 devdata->dfb->GetDeviceDescription(devdata->dfb, &caps);
290
291 SDL_DFB_DEBUG("SDL directfb video driver - %s %s\n", __DATE__, __TIME__);
292 SDL_DFB_DEBUG("Using %s (%s) driver.\n", caps.name, caps.vendor);
293 SDL_DFB_DEBUG("Found %d screens\n", devdata->numscreens);
294
295 for (i = 0; i < screencbdata->numscreens; i++) {
296 SDL_DFB_CHECKERR(devdata->dfb->
297 GetDisplayLayer(devdata->dfb,
298 screencbdata->gralayer[i], &layer));
299
300 SDL_DFB_CHECKERR(layer->
301 SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE));
302 layer->EnableCursor(layer, 1);
303 SDL_DFB_CHECKERR(layer->SetCursorOpacity(layer, 0xC0));
304
305 if (devdata->use_yuv_underlays) {
306 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_OPTIONS;
307 dlc.pixelformat = DSPF_ARGB;
308 dlc.options = DLOP_ALPHACHANNEL;
309
310 ret = layer->SetConfiguration(layer, &dlc);
311 if (ret) {
312 /* try AiRGB if the previous failed */
313 dlc.pixelformat = DSPF_AiRGB;
314 ret = layer->SetConfiguration(layer, &dlc);
315 }
316 }
317
318 SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer, DLSCL_SHARED));
319
320 /* Query layer configuration to determine the current mode and pixelformat */
321 layer->GetConfiguration(layer, &dlc);
322
323 if (DFBToSDLPixelFormat(dlc.pixelformat, &mode.format) != 0) {
324 SDL_DFB_ERR("Unknown dfb pixelformat %x !\n", dlc.pixelformat);
325 goto error;
326 }
327
328 mode.w = dlc.width;
329 mode.h = dlc.height;
330 mode.refresh_rate = 0;
331 mode.driverdata = NULL;
332
333 SDL_DFB_CALLOC(dispdata, 1, sizeof(*dispdata));
334
335 dispdata->layer = layer;
336 dispdata->pixelformat = dlc.pixelformat;
337 dispdata->cw = tcw[i];
338 dispdata->ch = tch[i];
339
340 /* YUV - Video layer */
341
342 dispdata->vidID = screencbdata->vidlayer[i];
343 dispdata->vidIDinuse = 0;
344
345 SDL_zero(display);
346
347 display.desktop_mode = mode;
348 display.current_mode = mode;
349 display.driverdata = dispdata;
350
351 SDL_AddVideoDisplay(&display);
352 }
353 SDL_DFB_FREE(screencbdata);
354 return;
355 error:
356 /* FIXME: Cleanup not complete, Free existing displays */
357 SDL_DFB_FREE(dispdata);
358 SDL_DFB_RELEASE(layer);
359 return;
360 }
361
362 void
363 DirectFB_GetDisplayModes(_THIS)
364 {
365 SDL_DFB_DEVICEDATA(_this);
366 DFB_DisplayData *dispdata =
367 (DFB_DisplayData *) SDL_CurrentDisplay.driverdata;
368 SDL_DisplayMode mode;
369 struct modes_callback_t data;
370 int i;
371 int ret;
372
373 data.nummodes = 0;
374 /* Enumerate the available fullscreen modes */
375 SDL_DFB_CALLOC(data.modelist, DFB_MAX_MODES, sizeof(SDL_DisplayMode));
376 SDL_DFB_CHECKERR(devdata->dfb->
377 EnumVideoModes(devdata->dfb, EnumModesCallback, &data));
378
379 for (i = 0; i < data.nummodes; ++i) {
380 mode = data.modelist[i];
381
382 mode.format = SDL_PIXELFORMAT_ARGB8888;
383 CheckSetDisplayMode(_this, dispdata, &mode);
384 mode.format = SDL_PIXELFORMAT_RGB888;
385 CheckSetDisplayMode(_this, dispdata, &mode);
386 mode.format = SDL_PIXELFORMAT_RGB24;
387 CheckSetDisplayMode(_this, dispdata, &mode);
388 mode.format = SDL_PIXELFORMAT_RGB565;
389 CheckSetDisplayMode(_this, dispdata, &mode);
390 mode.format = SDL_PIXELFORMAT_INDEX8;
391 CheckSetDisplayMode(_this, dispdata, &mode);
392 }
393 SDL_DFB_FREE(data.modelist);
394 return;
395 error:
396 SDL_DFB_FREE(data.modelist);
397 return;
398 }
399
400 int
401 DirectFB_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
402 {
403 /*
404 * FIXME: video mode switch is currently broken for 1.2.0
405 *
406 */
407
408 SDL_DFB_DEVICEDATA(_this);
409 DFB_DisplayData *data = (DFB_DisplayData *) SDL_CurrentDisplay.driverdata;
410 DFBDisplayLayerConfig config, rconfig;
411 DFBDisplayLayerConfigFlags fail = 0;
412 DFBResult ret;
413
414 SDL_DFB_CHECKERR(data->layer->
415 SetCooperativeLevel(data->layer, DLSCL_ADMINISTRATIVE));
416
417 SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &config));
418 config.flags = DLCONF_WIDTH | DLCONF_HEIGHT;
419 if (mode->format != SDL_PIXELFORMAT_UNKNOWN) {
420 config.flags |= DLCONF_PIXELFORMAT;
421 config.pixelformat = SDLToDFBPixelFormat(mode->format);
422 data->pixelformat = config.pixelformat;
423 }
424 config.width = mode->w;
425 config.height = mode->h;
426
427 if (devdata->use_yuv_underlays) {
428 config.flags |= DLCONF_OPTIONS;
429 config.options = DLOP_ALPHACHANNEL;
430 }
431
432 data->layer->TestConfiguration(data->layer, &config, &fail);
433
434 if (fail &
435 (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_OPTIONS))
436 {
437 SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
438 mode->format);
439 return -1;
440 }
441
442 SDL_DFB_DEBUG("Trace\n");
443 config.flags &= ~fail;
444 SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
445
446 /* Double check */
447 SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &rconfig));
448 SDL_DFB_CHECKERR(data->layer->
449 SetCooperativeLevel(data->layer, DLSCL_SHARED));
450
451 if ((config.width != rconfig.width) ||
452 (config.height != rconfig.height) ||
453 ((mode->format != SDL_PIXELFORMAT_UNKNOWN)
454 && (config.pixelformat != rconfig.pixelformat))) {
455 SDL_DFB_ERR("Error setting mode %dx%d-%x\n", mode->w, mode->h,
456 mode->format);
457 return -1;
458 }
459
460 data->pixelformat = rconfig.pixelformat;
461 data->cw = config.width;
462 data->ch = config.height;
463 SDL_CurrentDisplay.current_mode = *mode;
464
465 return 0;
466 error:
467 return -1;
468 }
469
470 void
471 DirectFB_QuitModes(_THIS)
472 {
473 DFB_DeviceData *devdata = (DFB_DeviceData *) _this->driverdata;
474 SDL_DisplayMode tmode;
475 DFBResult ret;
476 int i;
477
478 SDL_SelectVideoDisplay(0);
479
480 SDL_GetDesktopDisplayMode(&tmode);
481 tmode.format = SDL_PIXELFORMAT_UNKNOWN;
482 DirectFB_SetDisplayMode(_this, &tmode);
483
484 SDL_GetDesktopDisplayMode(&tmode);
485 DirectFB_SetDisplayMode(_this, &tmode);
486
487 for (i = 0; i < SDL_GetNumVideoDisplays(); i++) {
488 DFB_DisplayData *dispdata =
489 (DFB_DisplayData *) _this->displays[i].driverdata;
490
491 if (dispdata->layer) {
492 SDL_DFB_CHECK(dispdata->layer->
493 SetCooperativeLevel(dispdata->layer,
494 DLSCL_ADMINISTRATIVE));
495 SDL_DFB_CHECK(dispdata->layer->
496 SetCursorOpacity(dispdata->layer, 0x00));
497 SDL_DFB_CHECK(dispdata->layer->
498 SetCooperativeLevel(dispdata->layer, DLSCL_SHARED));
499 }
500
501 SDL_DFB_RELEASE(dispdata->layer);
502 SDL_DFB_RELEASE(dispdata->vidlayer);
503
504 }
505 }
506
507 /* vi: set ts=4 sw=4 expandtab: */