Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Roughly working framebuffer.
Browse files Browse the repository at this point in the history
  • Loading branch information
martinlowinski committed Jun 4, 2009
1 parent 6dc66ff commit f892237
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 29 deletions.
179 changes: 157 additions & 22 deletions src/video/ps3/SDL_ps3render.c
Expand Up @@ -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
Expand Down Expand Up @@ -64,23 +76,56 @@ static int SDL_PS3_RenderCopy(SDL_Renderer * renderer,
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) */,
}
};

typedef struct
{
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)
{
Expand Down Expand Up @@ -113,6 +158,8 @@ SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags)
}
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;
Expand All @@ -125,12 +172,12 @@ SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags)
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;
Expand Down Expand Up @@ -159,6 +206,42 @@ SDL_PS3_CreateRenderer(SDL_Window * window, Uint32 flags)
return renderer;
}

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)
{
Expand Down Expand Up @@ -238,8 +321,11 @@ SDL_PS3_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
(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 +
Expand All @@ -249,11 +335,61 @@ SDL_PS3_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
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);
}
}
Expand All @@ -265,6 +401,9 @@ SDL_PS3_RenderPresent(SDL_Renderer * renderer)
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")) {
Expand All @@ -274,25 +413,21 @@ SDL_PS3_RenderPresent(SDL_Renderer * renderer)
SDL_SaveBMP(data->screens[data->current_screen], file);
}

/* 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);
}

/* 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) {
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2 && data->double_buffering) {
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
Expand Down
12 changes: 6 additions & 6 deletions src/video/ps3/SDL_ps3video.c
Expand Up @@ -57,8 +57,8 @@ 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);
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 */
Expand Down Expand Up @@ -262,7 +262,7 @@ int SPE_Start(_THIS, spu_data_t * spe_data)
}

if (spe_data->keepalive)
SPE_WaitForMsg(_this, spe_data, SPU_READY);
SPE_WaitForMsg(spe_data, SPU_READY);
}


Expand Down Expand Up @@ -311,7 +311,7 @@ int SPE_Boot(_THIS, spu_data_t * spe_data)
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);
}

Expand All @@ -327,7 +327,7 @@ int SPE_Shutdown(_THIS, spu_data_t * spe_data)
}

/* 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 */
Expand All @@ -345,7 +345,7 @@ int SPE_SendMsg(_THIS, spu_data_t * spe_data, unsigned int msg)


/* 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];
Expand Down
2 changes: 1 addition & 1 deletion src/video/ps3/SDL_ps3video.h
Expand Up @@ -56,8 +56,8 @@
/* SPU thread data */
typedef struct spu_data {
spe_context_ptr_t ctx;
pthread_t thread;
spe_program_handle_t program;
pthread_t thread;
char * program_name;
unsigned int booted;
unsigned int keepalive;
Expand Down

0 comments on commit f892237

Please sign in to comment.