Code: Select all
// performance test with VSync IRQ, inspired by the VSync example on the cell add-on CD
//
// compile:
// gcc -I /usr/src/linux-2.6.16-cell-r1/include -lm vsync.c -o vsync
//
// tested on Gentoo, installed with this guide: http://wiki.ps2dev.org/ps3:linux:installing_gentoo
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdint.h>
#include <math.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/kd.h>
#include <sys/time.h>
#include <linux/fb.h>
#include <asm/ps3fb.h>
int width, height, memoryWidth, memoryHeight;
uint32_t* background;
void draw(uint32_t* fb)
{
int x, y, yp;
static int t = 0;
int barHeight = 20;
float amplitude = ((float) (height - barHeight)) / 2.0;
float frequency = 40.0;
// blit background
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
fb[y * memoryWidth + x] = background[y * width + x];
}
}
// draw a bar
yp = sin(((float)t) / frequency) * amplitude + amplitude;
for (y = yp; y < yp + barHeight; y++) {
if (y < height && y >= 0) {
for (x = 0; x < width; x++) {
fb[y * memoryWidth + x] = 0xffffff;
}
}
}
t++;
if (t == height) t = 0;
}
void enableCursor(int enable)
{
int fd = open("/dev/console", O_NONBLOCK);
if (fd >= 0) {
ioctl(fd, KDSETMODE, enable ? KD_TEXT : KD_GRAPHICS);
close(fd);
}
}
int main(int argc, char *argv[])
{
int fd;
void *addr;
int length;
struct ps3fb_ioctl_res res;
int x, y;
uint32_t frame = 0;
struct timeval tv;
uint32_t time;
int count;
// switch to graphics mode (disable cursor)
enableCursor(0);
// access framebuffer
fd = open("/dev/fb0", O_RDWR);
ioctl(fd, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res);
printf("xres: %d, yres: %d, xoff: %d, yoff: %d, num_frames: %d\n",
res.xres, res.yres, res.xoff, res.yoff, res.num_frames);
length = res.xres * res.yres * 4 * res.num_frames;
addr = mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0);
// stop flipping in kernel thread with vsync
ioctl(fd, PS3FB_IOCTL_ON, 0);
// create test background image
memoryWidth = res.xres;
memoryHeight = res.yres;
width = res.xres - 2 * res.xoff;
height = res.yres - 2 * res.yoff;
background = malloc(width * height * 4);
for (x = 0; x < width; x++) {
for (y = 0; y < height; y++) {
int c = (11 * x) & 255;
background[y * width + x] = x*y << 3;
}
}
// start timing
gettimeofday(&tv, NULL);
time = tv.tv_sec * 1000000 + tv.tv_usec;
// draw test
count = 300;
for (x = 0; x < count; x++) {
// wait for vsync interrupt */
uint32_t crt = 0;
ioctl(fd, FBIO_WAITFORVSYNC, (unsigned long)&crt);
// draw frame
draw(addr + frame * memoryWidth * 4 * memoryHeight);
// blit and flip with vsync request */
ioctl(fd, PS3FB_IOCTL_FSEL, (unsigned long)&frame);
// switch frame
frame = 1 - frame;
}
// end timing
gettimeofday(&tv, NULL);
time = tv.tv_sec * 1000000 + tv.tv_usec - time;
printf("fps: %d\n", count * 1000000 / time);
free(background);
// start flipping in kernel thread with vsync
ioctl(fd, PS3FB_IOCTL_OFF, 0);
munmap(NULL, length);
// close device
close(fd);
// back to text mode
enableCursor(1);
return 0;
}