1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 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
27 #include "SDL_DirectFB_events.h"
28 /*
29 * #include "SDL_DirectFB_keyboard.h"
30 */
31 #include "SDL_DirectFB_modes.h"
32 #include "SDL_DirectFB_mouse.h"
33 #include "SDL_DirectFB_opengl.h"
34 #include "SDL_DirectFB_window.h"
35 #include "SDL_DirectFB_WM.h"
36
37
38 /* DirectFB video driver implementation.
39 */
40
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <sys/mman.h>
44
45 #include <directfb.h>
46 #include <directfb_version.h>
47 #include <directfb_strings.h>
48
49 #include "SDL_video.h"
50 #include "SDL_mouse.h"
51 #include "../SDL_sysvideo.h"
52 #include "../SDL_pixels_c.h"
53 #include "../../events/SDL_events_c.h"
54 #include "SDL_DirectFB_video.h"
55 #include "SDL_DirectFB_events.h"
56 #include "SDL_DirectFB_render.h"
57 #include "SDL_DirectFB_mouse.h"
58 #include "SDL_DirectFB_shape.h"
59
60
61 #include "SDL_DirectFB_dyn.h"
62
63 /* Initialization/Query functions */
64 static int DirectFB_VideoInit(_THIS);
65 static void DirectFB_VideoQuit(_THIS);
66
67 static int DirectFB_Available(void);
68 static SDL_VideoDevice *DirectFB_CreateDevice(int devindex);
69
70 VideoBootStrap DirectFB_bootstrap = {
71 "directfb", "DirectFB",
72 DirectFB_Available, DirectFB_CreateDevice
73 };
74
75 static const DirectFBSurfaceDrawingFlagsNames(drawing_flags);
76 static const DirectFBSurfaceBlittingFlagsNames(blitting_flags);
77 static const DirectFBAccelerationMaskNames(acceleration_mask);
78
79 /* DirectFB driver bootstrap functions */
80
81 static int
DirectFB_Available(void)82 DirectFB_Available(void)
83 {
84 if (!SDL_DirectFB_LoadLibrary())
85 return 0;
86 SDL_DirectFB_UnLoadLibrary();
87 return 1;
88 }
89
90 static void
DirectFB_DeleteDevice(SDL_VideoDevice * device)91 DirectFB_DeleteDevice(SDL_VideoDevice * device)
92 {
93 SDL_DirectFB_UnLoadLibrary();
94 SDL_DFB_FREE(device->driverdata);
95 SDL_DFB_FREE(device);
96 }
97
98 static SDL_VideoDevice *
DirectFB_CreateDevice(int devindex)99 DirectFB_CreateDevice(int devindex)
100 {
101 SDL_VideoDevice *device;
102
103 if (!SDL_DirectFB_LoadLibrary()) {
104 return NULL;
105 }
106
107 /* Initialize all variables that we clean on shutdown */
108 SDL_DFB_ALLOC_CLEAR(device, sizeof(SDL_VideoDevice));
109
110 /* Set the function pointers */
111
112 /* Set the function pointers */
113 device->VideoInit = DirectFB_VideoInit;
114 device->VideoQuit = DirectFB_VideoQuit;
115 device->GetDisplayModes = DirectFB_GetDisplayModes;
116 device->SetDisplayMode = DirectFB_SetDisplayMode;
117 device->PumpEvents = DirectFB_PumpEventsWindow;
118 device->CreateWindow = DirectFB_CreateWindow;
119 device->CreateWindowFrom = DirectFB_CreateWindowFrom;
120 device->SetWindowTitle = DirectFB_SetWindowTitle;
121 device->SetWindowIcon = DirectFB_SetWindowIcon;
122 device->SetWindowPosition = DirectFB_SetWindowPosition;
123 device->SetWindowSize = DirectFB_SetWindowSize;
124 device->SetWindowOpacity = DirectFB_SetWindowOpacity;
125 device->ShowWindow = DirectFB_ShowWindow;
126 device->HideWindow = DirectFB_HideWindow;
127 device->RaiseWindow = DirectFB_RaiseWindow;
128 device->MaximizeWindow = DirectFB_MaximizeWindow;
129 device->MinimizeWindow = DirectFB_MinimizeWindow;
130 device->RestoreWindow = DirectFB_RestoreWindow;
131 device->SetWindowGrab = DirectFB_SetWindowGrab;
132 device->DestroyWindow = DirectFB_DestroyWindow;
133 device->GetWindowWMInfo = DirectFB_GetWindowWMInfo;
134
135 /* !!! FIXME: implement SetWindowBordered */
136
137 #if SDL_DIRECTFB_OPENGL
138 device->GL_LoadLibrary = DirectFB_GL_LoadLibrary;
139 device->GL_GetProcAddress = DirectFB_GL_GetProcAddress;
140 device->GL_MakeCurrent = DirectFB_GL_MakeCurrent;
141
142 device->GL_CreateContext = DirectFB_GL_CreateContext;
143 device->GL_SetSwapInterval = DirectFB_GL_SetSwapInterval;
144 device->GL_GetSwapInterval = DirectFB_GL_GetSwapInterval;
145 device->GL_SwapWindow = DirectFB_GL_SwapWindow;
146 device->GL_DeleteContext = DirectFB_GL_DeleteContext;
147
148 #endif
149
150 /* Shaped window support */
151 device->shape_driver.CreateShaper = DirectFB_CreateShaper;
152 device->shape_driver.SetWindowShape = DirectFB_SetWindowShape;
153 device->shape_driver.ResizeWindowShape = DirectFB_ResizeWindowShape;
154
155 device->free = DirectFB_DeleteDevice;
156
157 return device;
158 error:
159 if (device)
160 SDL_free(device);
161 return (0);
162 }
163
164 static void
DirectFB_DeviceInformation(IDirectFB * dfb)165 DirectFB_DeviceInformation(IDirectFB * dfb)
166 {
167 DFBGraphicsDeviceDescription desc;
168 int n;
169
170 dfb->GetDeviceDescription(dfb, &desc);
171
172 SDL_DFB_LOG( "DirectFB Device Information");
173 SDL_DFB_LOG( "===========================");
174 SDL_DFB_LOG( "Name: %s", desc.name);
175 SDL_DFB_LOG( "Vendor: %s", desc.vendor);
176 SDL_DFB_LOG( "Driver Name: %s", desc.driver.name);
177 SDL_DFB_LOG( "Driver Vendor: %s", desc.driver.vendor);
178 SDL_DFB_LOG( "Driver Version: %d.%d", desc.driver.major,
179 desc.driver.minor);
180
181 SDL_DFB_LOG( "Video memoory: %d", desc.video_memory);
182
183 SDL_DFB_LOG( "Blitting flags:");
184 for (n = 0; blitting_flags[n].flag; n++) {
185 if (desc.blitting_flags & blitting_flags[n].flag)
186 SDL_DFB_LOG( " %s", blitting_flags[n].name);
187 }
188
189 SDL_DFB_LOG( "Drawing flags:");
190 for (n = 0; drawing_flags[n].flag; n++) {
191 if (desc.drawing_flags & drawing_flags[n].flag)
192 SDL_DFB_LOG( " %s", drawing_flags[n].name);
193 }
194
195
196 SDL_DFB_LOG( "Acceleration flags:");
197 for (n = 0; acceleration_mask[n].mask; n++) {
198 if (desc.acceleration_mask & acceleration_mask[n].mask)
199 SDL_DFB_LOG( " %s", acceleration_mask[n].name);
200 }
201
202
203 }
204
readBoolEnv(const char * env_name,int def_val)205 static int readBoolEnv(const char *env_name, int def_val)
206 {
207 char *stemp;
208
209 stemp = SDL_getenv(env_name);
210 if (stemp)
211 return atoi(stemp);
212 else
213 return def_val;
214 }
215
216 static int
DirectFB_VideoInit(_THIS)217 DirectFB_VideoInit(_THIS)
218 {
219 IDirectFB *dfb = NULL;
220 DFB_DeviceData *devdata = NULL;
221 DFBResult ret;
222
223 SDL_DFB_ALLOC_CLEAR(devdata, sizeof(*devdata));
224
225 SDL_DFB_CHECKERR(DirectFBInit(NULL, NULL));
226
227 /* avoid switching to the framebuffer when we
228 * are running X11 */
229 ret = readBoolEnv(DFBENV_USE_X11_CHECK , 1);
230 if (ret) {
231 if (SDL_getenv("DISPLAY"))
232 DirectFBSetOption("system", "x11");
233 else
234 DirectFBSetOption("disable-module", "x11input");
235 }
236
237 /* FIXME: Reenable as default once multi kbd/mouse interface is sorted out */
238 devdata->use_linux_input = readBoolEnv(DFBENV_USE_LINUX_INPUT, 0); /* default: on */
239
240 if (!devdata->use_linux_input)
241 {
242 SDL_DFB_LOG("Disabling linux input\n");
243 DirectFBSetOption("disable-module", "linux_input");
244 }
245
246 SDL_DFB_CHECKERR(DirectFBCreate(&dfb));
247
248 DirectFB_DeviceInformation(dfb);
249
250 devdata->use_yuv_underlays = readBoolEnv(DFBENV_USE_YUV_UNDERLAY, 0); /* default: off */
251 devdata->use_yuv_direct = readBoolEnv(DFBENV_USE_YUV_DIRECT, 0); /* default is off! */
252
253 /* Create global Eventbuffer for axis events */
254 if (devdata->use_linux_input) {
255 SDL_DFB_CHECKERR(dfb->CreateInputEventBuffer(dfb, DICAPS_ALL,
256 DFB_TRUE,
257 &devdata->events));
258 } else {
259 SDL_DFB_CHECKERR(dfb->CreateInputEventBuffer(dfb, DICAPS_AXES
260 /* DICAPS_ALL */ ,
261 DFB_TRUE,
262 &devdata->events));
263 }
264
265 /* simple window manager support */
266 devdata->has_own_wm = readBoolEnv(DFBENV_USE_WM, 0);
267
268 devdata->initialized = 1;
269
270 devdata->dfb = dfb;
271 devdata->firstwin = NULL;
272 devdata->grabbed_window = NULL;
273
274 _this->driverdata = devdata;
275
276 DirectFB_InitModes(_this);
277
278 #if SDL_DIRECTFB_OPENGL
279 DirectFB_GL_Initialize(_this);
280 #endif
281
282 DirectFB_InitMouse(_this);
283 DirectFB_InitKeyboard(_this);
284
285 return 0;
286
287
288 error:
289 SDL_DFB_FREE(devdata);
290 SDL_DFB_RELEASE(dfb);
291 return -1;
292 }
293
294 static void
DirectFB_VideoQuit(_THIS)295 DirectFB_VideoQuit(_THIS)
296 {
297 DFB_DeviceData *devdata = (DFB_DeviceData *) _this->driverdata;
298
299 DirectFB_QuitModes(_this);
300 DirectFB_QuitKeyboard(_this);
301 DirectFB_QuitMouse(_this);
302
303 devdata->events->Reset(devdata->events);
304 SDL_DFB_RELEASE(devdata->events);
305 SDL_DFB_RELEASE(devdata->dfb);
306
307 #if SDL_DIRECTFB_OPENGL
308 DirectFB_GL_Shutdown(_this);
309 #endif
310
311 devdata->initialized = 0;
312 }
313
314 /* DirectFB driver general support functions */
315
316 static const struct {
317 DFBSurfacePixelFormat dfb;
318 Uint32 sdl;
319 } pixelformat_tab[] =
320 {
321 { DSPF_RGB32, SDL_PIXELFORMAT_RGB888 }, /* 24 bit RGB (4 byte, nothing@24, red 8@16, green 8@8, blue 8@0) */
322 { DSPF_ARGB, SDL_PIXELFORMAT_ARGB8888 }, /* 32 bit ARGB (4 byte, alpha 8@24, red 8@16, green 8@8, blue 8@0) */
323 { DSPF_RGB16, SDL_PIXELFORMAT_RGB565 }, /* 16 bit RGB (2 byte, red 5@11, green 6@5, blue 5@0) */
324 { DSPF_RGB332, SDL_PIXELFORMAT_RGB332 }, /* 8 bit RGB (1 byte, red 3@5, green 3@2, blue 2@0) */
325 { DSPF_ARGB4444, SDL_PIXELFORMAT_ARGB4444 }, /* 16 bit ARGB (2 byte, alpha 4@12, red 4@8, green 4@4, blue 4@0) */
326 { DSPF_ARGB1555, SDL_PIXELFORMAT_ARGB1555 }, /* 16 bit ARGB (2 byte, alpha 1@15, red 5@10, green 5@5, blue 5@0) */
327 { DSPF_RGB24, SDL_PIXELFORMAT_RGB24 }, /* 24 bit RGB (3 byte, red 8@16, green 8@8, blue 8@0) */
328 { DSPF_RGB444, SDL_PIXELFORMAT_RGB444 }, /* 16 bit RGB (2 byte, nothing @12, red 4@8, green 4@4, blue 4@0) */
329 { DSPF_YV12, SDL_PIXELFORMAT_YV12 }, /* 12 bit YUV (8 bit Y plane followed by 8 bit quarter size V/U planes) */
330 { DSPF_I420,SDL_PIXELFORMAT_IYUV }, /* 12 bit YUV (8 bit Y plane followed by 8 bit quarter size U/V planes) */
331 { DSPF_YUY2, SDL_PIXELFORMAT_YUY2 }, /* 16 bit YUV (4 byte/ 2 pixel, macropixel contains CbYCrY [31:0]) */
332 { DSPF_UYVY, SDL_PIXELFORMAT_UYVY }, /* 16 bit YUV (4 byte/ 2 pixel, macropixel contains YCbYCr [31:0]) */
333 { DSPF_RGB555, SDL_PIXELFORMAT_RGB555 }, /* 16 bit RGB (2 byte, nothing @15, red 5@10, green 5@5, blue 5@0) */
334 #if (ENABLE_LUT8)
335 { DSPF_LUT8, SDL_PIXELFORMAT_INDEX8 }, /* 8 bit LUT (8 bit color and alpha lookup from palette) */
336 #endif
337
338 #if (DFB_VERSION_ATLEAST(1,2,0))
339 { DSPF_BGR555, SDL_PIXELFORMAT_BGR555 }, /* 16 bit BGR (2 byte, nothing @15, blue 5@10, green 5@5, red 5@0) */
340 #else
341 { DSPF_UNKNOWN, SDL_PIXELFORMAT_BGR555 },
342 #endif
343
344 /* Pfff ... nonmatching formats follow */
345
346 { DSPF_ALUT44, SDL_PIXELFORMAT_UNKNOWN }, /* 8 bit ALUT (1 byte, alpha 4@4, color lookup 4@0) */
347 { DSPF_A8, SDL_PIXELFORMAT_UNKNOWN }, /* 8 bit alpha (1 byte, alpha 8@0), e.g. anti-aliased glyphs */
348 { DSPF_AiRGB, SDL_PIXELFORMAT_UNKNOWN }, /* 32 bit ARGB (4 byte, inv. alpha 8@24, red 8@16, green 8@8, blue 8@0) */
349 { DSPF_A1, SDL_PIXELFORMAT_UNKNOWN }, /* 1 bit alpha (1 byte/ 8 pixel, most significant bit used first) */
350 { DSPF_NV12, SDL_PIXELFORMAT_UNKNOWN }, /* 12 bit YUV (8 bit Y plane followed by one 16 bit quarter size CbCr [15:0] plane) */
351 { DSPF_NV16, SDL_PIXELFORMAT_UNKNOWN }, /* 16 bit YUV (8 bit Y plane followed by one 16 bit half width CbCr [15:0] plane) */
352 { DSPF_ARGB2554, SDL_PIXELFORMAT_UNKNOWN }, /* 16 bit ARGB (2 byte, alpha 2@14, red 5@9, green 5@4, blue 4@0) */
353 { DSPF_NV21, SDL_PIXELFORMAT_UNKNOWN }, /* 12 bit YUV (8 bit Y plane followed by one 16 bit quarter size CrCb [15:0] plane) */
354 { DSPF_AYUV, SDL_PIXELFORMAT_UNKNOWN }, /* 32 bit AYUV (4 byte, alpha 8@24, Y 8@16, Cb 8@8, Cr 8@0) */
355 { DSPF_A4, SDL_PIXELFORMAT_UNKNOWN }, /* 4 bit alpha (1 byte/ 2 pixel, more significant nibble used first) */
356 { DSPF_ARGB1666, SDL_PIXELFORMAT_UNKNOWN }, /* 1 bit alpha (3 byte/ alpha 1@18, red 6@16, green 6@6, blue 6@0) */
357 { DSPF_ARGB6666, SDL_PIXELFORMAT_UNKNOWN }, /* 6 bit alpha (3 byte/ alpha 6@18, red 6@16, green 6@6, blue 6@0) */
358 { DSPF_RGB18, SDL_PIXELFORMAT_UNKNOWN }, /* 6 bit RGB (3 byte/ red 6@16, green 6@6, blue 6@0) */
359 { DSPF_LUT2, SDL_PIXELFORMAT_UNKNOWN }, /* 2 bit LUT (1 byte/ 4 pixel, 2 bit color and alpha lookup from palette) */
360
361 #if (DFB_VERSION_ATLEAST(1,3,0))
362 { DSPF_RGBA4444, SDL_PIXELFORMAT_UNKNOWN }, /* 16 bit RGBA (2 byte, red 4@12, green 4@8, blue 4@4, alpha 4@0) */
363 #endif
364
365 #if (DFB_VERSION_ATLEAST(1,4,3))
366 { DSPF_RGBA5551, SDL_PIXELFORMAT_UNKNOWN }, /* 16 bit RGBA (2 byte, red 5@11, green 5@6, blue 5@1, alpha 1@0) */
367 { DSPF_YUV444P, SDL_PIXELFORMAT_UNKNOWN }, /* 24 bit full YUV planar (8 bit Y plane followed by an 8 bit Cb and an 8 bit Cr plane) */
368 { DSPF_ARGB8565, SDL_PIXELFORMAT_UNKNOWN }, /* 24 bit ARGB (3 byte, alpha 8@16, red 5@11, green 6@5, blue 5@0) */
369 { DSPF_AVYU, SDL_PIXELFORMAT_UNKNOWN }, /* 32 bit AVYU 4:4:4 (4 byte, alpha 8@24, Cr 8@16, Y 8@8, Cb 8@0) */
370 { DSPF_VYU, SDL_PIXELFORMAT_UNKNOWN }, /* 24 bit VYU 4:4:4 (3 byte, Cr 8@16, Y 8@8, Cb 8@0) */
371 #endif
372
373 { DSPF_UNKNOWN, SDL_PIXELFORMAT_INDEX1LSB },
374 { DSPF_UNKNOWN, SDL_PIXELFORMAT_INDEX1MSB },
375 { DSPF_UNKNOWN, SDL_PIXELFORMAT_INDEX4LSB },
376 { DSPF_UNKNOWN, SDL_PIXELFORMAT_INDEX4MSB },
377 { DSPF_UNKNOWN, SDL_PIXELFORMAT_BGR24 },
378 { DSPF_UNKNOWN, SDL_PIXELFORMAT_BGR888 },
379 { DSPF_UNKNOWN, SDL_PIXELFORMAT_RGBA8888 },
380 { DSPF_UNKNOWN, SDL_PIXELFORMAT_ABGR8888 },
381 { DSPF_UNKNOWN, SDL_PIXELFORMAT_BGRA8888 },
382 { DSPF_UNKNOWN, SDL_PIXELFORMAT_ARGB2101010 },
383 { DSPF_UNKNOWN, SDL_PIXELFORMAT_ABGR4444 },
384 { DSPF_UNKNOWN, SDL_PIXELFORMAT_ABGR1555 },
385 { DSPF_UNKNOWN, SDL_PIXELFORMAT_BGR565 },
386 { DSPF_UNKNOWN, SDL_PIXELFORMAT_YVYU }, /**< Packed mode: Y0+V0+Y1+U0 (1 pla */
387 };
388
389 Uint32
DirectFB_DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat)390 DirectFB_DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat)
391 {
392 int i;
393
394 for (i=0; pixelformat_tab[i].dfb != DSPF_UNKNOWN; i++)
395 if (pixelformat_tab[i].dfb == pixelformat)
396 {
397 return pixelformat_tab[i].sdl;
398 }
399 return SDL_PIXELFORMAT_UNKNOWN;
400 }
401
402 DFBSurfacePixelFormat
DirectFB_SDLToDFBPixelFormat(Uint32 format)403 DirectFB_SDLToDFBPixelFormat(Uint32 format)
404 {
405 int i;
406
407 for (i=0; pixelformat_tab[i].dfb != DSPF_UNKNOWN; i++)
408 if (pixelformat_tab[i].sdl == format)
409 {
410 return pixelformat_tab[i].dfb;
411 }
412 return DSPF_UNKNOWN;
413 }
414
DirectFB_SetSupportedPixelFormats(SDL_RendererInfo * ri)415 void DirectFB_SetSupportedPixelFormats(SDL_RendererInfo* ri)
416 {
417 int i, j;
418
419 for (i=0, j=0; pixelformat_tab[i].dfb != DSPF_UNKNOWN; i++)
420 if (pixelformat_tab[i].sdl != SDL_PIXELFORMAT_UNKNOWN)
421 ri->texture_formats[j++] = pixelformat_tab[i].sdl;
422 ri->num_texture_formats = j;
423 }
424
425 #endif /* SDL_VIDEO_DRIVER_DIRECTFB */
426