From a855d6202536ff28e5aae4f22a0f31d8f5b325d0 Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Sat, 21 Jan 2017 15:18:31 -0500 Subject: Port of Duke Nukem 3D This ports Fabien Sanglard's Chocolate Duke to run on a version of SDL for Rockbox. Change-Id: I8f2c4c78af19de10c1633ed7bb7a997b43256dd9 --- .../sdl/src/video/directfb/SDL_DirectFB_events.c | 219 ++++ .../sdl/src/video/directfb/SDL_DirectFB_events.h | 29 + .../sdl/src/video/directfb/SDL_DirectFB_keys.h | 135 +++ .../sdl/src/video/directfb/SDL_DirectFB_video.c | 1171 ++++++++++++++++++++ .../sdl/src/video/directfb/SDL_DirectFB_video.h | 62 ++ .../sdl/src/video/directfb/SDL_DirectFB_yuv.c | 290 +++++ .../sdl/src/video/directfb/SDL_DirectFB_yuv.h | 38 + 7 files changed, 1944 insertions(+) create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.c create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.h create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_keys.h create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.c create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.h create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.c create mode 100644 apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.h (limited to 'apps/plugins/sdl/src/video/directfb') diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.c b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.c new file mode 100644 index 0000000000..246b75b176 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.c @@ -0,0 +1,219 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Handle the event stream, converting DirectFB input events into SDL events */ + +#include +#include +#include +#include +#include + +#include + +#include "SDL.h" +#include "../SDL_sysvideo.h" +#include "../../events/SDL_sysevents.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.h" +#include "SDL_DirectFB_events.h" + +/* The translation tables from a DirectFB keycode to a SDL keysym */ +static SDLKey keymap[256]; +static SDL_keysym *DirectFB_TranslateKey (DFBInputEvent *ev, SDL_keysym *keysym); +static int DirectFB_TranslateButton (DFBInputEvent *ev); + +static int posted = 0; + + +void DirectFB_PumpEvents (_THIS) +{ + DFBInputEvent evt; + + while (HIDDEN->eventbuffer->GetEvent (HIDDEN->eventbuffer, + DFB_EVENT (&evt)) == DFB_OK) + { + SDL_keysym keysym; + + switch (evt.type) + { + case DIET_BUTTONPRESS: + posted += SDL_PrivateMouseButton(SDL_PRESSED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_BUTTONRELEASE: + posted += SDL_PrivateMouseButton(SDL_RELEASED, + DirectFB_TranslateButton (&evt), 0, 0); + break; + case DIET_KEYPRESS: + posted += SDL_PrivateKeyboard(SDL_PRESSED, DirectFB_TranslateKey(&evt, &keysym)); + break; + case DIET_KEYRELEASE: + posted += SDL_PrivateKeyboard(SDL_RELEASED, DirectFB_TranslateKey(&evt, &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) + { + static int last_x, last_y; + 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: + ; + } + } +} + +void DirectFB_InitOSKeymap (_THIS) +{ + int i; + + /* Initialize the DirectFB key translation table */ + for (i=0; iscancode = ev->key_id; + keysym->mod = KMOD_NONE; /* FIXME */ + keysym->unicode = (DFB_KEY_TYPE (ev->key_symbol) == DIKT_UNICODE) ? ev->key_symbol : 0; + + if (ev->key_symbol > 0 && ev->key_symbol < 128) + keysym->sym = ev->key_symbol; + else + keysym->sym = keymap[ev->key_id - DIKI_UNKNOWN]; + + return keysym; +} + +static int DirectFB_TranslateButton (DFBInputEvent *ev) +{ + switch (ev->button) + { + case DIBI_LEFT: + return 1; + case DIBI_MIDDLE: + return 2; + case DIBI_RIGHT: + return 3; + default: + return 0; + } +} diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.h b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.h new file mode 100644 index 0000000000..20f3967271 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_events.h @@ -0,0 +1,29 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +/* Functions to be exported */ +extern void DirectFB_InitOSKeymap(_THIS); +extern void DirectFB_PumpEvents(_THIS); + diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_keys.h b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_keys.h new file mode 100644 index 0000000000..2868ee6ffa --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_keys.h @@ -0,0 +1,135 @@ + +#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 + diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.c b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.c new file mode 100644 index 0000000000..f665ec6825 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.c @@ -0,0 +1,1171 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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 + + MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com + CRTC2 support is inspired by mplayer's dfbmga driver + written by Ville Syrj�� +*/ +#include "SDL_config.h" + +/* DirectFB video driver implementation. +*/ + +#include +#include +#include + +#include +#include + +#include "SDL_video.h" +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" +#include "../SDL_pixels_c.h" +#include "../../events/SDL_events_c.h" +#include "SDL_DirectFB_video.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 */ +struct DirectFBEnumRect { + SDL_Rect r; + struct DirectFBEnumRect* next; +}; + +static struct DirectFBEnumRect *enumlist = NULL; + + +/* DirectFB driver bootstrap functions */ + +static int DirectFB_Available(void) +{ + return 1; +} + +static void DirectFB_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device->hidden); + SDL_free(device); +} + +static SDL_VideoDevice *DirectFB_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + /* Initialize all variables that we clean on shutdown */ + device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); + if (device) + { + SDL_memset (device, 0, (sizeof *device)); + device->hidden = (struct SDL_PrivateVideoData *) 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 */ + 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->AllocHWSurface = DirectFB_AllocHWSurface; + device->CheckHWBlit = DirectFB_CheckHWBlit; + device->FillHWRect = DirectFB_FillHWRect; + device->SetHWColorKey = DirectFB_SetHWColorKey; + device->SetHWAlpha = DirectFB_SetHWAlpha; + device->LockHWSurface = DirectFB_LockHWSurface; + device->UnlockHWSurface = DirectFB_UnlockHWSurface; + device->FlipHWSurface = DirectFB_FlipHWSurface; + device->FreeHWSurface = DirectFB_FreeHWSurface; + device->ShowWMCursor = DirectFB_ShowWMCursor; + device->SetCaption = NULL; + device->SetIcon = NULL; + device->IconifyWindow = NULL; + device->GrabInput = NULL; + device->GetWMInfo = NULL; + device->InitOSKeymap = DirectFB_InitOSKeymap; + device->PumpEvents = DirectFB_PumpEvents; + + device->free = DirectFB_DeleteDevice; + + return device; +} + +VideoBootStrap DirectFB_bootstrap = { + "directfb", "DirectFB", + 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 EnumModesCallback (int width, + int height, + int bpp, + void *data) +{ + SDL_VideoDevice *this = (SDL_VideoDevice *)data; + struct DirectFBEnumRect *enumrect; + + HIDDEN->nummodes++; + + if (enumlist && enumlist->r.w == width && enumlist->r.h == height) + return DFENUM_OK; + + enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect)); + if (!enumrect) + { + SDL_OutOfMemory(); + return DFENUM_CANCEL; + } + + enumrect->r.w = (Uint16)width; + enumrect->r.h = (Uint16)height; + enumrect->next = enumlist; + + enumlist = enumrect; + + return DFENUM_OK; +} + +struct private_hwdata { + 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 (format->BitsPerPixel) + { + case 8: + 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; + + case 24: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + return DSPF_RGB24; + break; + + case 32: + if (format->Rmask == 0xFF0000 && + format->Gmask == 0x00FF00 && + format->Bmask == 0x0000FF) + { + if (format->Amask == 0xFF000000) + return DSPF_ARGB; + else + return DSPF_RGB32; + } + break; + } + } + else + { + 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; + + case DSPF_ARGB1555: + format->Rmask = 0x00007C00; + format->Gmask = 0x000003E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_RGB16: + format->Rmask = 0x0000F800; + format->Gmask = 0x000007E0; + format->Bmask = 0x0000001F; + break; + + case DSPF_ARGB: + format->Amask = 0; /* apps don't seem to like that: 0xFF000000; */ + /* fall through */ + case DSPF_RGB24: + case DSPF_RGB32: + format->Rmask = 0x00FF0000; + format->Gmask = 0x0000FF00; + format->Bmask = 0x000000FF; + break; + + case DSPF_LUT8: + format->Rmask = 0x000000FF; + format->Gmask = 0x000000FF; + format->Bmask = 0x000000FF; + + if (!format->palette) + format->palette = AllocatePalette(256); + break; + + default: + fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat); + return -1; + } + + format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8; + format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat); + + return 0; +} + + +int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat) +{ + int i; + DFBResult ret; +#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23) + DFBCardCapabilities caps; +#else + DFBGraphicsDeviceDescription caps; +#endif + DFBDisplayLayerConfig dlc; + struct DirectFBEnumRect *rect; + IDirectFB *dfb = NULL; + IDirectFBDisplayLayer *layer = NULL; + IDirectFBEventBuffer *events = NULL; + + HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL; + HIDDEN->enable_mga_crtc2 = 0; + HIDDEN->mga_crtc2_stretch_overscan = 1; + + ret = DirectFBInit (NULL, NULL); + if (ret) + { + SetDirectFBerror ("DirectFBInit", ret); + goto error; + } + + ret = DirectFBCreate (&dfb); + if (ret) + { + SetDirectFBerror ("DirectFBCreate", ret); + goto error; + } + + ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer", ret); + goto error; + } + + ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events); + if (ret) + { + SetDirectFBerror ("dfb->CreateEventBuffer", ret); + goto error; + } + + layer->EnableCursor (layer, 1); + + /* Query layer configuration to determine the current mode and pixelformat */ + layer->GetConfiguration (layer, &dlc); + + /* If current format is not supported use LUT8 as the default */ + if (DFBToSDLPixelFormat (dlc.pixelformat, vformat)) + DFBToSDLPixelFormat (DSPF_LUT8, vformat); + + /* Enumerate the available fullscreen modes */ + ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this); + if (ret) + { + SetDirectFBerror ("dfb->EnumVideoModes", ret); + goto error; + } + + HIDDEN->modelist = SDL_calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *)); + if (!HIDDEN->modelist) + { + SDL_OutOfMemory(); + goto error; + } + + for (i = 0, rect = enumlist; rect; ++i, rect = rect->next ) + { + HIDDEN->modelist[i] = &rect->r; + } + + HIDDEN->modelist[i] = NULL; + + + /* Query card capabilities to get the video memory size */ +#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; + this->info.hw_available = 1; + this->info.blit_hw = 1; + this->info.blit_hw_CC = 1; + 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); + if (ret) + { + SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret); + goto error; + } + + ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE); + if (ret) + { + SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret); + goto error; + } + + ret = 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 */ + dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + dlc.buffermode = DLBM_BACKVIDEO; + dlc.pixelformat = DSPF_RGB32; + + ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed ); + if (ret) + { + SetDirectFBerror ("c2layer->TestConfiguration", ret); + 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 ); + if (ret) + { + SetDirectFBerror ("c2layer->GetSurface", ret); + goto error; + } + + HIDDEN->c2framesize.x = 0; + HIDDEN->c2framesize.y = 0; + HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &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; + + error: + if (events) + events->Release (events); + + if (HIDDEN->c2frame) + HIDDEN->c2frame->Release (HIDDEN->c2frame); + + if (HIDDEN->c2layer) + HIDDEN->c2layer->Release (HIDDEN->c2layer); + + if (layer) + layer->Release (layer); + + if (dfb) + dfb->Release (dfb); + + return -1; +} + +static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) +{ + 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) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + 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) + { + SetDirectFBerror ("dfb->SetVideoMode", ret); + return NULL; + } + } + + /* Create primary surface */ + dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT; + dsc.caps = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0); + 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) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + return NULL; + } + + current->w = width; + 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, ¤t->hwdata->palette); + + current->flags |= SDL_HWPALETTE; + } + + current->hwdata->surface = surface; + + /* MGA CRTC2 stuff */ + if (HIDDEN->enable_mga_crtc2) + { + /* 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; + HIDDEN->c2dsize.w = width; + HIDDEN->c2dsize.h = height; + + 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 */ + 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 */ + if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w < (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && (float)HIDDEN->c2dsize.h < (float)HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan) + { + HIDDEN->c2dsize.w+=zoom_aspect_x; + HIDDEN->c2dsize.h+=zoom_aspect_y; + } + + /* one step down */ + HIDDEN->c2dsize.w-=zoom_aspect_x; + HIDDEN->c2dsize.h-=zoom_aspect_y; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h); + #endif + + HIDDEN->mga_crtc2_stretch = 1; + } + else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95) + { + while ((float)HIDDEN->c2dsize.w > (float)HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || (float)HIDDEN->c2dsize.h > (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; + } else { + #ifdef DIRECTFB_CRTC2_DEBUG + printf("Not stretching image\n"); + #endif + } + + /* Panning */ + if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w) + HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2; + else + HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2; + + if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h) + HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2; + else + HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2; + + #ifdef DIRECTFB_CRTC2_DEBUG + printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + #endif + } + } + + return current; +} + +static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + DFBSurfaceDescription dsc; + + /* fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n", + surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/ + + if (surface->w < 8 || surface->h < 8) + return -1; + + /* fill surface description */ + 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 */ + dsc.pixelformat = SDLToDFBPixelFormat (surface->format); + if (dsc.pixelformat == DSPF_UNKNOWN) + return -1; + + /* Allocate the hardware acceleration data */ + surface->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*surface->hwdata)); + if (surface->hwdata == NULL) + { + SDL_OutOfMemory(); + return -1; + } + + /* Create the surface */ + ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface); + if (ret) + { + SetDirectFBerror ("dfb->CreateSurface", ret); + free (surface->hwdata); + surface->hwdata = NULL; + return -1; + } + + surface->flags |= SDL_HWSURFACE | SDL_PREALLOC; + + return 0; +} + +static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface) +{ + if (surface->hwdata && HIDDEN->initialized) + { + surface->hwdata->surface->Release (surface->hwdata->surface); + free (surface->hwdata); + surface->hwdata = NULL; + } +} + +static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + /* fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n", + 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 DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect, + SDL_Surface *dst, SDL_Rect *dstrect) +{ + DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; + + DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h }; + DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h }; + + IDirectFBSurface *surface = dst->hwdata->surface; + + if (src->flags & SDL_SRCCOLORKEY) + { + flags |= DSBLIT_SRC_COLORKEY; + DirectFB_SetHWColorKey (NULL, src, src->format->colorkey); + } + + if (src->flags & SDL_SRCALPHA) + { + flags |= DSBLIT_BLEND_COLORALPHA; + surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha); + } + + surface->SetBlittingFlags (surface, flags); + + if (sr.w == dr.w && sr.h == dr.h) + surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y); + else + surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr); + + return 0; +} + +static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) +{ + SDL_PixelFormat *fmt = dst->format; + IDirectFBSurface *surface = dst->hwdata->surface; + + /* 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; +} + +static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key) +{ + SDL_PixelFormat *fmt = src->format; + IDirectFBSurface *surface = src->hwdata->surface; + + if (fmt->BitsPerPixel == 8) + surface->SetSrcColorKeyIndex (surface, key); + 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 int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha) +{ + return 0; +} + +static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface) +{ + if (HIDDEN->enable_mga_crtc2) + { + int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0); + if (HIDDEN->mga_crtc2_stretch) + 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 int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface) +{ + DFBResult ret; + void *data; + int pitch; + + ret = surface->hwdata->surface->Lock (surface->hwdata->surface, + DSLF_WRITE, &data, &pitch); + if (ret) + { + SetDirectFBerror ("surface->Lock", ret); + return -1; + } + + surface->pixels = data; + surface->pitch = pitch; + + return 0; +} + +static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface) +{ + surface->hwdata->surface->Unlock (surface->hwdata->surface); + surface->pixels = NULL; +} + +static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + 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 DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects) +{ + DFBRegion region; + int i; + int region_valid = 0; + IDirectFBSurface *surface = this->screen->hwdata->surface; + + for (i=0; i region.x2) + region.x2 = x2; + + if (y2 > region.y2) + region.y2 = y2; + } + else + { + region.x1 = rects[i].x; + region.y1 = rects[i].y; + region.x2 = x2; + region.y2 = y2; + + region_valid = 1; + } + } + + if (region_valid) + { + if (HIDDEN->enable_mga_crtc2) + { + if (HIDDEN->mga_crtc2_stretch) + HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); + else + HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); + + HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC); + } + else + surface->Flip (surface, ®ion, DSFLIP_WAITFORSYNC); + } +} + +int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) +{ + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (!palette) + return 0; + + if (firstcolor > 255) + return 0; + + if (firstcolor + ncolors > 256) + ncolors = 256 - firstcolor; + + if (ncolors > 0) + { + int i; + DFBColor entries[ncolors]; + + for (i=0; iSetEntries (palette, entries, ncolors, firstcolor); + } + + return 1; +} + +void DirectFB_VideoQuit(_THIS) +{ + struct DirectFBEnumRect *rect = enumlist; + + if (this->screen && this->screen->hwdata) + { + IDirectFBSurface *surface = this->screen->hwdata->surface; + IDirectFBPalette *palette = this->screen->hwdata->palette; + + if (palette) + palette->Release (palette); + + if (surface) + surface->Release (surface); + + this->screen->hwdata->surface = NULL; + this->screen->hwdata->palette = NULL; + } + + if (HIDDEN->c2frame) + { + HIDDEN->c2frame->Release (HIDDEN->c2frame); + HIDDEN->c2frame = NULL; + } + + if (HIDDEN->eventbuffer) + { + HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer); + HIDDEN->eventbuffer = NULL; + } + + if (HIDDEN->c2layer) + { + HIDDEN->c2layer->Release (HIDDEN->c2layer); + HIDDEN->c2layer = NULL; + } + + if (HIDDEN->layer) + { + HIDDEN->layer->Release (HIDDEN->layer); + HIDDEN->layer = NULL; + } + + if (HIDDEN->dfb) + { + HIDDEN->dfb->Release (HIDDEN->dfb); + HIDDEN->dfb = NULL; + } + + /* Free video mode list */ + if (HIDDEN->modelist) + { + free (HIDDEN->modelist); + HIDDEN->modelist = NULL; + } + + /* Free mode enumeration list */ + while (rect) + { + struct DirectFBEnumRect *next = rect->next; + free (rect); + rect = next; + } + enumlist = NULL; + + HIDDEN->initialized = 0; +} + + +int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor) +{ + /* We can only hide or show the default cursor */ + if ( cursor == NULL ) + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00); + } + else + { + HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF); + } + return 1; +} + +void DirectFB_FinalQuit(void) +{ +} diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.h b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.h new file mode 100644 index 0000000000..e1fa12c268 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_video.h @@ -0,0 +1,62 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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" + +#ifndef _SDL_DirectFB_video_h +#define _SDL_DirectFB_video_h + +#include + +#include "SDL_mouse.h" +#include "../SDL_sysvideo.h" + +#define _THIS SDL_VideoDevice *this + +/* Private display data */ + +struct SDL_PrivateVideoData +{ + int initialized; + + IDirectFB *dfb; + IDirectFBDisplayLayer *layer; + IDirectFBEventBuffer *eventbuffer; + + int nummodes; + SDL_Rect **modelist; + + /* MGA CRTC2 support */ + int enable_mga_crtc2; + int mga_crtc2_stretch; + float mga_crtc2_stretch_overscan; + IDirectFBDisplayLayer *c2layer; + IDirectFBSurface *c2frame; + DFBRectangle c2ssize; /* Real screen size */ + DFBRectangle c2dsize; /* Stretched screen size */ + DFBRectangle c2framesize; /* CRTC2 screen size */ +}; + +#define HIDDEN (this->hidden) + +void SetDirectFBerror (const char *function, DFBResult code); + +#endif /* _SDL_DirectFB_video_h */ diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.c b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.c new file mode 100644 index 0000000000..fd0cef1180 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.c @@ -0,0 +1,290 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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); + } +} + diff --git a/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.h b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.h new file mode 100644 index 0000000000..64bc86fa02 --- /dev/null +++ b/apps/plugins/sdl/src/video/directfb/SDL_DirectFB_yuv.h @@ -0,0 +1,38 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2012 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_video.h" + +extern SDL_Overlay *DirectFB_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); + +extern int DirectFB_LockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern void DirectFB_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay); + +extern int DirectFB_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *src, SDL_Rect *dst); + +extern void DirectFB_FreeYUVOverlay(_THIS, SDL_Overlay *overlay); + -- cgit v1.2.3