From 6dc66ff46d5e1e3482ba1d4a90ceddfde6c9f29b Mon Sep 17 00:00:00 2001 From: Martin Lowinski Date: Fri, 29 May 2009 09:50:21 +0000 Subject: [PATCH] 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 | 28 +++ include/SDL_config.h.in | 1 + src/video/SDL_sysvideo.h | 3 + src/video/SDL_video.c | 3 + src/video/ps3/SDL_ps3events.c | 36 +++ src/video/ps3/SDL_ps3events_c.h | 28 +++ src/video/ps3/SDL_ps3render.c | 317 ++++++++++++++++++++++++ src/video/ps3/SDL_ps3render_c.h | 29 +++ src/video/ps3/SDL_ps3video.c | 381 +++++++++++++++++++++++++++++ src/video/ps3/SDL_ps3video.h | 84 +++++++ src/video/ps3/spulibs/Makefile | 83 +++++++ src/video/ps3/spulibs/fb_writer.c | 193 +++++++++++++++ src/video/ps3/spulibs/spu_common.h | 108 ++++++++ 13 files changed, 1294 insertions(+) create mode 100644 src/video/ps3/SDL_ps3events.c create mode 100644 src/video/ps3/SDL_ps3events_c.h create mode 100644 src/video/ps3/SDL_ps3render.c create mode 100644 src/video/ps3/SDL_ps3render_c.h create mode 100644 src/video/ps3/SDL_ps3video.c create mode 100644 src/video/ps3/SDL_ps3video.h create mode 100644 src/video/ps3/spulibs/Makefile create mode 100644 src/video/ps3/spulibs/fb_writer.c create mode 100644 src/video/ps3/spulibs/spu_common.h diff --git a/configure.in b/configure.in index d8b1bcf80..d318d8f79 100644 --- a/configure.in +++ b/configure.in @@ -1501,6 +1501,33 @@ AC_HELP_STRING([--enable-video-ps2gs], [use PlayStation 2 GS video driver [[defa 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 + #include + ],[ + ],[ + 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 @@ case "$host" in CheckDirectFB CheckFusionSound CheckPS2GS + CheckPS3 CheckSVGA CheckVGL CheckWscons diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index c02193596..cdb2340ed 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -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 diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 1b54ed347..dced2b3eb 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -355,6 +355,9 @@ extern VideoBootStrap DirectFB_bootstrap; #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 diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 913bd4e05..d39b0384e 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -73,6 +73,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_PS2GS &PS2GS_bootstrap, #endif +#if SDL_VIDEO_DRIVER_PS3 + &PS3_bootstrap, +#endif #if SDL_VIDEO_DRIVER_VGL &VGL_bootstrap, #endif diff --git a/src/video/ps3/SDL_ps3events.c b/src/video/ps3/SDL_ps3events.c new file mode 100644 index 000000000..c495b0418 --- /dev/null +++ b/src/video/ps3/SDL_ps3events.c @@ -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: */ diff --git a/src/video/ps3/SDL_ps3events_c.h b/src/video/ps3/SDL_ps3events_c.h new file mode 100644 index 000000000..03491ef02 --- /dev/null +++ b/src/video/ps3/SDL_ps3events_c.h @@ -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: */ diff --git a/src/video/ps3/SDL_ps3render.c b/src/video/ps3/SDL_ps3render.c new file mode 100644 index 000000000..cd51bbf02 --- /dev/null +++ b/src/video/ps3/SDL_ps3render.c @@ -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: */ diff --git a/src/video/ps3/SDL_ps3render_c.h b/src/video/ps3/SDL_ps3render_c.h new file mode 100644 index 000000000..707ab7716 --- /dev/null +++ b/src/video/ps3/SDL_ps3render_c.h @@ -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: */ diff --git a/src/video/ps3/SDL_ps3video.c b/src/video/ps3/SDL_ps3video.c new file mode 100644 index 000000000..236c2771a --- /dev/null +++ b/src/video/ps3/SDL_ps3video.c @@ -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 +#include +#include +#include +#include + +#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: */ diff --git a/src/video/ps3/SDL_ps3video.h b/src/video/ps3/SDL_ps3video.h new file mode 100644 index 000000000..aa0c7d486 --- /dev/null +++ b/src/video/ps3/SDL_ps3video.h @@ -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 + +#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: */ diff --git a/src/video/ps3/spulibs/Makefile b/src/video/ps3/spulibs/Makefile new file mode 100644 index 000000000..de93a9dad --- /dev/null +++ b/src/video/ps3/spulibs/Makefile @@ -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 diff --git a/src/video/ps3/spulibs/fb_writer.c b/src/video/ps3/spulibs/fb_writer.c new file mode 100644 index 000000000..0eb51cc68 --- /dev/null +++ b/src/video/ps3/spulibs/fb_writer.c @@ -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 + * Dirk Herrendoerfer + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +#include "spu_common.h" + +#include +#include +#include +#include + +// 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); +} + + diff --git a/src/video/ps3/spulibs/spu_common.h b/src/video/ps3/spulibs/spu_common.h new file mode 100644 index 000000000..42c328c83 --- /dev/null +++ b/src/video/ps3/spulibs/spu_common.h @@ -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 + * Dirk Herrendoerfer + * SPE code based on research by: + * Rene Becker + * Thimo Emmerich + */ + +/* Common definitions/makros for SPUs */ + +#ifndef _SPU_COMMON_H +#define _SPU_COMMON_H + +#include +#include +#include + +/* 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 */ + +