Mercurial > sdl-ios-xcode
changeset 3142:c146645a770e gsoc2009_ps3
Roughly working framebuffer.
author | Martin Lowinski <martin@goldtopf.org> |
---|---|
date | Thu, 04 Jun 2009 07:02:15 +0000 |
parents | 3df74541339b |
children | 8fdabaa064c3 |
files | src/video/ps3/SDL_ps3render.c src/video/ps3/SDL_ps3video.c src/video/ps3/SDL_ps3video.h |
diffstat | 3 files changed, 165 insertions(+), 30 deletions(-) [+] |
line wrap: on
line diff
--- a/src/video/ps3/SDL_ps3render.c Fri May 29 09:50:21 2009 +0000 +++ b/src/video/ps3/SDL_ps3render.c Thu Jun 04 07:02:15 2009 +0000 @@ -26,6 +26,18 @@ #include "../SDL_yuv_sw_c.h" #include "../SDL_renderer_sw.h" +#include "SDL_ps3video.h" +#include "spulibs/spu_common.h" + +#include <fcntl.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <linux/kd.h> +#include <linux/fb.h> +#include <sys/mman.h> + +#include <asm/ps3fb.h> + /* Debugging * 0: No debug messages * 1: Video debug messages @@ -64,14 +76,20 @@ static void SDL_PS3_RenderPresent(SDL_Renderer * renderer); static void SDL_PS3_DestroyRenderer(SDL_Renderer * renderer); +/* Texture */ +static int PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static void PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); + SDL_RenderDriver SDL_PS3_RenderDriver = { SDL_PS3_CreateRenderer, { "ps3", - (/*SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |*/ - SDL_RENDERER_PRESENTFLIP2 /*| SDL_RENDERER_PRESENTFLIP3 | - SDL_RENDERER_PRESENTDISCARD*/), + (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTVSYNC | + SDL_RENDERER_PRESENTFLIP2) + /* (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY | + SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 | + SDL_RENDERER_PRESENTDISCARD) */, } }; @@ -79,8 +97,35 @@ { int current_screen; SDL_Surface *screens[3]; + SDL_VideoDisplay *display; + uint8_t *center[2]; + + /* width of input (bounded by writeable width) */ + unsigned int bounded_width; + /* height of input (bounded by writeable height) */ + unsigned int bounded_height; + /* offset from the left side (used for centering) */ + unsigned int offset_left; + /* offset from the upper side (used for centering) */ + unsigned int offset_top; + /* width of screen which is writeable */ + unsigned int wr_width; + /* width of screen which is writeable */ + unsigned int wr_height; + /* size of a screen line: width * bpp/8 */ + unsigned int line_length; + + /* Use two buffers in fb? res < 720p */ + unsigned int double_buffering; } SDL_PS3_RenderData; +typedef struct +{ + void *pixels; + int pitch; + int bpp; +} PS3_TextureData; + SDL_Renderer * SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags) { @@ -113,6 +158,8 @@ } SDL_zerop(data); + renderer->CreateTexture = PS3_CreateTexture; + renderer->DestroyTexture = PS3_DestroyTexture; renderer->RenderPoint = SDL_PS3_RenderPoint; renderer->RenderLine = SDL_PS3_RenderLine; renderer->RenderFill = SDL_PS3_RenderFill; @@ -125,12 +172,12 @@ renderer->driverdata = data; Setup_SoftwareRenderer(renderer); + data->double_buffering = 0; + 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; + data->double_buffering = 1; } else { renderer->info.flags |= SDL_RENDERER_PRESENTCOPY; n = 1; @@ -160,6 +207,42 @@ } static int +PS3_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { + deprintf(1, "PS3_CreateTexture()\n"); + PS3_TextureData *data; + data = (PS3_TextureData *) SDL_calloc(1, sizeof(*data)); + if (!data) { + SDL_OutOfMemory(); + return -1; + } + + data->pitch = (texture->w * SDL_BYTESPERPIXEL(texture->format)); + + data->pixels = NULL; + data->pixels = (void *)memalign(16, texture->h * data->pitch); + if (!data->pixels) { + PS3_DestroyTexture(renderer, texture); + SDL_OutOfMemory(); + return -1; + } + + texture->driverdata = data; + return 0; +} + +static void +PS3_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + PS3_TextureData *data = (PS3_TextureData *) texture->driverdata; + + if (!data) { + return; + } + + free(data->pixels); +} + +static int SDL_PS3_RenderPoint(SDL_Renderer * renderer, int x, int y) { SDL_PS3_RenderData *data = @@ -238,8 +321,11 @@ (SDL_PS3_RenderData *) renderer->driverdata; SDL_Window *window = SDL_GetWindowFromID(renderer->window); SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + PS3_TextureData *txdata = (PS3_TextureData *) texture->driverdata; + SDL_VideoData *devdata = display->device->driverdata; if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) { + deprintf(1, "SDL_ISPIXELFORMAT_FOURCC = true\n"); SDL_Surface *target = data->screens[data->current_screen]; void *pixels = (Uint8 *) target->pixels + dstrect->y * target->pitch + @@ -249,11 +335,61 @@ dstrect->w, dstrect->h, pixels, target->pitch); } else { + deprintf(1, "SDL_ISPIXELFORMAT_FOURCC = false\n"); 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; + /* For testing */ + int width = 1280; + int height = 720; + void *pixels = (void *)memalign(16, height * data->screens[0]->pitch); + SDL_memset(pixels, 0x42, height * data->screens[0]->pitch); + + /* Get screeninfo */ + struct fb_fix_screeninfo fb_finfo; + if (ioctl(devdata->fbdev, FBIOGET_FSCREENINFO, &fb_finfo)) { + SDL_SetError("[PS3] Can't get fixed screeninfo"); + return -1; + } + struct fb_var_screeninfo fb_vinfo; + if (ioctl(devdata->fbdev, FBIOGET_VSCREENINFO, &fb_vinfo)) { + SDL_SetError("[PS3] Can't get VSCREENINFO"); + return -1; + } + /* 16 and 15 bpp is reported as 16 bpp */ + txdata->bpp = fb_vinfo.bits_per_pixel; + if (txdata->bpp == 16) + txdata->bpp = fb_vinfo.red.length + fb_vinfo.green.length + fb_vinfo.blue.length; + + /* Adjust centering */ + data->bounded_width = width < fb_vinfo.xres ? width : fb_vinfo.xres; + data->bounded_height = height < fb_vinfo.yres ? height : fb_vinfo.yres; + data->offset_left = (fb_vinfo.xres - data->bounded_width) >> 1; + data->offset_top = (fb_vinfo.yres - data->bounded_height) >> 1; + data->center[0] = devdata->frame_buffer + data->offset_left * txdata->bpp/8 + + data->offset_top * fb_finfo.line_length; + data->center[1] = data->center[0] + fb_vinfo.yres * fb_finfo.line_length; + + /* Set SPU parms for copying the surface to framebuffer */ + devdata->fb_parms->data = (unsigned char *)pixels; + devdata->fb_parms->center = data->center[data->current_screen]; + devdata->fb_parms->out_line_stride = fb_finfo.line_length; + devdata->fb_parms->in_line_stride = surface->w * txdata->bpp / 8; + devdata->fb_parms->bounded_input_height = data->bounded_height; + devdata->fb_parms->bounded_input_width = data->bounded_width; + devdata->fb_parms->fb_pixel_size = txdata->bpp / 8; + + deprintf(3, "[PS3->SPU] fb_thread_data->argp = 0x%x\n", devdata->fb_thread_data->argp); + + /* Copying.. */ + SPE_SendMsg(devdata->fb_thread_data, SPU_START); + SPE_SendMsg(devdata->fb_thread_data, (unsigned int)devdata->fb_thread_data->argp); + + SPE_WaitForMsg(devdata->fb_thread_data, SPU_FIN); + free(pixels); + return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect); } } @@ -265,6 +401,9 @@ static int frame_number; SDL_PS3_RenderData *data = (SDL_PS3_RenderData *) renderer->driverdata; + SDL_Window *window = SDL_GetWindowFromID(renderer->window); + SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); + SDL_VideoData *devdata = display->device->driverdata; /* Send the data to the display */ if (SDL_getenv("SDL_VIDEO_PS3_SAVE_FRAMES")) { @@ -274,25 +413,21 @@ 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; + /* Wait for vsync */ + if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { + unsigned long crt = 0; + deprintf(1, "[PS3] Wait for vsync\n"); + ioctl(devdata->fbdev, FBIO_WAITFORVSYNC, &crt); } - /* 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); - */ + /* Page flip */ + deprintf(1, "[PS3] Page flip to buffer #%u 0x%x\n", data->current_screen, data->center[data->current_screen]); + ioctl(devdata->fbdev, PS3FB_IOCTL_FSEL, (unsigned long)&data->current_screen); + + /* Update the flipping chain, if any */ + if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2 && data->double_buffering) { + data->current_screen = (data->current_screen + 1) % 2; + } } static void
--- a/src/video/ps3/SDL_ps3video.c Fri May 29 09:50:21 2009 +0000 +++ b/src/video/ps3/SDL_ps3video.c Thu Jun 04 07:02:15 2009 +0000 @@ -57,8 +57,8 @@ 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); +int SPE_SendMsg(spu_data_t * spe_data, unsigned int msg); +int SPE_WaitForMsg(spu_data_t * spe_data, unsigned int msg); void SPE_RunContext(void *thread_argp); /* Stores the SPE executable name of fb_writer_spu */ @@ -262,7 +262,7 @@ } if (spe_data->keepalive) - SPE_WaitForMsg(_this, spe_data, SPU_READY); + SPE_WaitForMsg(spe_data, SPU_READY); } @@ -311,7 +311,7 @@ int SPE_Shutdown(_THIS, spu_data_t * spe_data) { if (spe_data->keepalive && spe_data->booted) { - SPE_SendMsg(_this, spe_data, SPU_EXIT); + SPE_SendMsg(spe_data, SPU_EXIT); SPE_Stop(_this, spe_data); } @@ -327,7 +327,7 @@ } /* Send message to the SPE via mailboxe */ -int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg) +int SPE_SendMsg(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 */ @@ -345,7 +345,7 @@ /* 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) +int SPE_WaitForMsg(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];
--- a/src/video/ps3/SDL_ps3video.h Fri May 29 09:50:21 2009 +0000 +++ b/src/video/ps3/SDL_ps3video.h Thu Jun 04 07:02:15 2009 +0000 @@ -56,8 +56,8 @@ /* SPU thread data */ typedef struct spu_data { spe_context_ptr_t ctx; + spe_program_handle_t program; pthread_t thread; - spe_program_handle_t program; char * program_name; unsigned int booted; unsigned int keepalive;