Added ps3 video driver based on the dummy driver. gsoc2009_ps3
authorMartin Lowinski <martin@goldtopf.org>
Fri, 29 May 2009 09:50:21 +0000
branchgsoc2009_ps3
changeset 3141 3df74541339b
parent 3140 9ef99b844c60
child 3142 c146645a770e
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.
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
--- 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 */
+
+