Mercurial > sdl-ios-xcode
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: */ |