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