Commit 2de3ba20 authored by Sam Lantinga's avatar Sam Lantinga

Date: Sat, 11 Aug 2007 02:03:16 +0200 (CEST)

From: couriersud arcor.de
To: slouken@libsdl.org
Subject: Directfb driver for SDL1.3

Hi,

the attachment contains a patch for a SDL1.3 directfb driver. It supports:

- Renderer "directfb":

Hardware acceleration as supported by the underlying directfb driver. With a
radeon X850, testsprite2 runs at 50% to 70% of OpenGL (X11, dri) performance.

Also supports hardware accelerated yuv overlays. This must be enabled by sett
ing:

export SDL_DIRECTFB_YUV_DIRECT=1

- Renderer "opengl"

Supports software opengl using mesa opengl (make linux-directfb).

Some more information may be found in README.DirectFB

There will certainly still be some bugs, and there is some debug code around.
 When I find some time, I will compile against directfb-0.9.25 as distributed
 with ubuntu 7.04.

The diff also contains a fix for SDL_LockYUVOverlay fixing a bug in  *pixels
and pitches initialization.

Kind regards,

couriersud

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%402588
parent fa64b7b1
SDL on DirectFB
Supports:
- Hardware YUV overlays
- OpenGL - software only
- 2D/3D accelerations (depends on directfb driver)
What you need:
DirectFB 1.0.0 - required
Kernel-Framebuffer support: required: vesafb, radeonfb ....
Mesa 7.0.x - optional for OpenGL
As of this writing 20070810 you need to pull Mesa from git and do the following:
------------------------
cd mesa
make linux-directfb
make
echo Installing - pleaser enter sudo pw.
sudo make install INSTALL_DIR=/usr/local/dfb_GL
cd src/mesa/drivers/directfb
make
sudo make install INSTALL_DIR=/usr/local/dfb_GL
------------------------
To run the SDL - testprograms:
export SDL_VIDEODRIVER=directfb
export LD_LIBRARY_PATH=/usr/local/dfb_GL/lib
export LD_PRELOAD=/usr/local/dfb_GL/libGL.so.7
./testgl
To use hardware accelerated YUV-overlays for YUV-textures, use:
export SDL_DIRECTFB_YUV_DIRECT=1
This is disabled by default. It will only support one concurrent
overlay and may behave strange if not used with SDL_CreateYUvOverlay
from SDLcompat.c.
...@@ -1440,19 +1440,21 @@ SDL_LockYUVOverlay(SDL_Overlay * overlay) ...@@ -1440,19 +1440,21 @@ SDL_LockYUVOverlay(SDL_Overlay * overlay)
< 0) { < 0) {
return -1; return -1;
} }
overlay->pixels[0] = (Uint8 *) pixels;
overlay->pitches[0] = pitch;
switch (overlay->format) { switch (overlay->format) {
case SDL_YV12_OVERLAY: case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY: case SDL_IYUV_OVERLAY:
overlay->pixels[0] = (Uint8 *) pixels; overlay->pitches[1] = pitch / 2;
overlay->pitches[2] = pitch / 2;
overlay->pixels[1] = overlay->pixels[1] =
overlay->pixels[0] + overlay->pitches[0] * overlay->h; overlay->pixels[0] + overlay->pitches[0] * overlay->h;
overlay->pixels[2] = overlay->pixels[2] =
overlay->pixels[1] + overlay->pitches[1] * overlay->h; overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
break; break;
case SDL_YUY2_OVERLAY: case SDL_YUY2_OVERLAY:
case SDL_UYVY_OVERLAY: case SDL_UYVY_OVERLAY:
case SDL_YVYU_OVERLAY: case SDL_YVYU_OVERLAY:
overlay->pixels[0] = (Uint8 *) pixels;
break; break;
} }
return 0; return 0;
......
...@@ -23,72 +23,99 @@ ...@@ -23,72 +23,99 @@
/* Handle the event stream, converting DirectFB input events into SDL events */ /* Handle the event stream, converting DirectFB input events into SDL events */
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <directfb.h> #include <directfb.h>
#include "SDL.h" #include "SDL.h"
#include "../SDL_sysvideo.h" #include "../SDL_sysvideo.h"
#include "../../events/SDL_sysevents.h" #include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_events.h" #include "SDL_DirectFB_events.h"
/* The translation tables from a DirectFB keycode to a SDL keysym */ /* The translation tables from a DirectFB keycode to a SDL keysym */
static SDLKey keymap[256]; static SDLKey keymap[256];
static SDL_keysym *DirectFB_TranslateKey(DFBInputEvent * ev,
SDL_keysym * keysym);
static int DirectFB_TranslateButton(DFBInputEvent * ev);
static int posted = 0; static SDL_keysym *DirectFB_TranslateKey(DFBInputDeviceKeyIdentifier key_id,
DFBInputDeviceKeySymbol key_symbol,
DFBInputDeviceModifierMask key_mod,
SDL_keysym * keysym);
static int DirectFB_TranslateButton(DFBInputDeviceButtonIdentifier button);
void void
DirectFB_PumpEvents(_THIS) DirectFB_PumpEventsWindow(_THIS)
{ {
DFBInputEvent evt; SDL_DFB_DEVICEDATA(_this);
DFB_WindowData *p;
DFBWindowEvent evt;
while (HIDDEN->eventbuffer->GetEvent(HIDDEN->eventbuffer, for (p = devdata->firstwin; p != NULL; p = p->next) {
while (p->eventbuffer->GetEvent(p->eventbuffer,
DFB_EVENT(&evt)) == DFB_OK) { DFB_EVENT(&evt)) == DFB_OK) {
SDL_keysym keysym; SDL_keysym keysym;
if (evt.clazz = DFEC_WINDOW) {
switch (evt.type) { switch (evt.type) {
case DIET_BUTTONPRESS: case DWET_BUTTONDOWN:
posted += SDL_PrivateMouseButton(SDL_PRESSED, SDL_SendMouseButton(devdata->mouse, SDL_PRESSED,
DirectFB_TranslateButton DirectFB_TranslateButton(evt.button));
(&evt), 0, 0);
break; break;
case DIET_BUTTONRELEASE: case DWET_BUTTONUP:
posted += SDL_PrivateMouseButton(SDL_RELEASED, SDL_SendMouseButton(devdata->mouse, SDL_RELEASED,
DirectFB_TranslateButton DirectFB_TranslateButton(evt.button));
(&evt), 0, 0);
break; break;
case DIET_KEYPRESS: case DWET_MOTION:
posted += SDL_SendMouseMotion(devdata->mouse, 0, evt.x, evt.y);
SDL_PrivateKeyboard(SDL_PRESSED,
DirectFB_TranslateKey(&evt, &keysym));
break; break;
case DIET_KEYRELEASE: case DWET_KEYDOWN:
posted += DirectFB_TranslateKey(evt.key_id, evt.key_symbol,
SDL_PrivateKeyboard(SDL_RELEASED, evt.modifiers, &keysym);
DirectFB_TranslateKey(&evt, &keysym)); SDL_SendKeyboardKey(devdata->keyboard, SDL_PRESSED,
keysym.scancode, keysym.sym);
break; break;
case DIET_AXISMOTION: case DWET_KEYUP:
if (evt.flags & DIEF_AXISREL) { DirectFB_TranslateKey(evt.key_id, evt.key_symbol,
if (evt.axis == DIAI_X) evt.modifiers, &keysym);
posted += SDL_PrivateMouseMotion(0, 1, evt.axisrel, 0); SDL_SendKeyboardKey(devdata->keyboard, SDL_RELEASED,
else if (evt.axis == DIAI_Y) keysym.scancode, keysym.sym);
posted += SDL_PrivateMouseMotion(0, 1, 0, evt.axisrel); break;
} case DWET_POSITION_SIZE:
SDL_SendWindowEvent(p->id, SDL_WINDOWEVENT_MOVED, evt.cx,
evt.cy);
SDL_SendWindowEvent(p->id, SDL_WINDOWEVENT_RESIZED, evt.w,
evt.h);
break;
case DWET_POSITION:
SDL_SendWindowEvent(p->id, SDL_WINDOWEVENT_MOVED, evt.cx,
evt.cy);
break;
case DWET_SIZE:
SDL_SendWindowEvent(p->id, SDL_WINDOWEVENT_RESIZED, evt.w,
evt.h);
break;
case DWET_CLOSE:
SDL_SendWindowEvent(p->id, SDL_WINDOWEVENT_CLOSE, 0, 0);
break;
case DWET_GOTFOCUS:
//TODO: Implement for yuv-overlay DirectFB_SwitchOverlayContext(this, evt.window_id);
SDL_SetKeyboardFocus(devdata->keyboard, p->id);
break;
case DWET_LOSTFOCUS:
SDL_SetKeyboardFocus(devdata->keyboard, 0);
break;
case DWET_ENTER:
//SDL_DirectFB_ReshowCursor(_this, 0);
SDL_SetMouseFocus(devdata->mouse, p->id);
break;
case DWET_LEAVE:
SDL_SetMouseFocus(devdata->mouse, 0);
//SDL_DirectFB_ReshowCursor(_this, 1);
break; break;
default: default:
; ;
} }
} }
}
}
} }
void void
...@@ -177,35 +204,80 @@ DirectFB_InitOSKeymap(_THIS) ...@@ -177,35 +204,80 @@ DirectFB_InitOSKeymap(_THIS)
keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = SDLK_SCROLLOCK; keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = SDLK_SCROLLOCK;
keymap[DIKI_PRINT - DIKI_UNKNOWN] = SDLK_PRINT; keymap[DIKI_PRINT - DIKI_UNKNOWN] = SDLK_PRINT;
keymap[DIKI_PAUSE - DIKI_UNKNOWN] = SDLK_PAUSE; keymap[DIKI_PAUSE - DIKI_UNKNOWN] = SDLK_PAUSE;
keymap[DIKI_KP_EQUAL - DIKI_UNKNOWN] = SDLK_KP_EQUALS;
keymap[DIKI_KP_DECIMAL - DIKI_UNKNOWN] = SDLK_KP_PERIOD;
keymap[DIKI_KP_0 - DIKI_UNKNOWN] = SDLK_KP0;
keymap[DIKI_KP_1 - DIKI_UNKNOWN] = SDLK_KP1;
keymap[DIKI_KP_2 - DIKI_UNKNOWN] = SDLK_KP2;
keymap[DIKI_KP_3 - DIKI_UNKNOWN] = SDLK_KP3;
keymap[DIKI_KP_4 - DIKI_UNKNOWN] = SDLK_KP4;
keymap[DIKI_KP_5 - DIKI_UNKNOWN] = SDLK_KP5;
keymap[DIKI_KP_6 - DIKI_UNKNOWN] = SDLK_KP6;
keymap[DIKI_KP_7 - DIKI_UNKNOWN] = SDLK_KP7;
keymap[DIKI_KP_8 - DIKI_UNKNOWN] = SDLK_KP8;
keymap[DIKI_KP_9 - DIKI_UNKNOWN] = SDLK_KP9;
keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = SDLK_KP_DIVIDE; keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = SDLK_KP_DIVIDE;
keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = SDLK_KP_MULTIPLY; keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = SDLK_KP_MULTIPLY;
keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = SDLK_KP_MINUS; keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = SDLK_KP_MINUS;
keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = SDLK_KP_PLUS; keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = SDLK_KP_PLUS;
keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = SDLK_KP_ENTER; keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = SDLK_KP_ENTER;
}
keymap[DIKI_QUOTE_LEFT - DIKI_UNKNOWN] = SDLK_BACKQUOTE; /* TLDE */
keymap[DIKI_MINUS_SIGN - DIKI_UNKNOWN] = SDLK_MINUS; /* AE11 */
keymap[DIKI_EQUALS_SIGN - DIKI_UNKNOWN] = SDLK_EQUALS; /* AE12 */
keymap[DIKI_BRACKET_LEFT - DIKI_UNKNOWN] = SDLK_RIGHTBRACKET; /* AD11 */
keymap[DIKI_BRACKET_RIGHT - DIKI_UNKNOWN] = SDLK_LEFTBRACKET; /* AD12 */
keymap[DIKI_BACKSLASH - DIKI_UNKNOWN] = SDLK_BACKSLASH; /* BKSL */
keymap[DIKI_SEMICOLON - DIKI_UNKNOWN] = SDLK_SEMICOLON; /* AC10 */
keymap[DIKI_QUOTE_RIGHT - DIKI_UNKNOWN] = SDLK_QUOTE; /* AC11 */
keymap[DIKI_COMMA - DIKI_UNKNOWN] = SDLK_COMMA; /* AB08 */
keymap[DIKI_PERIOD - DIKI_UNKNOWN] = SDLK_PERIOD; /* AB09 */
keymap[DIKI_SLASH - DIKI_UNKNOWN] = SDLK_SLASH; /* AB10 */
keymap[DIKI_LESS_SIGN - DIKI_UNKNOWN] = SDLK_LESS; /* 103rd */
}
static SDL_keysym * static SDL_keysym *
DirectFB_TranslateKey(DFBInputEvent * ev, SDL_keysym * keysym) DirectFB_TranslateKey(DFBInputDeviceKeyIdentifier key_id,
DFBInputDeviceKeySymbol key_symbol,
DFBInputDeviceModifierMask key_mod, SDL_keysym * keysym)
{ {
SDLMod mod = KMOD_NONE;
/*
* Set modifier information
*/
if (key_mod & DIMM_SHIFT)
mod = mod | KMOD_LSHIFT;
if (key_mod & DIMM_CONTROL)
mod = mod | KMOD_LCTRL;
if (key_mod & DIMM_ALT)
mod = mod | KMOD_LALT;
if (key_mod & DIMM_ALTGR)
mod = mod | KMOD_RALT;
if (key_mod & DIMM_META)
mod = mod | KMOD_LMETA;
/* Set the keysym information */ /* Set the keysym information */
keysym->scancode = ev->key_id; keysym->scancode = key_id;
keysym->mod = KMOD_NONE; /* FIXME */
keysym->mod = mod;
keysym->unicode = keysym->unicode =
(DFB_KEY_TYPE(ev->key_symbol) == DIKT_UNICODE) ? ev->key_symbol : 0; (DFB_KEY_TYPE(key_symbol) == DIKT_UNICODE) ? key_symbol : 0;
if (ev->key_symbol > 0 && ev->key_symbol < 128) if (key_symbol > 0 && key_symbol < 255)
keysym->sym = ev->key_symbol; keysym->sym = key_symbol;
else else
keysym->sym = keymap[ev->key_id - DIKI_UNKNOWN]; keysym->sym = keymap[key_id - DIKI_UNKNOWN];
return keysym; return keysym;
} }
static int static int
DirectFB_TranslateButton(DFBInputEvent * ev) DirectFB_TranslateButton(DFBInputDeviceButtonIdentifier button)
{ {
switch (ev->button) { switch (button) {
case DIBI_LEFT: case DIBI_LEFT:
return 1; return 1;
case DIBI_MIDDLE: case DIBI_MIDDLE:
...@@ -217,4 +289,76 @@ DirectFB_TranslateButton(DFBInputEvent * ev) ...@@ -217,4 +289,76 @@ DirectFB_TranslateButton(DFBInputEvent * ev)
} }
} }
/* vi: set ts=4 sw=4 expandtab: */ #if 0
void
DirectFB_PumpEvents(_THIS)
{
SDL_DFB_DEVICEDATA(_this);
DFBInputEvent evt;
static last_x = 0, last_y = 0;
while (devdata->eventbuffer->GetEvent(devdata->eventbuffer,
DFB_EVENT(&evt)) == DFB_OK) {
SDL_keysym keysym;
DFBInputDeviceModifierMask mod;
if (evt.clazz = DFEC_INPUT) {
if (evt.flags & DIEF_MODIFIERS)
mod = evt.modifiers;
else
mod = 0;
switch (evt.type) {
case DIET_BUTTONPRESS:
posted += SDL_PrivateMouseButton(SDL_PRESSED,
DirectFB_TranslateButton(evt.
button),
0, 0);
break;
case DIET_BUTTONRELEASE:
posted += SDL_PrivateMouseButton(SDL_RELEASED,
DirectFB_TranslateButton(evt.
button),
0, 0);
break;
case DIET_KEYPRESS:
posted += SDL_PrivateKeyboard(SDL_PRESSED,
DirectFB_TranslateKey(evt.
key_id,
evt.
key_symbol,
mod,
&keysym));
break;
case DIET_KEYRELEASE:
posted += SDL_PrivateKeyboard(SDL_RELEASED,
DirectFB_TranslateKey(evt.
key_id,
evt.
key_symbol,
mod,
&keysym));
break;
case DIET_AXISMOTION:
if (evt.flags & DIEF_AXISREL) {
if (evt.axis == DIAI_X)
posted +=
SDL_PrivateMouseMotion(0, 1, evt.axisrel, 0);
else if (evt.axis == DIAI_Y)
posted +=
SDL_PrivateMouseMotion(0, 1, 0, evt.axisrel);
} else if (evt.flags & DIEF_AXISABS) {
if (evt.axis == DIAI_X)
last_x = evt.axisabs;
else if (evt.axis == DIAI_Y)
last_y = evt.axisabs;
posted += SDL_PrivateMouseMotion(0, 0, last_x, last_y);
}
break;
default:
;
}
}
}
}
#endif
...@@ -25,5 +25,4 @@ ...@@ -25,5 +25,4 @@
/* Functions to be exported */ /* Functions to be exported */
extern void DirectFB_InitOSKeymap(_THIS); extern void DirectFB_InitOSKeymap(_THIS);
extern void DirectFB_PumpEvents(_THIS); extern void DirectFB_PumpEventsWindow(_THIS);
/* vi: set ts=4 sw=4 expandtab: */
#define SCANCODE_ESCAPE 1
#define SCANCODE_1 2
#define SCANCODE_2 3
#define SCANCODE_3 4
#define SCANCODE_4 5
#define SCANCODE_5 6
#define SCANCODE_6 7
#define SCANCODE_7 8
#define SCANCODE_8 9
#define SCANCODE_9 10
#define SCANCODE_0 11
#define SCANCODE_MINUS 12
#define SCANCODE_EQUAL 13
#define SCANCODE_BACKSPACE 14
#define SCANCODE_TAB 15
#define SCANCODE_Q 16
#define SCANCODE_W 17
#define SCANCODE_E 18
#define SCANCODE_R 19
#define SCANCODE_T 20
#define SCANCODE_Y 21
#define SCANCODE_U 22
#define SCANCODE_I 23
#define SCANCODE_O 24
#define SCANCODE_P 25
#define SCANCODE_BRACKET_LEFT 26
#define SCANCODE_BRACKET_RIGHT 27
#define SCANCODE_ENTER 28
#define SCANCODE_LEFTCONTROL 29
#define SCANCODE_A 30
#define SCANCODE_S 31
#define SCANCODE_D 32
#define SCANCODE_F 33
#define SCANCODE_G 34
#define SCANCODE_H 35
#define SCANCODE_J 36
#define SCANCODE_K 37
#define SCANCODE_L 38
#define SCANCODE_SEMICOLON 39
#define SCANCODE_APOSTROPHE 40
#define SCANCODE_GRAVE 41
#define SCANCODE_LEFTSHIFT 42
#define SCANCODE_BACKSLASH 43
#define SCANCODE_Z 44
#define SCANCODE_X 45
#define SCANCODE_C 46
#define SCANCODE_V 47
#define SCANCODE_B 48
#define SCANCODE_N 49
#define SCANCODE_M 50
#define SCANCODE_COMMA 51
#define SCANCODE_PERIOD 52
#define SCANCODE_SLASH 53
#define SCANCODE_RIGHTSHIFT 54
#define SCANCODE_KEYPADMULTIPLY 55
#define SCANCODE_LEFTALT 56
#define SCANCODE_SPACE 57
#define SCANCODE_CAPSLOCK 58
#define SCANCODE_F1 59
#define SCANCODE_F2 60
#define SCANCODE_F3 61
#define SCANCODE_F4 62
#define SCANCODE_F5 63
#define SCANCODE_F6 64
#define SCANCODE_F7 65
#define SCANCODE_F8 66
#define SCANCODE_F9 67
#define SCANCODE_F10 68
#define SCANCODE_NUMLOCK 69
#define SCANCODE_SCROLLLOCK 70
#define SCANCODE_KEYPAD7 71
#define SCANCODE_CURSORUPLEFT 71
#define SCANCODE_KEYPAD8 72
#define SCANCODE_CURSORUP 72
#define SCANCODE_KEYPAD9 73
#define SCANCODE_CURSORUPRIGHT 73
#define SCANCODE_KEYPADMINUS 74
#define SCANCODE_KEYPAD4 75
#define SCANCODE_CURSORLEFT 75
#define SCANCODE_KEYPAD5 76
#define SCANCODE_KEYPAD6 77
#define SCANCODE_CURSORRIGHT 77
#define SCANCODE_KEYPADPLUS 78
#define SCANCODE_KEYPAD1 79
#define SCANCODE_CURSORDOWNLEFT 79
#define SCANCODE_KEYPAD2 80
#define SCANCODE_CURSORDOWN 80
#define SCANCODE_KEYPAD3 81
#define SCANCODE_CURSORDOWNRIGHT 81
#define SCANCODE_KEYPAD0 82
#define SCANCODE_KEYPADPERIOD 83
#define SCANCODE_LESS 86
#define SCANCODE_F11 87
#define SCANCODE_F12 88
#define SCANCODE_KEYPADENTER 96
#define SCANCODE_RIGHTCONTROL 97
#define SCANCODE_CONTROL 97
#define SCANCODE_KEYPADDIVIDE 98
#define SCANCODE_PRINTSCREEN 99
#define SCANCODE_RIGHTALT 100
#define SCANCODE_BREAK 101 /* Beware: is 119 */
#define SCANCODE_BREAK_ALTERNATIVE 119 /* on some keyboards! */
#define SCANCODE_HOME 102
#define SCANCODE_CURSORBLOCKUP 90 /* Cursor key block */
#define SCANCODE_PAGEUP 104
#define SCANCODE_CURSORBLOCKLEFT 92 /* Cursor key block */
#define SCANCODE_CURSORBLOCKRIGHT 94 /* Cursor key block */
#define SCANCODE_END 107
#define SCANCODE_CURSORBLOCKDOWN 108 /* Cursor key block */
#define SCANCODE_PAGEDOWN 109
#define SCANCODE_INSERT 110
#define SCANCODE_REMOVE 111
#define SCANCODE_RIGHTWIN 126
#define SCANCODE_LEFTWIN 125
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_mouse.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_mouse_c.h"
static SDL_Cursor *DirectFB_CreateCursor(SDL_Surface * surface, int hot_x,
int hot_y);
static int DirectFB_ShowCursor(SDL_Cursor * cursor);
static void DirectFB_MoveCursor(SDL_Cursor * cursor);
static void DirectFB_FreeCursor(SDL_Cursor * cursor);
static void DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_WindowID windowID,
int x, int y);
static void DirectFB_FreeMouse(SDL_Mouse * mouse);
void
DirectFB_InitMouse(_THIS)
{
SDL_DFB_DEVICEDATA(_this);
SDL_Mouse mouse;
SDL_zero(mouse);
mouse.CreateCursor = DirectFB_CreateCursor;
mouse.ShowCursor = DirectFB_ShowCursor;
mouse.MoveCursor = DirectFB_MoveCursor;
mouse.FreeCursor = DirectFB_FreeCursor;
mouse.WarpMouse = DirectFB_WarpMouse;
mouse.FreeMouse = DirectFB_FreeMouse;
devdata->mouse = SDL_AddMouse(&mouse, -1);
}
void
DirectFB_QuitMouse(_THIS)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DelMouse(devdata->mouse);
}
/* Create a cursor from a surface */
static SDL_Cursor *
DirectFB_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
{
SDL_VideoDevice *dev = SDL_GetVideoDevice();
SDL_DFB_DEVICEDATA(dev);
DFB_CursorData *curdata;
DFBResult ret;
DFBSurfaceDescription dsc;
SDL_Cursor *cursor;
Uint32 *dest;
Uint32 *p;
int pitch, i;
SDL_DFB_CALLOC(cursor, 1, sizeof(*cursor));
SDL_DFB_CALLOC(curdata, 1, sizeof(*curdata));
dsc.flags =
DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
dsc.caps = DSCAPS_NONE; //DSCAPS_SYSTEMONLY;
dsc.width = surface->w;
dsc.height = surface->h;
dsc.pixelformat = DSPF_ARGB;
SDL_DFB_CHECKERR(devdata->dfb->
CreateSurface(devdata->dfb, &dsc, &curdata->surf));
curdata->hotx = hot_x;
curdata->hoty = hot_y;
cursor->driverdata = curdata;
SDL_DFB_CHECKERR(curdata->surf->
Lock(curdata->surf, DSLF_WRITE, (void *) &dest, &pitch));
//FIXME: Implies a lot of things, e.g. rgba format for SDL_SURFACE ....
p = surface->pixels;
for (i = 0; i < surface->w * surface->h; i++)
if (p[i] == 0x00000000)
dest[i] = 0x00000000;
else
dest[i] = p[i];
//memcpy(dest, surface->pixels, surface->w * surface->h * 4);
curdata->surf->Unlock(curdata->surf);
return cursor;
error:
return NULL;
}
/* Show the specified cursor, or hide if cursor is NULL */
static int
DirectFB_ShowCursor(SDL_Cursor * cursor)
{
SDL_DFB_CURSORDATA(cursor);
SDL_VideoDevice *dev = SDL_GetVideoDevice();
SDL_DFB_DEVICEDATA(dev);
#if 0
DFB_DisplayData *dispdata =
(DFB_DisplayData *) dev->displays[dev->current_display].driverdata;
#endif
DFBResult ret;
SDL_WindowID wid;
wid = SDL_GetFocusWindow();
if (!wid)
return -1;
else {
SDL_Window *window = SDL_GetWindowFromID(wid);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
SDL_DFB_CHECKERR(windata->window->
SetCursorShape(windata->window, curdata->surf,
curdata->hotx, curdata->hoty));
//FIXME: This is somehow a directfb issue
SDL_DFB_CHECKERR(dispdata->layer->
SetCooperativeLevel(dispdata->layer,
DLSCL_ADMINISTRATIVE));
SDL_DFB_CHECKERR(dispdata->layer->
SetCursorOpacity(dispdata->layer, 0xC0));
SDL_DFB_CHECKERR(dispdata->layer->
SetCooperativeLevel(dispdata->layer, DLSCL_SHARED));
}
#if 0
//TODO: Check administrative
SDL_DFB_CHECKERR(dispdata->layer->
SetCooperativeLevel(dispdata->layer,
DLSCL_ADMINISTRATIVE));
SDL_DFB_CHECKERR(dispdata->layer->
SetCursorShape(dispdata->layer, curdata->surf,
curdata->hotx, curdata->hoty));
SDL_DFB_CHECKERR(dispdata->layer->
SetCursorOpacity(dispdata->layer, 0xC0));
SDL_DFB_CHECKERR(dispdata->layer->
SetCooperativeLevel(dispdata->layer, DLSCL_SHARED));
#endif
return 0;
error:
return -1;
}
/* This is called when a mouse motion event occurs */
static void
DirectFB_MoveCursor(SDL_Cursor * cursor)
{
SDL_DFB_CURSORDATA(cursor);
/* Do we need to do something here ? */
}
/* Free a window manager cursor */
static void
DirectFB_FreeCursor(SDL_Cursor * cursor)
{
SDL_DFB_CURSORDATA(cursor);
SDL_DFB_RELEASE(curdata->surf);
SDL_DFB_FREE(cursor->driverdata);
SDL_DFB_FREE(cursor);
}
/* Warp the mouse to (x,y) */
static void
DirectFB_WarpMouse(SDL_Mouse * mouse, SDL_WindowID windowID, int x, int y)
{
// SDL_DFB_CURSORDATA(cursor);
SDL_Window *window = SDL_GetWindowFromID(windowID);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
DFB_WindowData *windata = (DFB_WindowData *) window->driverdata;
DFBResult ret;
int cx, cy;
SDL_DFB_CHECKERR(windata->window->GetPosition(windata->window, &cx, &cy));
SDL_DFB_CHECKERR(dispdata->layer->
WarpCursor(dispdata->layer, cx + x, cy + y));
error:
return;
}
/* Free the mouse when it's time */
static void
DirectFB_FreeMouse(SDL_Mouse * mouse)
{
// nothing yet
}
/* vi: set ts=4 sw=4 expandtab: */
...@@ -21,21 +21,23 @@ ...@@ -21,21 +21,23 @@
*/ */
#include "SDL_config.h" #include "SDL_config.h"
/* This is the DirectFB implementation of YUV video overlays */ #ifndef _SDL_DirectFB_mouse_h
#define _SDL_DirectFB_mouse_h
#include "SDL_video.h" typedef struct _DFB_CursorData DFB_CursorData;
#include "SDL_DirectFB_video.h"
extern SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, struct _DFB_CursorData
Uint32 format, {
SDL_Surface * display); IDirectFBSurface *surf;
int hotx;
int hoty;
};
extern int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay * overlay); #define SDL_DFB_CURSORDATA(curs) DFB_CursorData *curdata = (DFB_CursorData *) ((curs)->driverdata)
extern void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay); extern void DirectFB_InitMouse(_THIS);
extern void DirectFB_QuitMouse(_THIS);
extern int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, #endif /* _SDL_DirectFB_mouse_h */
SDL_Rect * src, SDL_Rect * dst);
extern void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay * overlay);
/* vi: set ts=4 sw=4 expandtab: */ /* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
SDL1.3 implementation by couriersud@arcor.de
*/
#include "SDL_config.h"
#include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_render.h"
#include "../SDL_rect_c.h"
#include "../SDL_yuv_sw_c.h"
/* GDI renderer implementation */
static SDL_Renderer *DirectFB_CreateRenderer(SDL_Window * window,
Uint32 flags);
static int DirectFB_DisplayModeChanged(SDL_Renderer * renderer);
static int DirectFB_CreateTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static int DirectFB_QueryTexturePixels(SDL_Renderer * renderer,
SDL_Texture * texture, void **pixels,
int *pitch);
static int DirectFB_SetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Color * colors,
int firstcolor, int ncolors);
static int DirectFB_GetTexturePalette(SDL_Renderer * renderer,
SDL_Texture * texture,
SDL_Color * colors, int firstcolor,
int ncolors);
static int DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int DirectFB_SetTextureColorMod(SDL_Renderer * renderer,
SDL_Texture * texture);
static int DirectFB_SetTextureBlendMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int DirectFB_SetTextureScaleMode(SDL_Renderer * renderer,
SDL_Texture * texture);
static int DirectFB_UpdateTexture(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
static int DirectFB_LockTexture(SDL_Renderer * renderer,
SDL_Texture * texture, const SDL_Rect * rect,
int markDirty, void **pixels, int *pitch);
static void DirectFB_UnlockTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static void DirectFB_DirtyTexture(SDL_Renderer * renderer,
SDL_Texture * texture, int numrects,
const SDL_Rect * rects);
static int DirectFB_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g,
Uint8 b, Uint8 a, const SDL_Rect * rect);
static int DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);
static void DirectFB_RenderPresent(SDL_Renderer * renderer);
static void DirectFB_DestroyTexture(SDL_Renderer * renderer,
SDL_Texture * texture);
static void DirectFB_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver DirectFB_RenderDriver = {
DirectFB_CreateRenderer,
{
"directfb",
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED),
(SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
SDL_TEXTUREMODULATE_ALPHA),
(SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_MOD),
(SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST),
14,
{
SDL_PIXELFORMAT_INDEX8,
SDL_PIXELFORMAT_INDEX4LSB,
SDL_PIXELFORMAT_RGB332,
SDL_PIXELFORMAT_RGB555,
SDL_PIXELFORMAT_RGB565,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ARGB4444,
SDL_PIXELFORMAT_ARGB1555,
SDL_PIXELFORMAT_RGB24,
SDL_PIXELFORMAT_YV12,
SDL_PIXELFORMAT_IYUV,
SDL_PIXELFORMAT_YUY2,
SDL_PIXELFORMAT_UYVY},
0,
0}
};
typedef struct
{
IDirectFBSurface *surface;
DFBSurfaceFlipFlags flipflags;
int isyuvdirect;
} DirectFB_RenderData;
typedef struct
{
IDirectFBDisplayLayer *vidlayer;
IDirectFBSurface *surface;
Uint32 format;
void *pixels;
int pitch;
IDirectFBPalette *palette;
} DirectFB_TextureData;
static void
UpdateYUVTextureData(SDL_Texture * texture)
{
/*
* Not needed - directfb supports yuv surfaces
*/
}
void
DirectFB_AddRenderDriver(_THIS)
{
int i;
for (i = 0; i < _this->num_displays; i++)
SDL_AddRenderDriver(i, &DirectFB_RenderDriver);
}
SDL_Renderer *
DirectFB_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_DFB_WINDOWDATA(window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_DFB_DEVICEDATA(display->device);
SDL_Renderer *renderer = NULL;
DirectFB_RenderData *data = NULL;
DFBResult ret;
DFBSurfaceDescription dsc;
DFBSurfaceCapabilities scaps;
char *p;
int i, n;
SDL_DFB_CALLOC(renderer, 1, sizeof(*renderer));
SDL_DFB_CALLOC(data, 1, sizeof(*data));
renderer->DisplayModeChanged = DirectFB_DisplayModeChanged;
renderer->CreateTexture = DirectFB_CreateTexture;
renderer->QueryTexturePixels = DirectFB_QueryTexturePixels;
renderer->SetTexturePalette = DirectFB_SetTexturePalette;
renderer->GetTexturePalette = DirectFB_GetTexturePalette;
renderer->SetTextureAlphaMod = DirectFB_SetTextureAlphaMod;
renderer->SetTextureColorMod = DirectFB_SetTextureColorMod;
renderer->SetTextureBlendMode = DirectFB_SetTextureBlendMode;
renderer->SetTextureScaleMode = DirectFB_SetTextureScaleMode;
renderer->UpdateTexture = DirectFB_UpdateTexture;
renderer->LockTexture = DirectFB_LockTexture;
renderer->UnlockTexture = DirectFB_UnlockTexture;
renderer->DirtyTexture = DirectFB_DirtyTexture;
renderer->RenderFill = DirectFB_RenderFill;
renderer->RenderCopy = DirectFB_RenderCopy;
renderer->RenderPresent = DirectFB_RenderPresent;
renderer->DestroyTexture = DirectFB_DestroyTexture;
renderer->DestroyRenderer = DirectFB_DestroyRenderer;
renderer->info = DirectFB_RenderDriver.info;
renderer->window = window->id; // SDL window id
renderer->driverdata = data;
renderer->info.flags =
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTDISCARD;
data->surface = windata->surface;
data->flipflags = 0;
if (flags & SDL_RENDERER_PRESENTVSYNC) {
data->flipflags = DSFLIP_ONSYNC;
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
data->surface->GetCapabilities(data->surface, &scaps);
if (scaps & DSCAPS_DOUBLE)
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
else if (scaps & DSCAPS_TRIPLE)
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
else
renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
data->isyuvdirect = 0;
p = getenv("SDL_DIRECTFB_YUV_DIRECT");
if (p)
data->isyuvdirect = atoi(p);
return renderer;
error:
SDL_DFB_FREE(renderer);
SDL_DFB_FREE(data);
return NULL;
}
static DFBSurfacePixelFormat
SDLToDFBPixelFormat(Uint32 format)
{
switch (format) {
case SDL_PIXELFORMAT_INDEX4LSB:
return DSPF_ALUT44;
case SDL_PIXELFORMAT_INDEX8:
return DSPF_LUT8;
case SDL_PIXELFORMAT_RGB332:
return DSPF_RGB332;
case SDL_PIXELFORMAT_RGB555:
return DSPF_ARGB1555;
case SDL_PIXELFORMAT_ARGB4444:
return DSPF_ARGB4444;
case SDL_PIXELFORMAT_ARGB1555:
return DSPF_ARGB1555;
case SDL_PIXELFORMAT_RGB565:
return DSPF_RGB16;
case SDL_PIXELFORMAT_RGB24:
return DSPF_RGB24;
case SDL_PIXELFORMAT_RGB888:
return DSPF_RGB32;
case SDL_PIXELFORMAT_ARGB8888:
return DSPF_ARGB;
case SDL_PIXELFORMAT_YV12:
return DSPF_YV12; /* Planar mode: Y + V + U (3 planes) */
case SDL_PIXELFORMAT_IYUV:
return DSPF_I420; /* Planar mode: Y + U + V (3 planes) */
case SDL_PIXELFORMAT_YUY2:
return DSPF_YUY2; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
case SDL_PIXELFORMAT_UYVY:
return DSPF_UYVY; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
case SDL_PIXELFORMAT_YVYU:
return DSPF_UNKNOWN; /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
case SDL_PIXELFORMAT_INDEX1LSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_INDEX1MSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_INDEX4MSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_RGB444:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGR24:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGR888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_RGBA8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_ABGR8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGRA8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_ARGB2101010:
return DSPF_UNKNOWN;
default:
return DSPF_UNKNOWN;
}
}
static int
DirectFB_DisplayModeChanged(SDL_Renderer * renderer)
{
SDL_DFB_RENDERERDATA(renderer);
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_DFB_WINDOWDATA(window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_DFB_DEVICEDATA(display->device);
DFBResult ret;
DFBSurfaceDescription dsc;
int i, n;
/*
* Nothing to do here
*/
return 0;
error:
return -1;
}
static int
DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
SDL_DFB_RENDERERDATA(renderer);
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_DFB_WINDOWDATA(window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_DFB_DEVICEDATA(display->device);
DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
DirectFB_TextureData *data;
DFBResult ret;
DFBSurfaceDescription dsc;
DFBDisplayLayerDescription laydsc;
DFBDisplayLayerConfig layconf;
SDL_DFB_CALLOC(data, 1, sizeof(*data));
texture->driverdata = data;
data->format = texture->format;
data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
data->vidlayer = NULL;
if (renddata->isyuvdirect && (dispdata->vidID >= 0)
&& SDL_ISPIXELFORMAT_FOURCC(data->format)) {
SDL_DFB_CHECKERR(devdata->dfb->
GetDisplayLayer(devdata->dfb, dispdata->vidID,
&data->vidlayer));
layconf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
layconf.width = texture->w;
layconf.height = texture->h;
layconf.pixelformat = SDLToDFBPixelFormat(data->format);
SDL_DFB_CHECKERR(data->vidlayer->
SetCooperativeLevel(data->vidlayer,
DLSCL_EXCLUSIVE));
SDL_DFB_CHECKERR(data->vidlayer->
SetConfiguration(data->vidlayer, &layconf));
SDL_DFB_CHECKERR(data->vidlayer->
GetSurface(data->vidlayer, &data->surface));
SDL_DFB_CHECKERR(data->vidlayer->
GetDescription(data->vidlayer, &laydsc));
SDL_DFB_DEBUG("Created HW YUV surface\n");
}
if (!data->vidlayer) {
/* fill surface description */
dsc.flags =
DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
dsc.width = texture->w;
dsc.height = texture->h;
/* Never use DSCAPS_VIDEOONLY here. It kills performance
* No DSCAPS_SYSTEMONLY either - let dfb decide
*/
dsc.caps = 0; //DSCAPS_PREMULTIPLIED;
/* find the right pixelformat */
dsc.pixelformat = SDLToDFBPixelFormat(data->format);
if (dsc.pixelformat == DSPF_UNKNOWN) {
SDL_SetError("Unknown pixel format %d\n", data->format);
goto error;
}
data->pixels = NULL;
/* Create the surface */
SDL_DFB_CHECKERR(devdata->dfb->
CreateSurface(devdata->dfb, &dsc, &data->surface));
if (SDL_ISPIXELFORMAT_INDEXED(data->format)
&& !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
SDL_DFB_CHECKERR(data->surface->
GetPalette(data->surface, &data->palette));
}
}
return 0;
error:
SDL_DFB_RELEASE(data->palette);
SDL_DFB_RELEASE(data->surface);
SDL_DFB_FREE(texture->driverdata);
return -1;
}
static int
DirectFB_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
void **pixels, int *pitch)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
/*
* Always fail here so in compat mode SDL_HWSURFACE is set !
*/
return -1;
}
static int
DirectFB_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Color * colors, int firstcolor,
int ncolors)
{
DirectFB_RenderData *renderdata =
(DirectFB_RenderData *) renderer->driverdata;
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
DFBResult ret;
if (SDL_ISPIXELFORMAT_INDEXED(data->format)
&& !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
DFBColor entries[256];
int i;
for (i = 0; i < ncolors; ++i) {
entries[i].r = colors[i].r;
entries[i].g = colors[i].g;
entries[i].b = colors[i].b;
entries[i].a = 0xFF;
}
SDL_DFB_CHECKERR(data->palette->
SetEntries(data->palette, entries, ncolors,
firstcolor));
return 0;
} else {
SDL_SetError("YUV textures don't have a palette");
return -1;
}
error:
return -1;
}
static int
DirectFB_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_Color * colors, int firstcolor, int ncolors)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
DFBResult ret;
if (SDL_ISPIXELFORMAT_INDEXED(data->format)
&& !SDL_ISPIXELFORMAT_FOURCC(data->format)) {
DFBColor entries[256];
int i;
SDL_DFB_CHECKERR(data->palette->
GetEntries(data->palette, entries, ncolors,
firstcolor));
for (i = 0; i < ncolors; ++i) {
colors[i].r = entries[i].r;
colors[i].g = entries[i].g;
colors[i].b = entries[i].b;
}
return 0;
} else {
SDL_SetError("YUV textures don't have a palette");
return -1;
}
error:
return -1;
}
static int
DirectFB_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
return 0;
}
static int
DirectFB_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
{
return 0;
}
static int
DirectFB_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->blendMode) {
case SDL_TEXTUREBLENDMODE_NONE:
case SDL_TEXTUREBLENDMODE_MASK:
case SDL_TEXTUREBLENDMODE_BLEND:
case SDL_TEXTUREBLENDMODE_MOD:
return 0;
default:
SDL_Unsupported();
texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
return -1;
}
}
static int
DirectFB_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
{
switch (texture->scaleMode) {
case SDL_TEXTURESCALEMODE_NONE:
case SDL_TEXTURESCALEMODE_FAST:
return 0;
case SDL_TEXTURESCALEMODE_SLOW:
case SDL_TEXTURESCALEMODE_BEST:
SDL_Unsupported();
texture->scaleMode = SDL_TEXTURESCALEMODE_FAST;
return -1;
default:
SDL_Unsupported();
texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
return -1;
}
return 0;
}
static int
DirectFB_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels, int pitch)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
DirectFB_RenderData *renderdata =
(DirectFB_RenderData *) renderer->driverdata;
if (data->pixels) {
Uint8 *src, *dst;
int row;
size_t length;
src = (Uint8 *) pixels;
dst =
(Uint8 *) data->pixels + rect->y * data->pitch +
rect->x * SDL_BYTESPERPIXEL(texture->format);
length = rect->w * SDL_BYTESPERPIXEL(texture->format);
for (row = 0; row < rect->h; ++row) {
SDL_memcpy(dst, src, length);
src += pitch;
dst += data->pitch;
}
} else {
SDL_SetError("FIXME: Update without lock!\n");
return -1;
}
return 0;
}
static int
DirectFB_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, int markDirty, void **pixels,
int *pitch)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
DFBResult ret;
void *fdata;
int fpitch;
SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
DSLF_WRITE | DSLF_READ, &fdata,
&fpitch));
data->pixels = fdata;
data->pitch = fpitch;
switch (texture->format) {
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
if (rect
&& (rect->x != 0 || rect->y != 0 || rect->w != texture->w
|| rect->h != texture->h)) {
SDL_SetError
("YV12 and IYUV textures only support full surface locks");
return -1;
}
break;
default:
/* Only one plane, no worries */
break;
}
*pitch = data->pitch;
*pixels = data->pixels;
return 0;
error:
return -1;
}
static void
DirectFB_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
data->surface->Unlock(data->surface);
data->pixels = NULL;
}
static void
DirectFB_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
int numrects, const SDL_Rect * rects)
{
//TODO: DirtyTexture
}
static int
DirectFB_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
Uint8 a, const SDL_Rect * rect)
{
DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
DFBResult ret;
SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, r, g, b, a));
SDL_DFB_CHECKERR(data->surface->
FillRectangle(data->surface, rect->x, rect->y, rect->w,
rect->h));
return 0;
error:
return -1;
}
static int
DirectFB_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
DirectFB_TextureData *texturedata =
(DirectFB_TextureData *) texture->driverdata;
DFBResult ret;
if (texturedata->vidlayer) {
int px, py;
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
SDL_DFB_DEVICEDATA(display->device);
DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
SDL_DFB_WINDOWDATA(window);
SDL_DFB_CHECKERR(texturedata->vidlayer->
SetSourceRectangle(texturedata->vidlayer, srcrect->x,
srcrect->y, srcrect->w,
srcrect->h));
windata->window->GetPosition(windata->window, &px, &py);
SDL_DFB_CHECKERR(texturedata->vidlayer->
SetScreenRectangle(texturedata->vidlayer,
px + dstrect->x, py + dstrect->y,
dstrect->w, dstrect->h));
} else {
DFBRectangle sr, dr;
DFBSurfaceBlittingFlags flags = 0;
sr.x = srcrect->x;
sr.y = srcrect->y;
sr.w = srcrect->w;
sr.h = srcrect->h;
dr.x = dstrect->x;
dr.y = dstrect->y;
dr.w = dstrect->w;
dr.h = dstrect->h;
if (texture->
modMode & (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA))
{
u8 alpha = 0xFF;
if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA)
alpha = texture->a;
if (texture->modMode & SDL_TEXTUREMODULATE_COLOR)
SDL_DFB_CHECKERR(data->surface->
SetColor(data->surface, texture->r,
texture->g, texture->b, alpha));
else
SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
0xFF, 0xFF, alpha));
// Only works together ....
flags |= DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR;
}
if (texture->
blendMode & (SDL_TEXTUREBLENDMODE_MASK |
SDL_TEXTUREBLENDMODE_BLEND)) {
flags |= DSBLIT_BLEND_ALPHACHANNEL;
} else {
flags |= DSBLIT_NOFX;
}
SDL_DFB_CHECKERR(data->surface->
SetBlittingFlags(data->surface, flags));
if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
SDL_DFB_CHECKERR(data->surface->
Blit(data->surface, texturedata->surface, &sr,
dr.x, dr.y));
} else {
SDL_DFB_CHECKERR(data->surface->
StretchBlit(data->surface, texturedata->surface,
&sr, &dr));
}
}
return 0;
error:
return -1;
}
static void
DirectFB_RenderPresent(SDL_Renderer * renderer)
{
DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
SDL_Window *window = SDL_GetWindowFromID(renderer->window);
SDL_DirtyRect *dirty;
DFBRectangle sr;
DFBResult ret;
sr.x = 0;
sr.y = 0;
sr.w = window->w;
sr.h = window->h;
/* Send the data to the display */
SDL_DFB_CHECKERR(data->surface->
Flip(data->surface, NULL, data->flipflags));
return;
error:
return;
}
static void
DirectFB_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
{
DirectFB_TextureData *data = (DirectFB_TextureData *) texture->driverdata;
if (!data) {
return;
}
SDL_DFB_RELEASE(data->palette);
SDL_DFB_RELEASE(data->surface);
SDL_DFB_RELEASE(data->vidlayer);
SDL_free(data);
texture->driverdata = NULL;
}
static void
DirectFB_DestroyRenderer(SDL_Renderer * renderer)
{
DirectFB_RenderData *data = (DirectFB_RenderData *) renderer->driverdata;
int i;
if (data) {
data->surface = NULL;
SDL_free(data);
}
SDL_free(renderer);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* SDL surface based renderer implementation */
#define SDL_DFB_RENDERERDATA(rend) DirectFB_RenderData *renddata = ((rend) ? (DirectFB_RenderData *) (rend)->driverdata : NULL)
extern void DirectFB_AddRenderDriver(_THIS);
/* vi: set ts=4 sw=4 expandtab: */
...@@ -19,10 +19,16 @@ ...@@ -19,10 +19,16 @@
Sam Lantinga Sam Lantinga
slouken@libsdl.org slouken@libsdl.org
MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com SDL1.3 implementation by couriersud@arcor.de
CRTC2 support is inspired by mplayer's dfbmga driver
written by Ville Syrj��<syrjala@sci.fi>
*/ */
/* TODO: Various
* Add Mouse support from 1.2 directfb driver
* - Interface is defined in SDL_Mouse.c.h
* - Default Cursor automatically created
*/
#include "SDL_config.h" #include "SDL_config.h"
/* DirectFB video driver implementation. /* DirectFB video driver implementation.
...@@ -42,44 +48,6 @@ ...@@ -42,44 +48,6 @@
#include "../../events/SDL_events_c.h" #include "../../events/SDL_events_c.h"
#include "SDL_DirectFB_video.h" #include "SDL_DirectFB_video.h"
#include "SDL_DirectFB_events.h" #include "SDL_DirectFB_events.h"
#include "SDL_DirectFB_yuv.h"
/* The implementation dependent data for the window manager cursor */
struct WMcursor
{
int unused;
};
/* Initialization/Query functions */
static int DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat);
static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat * format,
Uint32 flags);
static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface * current,
int width, int height, int bpp,
Uint32 flags);
static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors,
SDL_Color * colors);
static void DirectFB_VideoQuit(_THIS);
/* Hardware surface functions */
static int DirectFB_AllocHWSurface(_THIS, SDL_Surface * surface);
static int DirectFB_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect,
Uint32 color);
static int DirectFB_LockHWSurface(_THIS, SDL_Surface * surface);
static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface * surface);
static void DirectFB_FreeHWSurface(_THIS, SDL_Surface * surface);
static int DirectFB_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst);
static int DirectFB_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
SDL_Surface * dst, SDL_Rect * dstrect);
static int DirectFB_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key);
static int DirectFB_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha);
static int DirectFB_FlipHWSurface(_THIS, SDL_Surface * surface);
static int DirectFB_ShowWMCursor(_THIS, WMcursor * cursor);
/* Various screen update functions available */
static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect * rects);
/* This is the rect EnumModes2 uses */ /* This is the rect EnumModes2 uses */
struct DirectFBEnumRect struct DirectFBEnumRect
...@@ -88,8 +56,51 @@ struct DirectFBEnumRect ...@@ -88,8 +56,51 @@ struct DirectFBEnumRect
struct DirectFBEnumRect *next; struct DirectFBEnumRect *next;
}; };
static struct DirectFBEnumRect *enumlist = NULL; struct DirectFB_GLContext
{
IDirectFBGL *context;
};
/* Initialization/Query functions */
static int DirectFB_VideoInit(_THIS);
static void DirectFB_VideoQuit(_THIS);
static int DirectFB_CreateWindow(_THIS, SDL_Window * window);
static int DirectFB_CreateWindowFrom(_THIS, SDL_Window * window,
const void *data);
static void DirectFB_SetWindowTitle(_THIS, SDL_Window * window);
static void DirectFB_SetWindowPosition(_THIS, SDL_Window * window);
static void DirectFB_SetWindowSize(_THIS, SDL_Window * window);
static void DirectFB_ShowWindow(_THIS, SDL_Window * window);
static void DirectFB_HideWindow(_THIS, SDL_Window * window);
static void DirectFB_RaiseWindow(_THIS, SDL_Window * window);
static void DirectFB_MaximizeWindow(_THIS, SDL_Window * window);
static void DirectFB_MinimizeWindow(_THIS, SDL_Window * window);
static void DirectFB_RestoreWindow(_THIS, SDL_Window * window);
static void DirectFB_SetWindowGrab(_THIS, SDL_Window * window);
static void DirectFB_DestroyWindow(_THIS, SDL_Window * window);
static SDL_bool DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
static void DirectFB_GetDisplayModes(_THIS);
static int DirectFB_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
static int DirectFB_SetDisplayGammaRamp(_THIS, Uint16 * ramp);
static int DirectFB_GetDisplayGammaRamp(_THIS, Uint16 * ramp);
#if SDL_DIRECTFB_OPENGL
static int DirectFB_GL_LoadLibrary(_THIS, const char *path);
static void DirectFB_GL_UnloadLibrary(_THIS);
static void *DirectFB_GL_GetProcAddress(_THIS, const char *proc);
static SDL_GLContext DirectFB_GL_CreateContext(_THIS, SDL_Window * window);
static int DirectFB_GL_MakeCurrent(_THIS, SDL_Window * window,
SDL_GLContext context);
static int DirectFB_GL_SetSwapInterval(_THIS, int interval);
static int DirectFB_GL_GetSwapInterval(_THIS);
static void DirectFB_GL_SwapWindow(_THIS, SDL_Window * window);
static void DirectFB_GL_DeleteContext(_THIS, SDL_GLContext context);
#endif
/* DirectFB driver bootstrap functions */ /* DirectFB driver bootstrap functions */
...@@ -102,7 +113,7 @@ DirectFB_Available(void) ...@@ -102,7 +113,7 @@ DirectFB_Available(void)
static void static void
DirectFB_DeleteDevice(SDL_VideoDevice * device) DirectFB_DeleteDevice(SDL_VideoDevice * device)
{ {
SDL_free(device->hidden); SDL_free(device->driverdata);
SDL_free(device); SDL_free(device);
} }
...@@ -112,50 +123,60 @@ DirectFB_CreateDevice(int devindex) ...@@ -112,50 +123,60 @@ DirectFB_CreateDevice(int devindex)
SDL_VideoDevice *device; SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */ /* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice)); SDL_DFB_CALLOC(device, 1, sizeof(SDL_VideoDevice));
if (device) { SDL_DFB_CALLOC(device->gl_data, 1, sizeof(*device->gl_data));
SDL_memset(device, 0, (sizeof *device));
device->hidden = (struct SDL_PrivateVideoData *) /* Set the function pointers */
malloc(sizeof(*device->hidden));
}
if (device == NULL || device->hidden == NULL) {
SDL_OutOfMemory();
if (device) {
free(device);
}
return (0);
}
SDL_memset(device->hidden, 0, sizeof(*device->hidden));
/* Set the function pointers */ /* Set the function pointers */
device->VideoInit = DirectFB_VideoInit; device->VideoInit = DirectFB_VideoInit;
device->ListModes = DirectFB_ListModes;
device->SetVideoMode = DirectFB_SetVideoMode;
device->SetColors = DirectFB_SetColors;
device->UpdateRects = NULL;
device->CreateYUVOverlay = DirectFB_CreateYUVOverlay;
device->VideoQuit = DirectFB_VideoQuit; device->VideoQuit = DirectFB_VideoQuit;
device->AllocHWSurface = DirectFB_AllocHWSurface; device->GetDisplayModes = DirectFB_GetDisplayModes;
device->CheckHWBlit = DirectFB_CheckHWBlit; device->SetDisplayMode = DirectFB_SetDisplayMode;
device->FillHWRect = DirectFB_FillHWRect; #if 0
device->SetHWColorKey = DirectFB_SetHWColorKey; device->SetDisplayGammaRamp = DirectFB_SetDisplayGammaRamp;
device->SetHWAlpha = DirectFB_SetHWAlpha; device->GetDisplayGammaRamp = DirectFB_GetDisplayGammaRamp;
device->LockHWSurface = DirectFB_LockHWSurface; #else
device->UnlockHWSurface = DirectFB_UnlockHWSurface; device->SetDisplayGammaRamp = NULL;
device->FlipHWSurface = DirectFB_FlipHWSurface; device->GetDisplayGammaRamp = NULL;
device->FreeHWSurface = DirectFB_FreeHWSurface; #endif
device->ShowWMCursor = DirectFB_ShowWMCursor; device->PumpEvents = DirectFB_PumpEventsWindow;
device->SetCaption = NULL;
device->SetIcon = NULL; device->CreateWindow = DirectFB_CreateWindow;
device->IconifyWindow = NULL; device->CreateWindowFrom = DirectFB_CreateWindowFrom;
device->GrabInput = NULL; device->SetWindowTitle = DirectFB_SetWindowTitle;
device->GetWMInfo = NULL; device->SetWindowPosition = DirectFB_SetWindowPosition;
device->InitOSKeymap = DirectFB_InitOSKeymap; device->SetWindowSize = DirectFB_SetWindowSize;
device->PumpEvents = DirectFB_PumpEvents; device->ShowWindow = DirectFB_ShowWindow;
device->HideWindow = DirectFB_HideWindow;
device->RaiseWindow = DirectFB_RaiseWindow;
device->MaximizeWindow = DirectFB_MaximizeWindow;
device->MinimizeWindow = DirectFB_MinimizeWindow;
device->RestoreWindow = DirectFB_RestoreWindow;
device->SetWindowGrab = DirectFB_SetWindowGrab;
device->DestroyWindow = DirectFB_DestroyWindow;
device->GetWindowWMInfo = DirectFB_GetWindowWMInfo;
#if SDL_DIRECTFB_OPENGL
device->GL_LoadLibrary = DirectFB_GL_LoadLibrary;
device->GL_GetProcAddress = DirectFB_GL_GetProcAddress;
device->GL_MakeCurrent = DirectFB_GL_MakeCurrent;
device->GL_CreateContext = DirectFB_GL_CreateContext;
device->GL_SetSwapInterval = DirectFB_GL_SetSwapInterval;
device->GL_GetSwapInterval = DirectFB_GL_GetSwapInterval;
device->GL_SwapWindow = DirectFB_GL_SwapWindow;
device->GL_DeleteContext = DirectFB_GL_DeleteContext;
#endif
device->free = DirectFB_DeleteDevice; device->free = DirectFB_DeleteDevice;
return device; return device;
error:
if (device)
free(device);
return (0);
} }
VideoBootStrap DirectFB_bootstrap = { VideoBootStrap DirectFB_bootstrap = {
...@@ -163,214 +184,107 @@ VideoBootStrap DirectFB_bootstrap = { ...@@ -163,214 +184,107 @@ VideoBootStrap DirectFB_bootstrap = {
DirectFB_Available, DirectFB_CreateDevice DirectFB_Available, DirectFB_CreateDevice
}; };
static DFBSurfacePixelFormat
GetFormatForBpp(int bpp, IDirectFBDisplayLayer * layer)
{
DFBDisplayLayerConfig dlc;
int bytes = (bpp + 7) / 8;
layer->GetConfiguration(layer, &dlc);
if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1)
return dlc.pixelformat;
switch (bytes) {
case 1:
return DSPF_LUT8;
case 2:
return DSPF_RGB16;
case 3:
return DSPF_RGB24;
case 4:
return DSPF_RGB32;
}
return DSPF_UNKNOWN;
}
static DFBEnumerationResult static DFBEnumerationResult
EnumModesCallback(int width, int height, int bpp, void *data) EnumModesCallback(int width, int height, int bpp, void *data)
{ {
SDL_VideoDevice *this = (SDL_VideoDevice *) data; SDL_VideoDisplay *this = (SDL_VideoDisplay *) data;
struct DirectFBEnumRect *enumrect; DFB_DisplayData *dispdata = (DFB_DisplayData *) this->driverdata;
SDL_DisplayMode mode;
HIDDEN->nummodes++;
if (enumlist && enumlist->r.w == width && enumlist->r.h == height) mode.w = width;
return DFENUM_OK; mode.h = height;
mode.refresh_rate = 0;
mode.driverdata = NULL;
mode.format = 0;
enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect)); if (dispdata->nummodes < DFB_MAX_MODES) {
if (!enumrect) { dispdata->modelist[dispdata->nummodes++] = mode;
SDL_OutOfMemory();
return DFENUM_CANCEL;
} }
enumrect->r.w = (Uint16) width; SDL_DFB_DEBUG("w %d h %d bpp %d\n", width, height, bpp);
enumrect->r.h = (Uint16) height;
enumrect->next = enumlist;
enumlist = enumrect;
return DFENUM_OK; return DFENUM_OK;
} }
struct private_hwdata static int
{ DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat, Uint32 * fmt)
IDirectFBSurface *surface;
IDirectFBPalette *palette;
};
void
SetDirectFBerror(const char *function, DFBResult code)
{
const char *error = DirectFBErrorString(code);
if (error)
SDL_SetError("%s: %s", function, error);
else
SDL_SetError("Unknown error code from %s", function);
}
static DFBSurfacePixelFormat
SDLToDFBPixelFormat(SDL_PixelFormat * format)
{ {
if (format->Rmask && format->Gmask && format->Bmask) { switch (pixelformat) {
switch (format->BitsPerPixel) { case DSPF_ALUT44:
case 8: *fmt = SDL_PIXELFORMAT_INDEX4LSB;
return DSPF_LUT8;
case 16:
if (format->Rmask == 0xF800 &&
format->Gmask == 0x07E0 && format->Bmask == 0x001F)
return DSPF_RGB16;
/* fall through */
case 15:
if (format->Rmask == 0x7C00 &&
format->Gmask == 0x03E0 && format->Bmask == 0x001F)
return DSPF_ARGB1555;
break; break;
case DSPF_LUT8:
case 24: *fmt = SDL_PIXELFORMAT_INDEX8;
if (format->Rmask == 0xFF0000 &&
format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF)
return DSPF_RGB24;
break; break;
case DSPF_RGB332:
case 32: *fmt = SDL_PIXELFORMAT_RGB332;
if (format->Rmask == 0xFF0000 &&
format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF) {
if (format->Amask == 0xFF000000)
return DSPF_ARGB;
else
return DSPF_RGB32;
}
break; break;
} case DSPF_ARGB4444:
} else { *fmt = SDL_PIXELFORMAT_ARGB4444;
switch (format->BitsPerPixel) {
case 8:
return DSPF_LUT8;
case 15:
return DSPF_ARGB1555;
case 16:
return DSPF_RGB16;
case 24:
return DSPF_RGB24;
case 32:
return DSPF_RGB32;
}
}
return DSPF_UNKNOWN;
}
static SDL_Palette *
AllocatePalette(int size)
{
SDL_Palette *palette;
SDL_Color *colors;
palette = SDL_calloc(1, sizeof(SDL_Palette));
if (!palette) {
SDL_OutOfMemory();
return NULL;
}
colors = SDL_calloc(size, sizeof(SDL_Color));
if (!colors) {
SDL_OutOfMemory();
return NULL;
}
palette->ncolors = size;
palette->colors = colors;
return palette;
}
static int
DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat,
SDL_PixelFormat * format)
{
format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
format->BitsPerPixel = format->BytesPerPixel = 0;
switch (pixelformat) {
case DSPF_A8:
format->Amask = 0x000000FF;
break; break;
case SDL_PIXELFORMAT_ARGB1555:
case DSPF_ARGB1555: *fmt = SDL_PIXELFORMAT_ARGB1555;
format->Rmask = 0x00007C00;
format->Gmask = 0x000003E0;
format->Bmask = 0x0000001F;
break; break;
case DSPF_RGB16: case DSPF_RGB16:
format->Rmask = 0x0000F800; *fmt = SDL_PIXELFORMAT_RGB565;
format->Gmask = 0x000007E0;
format->Bmask = 0x0000001F;
break; break;
case DSPF_ARGB:
format->Amask = 0; /* apps don't seem to like that: 0xFF000000; */
/* fall through */
case DSPF_RGB24: case DSPF_RGB24:
*fmt = SDL_PIXELFORMAT_RGB24;
break;
case DSPF_RGB32: case DSPF_RGB32:
format->Rmask = 0x00FF0000; *fmt = SDL_PIXELFORMAT_RGB888;
format->Gmask = 0x0000FF00;
format->Bmask = 0x000000FF;
break; break;
case DSPF_ARGB:
case DSPF_LUT8: *fmt = SDL_PIXELFORMAT_ARGB8888;
format->Rmask = 0x000000FF;
format->Gmask = 0x000000FF;
format->Bmask = 0x000000FF;
if (!format->palette)
format->palette = AllocatePalette(256);
break; break;
case DSPF_YV12:
*fmt = SDL_PIXELFORMAT_YV12;
break; /* Planar mode: Y + V + U (3 planes) */
case DSPF_I420:
*fmt = SDL_PIXELFORMAT_IYUV;
break; /* Planar mode: Y + U + V (3 planes) */
case DSPF_YUY2:
*fmt = SDL_PIXELFORMAT_YUY2;
break; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
case DSPF_UYVY:
*fmt = SDL_PIXELFORMAT_UYVY;
break; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
default: default:
fprintf(stderr,
"SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n",
pixelformat);
return -1; return -1;
} }
return 0;
}
format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8; static DFBEnumerationResult
format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat); cbScreens(DFBScreenID screen_id, DFBScreenDescription desc,
void *callbackdata)
{
DFB_DeviceData *devdata = (DFB_DeviceData *) callbackdata;
return 0; devdata->screenid[devdata->numscreens++] = screen_id;
return DFENUM_OK;
} }
DFBEnumerationResult
cbLayers(DFBDisplayLayerID layer_id, DFBDisplayLayerDescription desc,
void *callbackdata)
{
DFB_DeviceData *devdata = (DFB_DeviceData *) callbackdata;
int if (desc.caps & DLCAPS_SURFACE) {
DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat) if ((desc.type & DLTF_GRAPHICS) && (desc.type & DLTF_VIDEO)) {
if (devdata->vidlayer[devdata->aux] == -1)
devdata->vidlayer[devdata->aux] = layer_id;
} else if (desc.type & DLTF_GRAPHICS) {
if (devdata->gralayer[devdata->aux] == -1)
devdata->gralayer[devdata->aux] = layer_id;
}
}
return DFENUM_OK;
}
static int
DirectFB_VideoInit(_THIS)
{ {
int i;
DFBResult ret;
#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
DFBCardCapabilities caps; DFBCardCapabilities caps;
#else #else
...@@ -380,801 +294,816 @@ DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat) ...@@ -380,801 +294,816 @@ DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat)
struct DirectFBEnumRect *rect; struct DirectFBEnumRect *rect;
IDirectFB *dfb = NULL; IDirectFB *dfb = NULL;
IDirectFBDisplayLayer *layer = NULL; IDirectFBDisplayLayer *layer = NULL;
IDirectFBEventBuffer *events = NULL;
HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL; SDL_VideoDisplay display;
HIDDEN->enable_mga_crtc2 = 0; DFB_DisplayData *dispdata;
HIDDEN->mga_crtc2_stretch_overscan = 1; DFB_DeviceData *devdata;
SDL_DisplayMode mode;
SDL_Keyboard keyboard;
int i;
DFBResult ret;
int tcw[DFB_MAX_SCREENS];
int tch[DFB_MAX_SCREENS];
ret = DirectFBInit(NULL, NULL); SDL_zero(keyboard);
if (ret) {
SetDirectFBerror("DirectFBInit", ret);
goto error;
}
ret = DirectFBCreate(&dfb); SDL_DFB_CHECKERR(DirectFBInit(NULL, NULL));
if (ret) { SDL_DFB_CHECKERR(DirectFBCreate(&dfb));
SetDirectFBerror("DirectFBCreate", ret);
goto error;
}
ret = dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer); SDL_DFB_CALLOC(devdata, 1, sizeof(*devdata));
if (ret) { devdata->numscreens = 0;
SetDirectFBerror("dfb->GetDisplayLayer", ret); for (i = 0; i < DFB_MAX_SCREENS; i++) {
goto error; devdata->gralayer[i] = -1;
devdata->vidlayer[i] = -1;
} }
SDL_DFB_CHECKERR(dfb->EnumScreens(dfb, &cbScreens, devdata));
for (i = 0; i < devdata->numscreens; i++) {
IDirectFBScreen *screen;
ret = dfb->CreateInputEventBuffer(dfb, DICAPS_ALL, DFB_FALSE, &events); SDL_DFB_CHECKERR(dfb->GetScreen(dfb, devdata->screenid[i], &screen));
if (ret) {
SetDirectFBerror("dfb->CreateEventBuffer", ret); devdata->aux = i;
goto error; SDL_DFB_CHECKERR(screen->
EnumDisplayLayers(screen, &cbLayers, devdata));
screen->GetSize(screen, &tcw[i], &tch[i]);
screen->Release(screen);
} }
layer->EnableCursor(layer, 1); /* Query card capabilities */
/* Query layer configuration to determine the current mode and pixelformat */ dfb->GetDeviceDescription(dfb, &caps);
layer->GetConfiguration(layer, &dlc);
/* If current format is not supported use LUT8 as the default */ SDL_DFB_DEBUG("SDL directfb video driver - %s %s\n", __DATE__, __TIME__);
if (DFBToSDLPixelFormat(dlc.pixelformat, vformat)) SDL_DFB_DEBUG("Using %s (%s) driver.\n", caps.name, caps.vendor);
DFBToSDLPixelFormat(DSPF_LUT8, vformat); SDL_DFB_DEBUG("Found %d screens\n", devdata->numscreens);
/* Enumerate the available fullscreen modes */ for (i = 0; i < devdata->numscreens; i++) {
ret = dfb->EnumVideoModes(dfb, EnumModesCallback, this); //SDL_DFB_CHECKERR( dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer) );
if (ret) { SDL_DFB_CHECKERR(dfb->
SetDirectFBerror("dfb->EnumVideoModes", ret); GetDisplayLayer(dfb, devdata->gralayer[i], &layer));
goto error; //SDL_DFB_CHECKERR( dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events) );
}
HIDDEN->modelist = SDL_calloc(HIDDEN->nummodes + 1, sizeof(SDL_Rect *)); SDL_DFB_CHECKERR(layer->
if (!HIDDEN->modelist) { SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE));
SDL_OutOfMemory(); layer->EnableCursor(layer, 1);
goto error; SDL_DFB_CHECKERR(layer->SetCursorOpacity(layer, 0xC0));
} SDL_DFB_CHECKERR(layer->SetCooperativeLevel(layer, DLSCL_SHARED));
for (i = 0, rect = enumlist; rect; ++i, rect = rect->next) { /* Query layer configuration to determine the current mode and pixelformat */
HIDDEN->modelist[i] = &rect->r; layer->GetConfiguration(layer, &dlc);
}
HIDDEN->modelist[i] = NULL; DFBToSDLPixelFormat(dlc.pixelformat, &mode.format);
mode.w = dlc.width;
mode.h = dlc.height;
mode.refresh_rate = 0;
mode.driverdata = NULL;
/* Query card capabilities to get the video memory size */ SDL_DFB_CALLOC(dispdata, 1, sizeof(*dispdata));
#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
dfb->GetCardCapabilities(dfb, &caps);
#else
dfb->GetDeviceDescription(dfb, &caps);
#endif
this->info.wm_available = 1; dispdata->layer = layer;
this->info.hw_available = 1; dispdata->pixelformat = dlc.pixelformat;
this->info.blit_hw = 1; dispdata->cw = tcw[i];
this->info.blit_hw_CC = 1; dispdata->ch = tch[i];
this->info.blit_hw_A = 1;
this->info.blit_fill = 1;
this->info.video_mem = caps.video_memory / 1024;
this->info.current_w = dlc.width;
this->info.current_h = dlc.height;
HIDDEN->initialized = 1;
HIDDEN->dfb = dfb;
HIDDEN->layer = layer;
HIDDEN->eventbuffer = events;
if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL)
HIDDEN->enable_mga_crtc2 = 1;
if (HIDDEN->enable_mga_crtc2) {
DFBDisplayLayerConfig dlc;
DFBDisplayLayerConfigFlags failed;
ret = dfb->GetDisplayLayer(dfb, 2, &HIDDEN->c2layer); /* YUV - Video layer */
if (ret) {
SetDirectFBerror("dfb->GetDisplayLayer(CRTC2)", ret);
goto error;
}
ret = dispdata->vidID = devdata->vidlayer[i];
HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer,
DLSCL_EXCLUSIVE);
if (ret) {
SetDirectFBerror
("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
goto error;
}
ret = SDL_zero(display);
HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer,
DLSCL_EXCLUSIVE);
if (ret) {
SetDirectFBerror
("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
goto error;
}
HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
/* Init the surface here as it got a fixed size */ display.desktop_mode = mode;
dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; display.current_mode = mode;
dlc.buffermode = DLBM_BACKVIDEO; display.driverdata = dispdata;
dlc.pixelformat = DSPF_RGB32;
ret = /* Enumerate the available fullscreen modes */
HIDDEN->c2layer->TestConfiguration(HIDDEN->c2layer, &dlc, SDL_DFB_CALLOC(dispdata->modelist, DFB_MAX_MODES,
&failed); sizeof(SDL_DisplayMode));
if (ret) { SDL_DFB_CHECKERR(dfb->
SetDirectFBerror("c2layer->TestConfiguration", ret); EnumVideoModes(dfb, EnumModesCallback, &display));
goto error;
}
ret = HIDDEN->c2layer->SetConfiguration(HIDDEN->c2layer, &dlc);
if (ret) {
SetDirectFBerror("c2layer->SetConfiguration", ret);
goto error;
}
ret = HIDDEN->c2layer->GetSurface(HIDDEN->c2layer, &HIDDEN->c2frame); SDL_AddVideoDisplay(&display);
if (ret) {
SetDirectFBerror("c2layer->GetSurface", ret);
goto error;
} }
HIDDEN->c2framesize.x = 0; devdata->initialized = 1;
HIDDEN->c2framesize.y = 0; devdata->dfb = dfb;
HIDDEN->c2frame->GetSize(HIDDEN->c2frame, &HIDDEN->c2framesize.w, devdata->firstwin = NULL;
&HIDDEN->c2framesize.h);
HIDDEN->c2frame->SetBlittingFlags(HIDDEN->c2frame, DSBLIT_NOFX);
HIDDEN->c2frame->SetColor(HIDDEN->c2frame, 0, 0, 0, 0xff);
/* Clear CRTC2 */
HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0);
HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0);
HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF);
/* Check if overscan is possibly set */
if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL) {
float overscan = 0;
if (SDL_sscanf
(SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f",
&overscan) == 1)
if (overscan > 0 && overscan < 2)
HIDDEN->mga_crtc2_stretch_overscan = overscan;
}
#ifdef DIRECTFB_CRTC2_DEBUG
printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan);
#endif
}
return 0; _this->driverdata = devdata;
error:
if (events)
events->Release(events);
if (HIDDEN->c2frame) #if SDL_DIRECTFB_OPENGL
HIDDEN->c2frame->Release(HIDDEN->c2frame); /* Opengl */
_this->gl_data->gl_active = 0;
_this->gl_data->gl_context = NULL;
#endif
if (HIDDEN->c2layer) DirectFB_AddRenderDriver(_this);
HIDDEN->c2layer->Release(HIDDEN->c2layer); DirectFB_InitMouse(_this);
//devdata->mouse = SDL_AddMouse(&mouse, -1);
devdata->keyboard = SDL_AddKeyboard(&keyboard, -1);
DirectFB_InitOSKeymap(_this);
if (layer) return 0;
layer->Release(layer);
if (dfb)
dfb->Release(dfb);
error:
//FIXME: Cleanup not complete, Free existing displays
SDL_DFB_FREE(dispdata);
SDL_DFB_FREE(dispdata->modelist);
SDL_DFB_RELEASE(layer);
SDL_DFB_RELEASE(dfb);
return -1; return -1;
} }
static SDL_Rect ** static void
DirectFB_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags) DirectFB_VideoQuit(_THIS)
{
if (flags & SDL_FULLSCREEN)
return HIDDEN->modelist;
else if (SDLToDFBPixelFormat(format) != DSPF_UNKNOWN)
return (SDL_Rect **) - 1;
return NULL;
}
static SDL_Surface *
DirectFB_SetVideoMode(_THIS, SDL_Surface * current, int width, int height,
int bpp, Uint32 flags)
{ {
DFB_DeviceData *devdata = (DFB_DeviceData *) _this->driverdata;
SDL_DisplayMode tmode;
DFBResult ret; DFBResult ret;
DFBSurfaceDescription dsc; int i;
DFBSurfacePixelFormat pixelformat;
IDirectFBSurface *surface;
fprintf(stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
width, height, bpp, flags);
flags |= SDL_FULLSCREEN;
/* Release previous primary surface */
if (current->hwdata && current->hwdata->surface) {
current->hwdata->surface->Release(current->hwdata->surface);
current->hwdata->surface = NULL;
/* And its palette if present */
if (current->hwdata->palette) {
current->hwdata->palette->Release(current->hwdata->palette);
current->hwdata->palette = NULL;
}
} else if (!current->hwdata) {
/* Allocate the hardware acceleration data */
current->hwdata =
(struct private_hwdata *) SDL_calloc(1, sizeof(*current->hwdata));
if (!current->hwdata) {
SDL_OutOfMemory();
return NULL;
}
}
/* Set cooperative level depending on flag SDL_FULLSCREEN */
if (flags & SDL_FULLSCREEN) {
ret = HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_FULLSCREEN);
if (ret && !HIDDEN->enable_mga_crtc2) {
DirectFBError("dfb->SetCooperativeLevel", ret);
flags &= ~SDL_FULLSCREEN;
}
} else
HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_NORMAL);
/* Set video mode */
ret = HIDDEN->dfb->SetVideoMode(HIDDEN->dfb, width, height, bpp);
if (ret) {
if (flags & SDL_FULLSCREEN) {
flags &= ~SDL_FULLSCREEN;
HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_NORMAL);
ret = HIDDEN->dfb->SetVideoMode(HIDDEN->dfb, width, height, bpp);
}
if (ret) { tmode = _this->displays[0].desktop_mode;
SetDirectFBerror("dfb->SetVideoMode", ret); tmode.format = SDL_PIXELFORMAT_UNKNOWN;
return NULL; DirectFB_SetDisplayMode(_this, &tmode);
} tmode = _this->displays[0].desktop_mode;
} DirectFB_SetDisplayMode(_this, &tmode);
for (i = 0; i < devdata->numscreens; i++) {
DFB_DisplayData *dispdata =
(DFB_DisplayData *) _this->displays[i].driverdata;
if (dispdata->layer) {
SDL_DFB_CHECK(dispdata->layer->
SetCooperativeLevel(dispdata->layer,
DLSCL_ADMINISTRATIVE));
SDL_DFB_CHECK(dispdata->layer->
SetCursorOpacity(dispdata->layer, 0x00));
SDL_DFB_CHECK(dispdata->layer->
SetCooperativeLevel(dispdata->layer, DLSCL_SHARED));
}
SDL_DFB_RELEASE(dispdata->layer);
/* Create primary surface */ /* Free video mode list */
dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; if (dispdata->modelist) {
dsc.caps = SDL_free(dispdata->modelist);
DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0); dispdata->modelist = NULL;
dsc.pixelformat = GetFormatForBpp(bpp, HIDDEN->layer);
ret = HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc, &surface);
if (ret && (flags & SDL_DOUBLEBUF)) {
/* Try without double buffering */
dsc.caps &= ~DSCAPS_FLIPPING;
ret = HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc, &surface);
} }
if (ret) { // Done by core
SetDirectFBerror("dfb->CreateSurface", ret); //SDL_free(dispdata);
return NULL;
} }
current->w = width; //SDL_DFB_RELEASE(devdata->eventbuffer);
current->h = height;
current->flags = SDL_HWSURFACE | SDL_PREALLOC;
if (flags & SDL_FULLSCREEN) {
current->flags |= SDL_FULLSCREEN;
this->UpdateRects = DirectFB_DirectUpdate;
} else
this->UpdateRects = DirectFB_WindowedUpdate;
if (dsc.caps & DSCAPS_FLIPPING)
current->flags |= SDL_DOUBLEBUF;
surface->GetPixelFormat(surface, &pixelformat);
DFBToSDLPixelFormat(pixelformat, current->format);
/* Get the surface palette (if supported) */
if (DFB_PIXELFORMAT_IS_INDEXED(pixelformat)) {
surface->GetPalette(surface, &current->hwdata->palette);
current->flags |= SDL_HWPALETTE;
}
current->hwdata->surface = surface; SDL_DFB_RELEASE(devdata->dfb);
/* MGA CRTC2 stuff */ SDL_DelMouse(devdata->mouse);
if (HIDDEN->enable_mga_crtc2) { SDL_DelKeyboard(devdata->keyboard);
/* no stretching if c2ssize == c2framesize */
HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
HIDDEN->c2ssize.w = width;
HIDDEN->c2ssize.h = height;
HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0; #if SDL_DIRECTFB_OPENGL
HIDDEN->c2dsize.w = width; DirectFB_GL_UnloadLibrary(_this);
HIDDEN->c2dsize.h = height; #endif
HIDDEN->mga_crtc2_stretch = 0;
if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL) {
/* Normally assume a picture aspect ratio of 4:3 */
int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j;
for (i = 1; i < 20; i++) {
for (j = 1; j < 10; j++) {
if ((float) width / (float) i * (float) j == height) {
zoom_aspect_x = i;
zoom_aspect_y = j;
/* break the loop */ devdata->initialized = 0;
i = 21; }
break;
}
}
}
#ifdef DIRECTFB_CRTC2_DEBUG
printf
("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n",
width, height, zoom_aspect_x, zoom_aspect_y);
printf("CRTC2 resolution: X: %d, Y: %d\n",
HIDDEN->c2framesize.w, HIDDEN->c2framesize.h);
#endif
/* don't stretch only slightly smaller/larger images */ static DFBSurfacePixelFormat
if ((float) width < (float) HIDDEN->c2framesize.w * 0.95 SDLToDFBPixelFormat(Uint32 format)
|| (float) height < (float) HIDDEN->c2framesize.h * 0.95) { {
while ((float) HIDDEN->c2dsize.w < switch (format) {
(float) HIDDEN->c2framesize.w * case SDL_PIXELFORMAT_INDEX4LSB:
HIDDEN->mga_crtc2_stretch_overscan return DSPF_ALUT44;
&& (float) HIDDEN->c2dsize.h < case SDL_PIXELFORMAT_INDEX8:
(float) HIDDEN->c2framesize.h * return DSPF_LUT8;
HIDDEN->mga_crtc2_stretch_overscan) { case SDL_PIXELFORMAT_RGB332:
HIDDEN->c2dsize.w += zoom_aspect_x; return DSPF_RGB332;
HIDDEN->c2dsize.h += zoom_aspect_y; case SDL_PIXELFORMAT_RGB555:
return DSPF_ARGB1555;
case SDL_PIXELFORMAT_ARGB4444:
return DSPF_ARGB4444;
case SDL_PIXELFORMAT_ARGB1555:
return DSPF_ARGB1555;
case SDL_PIXELFORMAT_RGB565:
return DSPF_RGB16;
case SDL_PIXELFORMAT_RGB24:
return DSPF_RGB24;
case SDL_PIXELFORMAT_RGB888:
return DSPF_RGB32;
case SDL_PIXELFORMAT_ARGB8888:
return DSPF_ARGB;
case SDL_PIXELFORMAT_YV12:
return DSPF_YV12; /* Planar mode: Y + V + U (3 planes) */
case SDL_PIXELFORMAT_IYUV:
return DSPF_I420; /* Planar mode: Y + U + V (3 planes) */
case SDL_PIXELFORMAT_YUY2:
return DSPF_YUY2; /* Packed mode: Y0+U0+Y1+V0 (1 plane) */
case SDL_PIXELFORMAT_UYVY:
return DSPF_UYVY; /* Packed mode: U0+Y0+V0+Y1 (1 plane) */
case SDL_PIXELFORMAT_YVYU:
return DSPF_UNKNOWN; /* Packed mode: Y0+V0+Y1+U0 (1 plane) */
case SDL_PIXELFORMAT_INDEX1LSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_INDEX1MSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_INDEX4MSB:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_RGB444:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGR24:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGR888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_RGBA8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_ABGR8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_BGRA8888:
return DSPF_UNKNOWN;
case SDL_PIXELFORMAT_ARGB2101010:
return DSPF_UNKNOWN;
default:
return DSPF_UNKNOWN;
} }
}
/* one step down */ static void
HIDDEN->c2dsize.w -= zoom_aspect_x; CheckSetDisplayMode(_THIS, DFB_DisplayData * data, SDL_DisplayMode * mode)
HIDDEN->c2dsize.h -= zoom_aspect_y; {
DFBDisplayLayerConfig config;
#ifdef DIRECTFB_CRTC2_DEBUG DFBDisplayLayerConfigFlags failed;
printf("Stretched resolution: X: %d, Y: %d\n",
HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
#endif
HIDDEN->mga_crtc2_stretch = 1; config.width = mode->w;
} else if ((float) width > (float) HIDDEN->c2framesize.w * 0.95 config.height = mode->h;
|| (float) height > config.pixelformat = SDLToDFBPixelFormat(mode->format);
(float) HIDDEN->c2framesize.h * 0.95) { config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
while ((float) HIDDEN->c2dsize.w > failed = 0;
(float) HIDDEN->c2framesize.w * data->layer->TestConfiguration(data->layer, &config, &failed);
HIDDEN->mga_crtc2_stretch_overscan if (failed == 0)
|| (float) HIDDEN->c2dsize.h > SDL_AddDisplayMode(_this->current_display, mode);
(float) HIDDEN->c2framesize.h *
HIDDEN->mga_crtc2_stretch_overscan) {
HIDDEN->c2dsize.w -= zoom_aspect_x;
HIDDEN->c2dsize.h -= zoom_aspect_y;
}
#ifdef DIRECTFB_CRTC2_DEBUG }
printf("Down-Stretched resolution: X: %d, Y: %d\n",
HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
#endif
HIDDEN->mga_crtc2_stretch = 1; static void
} else { DirectFB_GetDisplayModes(_THIS)
#ifdef DIRECTFB_CRTC2_DEBUG {
printf("Not stretching image\n"); //SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
#endif //SDL_DisplayMode mode;
} //SDL_AddDisplayMode(_this->current_display, &mode);
/* Panning */ SDL_DFB_DEVICEDATA(_this);
if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w) DFB_DisplayData *data = (DFB_DisplayData *) SDL_CurrentDisplay.driverdata;
HIDDEN->c2dsize.x = int i;
(HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2; SDL_DisplayMode mode;
else
HIDDEN->c2dsize.x =
(HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2;
if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h) for (i = 0; i < data->nummodes; ++i) {
HIDDEN->c2dsize.y = mode = data->modelist[i];
(HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2; //mode.format = SDL_PIXELFORMAT_UNKNOWN;
else
HIDDEN->c2dsize.y =
(HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2;
#ifdef DIRECTFB_CRTC2_DEBUG mode.format = SDL_PIXELFORMAT_INDEX8;
printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, CheckSetDisplayMode(_this, data, &mode);
HIDDEN->c2dsize.y); mode.format = SDL_PIXELFORMAT_RGB565;
#endif CheckSetDisplayMode(_this, data, &mode);
} mode.format = SDL_PIXELFORMAT_RGB24;
CheckSetDisplayMode(_this, data, &mode);
mode.format = SDL_PIXELFORMAT_RGB888;
CheckSetDisplayMode(_this, data, &mode);
} }
return current;
} }
static int int
DirectFB_AllocHWSurface(_THIS, SDL_Surface * surface) DirectFB_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
{ {
SDL_DFB_DEVICEDATA(_this);
DFB_DisplayData *data = (DFB_DisplayData *) SDL_CurrentDisplay.driverdata;
DFBDisplayLayerConfig config, rconfig;
DFBDisplayLayerConfigFlags fail = 0;
DFBResult ret; DFBResult ret;
DFBSurfaceDescription dsc;
/* fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n", SDL_DFB_CHECKERR(data->layer->
surface->w, surface->h, surface->format->BitsPerPixel, surface->flags); */ SetCooperativeLevel(data->layer, DLSCL_ADMINISTRATIVE));
if (surface->w < 8 || surface->h < 8) SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &config));
return -1; config.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_BUFFERMODE;
if (mode->format != SDL_PIXELFORMAT_UNKNOWN) {
config.flags |= DLCONF_PIXELFORMAT;
config.pixelformat = SDLToDFBPixelFormat(mode->format);
data->pixelformat = config.pixelformat;
}
config.width = mode->w;
config.height = mode->h;
/* fill surface description */ config.buffermode = DLBM_BACKVIDEO;
dsc.flags =
DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
dsc.width = surface->w;
dsc.height = surface->h;
dsc.caps = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
/* find the right pixelformat */ //config.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
dsc.pixelformat = SDLToDFBPixelFormat(surface->format);
if (dsc.pixelformat == DSPF_UNKNOWN)
return -1;
/* Allocate the hardware acceleration data */ data->layer->TestConfiguration(data->layer, &config, &fail);
surface->hwdata = if (fail & (DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT)) {
(struct private_hwdata *) SDL_calloc(1, sizeof(*surface->hwdata)); SDL_DFB_DEBUG("Error setting mode %dx%d-%x\n", mode->w, mode->h,
if (surface->hwdata == NULL) { mode->format);
SDL_OutOfMemory();
return -1; return -1;
} }
SDL_DFB_DEBUG("Trace\n");
config.flags &= ~fail;
SDL_DFB_CHECKERR(data->layer->SetConfiguration(data->layer, &config));
SDL_DFB_CHECKERR(data->layer->
SetCooperativeLevel(data->layer, DLSCL_ADMINISTRATIVE));
/* Double check */
SDL_DFB_CHECKERR(data->layer->GetConfiguration(data->layer, &rconfig));
/* Create the surface */ if ((config.width != rconfig.width) ||
ret = (config.height != rconfig.height) ||
HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc, (config.pixelformat != rconfig.pixelformat)) {
&surface->hwdata->surface); SDL_DFB_DEBUG("Error setting mode %dx%d-%x\n", mode->w, mode->h,
if (ret) { mode->format);
SetDirectFBerror("dfb->CreateSurface", ret);
free(surface->hwdata);
surface->hwdata = NULL;
return -1; return -1;
} }
surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
return 0; return 0;
error:
return -1;
} }
static void static int
DirectFB_FreeHWSurface(_THIS, SDL_Surface * surface) DirectFB_SetDisplayGammaRamp(_THIS, Uint16 * ramp)
{ {
if (surface->hwdata && HIDDEN->initialized) { return -1;
surface->hwdata->surface->Release(surface->hwdata->surface);
free(surface->hwdata);
surface->hwdata = NULL;
}
} }
static int static int
DirectFB_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst) DirectFB_GetDisplayGammaRamp(_THIS, Uint16 * ramp)
{ {
/* fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n", return -1;
src->hwdata, dst->hwdata); */
if (!src->hwdata || !dst->hwdata)
return 0;
src->flags |= SDL_HWACCEL;
src->map->hw_blit = DirectFB_HWAccelBlit;
return 1;
} }
static int static int
DirectFB_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect, DirectFB_CreateWindow(_THIS, SDL_Window * window)
SDL_Surface * dst, SDL_Rect * dstrect)
{ {
DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; SDL_DFB_DEVICEDATA(_this);
SDL_DFB_DISPLAYDATA(_this, window);
DFB_WindowData *windata;
DFBWindowOptions wopts;
DFBWindowDescription desc;
int ret, x, y;
SDL_DFB_DEBUG("Trace x %d y %d w %d h %d\n", window->x, window->y,
window->w, window->h);
window->driverdata = NULL;
SDL_DFB_CALLOC(window->driverdata, 1, sizeof(DFB_WindowData));
windata = (DFB_WindowData *) window->driverdata;
SDL_DFB_CHECKERR(devdata->dfb->
SetCooperativeLevel(devdata->dfb, DFSCL_NORMAL));
SDL_DFB_CHECKERR(dispdata->layer->
SetCooperativeLevel(dispdata->layer,
DLSCL_ADMINISTRATIVE));
/* Fill the window description. */
if (window->x == SDL_WINDOWPOS_CENTERED) {
x = (dispdata->cw - window->w) / 2;
} else if (window->x == SDL_WINDOWPOS_UNDEFINED) {
x = 0;
} else {
x = window->x;
}
if (window->y == SDL_WINDOWPOS_CENTERED) {
y = (dispdata->ch - window->h) / 2;
} else if (window->y == SDL_WINDOWPOS_UNDEFINED) {
y = 0;
} else {
y = window->y;
}
DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h }; desc.flags =
DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h }; DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS | DWDESC_PIXELFORMAT;
desc.flags |= DWDESC_POSX | DWDESC_POSY | DWDESC_SURFACE_CAPS;
desc.posx = x;
desc.posy = y;
desc.width = window->w;
desc.height = window->h;
IDirectFBSurface *surface = dst->hwdata->surface; desc.pixelformat = dispdata->pixelformat;
if (src->flags & SDL_SRCCOLORKEY) { desc.caps = 0; //DWCAPS_DOUBLEBUFFER;
flags |= DSBLIT_SRC_COLORKEY; desc.surface_caps = DSCAPS_DOUBLE | DSCAPS_TRIPLE; //| DSCAPS_PREMULTIPLIED;
DirectFB_SetHWColorKey(NULL, src, src->format->colorkey);
}
if (src->flags & SDL_SRCALPHA) { /* Create the window. */
flags |= DSBLIT_BLEND_COLORALPHA; SDL_DFB_CHECKERR(dispdata->layer->
surface->SetColor(surface, 0xff, 0xff, 0xff, src->format->alpha); CreateWindow(dispdata->layer, &desc, &windata->window));
}
surface->SetBlittingFlags(surface, flags); windata->window->GetOptions(windata->window, &wopts);
#if (DIRECTFB_MAJOR_VERSION == 1) && (DIRECTFB_MINOR_VERSION >= 0)
if (sr.w == dr.w && sr.h == dr.h) if (window->flags & SDL_WINDOW_RESIZABLE)
surface->Blit(surface, src->hwdata->surface, &sr, dr.x, dr.y); wopts |= DWOP_SCALE;
else else
surface->StretchBlit(surface, src->hwdata->surface, &sr, &dr); wopts |= DWOP_KEEP_SIZE;
#else
wopts |= DWOP_KEEP_SIZE; // if not we will crash ...
#endif
if (window->flags & SDL_WINDOW_FULLSCREEN)
wopts |= DWOP_KEEP_POSITION | DWOP_KEEP_STACKING | DWOP_KEEP_SIZE;
windata->window->SetOptions(windata->window, wopts);
/* Get the window's surface. */
SDL_DFB_CHECKERR(windata->window->
GetSurface(windata->window, &windata->surface));
windata->window->SetOpacity(windata->window, 0xFF);
SDL_DFB_CHECKERR(windata->window->
CreateEventBuffer(windata->window,
&(windata->eventbuffer)));
SDL_DFB_CHECKERR(windata->window->
EnableEvents(windata->window,
DWET_POSITION | DWET_SIZE | DWET_CLOSE |
DWET_ALL));
if (window->flags & SDL_WINDOW_FULLSCREEN)
windata->window->SetStackingClass(windata->window, DWSC_UPPER);
/* Make it the top most window. */
windata->window->RaiseToTop(windata->window);
windata->window->GetID(windata->window, &windata->windowID);
windata->id = window->id;
#if SDL_DIRECTFB_OPENGL
if (window->flags & SDL_WINDOW_OPENGL) {
if (!_this->gl_config.driver_loaded) {
/* no driver has been loaded, use default (ourselves) */
if (DirectFB_GL_LoadLibrary(_this, NULL) < 0) {
goto error;
}
}
_this->gl_data->gl_active = 1;
}
#endif
/* Add to list ... */
windata->next = devdata->firstwin;
windata->opacity = 0xFF;
devdata->firstwin = windata;
//SDL_DFB_CHECKERR( windata->surface->GetPalette(windata->surface, &windata->palette) );
return 0; return 0;
error:
SDL_DFB_RELEASE(windata->window);
SDL_DFB_RELEASE(windata->surface);
return -1;
} }
static int static int
DirectFB_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect, DirectFB_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
Uint32 color)
{ {
SDL_PixelFormat *fmt = dst->format; SDL_DFB_DEVICEDATA(_this);
IDirectFBSurface *surface = dst->hwdata->surface; SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
/* ugly */
surface->SetColor(surface,
(color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
(color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
(color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift),
0xFF);
surface->FillRectangle(surface, dstrect->x, dstrect->y, dstrect->w,
dstrect->h);
return 0; SDL_Unsupported();
return -1;
} }
static int static void
DirectFB_SetHWColorKey(_THIS, SDL_Surface * src, Uint32 key) DirectFB_SetWindowTitle(_THIS, SDL_Window * window)
{ {
SDL_PixelFormat *fmt = src->format; SDL_DFB_DEVICEDATA(_this);
IDirectFBSurface *surface = src->hwdata->surface; SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
if (fmt->BitsPerPixel == 8) SDL_Unsupported();
surface->SetSrcColorKeyIndex(surface, key); //return -1;
else
/* ugly */
surface->SetSrcColorKey(surface,
(key & fmt->Rmask) >> (fmt->Rshift -
fmt->Rloss),
(key & fmt->Gmask) >> (fmt->Gshift -
fmt->Gloss),
(key & fmt->Bmask) << (fmt->Bloss -
fmt->Bshift));
return 0;
} }
static void
static int DirectFB_SetWindowPosition(_THIS, SDL_Window * window)
DirectFB_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha)
{ {
return 0; SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
windata->window->MoveTo(windata->window, window->x, window->y);
} }
static int static void
DirectFB_FlipHWSurface(_THIS, SDL_Surface * surface) DirectFB_SetWindowSize(_THIS, SDL_Window * window)
{ {
if (HIDDEN->enable_mga_crtc2) { SDL_DFB_DEVICEDATA(_this);
int rtn = SDL_DFB_WINDOWDATA(window);
surface->hwdata->surface->Flip(surface->hwdata->surface, NULL, SDL_DFB_DISPLAYDATA(_this, window);
0);
if (HIDDEN->mga_crtc2_stretch) windata->window->Resize(windata->window, window->w, window->h);
HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame,
surface->hwdata->surface,
&HIDDEN->c2ssize, &HIDDEN->c2dsize);
else
HIDDEN->c2frame->Blit(HIDDEN->c2frame,
surface->hwdata->surface, NULL,
HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
return rtn;
} else
return surface->hwdata->surface->Flip(surface->hwdata->surface, NULL,
DSFLIP_WAITFORSYNC);
} }
static void
DirectFB_ShowWindow(_THIS, SDL_Window * window)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
static int windata->window->SetOpacity(windata->window, windata->opacity);
DirectFB_LockHWSurface(_THIS, SDL_Surface * surface)
}
static void
DirectFB_HideWindow(_THIS, SDL_Window * window)
{ {
DFBResult ret; SDL_DFB_DEVICEDATA(_this);
void *data; SDL_DFB_WINDOWDATA(window);
int pitch; SDL_DFB_DISPLAYDATA(_this, window);
ret = surface->hwdata->surface->Lock(surface->hwdata->surface, windata->window->GetOpacity(windata->window, &windata->opacity);
DSLF_WRITE, &data, &pitch); windata->window->SetOpacity(windata->window, 0);
if (ret) {
SetDirectFBerror("surface->Lock", ret);
return -1;
}
surface->pixels = data; }
surface->pitch = pitch; static void
DirectFB_RaiseWindow(_THIS, SDL_Window * window)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
windata->window->Raise(windata->window);
return 0;
} }
static void static void
DirectFB_UnlockHWSurface(_THIS, SDL_Surface * surface) DirectFB_MaximizeWindow(_THIS, SDL_Window * window)
{ {
surface->hwdata->surface->Unlock(surface->hwdata->surface); SDL_DFB_DEVICEDATA(_this);
surface->pixels = NULL; SDL_DFB_WINDOWDATA(window);
} SDL_DFB_DISPLAYDATA(_this, window);
SDL_Unsupported();
}
static void static void
DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects) DirectFB_MinimizeWindow(_THIS, SDL_Window * window)
{ {
if (HIDDEN->enable_mga_crtc2) { SDL_DFB_DEVICEDATA(_this);
if (HIDDEN->mga_crtc2_stretch) SDL_DFB_WINDOWDATA(window);
HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, SDL_DFB_DISPLAYDATA(_this, window);
this->screen->hwdata->surface,
&HIDDEN->c2ssize, &HIDDEN->c2dsize); SDL_Unsupported();
else
HIDDEN->c2frame->Blit(HIDDEN->c2frame,
this->screen->hwdata->surface, NULL,
HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
}
} }
static void static void
DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect * rects) DirectFB_RestoreWindow(_THIS, SDL_Window * window)
{ {
DFBRegion region; SDL_DFB_DEVICEDATA(_this);
int i; SDL_DFB_WINDOWDATA(window);
int region_valid = 0; SDL_DFB_DISPLAYDATA(_this, window);
IDirectFBSurface *surface = this->screen->hwdata->surface;
for (i = 0; i < numrects; ++i) { SDL_Unsupported();
int x2, y2;
if (!rects[i].w) /* Clipped? */ }
continue; static void
DirectFB_SetWindowGrab(_THIS, SDL_Window * window)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
x2 = rects[i].x + rects[i].w - 1; SDL_Unsupported();
y2 = rects[i].y + rects[i].h - 1;
if (region_valid) { }
if (rects[i].x < region.x1)
region.x1 = rects[i].x;
if (rects[i].y < region.y1) static void
region.y1 = rects[i].y; DirectFB_DestroyWindow(_THIS, SDL_Window * window)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
DFB_WindowData *p;
if (x2 > region.x2) SDL_DFB_DEBUG("Trace\n");
region.x2 = x2;
if (y2 > region.y2) SDL_DFB_RELEASE(windata->palette);
region.y2 = y2; SDL_DFB_RELEASE(windata->eventbuffer);
} else { SDL_DFB_RELEASE(windata->surface);
region.x1 = rects[i].x; SDL_DFB_RELEASE(windata->window);
region.y1 = rects[i].y;
region.x2 = x2;
region.y2 = y2;
region_valid = 1; /* Remove from list ... */
}
}
if (region_valid) { p = devdata->firstwin;
if (HIDDEN->enable_mga_crtc2) { while (p && p->next != windata)
if (HIDDEN->mga_crtc2_stretch) p = p->next;
HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, if (p)
&HIDDEN->c2ssize, p->next = windata->next;
&HIDDEN->c2dsize);
else else
HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, devdata->firstwin = windata->next;
HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); SDL_free(windata);
}
static SDL_bool
DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info)
{
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); SDL_Unsupported();
} else return SDL_FALSE;
surface->Flip(surface, &region, DSFLIP_WAITFORSYNC);
}
} }
int #if SDL_DIRECTFB_OPENGL
DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
#define OPENGL_REQUIRS_DLOPEN
#if defined(OPENGL_REQUIRS_DLOPEN) && defined(SDL_LOADSO_DLOPEN)
#include <dlfcn.h>
#define GL_LoadObject(X) dlopen(X, (RTLD_NOW|RTLD_GLOBAL))
#define GL_LoadFunction dlsym
#define GL_UnloadObject dlclose
#else
#define GL_LoadObject SDL_LoadObject
#define GL_LoadFunction SDL_LoadFunction
#define GL_UnloadObject SDL_UnloadObject
#endif
static int
DirectFB_GL_LoadLibrary(_THIS, const char *path)
{ {
IDirectFBPalette *palette = this->screen->hwdata->palette; SDL_DFB_DEVICEDATA(_this);
#
void *handle = NULL;
if (!palette) SDL_DFB_DEBUG("Loadlibrary : %s\n", path);
return 0;
if (firstcolor > 255) if (_this->gl_data->gl_active) {
return 0; SDL_SetError("OpenGL context already created");
return -1;
}
if (firstcolor + ncolors > 256)
ncolors = 256 - firstcolor;
if (ncolors > 0) { if (path == NULL) {
int i; path = SDL_getenv("SDL_VIDEO_GL_DRIVER");
DFBColor entries[ncolors]; if (path == NULL) {
path = "libGL.so";
}
}
for (i = 0; i < ncolors; i++) { handle = GL_LoadObject(path);
entries[i].a = 0xff; if (handle == NULL) {
entries[i].r = colors[i].r; SDL_DFB_ERR("Library not found: %s\n", path);
entries[i].g = colors[i].g; /* SDL_LoadObject() will call SDL_SetError() for us. */
entries[i].b = colors[i].b; return -1;
} }
palette->SetEntries(palette, entries, ncolors, firstcolor); SDL_DFB_DEBUG("Loaded library: %s\n", path);
/* Unload the old driver and reset the pointers */
DirectFB_GL_UnloadLibrary(_this);
_this->gl_config.dll_handle = handle;
_this->gl_config.driver_loaded = 1;
if (path) {
SDL_strlcpy(_this->gl_config.driver_path, path,
SDL_arraysize(_this->gl_config.driver_path));
} else {
*_this->gl_config.driver_path = '\0';
} }
return 1; devdata->glFinish = DirectFB_GL_GetProcAddress(_this, "glFinish");
devdata->glFlush = DirectFB_GL_GetProcAddress(_this, "glFlush");
return 0;
} }
void static void
DirectFB_VideoQuit(_THIS) DirectFB_GL_UnloadLibrary(_THIS)
{ {
struct DirectFBEnumRect *rect = enumlist; SDL_DFB_DEVICEDATA(_this);
if (this->screen && this->screen->hwdata) { int ret;
IDirectFBSurface *surface = this->screen->hwdata->surface;
IDirectFBPalette *palette = this->screen->hwdata->palette;
if (palette) if (_this->gl_config.driver_loaded) {
palette->Release(palette);
if (surface) ret = GL_UnloadObject(_this->gl_config.dll_handle);
surface->Release(surface); if (ret)
SDL_DFB_ERR("Error #%d trying to unload library.\n", ret);
this->screen->hwdata->surface = NULL; _this->gl_config.dll_handle = NULL;
this->screen->hwdata->palette = NULL; _this->gl_config.driver_loaded = 0;
} }
}
if (HIDDEN->c2frame) { static void *
HIDDEN->c2frame->Release(HIDDEN->c2frame); DirectFB_GL_GetProcAddress(_THIS, const char *proc)
HIDDEN->c2frame = NULL; {
} SDL_DFB_DEVICEDATA(_this);
int ret;
void *handle;
if (HIDDEN->eventbuffer) { SDL_DFB_DEBUG("Trace %s\n", proc);
HIDDEN->eventbuffer->Release(HIDDEN->eventbuffer); handle = _this->gl_config.dll_handle;
HIDDEN->eventbuffer = NULL; return GL_LoadFunction(handle, proc);
} }
if (HIDDEN->c2layer) { static SDL_GLContext
HIDDEN->c2layer->Release(HIDDEN->c2layer); DirectFB_GL_CreateContext(_THIS, SDL_Window * window)
HIDDEN->c2layer = NULL; {
SDL_DFB_DEVICEDATA(_this);
SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
int ret;
IDirectFBGL *context = NULL;
SDL_DFB_DEBUG("Trace\n");
SDL_DFB_CHECKERR(windata->surface->GetGL(windata->surface, &context));
SDL_DFB_CHECKERR(context->Unlock(context));
if (DirectFB_GL_MakeCurrent(_this, window, context) < 0) {
DirectFB_GL_DeleteContext(_this, context);
return NULL;
} }
if (HIDDEN->layer) { return context;
HIDDEN->layer->Release(HIDDEN->layer);
HIDDEN->layer = NULL;
}
if (HIDDEN->dfb) { error:
HIDDEN->dfb->Release(HIDDEN->dfb); return NULL;
HIDDEN->dfb = NULL; }
}
/* Free video mode list */ static int
if (HIDDEN->modelist) { DirectFB_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
free(HIDDEN->modelist); {
HIDDEN->modelist = NULL; SDL_DFB_DEVICEDATA(_this);
} SDL_DFB_WINDOWDATA(window);
SDL_DFB_DISPLAYDATA(_this, window);
IDirectFBGL *dfb_context = (IDirectFBGL *) context;
int ret;
/* Free mode enumeration list */ if (dfb_context) {
while (rect) { dfb_context->Unlock(dfb_context);
struct DirectFBEnumRect *next = rect->next; SDL_DFB_CHECKERR(dfb_context->Lock(dfb_context));
free(rect);
rect = next;
} }
enumlist = NULL; if (windata)
windata->gl_context = dfb_context;
return 0;
error:
return -1;
}
static int
DirectFB_GL_SetSwapInterval(_THIS, int interval)
{
SDL_DFB_DEVICEDATA(_this);
SDL_Unsupported();
return -1;
HIDDEN->initialized = 0;
} }
static int
DirectFB_GL_GetSwapInterval(_THIS)
{
SDL_DFB_DEVICEDATA(_this);
int SDL_Unsupported();
DirectFB_ShowWMCursor(_THIS, WMcursor * cursor) return -1;
}
static void
DirectFB_GL_SwapWindow(_THIS, SDL_Window * window)
{ {
/* We can only hide or show the default cursor */ SDL_DFB_DEVICEDATA(_this);
if (cursor == NULL) { SDL_DFB_WINDOWDATA(window);
HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00); SDL_DFB_DISPLAYDATA(_this, window);
} else { int ret;
HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF); void *p;
} int pitch;
return 1; DFBRegion region;
region.x1 = 0;
region.y1 = 0;
region.x2 = window->w;
region.y2 = window->h;
if (devdata->glFinish)
devdata->glFinish();
else if (devdata->glFlush)
devdata->glFlush();
SDL_DFB_CHECKERR(windata->gl_context->Unlock(windata->gl_context));
SDL_DFB_CHECKERR(windata->surface->
Flip(windata->surface, &region, DSFLIP_ONSYNC));
SDL_DFB_CHECKERR(windata->gl_context->Lock(windata->gl_context));
return;
error:
return;
} }
void static void
DirectFB_FinalQuit(void) DirectFB_GL_DeleteContext(_THIS, SDL_GLContext context)
{ {
IDirectFBGL *dfb_context = (IDirectFBGL *) context;
SDL_DFB_DEVICEDATA(_this);
dfb_context->Unlock(dfb_context);
dfb_context->Release(dfb_context);
} }
/* vi: set ts=4 sw=4 expandtab: */ #endif
...@@ -25,39 +25,155 @@ ...@@ -25,39 +25,155 @@
#define _SDL_DirectFB_video_h #define _SDL_DirectFB_video_h
#include <directfb.h> #include <directfb.h>
#include <directfb_version.h>
#define LOG_CHANNEL stdout
#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
#error "SDL_DIRECTFB: Please compile against libdirectfb version >=0.9.24"
#endif
#if (DIRECTFB_MAJOR_VERSION >= 1) && (DIRECTFB_MINOR_VERSION >= 0) && (DIRECTFB_MICRO_VERSION >= 0 )
#define SDL_DIRECTFB_OPENGL 1
#include <directfbgl.h>
#endif
#if SDL_DIRECTFB_OPENGL
#include "SDL_loadso.h"
#endif
#include "SDL_mouse.h" #include "SDL_mouse.h"
#include "../SDL_sysvideo.h" #include "../SDL_sysvideo.h"
#define _THIS SDL_VideoDevice *this #define DEBUG 1
#define SDL_DFB_RELEASE(x) do { if ( x ) { x->Release(x); x = NULL; } } while (0)
#define SDL_DFB_FREE(x) do { if ( x ) { SDL_free(x); x = NULL; } } while (0)
#define SDL_DFB_UNLOCK(x) do { if ( x ) { x->Unlock(x); } } while (0)
#if DEBUG
#define SDL_DFB_DEBUG(x...) do { fprintf(LOG_CHANNEL, "%s:", __FUNCTION__); fprintf(LOG_CHANNEL, x); } while (0)
#define SDL_DFB_DEBUGC(x...) do { fprintf(LOG_CHANNEL, x); } while (0)
#else
#define SDL_DFB_DEBUG(x...) do { } while (0)
#define SDL_DFB_DEBUGC(x...) do { } while (0)
#endif
#define SDL_DFB_CONTEXT "SDL_DirectFB"
#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)
#define SDL_DFB_CHECK(x...) \
do { \
ret = x; \
if (ret != DFB_OK) { \
fprintf(LOG_CHANNEL, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
SDL_SetError( #x, DirectFBErrorString (ret) ); \
} \
} while (0)
#define SDL_DFB_CHECKERR(x...) \
do { \
ret = x; \
if (ret != DFB_OK) { \
fprintf(LOG_CHANNEL, "%s <%d>:\n", __FILE__, __LINE__ ); \
fprintf(LOG_CHANNEL, "\t%s\n", #x ); \
fprintf(LOG_CHANNEL, "\t%s\n", DirectFBErrorString (ret) ); \
SDL_SetError( #x, DirectFBErrorString (ret) ); \
goto error; \
} \
} while (0)
#define SDL_DFB_CALLOC(r, n, s) \
do { \
r = SDL_calloc (n, s); \
if (!(r)) { \
fprintf( LOG_CHANNEL, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
SDL_OutOfMemory(); \
goto error; \
} \
} while (0)
/* Private display data */ /* Private display data */
struct SDL_PrivateVideoData #define SDL_DFB_DEVICEDATA(dev) DFB_DeviceData *devdata = (DFB_DeviceData *) ((dev)->driverdata)
#define SDL_DFB_WINDOWDATA(win) DFB_WindowData *windata = ((win) ? (DFB_WindowData *) ((win)->driverdata) : NULL)
#define SDL_DFB_DISPLAYDATA(dev, win) DFB_DisplayData *dispdata = ((win && dev) ? (DFB_DisplayData *) (dev)->displays[(win)->display].driverdata : NULL)
typedef struct _DFB_DisplayData DFB_DisplayData;
#define DFB_MAX_SCREENS 10
#define DFB_MAX_MODES 50
struct _DFB_DisplayData
{
IDirectFBDisplayLayer *layer;
DFBSurfacePixelFormat pixelformat;
DFBDisplayLayerID vidID;
int cw;
int ch;
int nummodes;
SDL_DisplayMode *modelist;
#if 0
WMcursor *last_cursor;
WMcursor *blank_cursor;
WMcursor *default_cursor;
#endif
};
typedef struct _DFB_WindowData DFB_WindowData;
struct _DFB_WindowData
{
IDirectFBSurface *surface;
IDirectFBPalette *palette;
IDirectFBWindow *window;
IDirectFBGL *gl_context;
IDirectFBEventBuffer *eventbuffer;
DFBWindowID windowID;
int id; // SDL window id
DFB_WindowData *next;
u8 opacity;
};
typedef struct _DFB_DeviceData DFB_DeviceData;
struct _DFB_DeviceData
{ {
int initialized; int initialized;
IDirectFB *dfb; IDirectFB *dfb;
IDirectFBDisplayLayer *layer; int mouse;
IDirectFBEventBuffer *eventbuffer; int keyboard;
DFB_WindowData *firstwin;
int nummodes; int numscreens;
SDL_Rect **modelist; DFBScreenID screenid[DFB_MAX_SCREENS];
DFBDisplayLayerID gralayer[DFB_MAX_SCREENS];
/* MGA CRTC2 support */ DFBDisplayLayerID vidlayer[DFB_MAX_SCREENS];
int enable_mga_crtc2;
int mga_crtc2_stretch; // auxiliary integer for callbacks
float mga_crtc2_stretch_overscan; int aux;
IDirectFBDisplayLayer *c2layer;
IDirectFBSurface *c2frame; // OpenGL
DFBRectangle c2ssize; /* Real screen size */ void (*glFinish) (void);
DFBRectangle c2dsize; /* Stretched screen size */ void (*glFlush) (void);
DFBRectangle c2framesize; /* CRTC2 screen size */
}; };
#define HIDDEN (this->hidden) struct SDL_GLDriverData
{
int gl_active; /* to stop switching drivers while we have a valid context */
void SetDirectFBerror(const char *function, DFBResult code); #if SDL_DIRECTFB_OPENGL
IDirectFBGL *gl_context;
#endif /* SDL_DIRECTFB_OPENGL */
};
#endif /* _SDL_DirectFB_video_h */ #endif /* _SDL_DirectFB_video_h */
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2006 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* This is the DirectFB implementation of YUV video overlays */
#include "SDL_video.h"
#include "SDL_DirectFB_yuv.h"
#include "../SDL_yuvfuncs.h"
/* The functions used to manipulate software video overlays */
static struct private_yuvhwfuncs directfb_yuvfuncs = {
DirectFB_LockYUVOverlay,
DirectFB_UnlockYUVOverlay,
DirectFB_DisplayYUVOverlay,
DirectFB_FreeYUVOverlay
};
struct private_yuvhwdata
{
DFBDisplayLayerID layer_id;
IDirectFBDisplayLayer *layer;
IDirectFBSurface *surface;
/* These are just so we don't have to allocate them separately */
Uint16 pitches[3];
Uint8 *planes[3];
};
static DFBEnumerationResult
enum_layers_callback(DFBDisplayLayerID id,
DFBDisplayLayerDescription desc, void *data)
{
struct private_yuvhwdata *hwdata = (struct private_yuvhwdata *) data;
/* we don't want the primary */
if (id == DLID_PRIMARY)
return DFENUM_OK;
/* take the one with a surface for video */
if ((desc.caps & DLCAPS_SURFACE) && (desc.type & DLTF_VIDEO)) {
hwdata->layer_id = id;
return DFENUM_CANCEL;
}
return DFENUM_OK;
}
static DFBResult
CreateYUVSurface(_THIS, struct private_yuvhwdata *hwdata,
int width, int height, Uint32 format)
{
DFBResult ret;
IDirectFB *dfb = HIDDEN->dfb;
IDirectFBDisplayLayer *layer;
DFBDisplayLayerConfig conf;
ret = dfb->EnumDisplayLayers(dfb, enum_layers_callback, hwdata);
if (ret) {
SetDirectFBerror("IDirectFB::EnumDisplayLayers", ret);
return ret;
}
if (!hwdata->layer_id)
return DFB_UNSUPPORTED;
ret = dfb->GetDisplayLayer(dfb, hwdata->layer_id, &layer);
if (ret) {
SetDirectFBerror("IDirectFB::GetDisplayLayer", ret);
return ret;
}
conf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
conf.width = width;
conf.height = height;
switch (format) {
case SDL_YV12_OVERLAY:
conf.pixelformat = DSPF_YV12;
break;
case SDL_IYUV_OVERLAY:
conf.pixelformat = DSPF_I420;
break;
case SDL_YUY2_OVERLAY:
conf.pixelformat = DSPF_YUY2;
break;
case SDL_UYVY_OVERLAY:
conf.pixelformat = DSPF_UYVY;
break;
default:
fprintf(stderr, "SDL_DirectFB: Unsupported YUV format (0x%08x)!\n",
format);
break;
}
/* Need to set coop level or newer DirectFB versions will fail here. */
ret = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if (ret) {
SetDirectFBError
("IDirectFBDisplayLayer::SetCooperativeLevel() failed", ret);
layer->Release(layer);
return ret;
}
ret = layer->SetConfiguration(layer, &conf);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::SetConfiguration", ret);
layer->Release(layer);
return ret;
}
ret = layer->GetSurface(layer, &hwdata->surface);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::GetSurface", ret);
layer->Release(layer);
return ret;
}
hwdata->layer = layer;
return DFB_OK;
}
SDL_Overlay *
DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format,
SDL_Surface * display)
{
SDL_Overlay *overlay;
struct private_yuvhwdata *hwdata;
/* Create the overlay structure */
overlay = SDL_calloc(1, sizeof(SDL_Overlay));
if (!overlay) {
SDL_OutOfMemory();
return NULL;
}
/* Fill in the basic members */
overlay->format = format;
overlay->w = width;
overlay->h = height;
/* Set up the YUV surface function structure */
overlay->hwfuncs = &directfb_yuvfuncs;
/* Create the pixel data and lookup tables */
hwdata = SDL_calloc(1, sizeof(struct private_yuvhwdata));
overlay->hwdata = hwdata;
if (!hwdata) {
SDL_OutOfMemory();
SDL_FreeYUVOverlay(overlay);
return NULL;
}
if (CreateYUVSurface(this, hwdata, width, height, format)) {
SDL_FreeYUVOverlay(overlay);
return NULL;
}
overlay->hw_overlay = 1;
/* Set up the plane pointers */
overlay->pitches = hwdata->pitches;
overlay->pixels = hwdata->planes;
switch (format) {
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
overlay->planes = 3;
break;
default:
overlay->planes = 1;
break;
}
/* We're all done.. */
return overlay;
}
int
DirectFB_LockYUVOverlay(_THIS, SDL_Overlay * overlay)
{
DFBResult ret;
void *data;
int pitch;
IDirectFBSurface *surface = overlay->hwdata->surface;
ret = surface->Lock(surface, DSLF_READ | DSLF_WRITE, &data, &pitch);
if (ret) {
SetDirectFBerror("IDirectFBSurface::Lock", ret);
return -1;
}
/* Find the pitch and offset values for the overlay */
overlay->pitches[0] = (Uint16) pitch;
overlay->pixels[0] = (Uint8 *) data;
switch (overlay->format) {
case SDL_YV12_OVERLAY:
case SDL_IYUV_OVERLAY:
/* Add the two extra planes */
overlay->pitches[1] = overlay->pitches[0] / 2;
overlay->pitches[2] = overlay->pitches[0] / 2;
overlay->pixels[1] =
overlay->pixels[0] + overlay->pitches[0] * overlay->h;
overlay->pixels[2] =
overlay->pixels[1] + overlay->pitches[1] * overlay->h / 2;
break;
default:
/* Only one plane, no worries */
break;
}
return 0;
}
void
DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay * overlay)
{
IDirectFBSurface *surface = overlay->hwdata->surface;
overlay->pixels[0] = overlay->pixels[1] = overlay->pixels[2] = NULL;
surface->Unlock(surface);
}
int
DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay * overlay, SDL_Rect * src,
SDL_Rect * dst)
{
DFBResult ret;
DFBDisplayLayerConfig conf;
IDirectFBDisplayLayer *primary = HIDDEN->layer;
IDirectFBDisplayLayer *layer = overlay->hwdata->layer;
primary->GetConfiguration(primary, &conf);
ret = layer->SetScreenLocation(layer,
dst->x / (float) conf.width,
dst->y / (float) conf.height,
dst->w / (float) conf.width,
dst->h / (float) conf.height);
if (ret) {
SetDirectFBerror("IDirectFBDisplayLayer::SetScreenLocation", ret);
return -1;
}
return 0;
}
void
DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay * overlay)
{
struct private_yuvhwdata *hwdata;
hwdata = overlay->hwdata;
if (hwdata) {
if (hwdata->surface)
hwdata->surface->Release(hwdata->surface);
if (hwdata->layer)
hwdata->layer->Release(hwdata->layer);
free(hwdata);
}
}
/* vi: set ts=4 sw=4 expandtab: */
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