Roughly working framebuffer.
--- 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;