Commit 8b3eb38d authored by Sam Lantinga's avatar Sam Lantinga

Updated the DirectFB support, from Couriersud

attached is a working directfb driver diff which works with the current
changes. There are a number of changes around it as well, e.g.
configure.in.

The directfb renderdriver right now still depends on a some "includes"
from src/video/directfb. That's why it is not yet moved to the new
render folder.
parent d1f0fa42
...@@ -71,9 +71,9 @@ works at least on all directfb supported platforms. ...@@ -71,9 +71,9 @@ works at least on all directfb supported platforms.
As of this writing 20100802 you need to pull Mesa from git and do the following: As of this writing 20100802 you need to pull Mesa from git and do the following:
------------------------ ------------------------
git checkout 2c9fdaf7292423c157fc79b5ce43f0f199dd753a
cd mesa
git clone git://anongit.freedesktop.org/git/mesa/mesa git clone git://anongit.freedesktop.org/git/mesa/mesa
cd mesa
git checkout 2c9fdaf7292423c157fc79b5ce43f0f199dd753a
------------------------ ------------------------
Edit configs/linux-directfb so that the Directories-section looks like Edit configs/linux-directfb so that the Directories-section looks like
......
...@@ -1312,8 +1312,7 @@ AC_HELP_STRING([--enable-video-directfb], [use DirectFB video driver [[default=n ...@@ -1312,8 +1312,7 @@ AC_HELP_STRING([--enable-video-directfb], [use DirectFB video driver [[default=n
video_directfb=no video_directfb=no
DIRECTFB_REQUIRED_VERSION=1.0.0 DIRECTFB_REQUIRED_VERSION=1.0.0
AC_PATH_PROGS(DIRECTFBCONFIG, directfb-config, no, [$prefix/bin:$PATH])
AC_PATH_PROG(DIRECTFBCONFIG, directfb-config, no)
if test x$DIRECTFBCONFIG = xno; then if test x$DIRECTFBCONFIG = xno; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no) AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
if test x$PKG_CONFIG != xno; then if test x$PKG_CONFIG != xno; then
...@@ -1353,13 +1352,15 @@ AC_HELP_STRING([--enable-directfb-shared], [dynamically load directfb support [[ ...@@ -1353,13 +1352,15 @@ AC_HELP_STRING([--enable-directfb-shared], [dynamically load directfb support [[
, enable_directfb_shared=yes) , enable_directfb_shared=yes)
AC_DEFINE(SDL_VIDEO_DRIVER_DIRECTFB) AC_DEFINE(SDL_VIDEO_DRIVER_DIRECTFB)
AC_DEFINE(SDL_VIDEO_RENDER_DIRECTFB)
SOURCES="$SOURCES $srcdir/src/video/directfb/*.c" SOURCES="$SOURCES $srcdir/src/video/directfb/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $DIRECTFB_CFLAGS" EXTRA_CFLAGS="$EXTRA_CFLAGS $DIRECTFB_CFLAGS"
AC_MSG_CHECKING(for directfb dynamic loading support) AC_MSG_CHECKING(for directfb dynamic loading support)
directfb_shared=no directfb_shared=no
directfb_lib=[`find_lib "libdirectfb.so.*" "$DIRECTFB_LIBS" | sed 's/.*\/\(.*\)/\1/; q'`] directfb_lib=[`find_lib "libdirectfb.so.*" "$DIRECTFB_LIBS"`]
# | sed 's/.*\/\(.*\)/\1/; q'`]
AC_MSG_WARN("directfb $directfb_lib")
if test x$have_loadso != xyes && \ if test x$have_loadso != xyes && \
test x$enable_directfb_shared = xyes; then test x$enable_directfb_shared = xyes; then
AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic directfb loading]) AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic directfb loading])
......
...@@ -279,6 +279,7 @@ ...@@ -279,6 +279,7 @@
#undef SDL_VIDEO_RENDER_D3D #undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_OGL #undef SDL_VIDEO_RENDER_OGL
#undef SDL_VIDEO_RENDER_OGL_ES #undef SDL_VIDEO_RENDER_OGL_ES
#undef SDL_VIDEO_RENDER_DIRECTFB
/* Enable OpenGL support */ /* Enable OpenGL support */
#undef SDL_VIDEO_OPENGL #undef SDL_VIDEO_OPENGL
......
...@@ -77,7 +77,7 @@ struct SDL_SysWMinfo; ...@@ -77,7 +77,7 @@ struct SDL_SysWMinfo;
#endif /* defined(SDL_VIDEO_DRIVER_X11) */ #endif /* defined(SDL_VIDEO_DRIVER_X11) */
#if defined(SDL_VIDEO_DRIVER_DIRECTFB) #if defined(SDL_VIDEO_DRIVER_DIRECTFB)
#include <directfb/directfb.h> #include <directfb.h>
#endif #endif
#if defined(SDL_VIDEO_DRIVER_COCOA) #if defined(SDL_VIDEO_DRIVER_COCOA)
......
...@@ -52,6 +52,9 @@ static const SDL_RenderDriver *render_drivers[] = { ...@@ -52,6 +52,9 @@ static const SDL_RenderDriver *render_drivers[] = {
#endif #endif
#if SDL_VIDEO_RENDER_OGL_ES #if SDL_VIDEO_RENDER_OGL_ES
&GL_ES_RenderDriver, &GL_ES_RenderDriver,
#endif
#if SDL_VIDEO_RENDER_DIRECTFB
&DirectFB_RenderDriver,
#endif #endif
&SW_RenderDriver &SW_RenderDriver
}; };
......
...@@ -127,6 +127,9 @@ extern SDL_RenderDriver GL_RenderDriver; ...@@ -127,6 +127,9 @@ extern SDL_RenderDriver GL_RenderDriver;
#if SDL_VIDEO_RENDER_OGL_ES #if SDL_VIDEO_RENDER_OGL_ES
extern SDL_RenderDriver GL_ES_RenderDriver; extern SDL_RenderDriver GL_ES_RenderDriver;
#endif #endif
#if SDL_VIDEO_RENDER_DIRECTFB
extern SDL_RenderDriver DirectFB_RenderDriver;
#endif
extern SDL_RenderDriver SW_RenderDriver; extern SDL_RenderDriver SW_RenderDriver;
#endif /* _SDL_sysrender_h */ #endif /* _SDL_sysrender_h */
......
...@@ -18,14 +18,13 @@ ...@@ -18,14 +18,13 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
*/
#include "SDL_config.h"
//#include "SDL_syswm.h" SDL1.3 DirectFB driver by couriersud@arcor.de
//#include "../SDL_sysvideo.h"
//#include "../../events/SDL_keyboard_c.h" */
#include "SDL_DirectFB_video.h" #include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_window.h"
#include "../../events/SDL_windowevents_c.h" #include "../../events/SDL_windowevents_c.h"
...@@ -127,6 +126,11 @@ DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window) ...@@ -127,6 +126,11 @@ DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window)
if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN)) if (!windata->is_managed || (window->flags & SDL_WINDOW_FULLSCREEN))
return; return;
SDL_DFB_CHECK(s->SetSrcBlendFunction(s, DSBF_ONE));
SDL_DFB_CHECK(s->SetDstBlendFunction(s, DSBF_ZERO));
SDL_DFB_CHECK(s->SetDrawingFlags(s, DSDRAW_NOFX));
SDL_DFB_CHECK(s->SetBlittingFlags(s, DSBLIT_NOFX));
LoadFont(_this, window); LoadFont(_this, window);
//s->SetDrawingFlags(s, DSDRAW_BLEND); //s->SetDrawingFlags(s, DSDRAW_BLEND);
s->SetColor(s, COLOR_EXPAND(t->frame_color)); s->SetColor(s, COLOR_EXPAND(t->frame_color));
...@@ -181,8 +185,10 @@ DFBResult ...@@ -181,8 +185,10 @@ DFBResult
DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch) DirectFB_WM_GetClientSize(_THIS, SDL_Window * window, int *cw, int *ch)
{ {
SDL_DFB_WINDOWDATA(window); SDL_DFB_WINDOWDATA(window);
IDirectFBWindow *dfbwin = windata->dfbwin;
SDL_DFB_CHECK(windata->window->GetSize(windata->window, cw, ch)); SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, cw, ch));
dfbwin->GetSize(dfbwin, cw, ch);
*cw -= windata->theme.left_size + windata->theme.right_size; *cw -= windata->theme.left_size + windata->theme.right_size;
*ch -= *ch -=
windata->theme.top_size + windata->theme.caption_size + windata->theme.top_size + windata->theme.caption_size +
...@@ -197,6 +203,9 @@ DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h) ...@@ -197,6 +203,9 @@ DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h)
if (!windata->is_managed) if (!windata->is_managed)
windata->theme = theme_none; windata->theme = theme_none;
else if (flags & SDL_WINDOW_BORDERLESS)
//desc.caps |= DWCAPS_NODECORATION;)
windata->theme = theme_none;
else if (flags & SDL_WINDOW_FULLSCREEN) { else if (flags & SDL_WINDOW_FULLSCREEN) {
windata->theme = theme_none; windata->theme = theme_none;
} else if (flags & SDL_WINDOW_MAXIMIZED) { } else if (flags & SDL_WINDOW_MAXIMIZED) {
...@@ -220,37 +229,6 @@ DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h) ...@@ -220,37 +229,6 @@ DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h)
windata->theme.caption_size + windata->theme.bottom_size; windata->theme.caption_size + windata->theme.bottom_size;
} }
void
DirectFB_WM_MaximizeWindow(_THIS, SDL_Window * window)
{
SDL_DFB_WINDOWDATA(window);
SDL_VideoDisplay *display = window->display;
SDL_DFB_CHECK(windata->window->GetPosition(windata->window,
&windata->restore.x, &windata->restore.y));
SDL_DFB_CHECK(windata->window->GetSize(windata->window, &windata->restore.w,
&windata->restore.h));
DirectFB_WM_AdjustWindowLayout(window, window->flags | SDL_WINDOW_MAXIMIZED, display->current_mode.w, display->current_mode.h) ;
SDL_DFB_CHECK(windata->window->MoveTo(windata->window, 0, 0));
SDL_DFB_CHECK(windata->window->Resize(windata->window,
display->current_mode.w, display->current_mode.h));
}
void
DirectFB_WM_RestoreWindow(_THIS, SDL_Window * window)
{
SDL_DFB_WINDOWDATA(window);
DirectFB_WM_AdjustWindowLayout(window, window->flags & ~(SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED),
windata->restore.w, windata->restore.h);
SDL_DFB_CHECK(windata->window->Resize(windata->window, windata->restore.w,
windata->restore.h));
SDL_DFB_CHECK(windata->window->MoveTo(windata->window, windata->restore.x,
windata->restore.y));
}
enum enum
{ {
...@@ -307,20 +285,20 @@ WMPos(DFB_WindowData * p, int x, int y) ...@@ -307,20 +285,20 @@ WMPos(DFB_WindowData * p, int x, int y)
return pos; return pos;
} }
static int wm_grab;
static int wm_lastx;
static int wm_lasty;
int int
DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt) DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
{ {
SDL_DFB_DEVICEDATA(_this); SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window); SDL_DFB_WINDOWDATA(window);
DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL); DFB_WindowData *gwindata = ((devdata->grabbed_window) ? (DFB_WindowData *) ((devdata->grabbed_window)->driverdata) : NULL);
IDirectFBWindow *dfbwin = windata->dfbwin;
DFBWindowOptions wopts;
if (!windata->is_managed) if (!windata->is_managed)
return 0; return 0;
SDL_DFB_CHECK(dfbwin->GetOptions(dfbwin, &wopts));
switch (evt->type) { switch (evt->type) {
case DWET_BUTTONDOWN: case DWET_BUTTONDOWN:
if (evt->buttons & DIBM_LEFT) { if (evt->buttons & DIBM_LEFT) {
...@@ -329,59 +307,99 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt) ...@@ -329,59 +307,99 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
case WM_POS_NONE: case WM_POS_NONE:
return 0; return 0;
case WM_POS_CLOSE: case WM_POS_CLOSE:
wm_grab = WM_POS_NONE; windata->wm_grab = WM_POS_NONE;
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0, SDL_SendWindowEvent(window, SDL_WINDOWEVENT_CLOSE, 0,
0); 0);
return 1; return 1;
case WM_POS_MAX: case WM_POS_MAX:
wm_grab = WM_POS_NONE; windata->wm_grab = WM_POS_NONE;
if (window->flags & SDL_WINDOW_MAXIMIZED) { if (window->flags & SDL_WINDOW_MAXIMIZED) {
SDL_RestoreWindow(window); SDL_RestoreWindow(window);
} else { } else {
SDL_MaximizeWindow(window); SDL_MaximizeWindow(window);
} }
return 1; return 1;
case WM_POS_CAPTION: case WM_POS_CAPTION:
DirectFB_RaiseWindow(_this, window); if (!(wopts & DWOP_KEEP_STACKING)) {
DirectFB_RaiseWindow(_this, window);
}
if (window->flags & SDL_WINDOW_MAXIMIZED)
return 1;
/* fall through */ /* fall through */
default: default:
wm_grab = pos; windata->wm_grab = pos;
if (gwindata != NULL) if (gwindata != NULL)
SDL_DFB_CHECK(gwindata->window->UngrabPointer(gwindata->window)); SDL_DFB_CHECK(gwindata->dfbwin->UngrabPointer(gwindata->dfbwin));
SDL_DFB_CHECK(windata->window->GrabPointer(windata->window)); SDL_DFB_CHECK(dfbwin->GrabPointer(dfbwin));
wm_lastx = evt->cx; windata->wm_lastx = evt->cx;
wm_lasty = evt->cy; windata->wm_lasty = evt->cy;
} }
} }
return 1; return 1;
case DWET_BUTTONUP: case DWET_BUTTONUP:
if (!windata->wm_grab)
return 0;
if (!(evt->buttons & DIBM_LEFT)) {
if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
int dx = evt->cx - windata->wm_lastx;
int dy = evt->cy - windata->wm_lasty;
if (!(wopts & DWOP_KEEP_SIZE)) {
int cw, ch;
if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
dx = 0;
else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
dy = 0;
SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
/* necessary to trigger an event - ugly*/
SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx + 1, ch + dy));
SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
}
}
SDL_DFB_CHECK(dfbwin->UngrabPointer(dfbwin));
if (gwindata != NULL)
SDL_DFB_CHECK(gwindata->dfbwin->GrabPointer(gwindata->dfbwin));
windata->wm_grab = WM_POS_NONE;
return 1;
}
break; break;
case DWET_MOTION: case DWET_MOTION:
if (!wm_grab) if (!windata->wm_grab)
return 0; return 0;
if (evt->buttons & DIBM_LEFT) { if (evt->buttons & DIBM_LEFT) {
int dx = evt->cx - wm_lastx; int dx = evt->cx - windata->wm_lastx;
int dy = evt->cy - wm_lasty; int dy = evt->cy - windata->wm_lasty;
int cw, ch;
if (windata->wm_grab & WM_POS_CAPTION) {
if (wm_grab & WM_POS_CAPTION) if (!(wopts & DWOP_KEEP_POSITION))
SDL_DFB_CHECK(windata->window->Move(windata->window, dx, dy)); SDL_DFB_CHECK(dfbwin->Move(dfbwin, dx, dy));
if (wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
if ((wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
dx = 0;
else if ((wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
dy = 0;
SDL_DFB_CHECK(windata->window->GetSize(windata->window, &cw, &ch));
SDL_DFB_CHECK(windata->window->Resize(windata->window, cw + dx, ch + dy));
} }
wm_lastx = evt->cx; if (windata->wm_grab & (WM_POS_RIGHT | WM_POS_BOTTOM)) {
wm_lasty = evt->cy; if (!(wopts & DWOP_KEEP_SIZE)) {
return 1; int cw, ch;
/* Make sure all events are disabled for this operation ! */
SDL_DFB_CHECK(dfbwin->DisableEvents(dfbwin, DWET_ALL));
if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_BOTTOM)
dx = 0;
else if ((windata->wm_grab & (WM_POS_BOTTOM | WM_POS_RIGHT)) == WM_POS_RIGHT)
dy = 0;
SDL_DFB_CHECK(dfbwin->GetSize(dfbwin, &cw, &ch));
SDL_DFB_CHECK(dfbwin->Resize(dfbwin, cw + dx, ch + dy));
SDL_DFB_CHECK(dfbwin->EnableEvents(dfbwin, DWET_ALL));
}
}
windata->wm_lastx = evt->cx;
windata->wm_lasty = evt->cy;
return 1;
} }
SDL_DFB_CHECK(windata->window->UngrabPointer(windata->window));
if (gwindata != NULL)
SDL_DFB_CHECK(gwindata->window->GrabPointer(gwindata->window));
wm_grab = WM_POS_NONE;
break; break;
case DWET_KEYDOWN: case DWET_KEYDOWN:
break; break;
...@@ -392,3 +410,4 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt) ...@@ -392,3 +410,4 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
} }
return 0; return 0;
} }
...@@ -18,12 +18,16 @@ ...@@ -18,12 +18,16 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#ifndef _SDL_directfb_wm_h #ifndef _SDL_directfb_wm_h
#define _SDL_directfb_wm_h #define _SDL_directfb_wm_h
#include "SDL_DirectFB_video.h"
typedef struct _DFB_Theme DFB_Theme; typedef struct _DFB_Theme DFB_Theme;
struct _DFB_Theme struct _DFB_Theme
{ {
...@@ -42,8 +46,6 @@ struct _DFB_Theme ...@@ -42,8 +46,6 @@ struct _DFB_Theme
}; };
extern void DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h); extern void DirectFB_WM_AdjustWindowLayout(SDL_Window * window, int flags, int w, int h);
extern void DirectFB_WM_MaximizeWindow(_THIS, SDL_Window * window);
extern void DirectFB_WM_RestoreWindow(_THIS, SDL_Window * window);
extern void DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window); extern void DirectFB_WM_RedrawLayout(_THIS, SDL_Window * window);
extern int DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, extern int DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window,
......
...@@ -18,7 +18,11 @@ ...@@ -18,7 +18,11 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h" #include "SDL_config.h"
#include "SDL_DirectFB_video.h" #include "SDL_DirectFB_video.h"
...@@ -41,6 +45,7 @@ static struct _SDL_DirectFB_Symbols ...@@ -41,6 +45,7 @@ static struct _SDL_DirectFB_Symbols
#define DFB_SYM(ret, name, args, al, func) ret name args { func SDL_DirectFB_Symbols.name al ; } #define DFB_SYM(ret, name, args, al, func) ret name args { func SDL_DirectFB_Symbols.name al ; }
DFB_SYMS DFB_SYMS
#undef DFB_SYM #undef DFB_SYM
static void *handle = NULL; static void *handle = NULL;
int int
...@@ -55,7 +60,7 @@ SDL_DirectFB_LoadLibrary(void) ...@@ -55,7 +60,7 @@ SDL_DirectFB_LoadLibrary(void)
#define DFB_SYM(ret, name, args, al, func) if (!(SDL_DirectFB_Symbols.name = SDL_LoadFunction(handle, # name))) retval = 0; #define DFB_SYM(ret, name, args, al, func) if (!(SDL_DirectFB_Symbols.name = SDL_LoadFunction(handle, # name))) retval = 0;
DFB_SYMS DFB_SYMS
#undef DFB_SYM #undef DFB_SYM
if (! if (!
(SDL_DirectFB_Symbols.directfb_major_version = (SDL_DirectFB_Symbols.directfb_major_version =
SDL_LoadFunction(handle, "directfb_major_version"))) SDL_LoadFunction(handle, "directfb_major_version")))
retval = 0; retval = 0;
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#ifndef _SDL_DirectFB_dyn_h #ifndef _SDL_DirectFB_dyn_h
...@@ -33,7 +36,6 @@ ...@@ -33,7 +36,6 @@
DFB_SYM(DFBResult, DirectFBCreate, (IDirectFB **interface), (interface), return) \ DFB_SYM(DFBResult, DirectFBCreate, (IDirectFB **interface), (interface), return) \
DFB_SYM(const char *, DirectFBCheckVersion, (unsigned int required_major, unsigned int required_minor, unsigned int required_micro), \ DFB_SYM(const char *, DirectFBCheckVersion, (unsigned int required_major, unsigned int required_minor, unsigned int required_micro), \
(required_major, required_minor, required_micro), return) (required_major, required_minor, required_micro), return)
// #define SDL_VIDEO_DRIVER_DIRECTFB_DYNAMIC "/usr/lib/libdirectfb-1.2.so.0"
int SDL_DirectFB_LoadLibrary(void); int SDL_DirectFB_LoadLibrary(void);
void SDL_DirectFB_UnLoadLibrary(void); void SDL_DirectFB_UnLoadLibrary(void);
......
This diff is collapsed.
...@@ -18,13 +18,19 @@ ...@@ -18,13 +18,19 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#include "SDL_DirectFB_video.h" #ifndef _SDL_DirectFB_events_h
#define _SDL_DirectFB_events_h
#include "../SDL_sysvideo.h"
/* Functions to be exported */ /* Functions to be exported */
extern void DirectFB_InitKeyboard(_THIS); extern void DirectFB_InitKeyboard(_THIS);
extern void DirectFB_QuitKeyboard(_THIS); extern void DirectFB_QuitKeyboard(_THIS);
extern void DirectFB_PumpEventsWindow(_THIS); extern void DirectFB_PumpEventsWindow(_THIS);
extern SDLKey DirectFB_GetLayoutKey(_THIS, SDLKey physicalKey);
#endif
This diff is collapsed.
...@@ -18,32 +18,36 @@ ...@@ -18,32 +18,36 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#ifndef _SDL_directfb_modes_h #ifndef _SDL_directfb_modes_h
#define _SDL_directfb_modes_h #define _SDL_directfb_modes_h
#include "SDL_DirectFB_video.h" #include <directfb.h>
#include "../SDL_sysvideo.h"
#define SDL_DFB_DISPLAYDATA(dev, win) DFB_DisplayData *dispdata = ((win && dev) ? (DFB_DisplayData *) (win)->display->driverdata : NULL) #define SDL_DFB_DISPLAYDATA(win) DFB_DisplayData *dispdata = ((win) ? (DFB_DisplayData *) (win)->display->driverdata : NULL)
typedef struct _DFB_DisplayData DFB_DisplayData; typedef struct _DFB_DisplayData DFB_DisplayData;
struct _DFB_DisplayData struct _DFB_DisplayData
{ {
IDirectFBDisplayLayer *layer; IDirectFBDisplayLayer *layer;
DFBSurfacePixelFormat pixelformat; DFBSurfacePixelFormat pixelformat;
/* FIXME: support for multiple video layer. /* FIXME: support for multiple video layer.
* However, I do not know any card supporting * However, I do not know any card supporting
* more than one * more than one
*/ */
DFBDisplayLayerID vidID; DFBDisplayLayerID vidID;
IDirectFBDisplayLayer *vidlayer; IDirectFBDisplayLayer *vidlayer;
int vidIDinuse; int vidIDinuse;
int cw; int cw;
int ch; int ch;
}; };
...@@ -52,6 +56,8 @@ extern void DirectFB_GetDisplayModes(_THIS, SDL_VideoDisplay * display); ...@@ -52,6 +56,8 @@ extern void DirectFB_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int DirectFB_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode); extern int DirectFB_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern void DirectFB_QuitModes(_THIS); extern void DirectFB_QuitModes(_THIS);
extern void DirectFB_SetContext(_THIS, SDL_Window *window);
#endif /* _SDL_directfb_modes_h */ #endif /* _SDL_directfb_modes_h */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
...@@ -18,7 +18,11 @@ ...@@ -18,7 +18,11 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h" #include "SDL_config.h"
#include "SDL_DirectFB_video.h" #include "SDL_DirectFB_video.h"
...@@ -123,8 +127,8 @@ DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y) ...@@ -123,8 +127,8 @@ DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
Uint32 *p; Uint32 *p;
int pitch, i; int pitch, i;
SDL_DFB_CALLOC(cursor, 1, sizeof(*cursor)); SDL_DFB_ALLOC_CLEAR(cursor, 1, sizeof(*cursor));
SDL_DFB_CALLOC(curdata, 1, sizeof(*curdata)); SDL_DFB_ALLOC_CLEAR(curdata, 1, sizeof(*curdata));
dsc.flags = dsc.flags =
DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS; DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
...@@ -175,7 +179,7 @@ DirectFB_ShowCursor(SDL_Cursor * cursor) ...@@ -175,7 +179,7 @@ DirectFB_ShowCursor(SDL_Cursor * cursor)
if (cursor) if (cursor)
SDL_DFB_CHECKERR(windata->window-> SDL_DFB_CHECKERR(windata->window->
SetCursorShape(windata->window, SetCursorShape(windata->dfbwin,
curdata->surf, curdata->hotx, curdata->surf, curdata->hotx,
curdata->hoty)); curdata->hoty));
...@@ -224,7 +228,7 @@ DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window, int x, int y) ...@@ -224,7 +228,7 @@ DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_Window * window, int x, int y)
DFBResult ret; DFBResult ret;
int cx, cy; int cx, cy;
SDL_DFB_CHECKERR(windata->window->GetPosition(windata->window, &cx, &cy)); SDL_DFB_CHECKERR(windata->dfbwin->GetPosition(windata->dfbwin, &cx, &cy));
SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer, SDL_DFB_CHECKERR(dispdata->layer->WarpCursor(dispdata->layer,
cx + x + windata->client.x, cx + x + windata->client.x,
cy + y + windata->client.y)); cy + y + windata->client.y));
...@@ -253,7 +257,6 @@ DirectFB_InitMouse(_THIS) ...@@ -253,7 +257,6 @@ DirectFB_InitMouse(_THIS)
void void
DirectFB_QuitMouse(_THIS) DirectFB_QuitMouse(_THIS)
{ {
//SDL_DFB_DEVICEDATA(_this);
} }
......
...@@ -18,19 +18,24 @@ ...@@ -18,19 +18,24 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#ifndef _SDL_DirectFB_mouse_h #ifndef _SDL_DirectFB_mouse_h
#define _SDL_DirectFB_mouse_h #define _SDL_DirectFB_mouse_h
typedef struct _DFB_CursorData DFB_CursorData; #include <directfb.h>
#include "../SDL_sysvideo.h"
typedef struct _DFB_CursorData DFB_CursorData;
struct _DFB_CursorData struct _DFB_CursorData
{ {
IDirectFBSurface *surf; IDirectFBSurface *surf;
int hotx; int hotx;
int hoty; int hoty;
}; };
#define SDL_DFB_CURSORDATA(curs) DFB_CursorData *curdata = (DFB_CursorData *) ((curs) ? (curs)->driverdata : NULL) #define SDL_DFB_CURSORDATA(curs) DFB_CursorData *curdata = (DFB_CursorData *) ((curs) ? (curs)->driverdata : NULL)
......
...@@ -13,16 +13,26 @@ ...@@ -13,16 +13,26 @@
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with _this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#include "SDL_DirectFB_video.h" #include "SDL_DirectFB_video.h"
#if SDL_DIRECTFB_OPENGL
#include "SDL_DirectFB_opengl.h"
#include "SDL_DirectFB_window.h"
#include <directfbgl.h>
#include "SDL_loadso.h"
#endif
#if SDL_DIRECTFB_OPENGL #if SDL_DIRECTFB_OPENGL
struct SDL_GLDriverData struct SDL_GLDriverData
...@@ -177,7 +187,7 @@ DirectFB_GL_CreateContext(_THIS, SDL_Window * window) ...@@ -177,7 +187,7 @@ DirectFB_GL_CreateContext(_THIS, SDL_Window * window)
SDL_DFB_WINDOWDATA(window); SDL_DFB_WINDOWDATA(window);
DirectFB_GLContext *context; DirectFB_GLContext *context;
SDL_DFB_CALLOC(context, 1, sizeof(DirectFB_GLContext)); SDL_DFB_ALLOC_CLEAR(context, sizeof(DirectFB_GLContext));
SDL_DFB_CHECKERR(windata->surface->GetGL(windata->surface, SDL_DFB_CHECKERR(windata->surface->GetGL(windata->surface,
&context->context)); &context->context));
......
...@@ -18,23 +18,29 @@ ...@@ -18,23 +18,29 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#ifndef _SDL_directfb_opengl_h #ifndef _SDL_directfb_opengl_h
#define _SDL_directfb_opengl_h #define _SDL_directfb_opengl_h
#include "SDL_DirectFB_video.h"
#if SDL_DIRECTFB_OPENGL #if SDL_DIRECTFB_OPENGL
#include "SDL_opengl.h" #include "SDL_opengl.h"
typedef struct _DirectFB_GLContext DirectFB_GLContext; typedef struct _DirectFB_GLContext DirectFB_GLContext;
struct _DirectFB_GLContext struct _DirectFB_GLContext
{ {
IDirectFBGL *context; IDirectFBGL *context;
DirectFB_GLContext *next; DirectFB_GLContext *next;
SDL_Window *sdl_window; SDL_Window *sdl_window;
int is_locked; int is_locked;
}; };
/* OpenGL functions */ /* OpenGL functions */
......
This diff is collapsed.
...@@ -18,13 +18,12 @@ ...@@ -18,13 +18,12 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
*/
#include "SDL_config.h"
/* SDL surface based renderer implementation */ SDL1.3 DirectFB driver by couriersud@arcor.de
*/
#define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL)
extern void DirectFB_AddRenderDriver(_THIS); /* SDL surface based renderer implementation */
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
This diff is collapsed.
...@@ -18,28 +18,22 @@ ...@@ -18,28 +18,22 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h" #include "SDL_config.h"
#ifndef _SDL_DirectFB_video_h #ifndef _SDL_DirectFB_video_h
#define _SDL_DirectFB_video_h #define _SDL_DirectFB_video_h
#include "../SDL_sysvideo.h"
#include <directfb.h> #include <directfb.h>
#include <directfb_version.h> #include <directfb_version.h>
#include "SDL_mouse.h" #include "../SDL_sysvideo.h"
#include "SDL_scancode.h"
#include "SDL_render.h"
/* Set below to 1 to compile with (old) multi mice/keyboard api. Code left in
* in case we see this again ...
*/
#define USE_MULTI_API (0)
#define DEBUG 1
#define LOG_CHANNEL stdout
#define DFB_VERSIONNUM(X, Y, Z) \ #define DFB_VERSIONNUM(X, Y, Z) \
((X)*1000 + (Y)*100 + (Z)) ((X)*1000 + (Y)*100 + (Z))
...@@ -52,25 +46,29 @@ ...@@ -52,25 +46,29 @@
#if (DFB_VERSION_ATLEAST(1,0,0)) #if (DFB_VERSION_ATLEAST(1,0,0))
#define SDL_DIRECTFB_OPENGL 1 #define SDL_DIRECTFB_OPENGL 1
#include <directfbgl.h>
#else #else
#error "SDL_DIRECTFB: Please compile against libdirectfb version >= 1.0.0" #error "SDL_DIRECTFB: Please compile against libdirectfb version >= 1.0.0"
#endif #endif
#if SDL_DIRECTFB_OPENGL /* Set below to 1 to compile with (old) multi mice/keyboard api. Code left in
#include "SDL_loadso.h" * in case we see this again ...
#endif */
#include "SDL_DirectFB_events.h" #define USE_MULTI_API (0)
/*
* #include "SDL_DirectFB_gamma.h" /* Support for LUT8/INDEX8 pixel format.
* #include "SDL_DirectFB_keyboard.h" * This is broken in DirectFB 1.4.3. It works in 1.4.0 and 1.4.5
* occurred.
*/ */
#include "SDL_DirectFB_modes.h"
#include "SDL_DirectFB_mouse.h" #if (DFB_COMPILEDVERSION == DFB_VERSIONNUM(1, 4, 3))
#include "SDL_DirectFB_opengl.h" #define ENABLE_LUT8 (0)
#include "SDL_DirectFB_window.h" #else
#include "SDL_DirectFB_WM.h" #define ENABLE_LUT8 (1)
#endif
#define DIRECTFB_DEBUG 1
#define LOG_CHANNEL stdout
#define DFBENV_USE_YUV_UNDERLAY "SDL_DIRECTFB_YUV_UNDERLAY" /* Default: off */ #define DFBENV_USE_YUV_UNDERLAY "SDL_DIRECTFB_YUV_UNDERLAY" /* Default: off */
#define DFBENV_USE_YUV_DIRECT "SDL_DIRECTFB_YUV_DIRECT" /* Default: off */ #define DFBENV_USE_YUV_DIRECT "SDL_DIRECTFB_YUV_DIRECT" /* Default: off */
...@@ -82,76 +80,103 @@ ...@@ -82,76 +80,103 @@
#define SDL_DFB_FREE(x) do { if ( (x) != NULL ) { SDL_free(x); x = NULL; } } while (0) #define SDL_DFB_FREE(x) do { if ( (x) != NULL ) { SDL_free(x); x = NULL; } } while (0)
#define SDL_DFB_UNLOCK(x) do { if ( (x) != NULL ) { x->Unlock(x); } } while (0) #define SDL_DFB_UNLOCK(x) do { if ( (x) != NULL ) { x->Unlock(x); } } while (0)
#if DEBUG
/* FIXME: do something with DEBUG */
#endif
#define SDL_DFB_CONTEXT "SDL_DirectFB" #define SDL_DFB_CONTEXT "SDL_DirectFB"
static inline DFBResult sdl_dfb_check(DFBResult ret, const char *src_file, int src_line, const char *src_code) { #define SDL_DFB_ERR(x...) \
do { \
fprintf(LOG_CHANNEL, "%s: %s <%d>:\n\t", \
SDL_DFB_CONTEXT, __FILE__, __LINE__ ); \
fprintf(LOG_CHANNEL, x ); \
} while (0)
#if (DIRECTFB_DEBUG)
#define SDL_DFB_LOG(x...) \
do { \
fprintf(LOG_CHANNEL, SDL_DFB_CONTEXT); \
fprintf(LOG_CHANNEL, x ); \
fprintf(LOG_CHANNEL, "\n"); \
} while (0)
#define SDL_DFB_DEBUG(x...) SDL_DFB_ERR( x )
static inline DFBResult sdl_dfb_check(DFBResult ret, const char *src_file, int src_line) {
if (ret != DFB_OK) { if (ret != DFB_OK) {
fprintf(LOG_CHANNEL, "%s <%d>:\n\t", src_file, src_line ); SDL_DFB_LOG("%s (%d):%s", src_file, src_line, DirectFBErrorString (ret) );
fprintf(LOG_CHANNEL, "\t%s\n", src_code ); SDL_SetError("%s:%s", SDL_DFB_CONTEXT, DirectFBErrorString (ret) );
fprintf(LOG_CHANNEL, "\t%s\n", DirectFBErrorString (ret) );
SDL_SetError( src_code, DirectFBErrorString (ret) );
} }
return ret; return ret;
} }
#define SDL_DFB_CHECK(x...) sdl_dfb_check( x, __FILE__, __LINE__, #x ) #define SDL_DFB_CHECK(x...) do { sdl_dfb_check( x, __FILE__, __LINE__); } while (0)
#define SDL_DFB_CHECKERR(x...) do { if ( sdl_dfb_check( x, __FILE__, __LINE__) != DFB_OK ) goto error; } while (0)
#define SDL_DFB_CHECKERR(x...) if ( sdl_dfb_check( x, __FILE__, __LINE__, #x ) != DFB_OK ) goto error #else
#define SDL_DFB_DEBUG(x...) \ #define SDL_DFB_CHECK(x...) x
do { \ #define SDL_DFB_CHECKERR(x...) do { if (x != DFB_OK ) goto error; } while (0)
fprintf(LOG_CHANNEL, "%s: %s <%d>:\n\t", \ #define SDL_DFB_LOG(x...) do {} while (0)
SDL_DFB_CONTEXT, __FILE__, __LINE__ ); \ #define SDL_DFB_DEBUG(x...) do {} while (0)
fprintf(LOG_CHANNEL, x ); \
} while (0) #endif
#define SDL_DFB_ERR(x...) SDL_DFB_DEBUG( x )
#define SDL_DFB_CALLOC(r, n, s) \ #define SDL_DFB_CALLOC(r, n, s) \
do { \ do { \
r = SDL_calloc (n, s); \ r = SDL_calloc (n, s); \
if (!(r)) { \ if (!(r)) { \
fprintf( LOG_CHANNEL, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ SDL_DFB_ERR("Out of memory"); \
SDL_OutOfMemory(); \ SDL_OutOfMemory(); \
goto error; \ goto error; \
} \ } \
} while (0) } while (0)
#define SDL_DFB_ALLOC_CLEAR(r, s) SDL_DFB_CALLOC(r, 1, s)
/* Private display data */ /* Private display data */
#define SDL_DFB_DEVICEDATA(dev) DFB_DeviceData *devdata = (dev ? (DFB_DeviceData *) ((dev)->driverdata) : NULL) #define SDL_DFB_DEVICEDATA(dev) DFB_DeviceData *devdata = (dev ? (DFB_DeviceData *) ((dev)->driverdata) : NULL)
#define DFB_MAX_SCREENS 10 #define DFB_MAX_SCREENS 10
typedef struct _DFB_KeyboardData DFB_KeyboardData;
struct _DFB_KeyboardData
{
const SDL_ScanCode *map; /* keyboard scancode map */
int map_size; /* size of map */
int map_adjust; /* index adjust */
int is_generic; /* generic keyboard */
int id;
};
typedef struct _DFB_DeviceData DFB_DeviceData; typedef struct _DFB_DeviceData DFB_DeviceData;
struct _DFB_DeviceData struct _DFB_DeviceData
{ {
int initialized; int initialized;
IDirectFB *dfb; IDirectFB *dfb;
int num_mice; int num_mice;
int mouse_id[0x100]; int mouse_id[0x100];
int num_keyboard; int num_keyboard;
struct DFB_KeyboardData keyboard[10];
{ SDL_Window *firstwin;
int is_generic;
int id; int use_yuv_underlays;
} keyboard[10]; int use_yuv_direct;
DFB_WindowData *firstwin; int use_linux_input;
int has_own_wm;
int use_yuv_underlays;
int use_linux_input;
int has_own_wm;
/* window grab */ /* window grab */
SDL_Window *grabbed_window; SDL_Window *grabbed_window;
/* global events */ /* global events */
IDirectFBEventBuffer *events; IDirectFBEventBuffer *events;
}; };
Uint32 DirectFB_DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat);
DFBSurfacePixelFormat DirectFB_SDLToDFBPixelFormat(Uint32 format);
void DirectFB_SetSupportedPixelFormats(SDL_RendererInfo *ri);
#endif /* _SDL_DirectFB_video_h */ #endif /* _SDL_DirectFB_video_h */
This diff is collapsed.
...@@ -18,12 +18,15 @@ ...@@ -18,12 +18,15 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
SDL1.3 DirectFB driver by couriersud@arcor.de
*/ */
#include "SDL_config.h"
#ifndef _SDL_directfb_window_h #ifndef _SDL_directfb_window_h
#define _SDL_directfb_window_h #define _SDL_directfb_window_h
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_WM.h" #include "SDL_DirectFB_WM.h"
#define SDL_DFB_WINDOWDATA(win) DFB_WindowData *windata = ((win) ? (DFB_WindowData *) ((win)->driverdata) : NULL) #define SDL_DFB_WINDOWDATA(win) DFB_WindowData *windata = ((win) ? (DFB_WindowData *) ((win)->driverdata) : NULL)
...@@ -31,22 +34,28 @@ ...@@ -31,22 +34,28 @@
typedef struct _DFB_WindowData DFB_WindowData; typedef struct _DFB_WindowData DFB_WindowData;
struct _DFB_WindowData struct _DFB_WindowData
{ {
IDirectFBSurface *surface; IDirectFBSurface *window_surface; /* window surface */
IDirectFBSurface *window_surface; /* only used with has_own_wm */ IDirectFBSurface *surface; /* client drawing surface */
IDirectFBWindow *window; IDirectFBWindow *dfbwin;
IDirectFBEventBuffer *eventbuffer; IDirectFBEventBuffer *eventbuffer;
SDL_Window *sdl_window; //SDL_Window *sdlwin;
DFB_WindowData *next; SDL_Window *next;
Uint8 opacity; Uint8 opacity;
DFBRectangle client; DFBRectangle client;
DFBDimension size; DFBDimension size;
DFBRectangle restore;
/* WM extras */ /* WM extras */
DFBRectangle restore; int is_managed;
int is_managed; int wm_needs_redraw;
int wm_needs_redraw; IDirectFBSurface *icon;
IDirectFBSurface *icon; IDirectFBFont *font;
IDirectFBFont *font; DFB_Theme theme;
DFB_Theme theme;
/* WM moving and sizing */
int wm_grab;
int wm_lastx;
int wm_lasty;
}; };
extern int DirectFB_CreateWindow(_THIS, SDL_Window * window); extern int DirectFB_CreateWindow(_THIS, SDL_Window * window);
...@@ -69,7 +78,7 @@ extern void DirectFB_DestroyWindow(_THIS, SDL_Window * window); ...@@ -69,7 +78,7 @@ extern void DirectFB_DestroyWindow(_THIS, SDL_Window * window);
extern SDL_bool DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window, extern SDL_bool DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info); struct SDL_SysWMinfo *info);
//extern void DirectFB_AdjustWindowSurface(_THIS, SDL_Window * window); extern void DirectFB_AdjustWindowSurface(SDL_Window * window);
#endif /* _SDL_directfb_window_h */ #endif /* _SDL_directfb_window_h */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment