changeset 3141:3df74541339b gsoc2009_ps3

Added ps3 video driver based on the dummy driver. Added spulib for copying to framebuffer. Added SPU managing functions. Added open/close and taking control of the framebuffer.
author Martin Lowinski <martin@goldtopf.org>
date Fri, 29 May 2009 09:50:21 +0000
parents 9ef99b844c60
children c146645a770e
files configure.in include/SDL_config.h.in src/video/SDL_sysvideo.h src/video/SDL_video.c src/video/ps3/SDL_ps3events.c src/video/ps3/SDL_ps3events_c.h src/video/ps3/SDL_ps3render.c src/video/ps3/SDL_ps3render_c.h src/video/ps3/SDL_ps3video.c src/video/ps3/SDL_ps3video.h src/video/ps3/spulibs/Makefile src/video/ps3/spulibs/fb_writer.c src/video/ps3/spulibs/spu_common.h
diffstat 13 files changed, 1294 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/configure.in	Sat May 23 22:49:46 2009 +0000
+++ b/configure.in	Fri May 29 09:50:21 2009 +0000
@@ -1501,6 +1501,33 @@
     fi
 }
 
+dnl See if we're running on PlayStation 3 Cell hardware
+CheckPS3()
+{
+  AC_ARG_ENABLE(video-ps3,
+                AC_HELP_STRING([--enable-video-ps3], [use PlayStation 3 Cell driver [[default=yes]]]),
+                , enable_video_ps3=yes)
+  if test x$enable_video = xyes -a x$enable_video_ps3 = xyes; then 
+    AC_MSG_CHECKING(for PlayStation 3 Cell support)
+    video_ps3=no
+    AC_TRY_COMPILE([
+      #include <linux/fb.h>
+      #include <asm/ps3fb.h>
+    ],[  
+    ],[  
+      video_ps3=yes
+    ])   
+    AC_MSG_RESULT($video_ps3)
+    if test x$video_ps3 = xyes; then 
+      AC_DEFINE(SDL_VIDEO_DRIVER_PS3)
+      SOURCES="$SOURCES $srcdir/src/video/ps3/*.c"
+      EXTRA_CFLAGS="$EXTRA_CFLAGS -I/opt/cell/sdk/usr/include"
+      EXTRA_LDFLAGS="$EXTRA_LDFLAGS -L/opt/cell/sdk/usr/lib -lspe2 -lfb_writer_spu"
+      have_video=yes
+    fi   
+  fi
+}
+
 dnl Find the SVGAlib includes and libraries
 CheckSVGA()
 {
@@ -2380,6 +2407,7 @@
         CheckDirectFB
         CheckFusionSound
         CheckPS2GS
+        CheckPS3
         CheckSVGA
         CheckVGL
         CheckWscons
--- a/include/SDL_config.h.in	Sat May 23 22:49:46 2009 +0000
+++ b/include/SDL_config.h.in	Fri May 29 09:50:21 2009 +0000
@@ -287,6 +287,7 @@
 #undef SDL_VIDEO_DRIVER_PHOTON
 #undef SDL_VIDEO_DRIVER_QNXGF
 #undef SDL_VIDEO_DRIVER_PS2GS
+#undef SDL_VIDEO_DRIVER_PS3
 #undef SDL_VIDEO_DRIVER_RISCOS
 #undef SDL_VIDEO_DRIVER_SVGALIB
 #undef SDL_VIDEO_DRIVER_VGL
--- a/src/video/SDL_sysvideo.h	Sat May 23 22:49:46 2009 +0000
+++ b/src/video/SDL_sysvideo.h	Fri May 29 09:50:21 2009 +0000
@@ -355,6 +355,9 @@
 #if SDL_VIDEO_DRIVER_PS2GS
 extern VideoBootStrap PS2GS_bootstrap;
 #endif
+#if SDL_VIDEO_DRIVER_PS3
+extern VideoBootStrap PS3_bootstrap;
+#endif
 #if SDL_VIDEO_DRIVER_VGL
 extern VideoBootStrap VGL_bootstrap;
 #endif
--- a/src/video/SDL_video.c	Sat May 23 22:49:46 2009 +0000
+++ b/src/video/SDL_video.c	Fri May 29 09:50:21 2009 +0000
@@ -73,6 +73,9 @@
 #if SDL_VIDEO_DRIVER_PS2GS
     &PS2GS_bootstrap,
 #endif
+#if SDL_VIDEO_DRIVER_PS3
+    &PS3_bootstrap,
+#endif
 #if SDL_VIDEO_DRIVER_VGL
     &VGL_bootstrap,
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3events.c	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,36 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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 "../../events/SDL_sysevents.h"
+#include "../../events/SDL_events_c.h"
+
+#include "SDL_ps3video.h"
+#include "SDL_ps3events_c.h"
+
+void
+PS3_PumpEvents(_THIS)
+{
+    /* do nothing. */
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3events_c.h	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,28 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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_ps3video.h"
+
+extern void PS3_PumpEvents(_THIS);
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3render.c	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,317 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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_video.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_yuv_sw_c.h"
+#include "../SDL_renderer_sw.h"
+
+/* Debugging
+ * 0: No debug messages
+ * 1: Video debug messages
+ * 2: SPE debug messages
+ * 3: Memory adresses
+ */
+#define DEBUG_LEVEL 2
+
+#ifdef DEBUG_LEVEL
+#define deprintf( level, fmt, args... ) \
+    do \
+{ \
+    if ( (unsigned)(level) <= DEBUG_LEVEL ) \
+    { \
+        fprintf( stdout, fmt, ##args ); \
+        fflush( stdout ); \
+    } \
+} while ( 0 )
+#else
+#define deprintf( level, fmt, args... )
+#endif
+
+/* SDL surface based renderer implementation */
+
+static SDL_Renderer *SDL_PS3_CreateRenderer(SDL_Window * window,
+                                              Uint32 flags);
+static int SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y);
+static int SDL_PS3_RenderLine(SDL_Renderer * renderer, int x1, int y1,
+                                int x2, int y2);
+static int SDL_PS3_RenderFill(SDL_Renderer * renderer,
+                                const SDL_Rect * rect);
+static int SDL_PS3_RenderCopy(SDL_Renderer * renderer,
+                                SDL_Texture * texture,
+                                const SDL_Rect * srcrect,
+                                const SDL_Rect * dstrect);
+static void SDL_PS3_RenderPresent(SDL_Renderer * renderer);
+static void SDL_PS3_DestroyRenderer(SDL_Renderer * renderer);
+
+
+SDL_RenderDriver SDL_PS3_RenderDriver = {
+    SDL_PS3_CreateRenderer,
+    {
+     "ps3",
+     (/*SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |*/
+      SDL_RENDERER_PRESENTFLIP2 /*| SDL_RENDERER_PRESENTFLIP3 |
+      SDL_RENDERER_PRESENTDISCARD*/),
+     }
+};
+
+typedef struct
+{
+    int current_screen;
+    SDL_Surface *screens[3];
+} SDL_PS3_RenderData;
+
+SDL_Renderer *
+SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags)
+{
+    deprintf(1, "SDL_PS3_CreateRenderer()\n");
+    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
+    SDL_DisplayMode *displayMode = &display->current_mode;
+    SDL_Renderer *renderer;
+    SDL_PS3_RenderData *data;
+    int i, n;
+    int bpp;
+    Uint32 Rmask, Gmask, Bmask, Amask;
+
+    if (!SDL_PixelFormatEnumToMasks
+        (displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
+        SDL_SetError("Unknown display format");
+        return NULL;
+    }
+
+    renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
+    if (!renderer) {
+        SDL_OutOfMemory();
+        return NULL;
+    }
+
+    data = (SDL_PS3_RenderData *) SDL_malloc(sizeof(*data));
+    if (!data) {
+        SDL_PS3_DestroyRenderer(renderer);
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    SDL_zerop(data);
+
+    renderer->RenderPoint = SDL_PS3_RenderPoint;
+    renderer->RenderLine = SDL_PS3_RenderLine;
+    renderer->RenderFill = SDL_PS3_RenderFill;
+    renderer->RenderCopy = SDL_PS3_RenderCopy;
+    renderer->RenderPresent = SDL_PS3_RenderPresent;
+    renderer->DestroyRenderer = SDL_PS3_DestroyRenderer;
+    renderer->info.name = SDL_PS3_RenderDriver.info.name;
+    renderer->info.flags = 0;
+    renderer->window = window->id;
+    renderer->driverdata = data;
+    Setup_SoftwareRenderer(renderer);
+
+    if (flags & SDL_RENDERER_PRESENTFLIP2) {
+        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
+        n = 2;
+    } else if (flags & SDL_RENDERER_PRESENTFLIP3) {
+        renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
+        n = 3;
+    } else {
+        renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
+        n = 1;
+    }
+    for (i = 0; i < n; ++i) {
+        data->screens[i] =
+            SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask,
+                                 Bmask, Amask);
+        if (!data->screens[i]) {
+            SDL_PS3_DestroyRenderer(renderer);
+            return NULL;
+        }
+        /* Allocate aligned memory for pixels */
+        SDL_free(data->screens[i]->pixels);
+        data->screens[i]->pixels = (void *)memalign(16, data->screens[i]->h * data->screens[i]->pitch);
+        if (!data->screens[i]->pixels) {
+            SDL_FreeSurface(data->screens[i]);
+            SDL_OutOfMemory();
+            return NULL;
+        }
+        SDL_memset(data->screens[i]->pixels, 0, data->screens[i]->h * data->screens[i]->pitch);
+        SDL_SetSurfacePalette(data->screens[i], display->palette);
+    }
+    data->current_screen = 0;
+
+    return renderer;
+}
+
+static int
+SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y)
+{
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+    SDL_Surface *target = data->screens[data->current_screen];
+    int status;
+
+    if (renderer->blendMode == SDL_BLENDMODE_NONE ||
+        renderer->blendMode == SDL_BLENDMODE_MASK) {
+        Uint32 color =
+            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
+                        renderer->a);
+
+        status = SDL_DrawPoint(target, x, y, color);
+    } else {
+        status =
+            SDL_BlendPoint(target, x, y, renderer->blendMode, renderer->r,
+                           renderer->g, renderer->b, renderer->a);
+    }
+    return status;
+}
+
+static int
+SDL_PS3_RenderLine(SDL_Renderer * renderer, int x1, int y1, int x2, int y2)
+{
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+    SDL_Surface *target = data->screens[data->current_screen];
+    int status;
+
+    if (renderer->blendMode == SDL_BLENDMODE_NONE ||
+        renderer->blendMode == SDL_BLENDMODE_MASK) {
+        Uint32 color =
+            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
+                        renderer->a);
+
+        status = SDL_DrawLine(target, x1, y1, x2, y2, color);
+    } else {
+        status =
+            SDL_BlendLine(target, x1, y1, x2, y2, renderer->blendMode,
+                          renderer->r, renderer->g, renderer->b, renderer->a);
+    }
+    return status;
+}
+
+static int
+SDL_PS3_RenderFill(SDL_Renderer * renderer, const SDL_Rect * rect)
+{
+    deprintf(1, "SDL_PS3_RenderFill()\n");
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+    SDL_Surface *target = data->screens[data->current_screen];
+    SDL_Rect real_rect = *rect;
+    int status;
+
+    if (renderer->blendMode == SDL_BLENDMODE_NONE) {
+        Uint32 color =
+            SDL_MapRGBA(target->format, renderer->r, renderer->g, renderer->b,
+                        renderer->a);
+
+        status = SDL_FillRect(target, &real_rect, color);
+    } else {
+        status =
+            SDL_BlendRect(target, &real_rect, renderer->blendMode,
+                          renderer->r, renderer->g, renderer->b, renderer->a);
+    }
+    return status;
+}
+
+static int
+SDL_PS3_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
+                     const SDL_Rect * srcrect, const SDL_Rect * dstrect)
+{
+    deprintf(1, "SDL_PS3_RenderCopy()\n");
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
+
+    if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
+        SDL_Surface *target = data->screens[data->current_screen];
+        void *pixels =
+            (Uint8 *) target->pixels + dstrect->y * target->pitch +
+            dstrect->x * target->format->BytesPerPixel;
+        return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
+                                   srcrect, display->current_mode.format,
+                                   dstrect->w, dstrect->h, pixels,
+                                   target->pitch);
+    } else {
+        SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
+        SDL_Surface *target = data->screens[data->current_screen];
+        SDL_Rect real_srcrect = *srcrect;
+        SDL_Rect real_dstrect = *dstrect;
+
+        return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
+    }
+}
+
+static void
+SDL_PS3_RenderPresent(SDL_Renderer * renderer)
+{
+    deprintf(1, "SDL_PS3_RenderPresent()\n");
+    static int frame_number;
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+
+    /* Send the data to the display */
+    if (SDL_getenv("SDL_VIDEO_PS3_SAVE_FRAMES")) {
+        char file[128];
+        SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
+                     renderer->window, ++frame_number);
+        SDL_SaveBMP(data->screens[data->current_screen], file);
+    }
+
+    /* Update the flipping chain, if any */
+    if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
+        data->current_screen = (data->current_screen + 1) % 2;
+    } else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
+        data->current_screen = (data->current_screen + 1) % 3;
+    }
+
+    /* How to access the framebuffer from here? 
+    unsigned long crt = 0;
+    unsigned int s_center_index = 0;
+    unsigned int * s_center[2];
+    s_center[0] = frame_buffer;
+    // Wait for vsync
+    deprintf(1, "[PS3] Wait for vsync\n");
+    ioctl(fbdev, FBIO_WAITFORVSYNC, &crt);
+    // Page flip
+    deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", s_center_index, s_center[s_center_index]);
+    ioctl(fbdev, PS3FB_IOCTL_FSEL, (unsigned long)&s_center_index);
+    */
+}
+
+static void
+SDL_PS3_DestroyRenderer(SDL_Renderer * renderer)
+{
+    deprintf(1, "SDL_PS3_DestroyRenderer()\n");
+    SDL_PS3_RenderData *data =
+        (SDL_PS3_RenderData *) renderer->driverdata;
+    int i;
+
+    if (data) {
+        for (i = 0; i < SDL_arraysize(data->screens); ++i) {
+            if (data->screens[i]) {
+                SDL_FreeSurface(data->screens[i]);
+            }
+        }
+        SDL_free(data);
+    }
+    SDL_free(renderer);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3render_c.h	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,29 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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"
+
+/* Default framebuffer device on PS3 */
+/* SDL surface based renderer implementation */
+
+extern SDL_RenderDriver SDL_PS3_RenderDriver;
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3video.c	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,381 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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 PS3 video driver implementation based on dummy video driver
+ *
+ * Initial work by Ryan C. Gordon (icculus@icculus.org). A good portion
+ *  of this was cut-and-pasted from Stephane Peter's work in the AAlib
+ *  SDL video driver.  Renamed to "DUMMY" by Sam Lantinga.
+ */
+
+#include "SDL_video.h"
+#include "SDL_mouse.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_events_c.h"
+#include "spulibs/spu_common.h"
+
+#include "SDL_ps3video.h"
+#include "SDL_ps3events_c.h"
+#include "SDL_ps3render_c.h"
+
+#include <fcntl.h>
+#include <linux/fb.h>
+#include <asm/ps3fb.h>
+#include <libspe2.h>
+#include <sys/mman.h>
+
+#define PS3VID_DRIVER_NAME "ps3"
+
+/* Initialization/Query functions */
+static int PS3_VideoInit(_THIS);
+static int PS3_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
+static void PS3_VideoQuit(_THIS);
+
+/* SPU specific functions */
+int SPE_Start(_THIS, spu_data_t * spe_data);
+int SPE_Stop(_THIS, spu_data_t * spe_data);
+int SPE_Boot(_THIS, spu_data_t * spe_data);
+int SPE_Shutdown(_THIS, spu_data_t * spe_data);
+int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg);
+int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg);
+void SPE_RunContext(void *thread_argp);
+
+/* Stores the SPE executable name of fb_writer_spu */
+extern spe_program_handle_t fb_writer_spu;
+
+/* PS3 driver bootstrap functions */
+
+static int
+PS3_Available(void)
+{
+    deprintf(1, "PS3_Available()\n");
+    const char *envr = SDL_getenv("SDL_VIDEODRIVER");
+    if ((envr) && (SDL_strcmp(envr, PS3VID_DRIVER_NAME) == 0)) {
+        return (1);
+    }
+
+    return (0);
+}
+
+static void
+PS3_DeleteDevice(SDL_VideoDevice * device)
+{
+    deprintf(1, "PS3_DeleteDevice()\n");
+    SDL_free(device->driverdata);
+    SDL_free(device);
+}
+
+static SDL_VideoDevice *
+PS3_CreateDevice(int devindex)
+{
+    deprintf(1, "PS3_CreateDevice()\n");
+    SDL_VideoDevice *device;
+    SDL_VideoData *data;
+
+    /* Initialize all variables that we clean on shutdown */
+    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+    if (!device) {
+        SDL_OutOfMemory();
+        if (device) {
+            SDL_free(device);
+        }
+        return (0);
+    }
+    data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+    if (!data) {
+        SDL_OutOfMemory();
+        SDL_free(device);
+        return (0);
+    }
+    device->driverdata = data;
+
+    /* Set the function pointers */
+    device->VideoInit = PS3_VideoInit;
+    device->VideoQuit = PS3_VideoQuit;
+    device->SetDisplayMode = PS3_SetDisplayMode;
+    device->PumpEvents = PS3_PumpEvents;
+
+    device->free = PS3_DeleteDevice;
+
+    return device;
+}
+
+VideoBootStrap PS3_bootstrap = {
+    PS3VID_DRIVER_NAME, "SDL PS3 Cell video driver",
+    PS3_Available, PS3_CreateDevice
+};
+
+
+int
+PS3_VideoInit(_THIS)
+{
+    deprintf(1, "PS3_VideoInit()\n");
+
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    SDL_DisplayMode mode;
+
+    /* Use a fake 32-bpp desktop mode */
+    mode.format = SDL_PIXELFORMAT_RGB888;
+    //mode.w = 1024;
+    //mode.h = 768;
+    mode.w = 1920;
+    mode.h = 1080;
+    mode.refresh_rate = 0;
+    mode.driverdata = NULL;
+    SDL_AddBasicVideoDisplay(&mode);
+    SDL_AddRenderDriver(0, &SDL_PS3_RenderDriver);
+
+    SDL_zero(mode);
+    SDL_AddDisplayMode(0, &mode);
+
+    /* 
+     *PS3 stuff 
+     */
+
+    /* Create SPU fb_parms and thread structure */
+    data->fb_parms = (struct fb_writer_parms_t *)
+        memalign(16, sizeof(struct fb_writer_parms_t));
+    data->fb_thread_data = (spu_data_t *) malloc(sizeof(spu_data_t));
+    if (data->fb_parms == NULL || data->fb_thread_data == NULL) {
+        SDL_OutOfMemory();
+        return -1;
+    }
+    data->fb_thread_data->program = fb_writer_spu;
+    data->fb_thread_data->program_name = "fb_writer_spu";
+    data->fb_thread_data->argp = (void *)data->fb_parms;
+    data->fb_thread_data->keepalive = 1;
+    data->fb_thread_data->booted = 0;
+
+    SPE_Start(_this, data->fb_thread_data);
+
+    /* Open the device */
+    data->fbdev = open(PS3DEV, O_RDWR);
+    if (data->fbdev < 0) {
+        SDL_SetError("[PS3] Unable to open device %s", PS3DEV);
+        return -1;
+    }
+
+    /* Take control of frame buffer from kernel, for details see
+     * http://felter.org/wesley/files/ps3/linux-20061110-docs/ApplicationProgrammingEnvironment.html
+     * kernel will no longer flip the screen itself
+     */
+    ioctl(data->fbdev, PS3FB_IOCTL_ON, 0);
+
+    /* Unblank screen */
+    ioctl(data->fbdev, FBIOBLANK, 0);
+
+    struct fb_fix_screeninfo fb_finfo;
+    if (ioctl(data->fbdev, FBIOGET_FSCREENINFO, &fb_finfo)) {
+        SDL_SetError("[PS3] Can't get fixed screeninfo");
+        return (0);
+    }
+
+    /* Note: on PS3, fb_finfo.smem_len is enough for double buffering */
+    if ((data->frame_buffer = (uint8_t *)mmap(0, fb_finfo.smem_len,
+        PROT_READ | PROT_WRITE, MAP_SHARED,
+        data->fbdev, 0)) == (uint8_t *) - 1) {
+        SDL_SetError("[PS3] Can't mmap for %s", PS3DEV);
+        return (0);
+    } else {
+        //current->flags |= SDL_DOUBLEBUF;
+    }
+
+    /* Blank screen */
+    memset(data->frame_buffer, 0x00, fb_finfo.smem_len);
+
+    /* We're done! */
+    return 0;
+}
+
+static int
+PS3_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
+{
+    deprintf(1, "PS3_SetDisplayMode()\n");
+    return 0;
+}
+
+void
+PS3_VideoQuit(_THIS)
+{
+    deprintf(1, "PS3_VideoQuit()\n");
+    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+    if (data->frame_buffer) {
+        struct fb_fix_screeninfo fb_finfo;
+        if (ioctl(data->fbdev, FBIOGET_FSCREENINFO, &fb_finfo) != -1) {
+            munmap(data->frame_buffer, fb_finfo.smem_len);
+            data->frame_buffer = 0;
+        }
+    }
+
+    if (data->fb_parms)
+        free((void *)data->fb_parms);
+    if (data->fb_thread_data) {
+        SPE_Shutdown(_this, data->fb_thread_data);
+        free((void *)data->fb_thread_data);
+    }
+}
+
+
+/*
+ * SPE handling
+ */
+
+/* Start the SPE thread */
+int SPE_Start(_THIS, spu_data_t * spe_data)
+{
+  deprintf(2, "[PS3->SPU] Start SPE: %s\n", spe_data->program_name);
+  if (!(spe_data->booted))
+    SPE_Boot(_this, spe_data);
+
+  /* To allow re-running of context, spe_ctx_entry has to be set before each call */
+  spe_data->entry = SPE_DEFAULT_ENTRY;
+  spe_data->error_code = 0;
+
+  /* Create SPE thread and run */
+  deprintf(2, "[PS3->SPU] Create Thread: %s\n", spe_data->program_name);
+  if (pthread_create
+      (&spe_data->thread, NULL, (void *)&SPE_RunContext, (void *)spe_data)) {
+    deprintf(2, "[PS3->SPU] Could not create pthread for spe: %s\n", spe_data->program_name);
+    SDL_SetError("[PS3->SPU] Could not create pthread for spe");
+    return -1;
+  }
+
+  if (spe_data->keepalive)
+    SPE_WaitForMsg(_this, spe_data, SPU_READY);
+}
+
+
+/* Stop the SPE thread */
+int SPE_Stop(_THIS, spu_data_t * spe_data)
+{
+  deprintf(2, "[PS3->SPU] Stop SPE: %s\n", spe_data->program_name);
+  /* Wait for SPE thread to complete */
+  deprintf(2, "[PS3->SPU] Wait for SPE thread to complete: %s\n", spe_data->program_name);
+  if (pthread_join(spe_data->thread, NULL)) {
+    deprintf(2, "[PS3->SPU] Failed joining the thread: %s\n", spe_data->program_name);
+    SDL_SetError("[PS3->SPU] Failed joining the thread");
+    return -1;
+  }
+
+  return 0;
+}
+
+/* Create SPE context and load program */
+int SPE_Boot(_THIS, spu_data_t * spe_data)
+{
+  /* Create SPE context */
+  deprintf(2, "[PS3->SPU] Create SPE Context: %s\n", spe_data->program_name);
+  spe_data->ctx = spe_context_create(0, NULL);
+  if (spe_data->ctx == NULL) {
+    deprintf(2, "[PS3->SPU] Failed creating SPE context: %s\n", spe_data->program_name);
+    SDL_SetError("[PS3->SPU] Failed creating SPE context");
+    return -1;
+  }
+
+  /* Load SPE object into SPE local store */
+  deprintf(2, "[PS3->SPU] Load Program into SPE: %s\n", spe_data->program_name);
+  if (spe_program_load(spe_data->ctx, &spe_data->program)) {
+    deprintf(2, "[PS3->SPU] Failed loading program into SPE context: %s\n", spe_data->program_name);
+    SDL_SetError
+        ("[PS3->SPU] Failed loading program into SPE context");
+    return -1;
+  }
+  spe_data->booted = 1;
+  deprintf(2, "[PS3->SPU] SPE boot successful\n");
+
+  return 0;
+}
+
+/* (Stop and) shutdown the SPE */
+int SPE_Shutdown(_THIS, spu_data_t * spe_data)
+{
+  if (spe_data->keepalive && spe_data->booted) {
+    SPE_SendMsg(_this, spe_data, SPU_EXIT);
+    SPE_Stop(_this, spe_data);
+  }
+
+  /* Destroy SPE context */
+  deprintf(2, "[PS3->SPU] Destroy SPE context: %s\n", spe_data->program_name);
+  if (spe_context_destroy(spe_data->ctx)) {
+    deprintf(2, "[PS3->SPU] Failed destroying context: %s\n", spe_data->program_name);
+    SDL_SetError("[PS3->SPU] Failed destroying context");
+    return -1;
+  }
+  deprintf(2, "[PS3->SPU] SPE shutdown successful: %s\n", spe_data->program_name);
+  return 0;
+}
+
+/* Send message to the SPE via mailboxe */
+int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg)
+{
+  deprintf(2, "[PS3->SPU] Sending message %u to %s\n", msg, spe_data->program_name);
+  /* Send one message, block until message was sent */
+  unsigned int spe_in_mbox_msgs[1];
+  spe_in_mbox_msgs[0] = msg;
+  int in_mbox_write = spe_in_mbox_write(spe_data->ctx, spe_in_mbox_msgs, 1, SPE_MBOX_ALL_BLOCKING);
+
+  if (1 > in_mbox_write) {
+    deprintf(2, "[PS3->SPU] No message could be written to %s\n", spe_data->program_name);
+    SDL_SetError("[PS3->SPU] No message could be written");
+    return -1;
+  }
+  return 0;
+}
+
+
+/* Read 1 message from SPE, block until at least 1 message was received */
+int SPE_WaitForMsg(_THIS, spu_data_t * spe_data, unsigned int msg)
+{
+  deprintf(2, "[PS3->SPU] Waiting for message from %s\n", spe_data->program_name);
+  unsigned int out_messages[1];
+  while (!spe_out_mbox_status(spe_data->ctx));
+  int mbox_read = spe_out_mbox_read(spe_data->ctx, out_messages, 1);
+  deprintf(2, "[PS3->SPU] Got message from %s, message was %u\n", spe_data->program_name, out_messages[0]);
+  if (out_messages[0] == msg)
+    return 0;
+  else
+    return -1;
+}
+
+/* Re-runnable invocation of the spe_context_run call */
+void SPE_RunContext(void *thread_argp)
+{ 
+  /* argp is the pointer to argument to be passed to the SPE program */
+  spu_data_t *args = (spu_data_t *) thread_argp;
+  deprintf(3, "[PS3->SPU] void* argp=0x%x\n", (unsigned int)args->argp);
+  
+  /* Run it.. */
+  deprintf(2, "[PS3->SPU] Run SPE program: %s\n", args->program_name);
+  if (spe_context_run
+      (args->ctx, &args->entry, 0, (void *)args->argp, NULL,
+       NULL) < 0) {
+    deprintf(2, "[PS3->SPU] Failed running SPE context: %s\n", args->program_name);
+    SDL_SetError("[PS3->SPU] Failed running SPE context: %s", args->program_name);
+    exit(1);
+  }
+
+  pthread_exit(NULL);
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/SDL_ps3video.h	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,84 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2009 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 <libspe2.h>
+
+#ifndef _SDL_ps3video_h
+#define _SDL_ps3video_h
+
+#include "../SDL_sysvideo.h"
+
+/* Debugging
+ * 0: No debug messages
+ * 1: Video debug messages
+ * 2: SPE debug messages
+ * 3: Memory adresses
+ */
+#define DEBUG_LEVEL 2
+
+#ifdef DEBUG_LEVEL
+#define deprintf( level, fmt, args... ) \
+    do \
+{ \
+    if ( (unsigned)(level) <= DEBUG_LEVEL ) \
+    { \
+        fprintf( stdout, fmt, ##args ); \
+        fflush( stdout ); \
+    } \
+} while ( 0 )
+#else
+#define deprintf( level, fmt, args... )
+#endif
+
+/* Default framebuffer device on PS3 */
+#define PS3DEV "/dev/fb0"
+
+/* SPU thread data */
+typedef struct spu_data {
+    spe_context_ptr_t ctx;
+    pthread_t thread;
+    spe_program_handle_t program;
+    char * program_name;
+    unsigned int booted;
+    unsigned int keepalive;
+    unsigned int entry;
+    int error_code;
+    void * argp;
+} spu_data_t;
+
+/* Private display data */
+typedef struct SDL_VideoData
+{
+    /* Framebuffer device descriptor */
+    int fbdev;
+    /* mmap'd access to fbdev */
+    uint8_t * frame_buffer; 
+    /* SPE threading stuff */
+    spu_data_t * fb_thread_data;
+    /* Framebuffer transfer data */
+    volatile struct fb_writer_parms_t * fb_parms __attribute__((aligned(128)));
+} SDL_VideoData;
+
+#endif /* _SDL_ps3video_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/spulibs/Makefile	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,83 @@
+# This Makefile is for building the CELL BE SPU libs
+# libfb_writer_spu.so, libyuv2rgb_spu.so, libbilin_scaler_spu.so
+
+# Toolchain
+SPU_GCC=/usr/bin/spu-gcc
+PPU_GCC=/usr/bin/gcc
+PPU_EMBEDSPU=/usr/bin/embedspu
+PPU_AR=/usr/bin/ar
+PPU_LD=/usr/bin/ld
+INSTALL=/usr/bin/install
+
+SPU_CFLAGS=-W -Wall -Winline -Wno-main -I. -I /usr/spu/include -I /opt/cell/sdk/usr/spu/include -finline-limit=10000 -Winline -ftree-vectorize -funroll-loops -fmodulo-sched -ffast-math -fPIC -O2
+
+# Usually /usr/lib, depending on your distribution
+PREFIX=/usr/lib
+
+
+all: libfb_writer_spu.a libfb_writer_spu.so
+#				libyuv2rgb_spu.so libyuv2rgb_spu.a \
+#				libbilin_scaler_spu.so libbilin_scaler_spu.a
+
+
+# fb_writer
+fb_writer_spu-embed.o: fb_writer.c spu_common.h
+	$(SPU_GCC) $(SPU_CFLAGS) -o fb_writer_spu fb_writer.c -lm
+	$(PPU_EMBEDSPU) -m32 fb_writer_spu fb_writer_spu fb_writer_spu-embed.o
+
+libfb_writer_spu.so: fb_writer_spu-embed.o
+	$(PPU_LD) -o libfb_writer_spu.so -shared -soname=libfb_writer_spu.so fb_writer_spu-embed.o
+
+libfb_writer_spu.a: fb_writer_spu-embed.o
+	$(PPU_AR) -qcs libfb_writer_spu.a fb_writer_spu-embed.o
+
+
+# yuv2rgb_converter
+yuv2rgb_spu-embed.o: yuv2rgb_converter.c spu_common.h
+	$(SPU_GCC) $(SPU_CFLAGS) -o yuv2rgb_spu yuv2rgb_converter.c -lm
+	$(PPU_EMBEDSPU) -m32 yuv2rgb_spu yuv2rgb_spu yuv2rgb_spu-embed.o
+
+libyuv2rgb_spu.a: yuv2rgb_spu-embed.o
+	$(PPU_AR) -qcs libyuv2rgb_spu.a yuv2rgb_spu-embed.o
+
+libyuv2rgb_spu.so: yuv2rgb_spu-embed.o
+	$(PPU_LD) -o libyuv2rgb_spu.so -shared -soname=libyuv2rgb_spu.so yuv2rgb_spu-embed.o
+
+
+# bilin_scaler
+bilin_scaler_spu-embed.o: bilin_scaler.c spu_common.h
+	$(SPU_GCC) $(SPU_CFLAGS) -o bilin_scaler_spu bilin_scaler.c -lm
+	$(PPU_EMBEDSPU) -m32 bilin_scaler_spu bilin_scaler_spu bilin_scaler_spu-embed.o
+
+libbilin_scaler_spu.a: bilin_scaler_spu-embed.o
+	$(PPU_AR) -qcs libbilin_scaler_spu.a bilin_scaler_spu-embed.o
+
+libbilin_scaler_spu.so: bilin_scaler_spu-embed.o
+	$(PPU_LD) -o libbilin_scaler_spu.so -shared -soname=libbilin_scaler_spu.so bilin_scaler_spu-embed.o
+
+install: libfb_writer_spu.a libfb_writer_spu.so
+#				libyuv2rgb_spu.so libyuv2rgb_spu.a \
+#				libbilin_scaler_spu.so libbilin_scaler_spu.a
+	$(INSTALL) -c -m 0755 libfb_writer_spu.so $(PREFIX)/.
+	$(INSTALL) -c -m 0655 libfb_writer_spu.a $(PREFIX)/.
+#	$(INSTALL) -c -m 0755 libyuv2rgb_spu.so $(PREFIX)/.
+#	$(INSTALL) -c -m 0655 libyuv2rgb_spu.a $(PREFIX)/.
+#	$(INSTALL) -c -m 0755 libbilin_scaler_spu.so $(PREFIX)/.
+#	$(INSTALL) -c -m 0655 libbilin_scaler_spu.a $(PREFIX)/.
+
+
+uninstall: $(PREFIX)/libfb_writer_spu.so $(PREFIX)/libfb_writer_spu.a
+#		$(PREFIX)/libyuv2rgb_spu.so $(PREFIX)/libyuv2rgb_spu.a \
+#		$(PREFIX)/libbilin_scaler_spu.so $(PREFIX)/libbilin_scaler_spu.a
+	rm -f $(PREFIX)/libfb_writer_spu.a
+	rm -f $(PREFIX)/libfb_writer_spu.so
+#	rm -f $(PREFIX)/libyuv2rgb_spu.so
+#	rm -f $(PREFIX)/libyuv2rgb_spu.a
+#	rm -f $(PREFIX)/libbilin_scaler_spu.so
+#	rm -f $(PREFIX)/libbilin_scaler_spu.a
+
+
+clean:
+	rm -f bilin_scaler_spu-embed.o libbilin_scaler_spu.so libbilin_scaler_spu.a bilin_scaler_spu
+	rm -f yuv2rgb_spu-embed.o libyuv2rgb_spu.so libyuv2rgb_spu.a yuv2rgb_spu
+	rm -f fb_writer_spu-embed.o libfb_writer_spu.so libfb_writer_spu.a fb_writer_spu
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/spulibs/fb_writer.c	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,193 @@
+/*
+ * SDL - Simple DirectMedia Layer
+ * CELL BE Support for PS3 Framebuffer
+ * Copyright (C) 2008, 2009 International Business Machines Corporation
+ *
+ * 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
+ *
+ *  Martin Lowinski  <lowinski [at] de [dot] ibm [ibm] com>
+ *  Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com>
+ *  SPE code based on research by:
+ *  Rene Becker
+ *  Thimo Emmerich
+ */
+
+#include "spu_common.h"
+
+#include <spu_intrinsics.h>
+#include <spu_mfcio.h>
+#include <stdio.h>
+#include <string.h>
+
+// Debugging
+//#define DEBUG
+
+#ifdef DEBUG
+#define deprintf(fmt, args... ) \
+	fprintf( stdout, fmt, ##args ); \
+	fflush( stdout );
+#else
+#define deprintf( fmt, args... )
+#endif
+
+void cpy_to_fb(unsigned int);
+
+/* fb_writer_spu parms */
+static volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128)));
+
+/* Code running on SPU */
+int main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused)))
+{
+	deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id);
+	uint32_t ea_mfc, mbox;
+	// send ready message
+	spu_write_out_mbox(SPU_READY);
+
+	while (1) {
+		/* Check mailbox */
+		mbox = spu_read_in_mbox();
+		deprintf("[SPU] Message is %u\n", mbox);
+		switch (mbox) {
+			case SPU_EXIT:
+				deprintf("[SPU] fb_writer goes down...\n");
+				return 0;
+			case SPU_START:
+				break;
+			default:
+				deprintf("[SPU] Cannot handle message\n");
+				continue;
+		}
+
+		/* Tag Manager setup */
+		unsigned int tags;
+		tags = mfc_multi_tag_reserve(5);
+		if (tags == MFC_TAG_INVALID) {
+			deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n");
+			return 0;
+		}
+
+		/* Framebuffer parms */
+		ea_mfc = spu_read_in_mbox();
+		deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc);
+		spu_mfcdma32(&parms, (unsigned int)ea_mfc,
+				sizeof(struct fb_writer_parms_t), tags,
+				MFC_GET_CMD);
+		deprintf("[SPU] argp = %u\n", (unsigned int)argp);
+		DMA_WAIT_TAG(tags);
+
+		/* Copy parms->data to framebuffer */
+		deprintf("[SPU] Copying to framebuffer started\n");
+		cpy_to_fb(tags);
+		deprintf("[SPU] Copying to framebuffer done!\n");
+
+		mfc_multi_tag_release(tags, 5);
+		deprintf("[SPU] fb_writer_spu... done!\n");
+		/* Send FIN msg */
+		spu_write_out_mbox(SPU_FIN);
+	}
+
+	return 0;
+}
+
+void cpy_to_fb(unsigned int tag_id_base)
+{
+	unsigned int i;
+	unsigned char current_buf;
+	uint8_t *in = parms.data;
+
+	/* Align fb pointer which was centered before */
+	uint8_t *fb =
+	    (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0);
+
+	uint32_t bounded_input_height = parms.bounded_input_height;
+	uint32_t bounded_input_width = parms.bounded_input_width;
+	uint32_t fb_pixel_size = parms.fb_pixel_size;
+
+	uint32_t out_line_stride = parms.out_line_stride;
+	uint32_t in_line_stride = parms.in_line_stride;
+	uint32_t in_line_size = bounded_input_width * fb_pixel_size;
+
+	current_buf = 0;
+
+	/* Local store buffer */
+	static volatile uint8_t buf[4][BUFFER_SIZE]
+	    __attribute__ ((aligned(128)));
+	/* do 4-times multibuffering using DMA list, process in two steps */
+	for (i = 0; i < bounded_input_height >> 2; i++) {
+		/* first buffer */
+		DMA_WAIT_TAG(tag_id_base + 1);
+		// retrieve buffer
+		spu_mfcdma32(buf[0], (unsigned int)in, in_line_size,
+			     tag_id_base + 1, MFC_GETB_CMD);
+		DMA_WAIT_TAG(tag_id_base + 1);
+		// store buffer
+		spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size,
+			     tag_id_base + 1, MFC_PUTB_CMD);
+		in += in_line_stride;
+		fb += out_line_stride;
+		deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in,
+		       fb);
+
+		/* second buffer */
+		DMA_WAIT_TAG(tag_id_base + 2);
+		// retrieve buffer
+		spu_mfcdma32(buf[1], (unsigned int)in, in_line_size,
+			     tag_id_base + 2, MFC_GETB_CMD);
+		DMA_WAIT_TAG(tag_id_base + 2);
+		// store buffer
+		spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size,
+			     tag_id_base + 2, MFC_PUTB_CMD);
+		in += in_line_stride;
+		fb += out_line_stride;
+		deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in,
+		       fb);
+
+		/* third buffer */
+		DMA_WAIT_TAG(tag_id_base + 3);
+		// retrieve buffer
+		spu_mfcdma32(buf[2], (unsigned int)in, in_line_size,
+			     tag_id_base + 3, MFC_GETB_CMD);
+		DMA_WAIT_TAG(tag_id_base + 3);
+		// store buffer
+		spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size,
+			     tag_id_base + 3, MFC_PUTB_CMD);
+		in += in_line_stride;
+		fb += out_line_stride;
+		deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in,
+		       fb);
+
+		/* fourth buffer */
+		DMA_WAIT_TAG(tag_id_base + 4);
+		// retrieve buffer
+		spu_mfcdma32(buf[3], (unsigned int)in, in_line_size,
+			     tag_id_base + 4, MFC_GETB_CMD);
+		DMA_WAIT_TAG(tag_id_base + 4);
+		// store buffer
+		spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size,
+			     tag_id_base + 4, MFC_PUTB_CMD);
+		in += in_line_stride;
+		fb += out_line_stride;
+		deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in,
+		       fb);
+		deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i,
+		       bounded_input_height >> 2);
+	}
+	DMA_WAIT_TAG(tag_id_base + 2);
+	DMA_WAIT_TAG(tag_id_base + 3);
+	DMA_WAIT_TAG(tag_id_base + 4);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ps3/spulibs/spu_common.h	Fri May 29 09:50:21 2009 +0000
@@ -0,0 +1,108 @@
+/*
+ * SDL - Simple DirectMedia Layer
+ * CELL BE Support for PS3 Framebuffer
+ * Copyright (C) 2008, 2009 International Business Machines Corporation
+ *
+ * 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
+ *
+ *  Martin Lowinski  <lowinski [at] de [dot] ibm [ibm] com>
+ *  Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com>
+ *  SPE code based on research by:
+ *  Rene Becker
+ *  Thimo Emmerich
+ */
+
+/* Common definitions/makros for SPUs */
+
+#ifndef _SPU_COMMON_H
+#define _SPU_COMMON_H
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+/* Tag management */
+#define DMA_WAIT_TAG(_tag)     \
+    mfc_write_tag_mask(1<<(_tag)); \
+    mfc_read_tag_status_all();
+
+/* SPU mailbox messages */
+#define SPU_READY	0
+#define SPU_START	1
+#define SPU_FIN		2
+#define SPU_EXIT	3
+
+/* Tags */
+#define RETR_BUF	0
+#define STR_BUF		1
+#define TAG_INIT	2
+
+/* Buffersizes */
+#define MAX_HDTV_WIDTH 1920
+#define MAX_HDTV_HEIGHT 1080
+/* One stride of HDTV */
+#define BUFFER_SIZE 7680
+
+/* fb_writer ppu/spu exchange parms */
+struct fb_writer_parms_t {
+	uint8_t *data;
+	uint8_t *center;
+	uint32_t out_line_stride;
+	uint32_t in_line_stride;
+	uint32_t bounded_input_height;
+	uint32_t bounded_input_width;
+	uint32_t fb_pixel_size;
+
+	/* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */
+	char padding[4];
+} __attribute__((aligned(128)));
+
+/* yuv2rgb ppu/spu exchange parms */
+struct yuv2rgb_parms_t {
+	uint8_t* y_plane;
+	uint8_t* v_plane;
+	uint8_t* u_plane;
+
+	uint8_t* dstBuffer;
+
+	unsigned int src_pixel_width;
+	unsigned int src_pixel_height;
+
+	/* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */
+	char padding[128 - ((4 * sizeof(uint8_t *) + 2 * sizeof(unsigned int)) & 0x7F)];
+} __attribute__((aligned(128)));
+
+/* bilin_scaler ppu/spu exchange parms */
+struct scale_parms_t {
+	uint8_t* y_plane;
+	uint8_t* v_plane;
+	uint8_t* u_plane;
+
+	uint8_t* dstBuffer;
+
+	unsigned int src_pixel_width;
+	unsigned int src_pixel_height;
+
+	unsigned int dst_pixel_width;
+	unsigned int dst_pixel_height;
+
+	/* This padding is to fulfill the need for 16 byte alignment. On parm change, update! */
+	char padding[128 - ((4 * sizeof(uint8_t *) + 4 * sizeof(unsigned int)) & 0x7F)];
+} __attribute__((aligned(128)));
+
+#endif /* _SPU_COMMON_H */
+
+