changeset 977:eb704fa22d05 akira

add frame buffer utitilties
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 01 Oct 2010 22:01:53 +0900
parents 537d7aa24575
children 5eb651827ae3
files old/framebuffer/cp_fb.c old/framebuffer/cp_fb.h old/framebuffer/fb_info.c old/framebuffer/fb_test.c
diffstat 4 files changed, 692 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/framebuffer/cp_fb.c	Fri Oct 01 22:01:53 2010 +0900
@@ -0,0 +1,205 @@
+// cp_fb.c 
+//
+// Copyright (c) 2006, Mike Acton <macton@cellperformance.com>
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
+// documentation files (the "Software"), to deal in the Software without restriction, including without
+// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+
+// NOTES:
+// From Geert Uytterhoeven 2007-01-26 04:50:44, 
+//      http://patchwork.ozlabs.org/linuxppc/patch?id=9143
+//
+//     "As the actual graphics hardware cannot be accessed directly by Linux,
+//     ps3fb uses a virtual frame buffer in main memory. The actual screen image is
+//     copied to graphics memory by the GPU on every vertical blank, by making a
+//     hypervisor call."
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+#include <sys/time.h>
+#include <asm/ps3fb.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include "cp_fb.h"
+
+static inline const char*
+select_error_str( int existing_error, const char* const existing_error_str, int new_error, const char* const new_error_str )
+{
+  // Only report the first error found - any error that follows is probably just a cascading effect.
+  const char* error_str = (char*)( (~(intptr_t)existing_error & (intptr_t)new_error & (intptr_t)new_error_str)
+                                 |  ((intptr_t)existing_error & (intptr_t)existing_error_str) );
+
+  return (error_str);
+}
+
+int
+cp_fb_open( cp_fb* const restrict fb )
+{
+    const char*    error_str      = NULL;
+    int            error          = 0;
+
+    // Open framebuffer device
+
+    const int   fb_fd             = open( "/dev/fb0", O_RDWR );
+    const int   open_fb_error     = (fb_fd >> ((sizeof(int)<<3)-1));
+    const char* open_fb_error_str = "Could not open /dev/fb0. Check permissions.";
+  
+    error_str = select_error_str( error, error_str, open_fb_error, open_fb_error_str );
+    error     = error | open_fb_error;
+
+    // Check for vsync
+
+    struct fb_vblank vblank;
+
+    const int   get_vblank_error     = ioctl(fb_fd, FBIOGET_VBLANK, (unsigned long)&vblank);
+    const char* get_vblank_error_str = "Could not get vblank info (FBIOGET_VBLANK)";
+
+    error_str = select_error_str( error, error_str, get_vblank_error, get_vblank_error_str );
+    error     = error | get_vblank_error;
+
+    const int   has_vsync            = vblank.flags & FB_VBLANK_HAVE_VSYNC;
+    const int   has_vsync_error      = (~(-has_vsync|has_vsync))>>((sizeof(int)<<3)-1);
+    const char* has_vsync_error_str  = "No vsync available (FB_VBLANK_HAVE_VSYNC)";
+
+    error_str = select_error_str( error, error_str, has_vsync_error, has_vsync_error_str );
+    error     = error | has_vsync_error;
+
+    // Get screen resolution and frame count
+
+    struct ps3fb_ioctl_res res;
+
+    const int   screeninfo_error     = ioctl(fb_fd, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res);
+    const char* screeninfo_error_str = "Could not get screen info (PS3_IOCTL_SCREENINFO)";
+
+    error_str = select_error_str( error, error_str, screeninfo_error, screeninfo_error_str );
+    error     = error | screeninfo_error;
+
+    const int   has_at_least_double_buffer           = (res.num_frames - 2) >> ((sizeof(res.num_frames)<<3)-1);
+    const int   has_at_least_double_buffer_error     = ~has_at_least_double_buffer;
+    const char* has_at_least_double_buffer_error_str = "Could not get screen info (PS3_IOCTL_SCREENINFO)";
+
+    error_str = select_error_str( error, error_str, has_at_least_double_buffer_error, has_at_least_double_buffer_error_str );
+    error     = error | has_at_least_double_buffer_error;
+
+    const uint32_t bpp                      = 4; // This is fixed for PS3 fb, and there's not a test for it.
+    const uint32_t frame_size               = res.xres * res.yres * bpp;
+    const uint32_t double_buffer_frame_size = frame_size * 2;
+
+    // const uint32_t frame_top_margin_size    = res.xres * res.yoff * bpp;
+    // const uint32_t frame_bottom_margin_size = frame_top_margin_size;
+    // const uint32_t frame_size               = frame_full_size; /* - ( frame_top_margin_size + frame_bottom_margin_size ); */
+    // const uint32_t double_buffer_frame_size = frame_size * 2;
+
+    const uintptr_t fb_addr           = (uintptr_t)mmap(NULL, double_buffer_frame_size, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0);
+    const int       fb_mmap_error     = fb_addr >> ((sizeof(uintptr_t)<<3)-1);
+    const char*     fb_mmap_error_str = "Could not get mmap frame buffer";
+
+    error_str = select_error_str( error, error_str, fb_mmap_error, fb_mmap_error_str );
+    error     = error | fb_mmap_error;
+
+    // Take control of frame buffer from kernel
+    ioctl(fb_fd, PS3FB_IOCTL_ON, 0);
+
+    // yoff is the number of lines that cannot be copied to the CRT before the vblank. For the most part this represents
+    // unusable frame buffer space. While it is possible to draw to the area if you draw in the opposite frame buffer's
+    // offset space, which will (due to poor draw timing by ps3fb) be the thing that is actually drawn, it's very 
+    // difficult to work with in practice. So:
+    //
+    //     (1)  The y offset area will be treated as "off limits".
+    //     (2)  An equivalent border will be created at the bottom, so the frame looks balanced even though it is
+    //          not entirely full screen. 
+
+    // xoff is the number of lines that cannot be copied to the CRT before the hblank.
+    // Similar to the y offset space, the x offset space is displayed on the wrong (previous) line. So:
+    //
+    //     (1)  The x offset area will be treated as "off limits".
+    //     (2)  An equivalent border will be created at the right, so the frame looks balanced even though it is
+    //          not entirely full screen. 
+
+    uintptr_t draw_start_addr = fb_addr;
+    uintptr_t draw_next_addr  = draw_start_addr + ( res.yres * res.xres * bpp );
+    uintptr_t drawable_h      = res.yres - ( 2 * res.yoff );
+    uintptr_t drawable_w      = res.xres - ( 2 * res.xoff );
+
+    // xoff is the number of lines that cannot be copied to the CRT before the hblank. This area is much easier to use. 
+    // Similar to the y offset space, the x offset space is displayed on the wrong (previous) line. So:
+    // In principle, it is possible to steal back the x offset space by shifting back the line address to the 
+    // start of the border of the previous line. Like so:
+    //
+    //     (1)  One additional line will be taken from the height so the a complete horizontal line can be started
+    //          early.
+    //     (2)  The frame buffer address returned in cp_fb will be offset by (xres-xoff) in order for the remaining
+    //          space to represent a rectangular area of drawable memory.
+    //
+    //     i.e. 
+    //     uintptr_t draw_start_addr = fb_addr + ( ( res.xres - res.xoff ) * bpp );
+    //     uintptr_t draw_next_addr  = draw_start_addr + ( res.yres * res.xres * bpp );
+    //     uintptr_t drawable_h      = res.yres - 1 - ( 2 * res.yoff );
+    //     uintptr_t drawable_w      = res.xres;
+    //
+    //     But I wouldn't recommend it, since on some CRTs the effect of this would be that the frame does not appear
+    //     square.
+
+    fb->stride        = res.xres;
+    fb->w             = drawable_w;
+    fb->h             = drawable_h;
+    fb->fd            = fb_fd;
+    fb->start_addr    = fb_addr;
+    fb->size          = double_buffer_frame_size;
+    fb->draw_addr[0]  = draw_start_addr;
+    fb->draw_addr[1]  = draw_next_addr;
+
+    // Clear out the whole buffer. Any unused space is black. It's also convinient to start with a cleared frame
+    // buffer for the user.
+
+    memset((void*)fb_addr, 0x00, double_buffer_frame_size );
+
+    return (error);
+}
+
+void
+cp_fb_close( const cp_fb* const restrict fb )
+{
+    // Give frame buffer control back to the kernel
+    ioctl(fb->fd, PS3FB_IOCTL_OFF, 0);
+
+    munmap( (void*)fb->start_addr, fb->size );
+
+    close(fb->fd);
+}
+
+void
+cp_fb_wait_vsync( cp_fb* const restrict fb )
+{
+    unsigned long crt = 0;
+
+    ioctl(fb->fd, FBIO_WAITFORVSYNC, &crt );
+}
+
+void
+cp_fb_flip( cp_fb* const restrict fb, unsigned long field_ndx )
+{
+    ioctl(fb->fd, PS3FB_IOCTL_FSEL,  &field_ndx );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/framebuffer/cp_fb.h	Fri Oct 01 22:01:53 2010 +0900
@@ -0,0 +1,51 @@
+// cp_fb.h 
+//
+// Copyright (c) 2006, Mike Acton <macton@cellperformance.com>
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
+// documentation files (the "Software"), to deal in the Software without restriction, including without
+// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef CP_FB_H
+#define CP_FB_H
+
+#if defined(__cplusplus)
+extern "C" 
+{
+#endif
+
+typedef struct cp_fb cp_fb;
+
+struct cp_fb
+{
+    uint32_t  w;
+    uint32_t  h;
+    uint32_t  stride;
+    uintptr_t start_addr;
+    uintptr_t draw_addr[2];
+    uint32_t  size;
+    int       fd;
+};
+
+int  cp_fb_open( cp_fb* const restrict fb );
+void cp_fb_close( const cp_fb* const restrict fb );
+void cp_fb_wait_vsync( cp_fb* const restrict fb );
+void cp_fb_flip( cp_fb* const restrict fb, unsigned long field_ndx );
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* CP_FB_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/framebuffer/fb_info.c	Fri Oct 01 22:01:53 2010 +0900
@@ -0,0 +1,238 @@
+// fbinfo.c 
+//
+// Copyright (c) 2006, Mike Acton <macton@cellperformance.com>
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
+// documentation files (the "Software"), to deal in the Software without restriction, including without
+// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <linux/fb.h>
+#include <asm/ps3fb.h>
+
+int
+main( void )
+{
+    const int   fb_file           = open( "/dev/fb0", O_RDWR );
+    const int   open_fb_error     = (fb_file >> ((sizeof(int)*8)-1));
+
+    if ( open_fb_error < 0 )
+    {
+        printf("Could not open /dev/fb0. Check permissions\n");
+        return (-1);
+    }
+
+    struct fb_vblank vblank;
+
+    int get_vblank_error = ioctl(fb_file, FBIOGET_VBLANK, (unsigned long)&vblank);
+
+    if ( get_vblank_error == -1 )
+    {
+        printf("Warning: FBIOGET_VBLANK Failed\n");
+    }
+    else
+    {
+        printf("FBIOGET_VBLANK:\n");
+        printf("  flags:\n");
+        printf("    FB_VBLANK_VBLANKING   : %s\n",(vblank.flags&FB_VBLANK_VBLANKING)  ?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HBLANKING   : %s\n",(vblank.flags&FB_VBLANK_HBLANKING)  ?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_VBLANK : %s\n",(vblank.flags&FB_VBLANK_HAVE_VBLANK)?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_HBLANK : %s\n",(vblank.flags&FB_VBLANK_HAVE_HBLANK)?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_COUNT  : %s\n",(vblank.flags&FB_VBLANK_HAVE_COUNT) ?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_VCOUNT : %s\n",(vblank.flags&FB_VBLANK_HAVE_VCOUNT)?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_HCOUNT : %s\n",(vblank.flags&FB_VBLANK_HAVE_HCOUNT)?"TRUE":"FALSE");
+        printf("    FB_VBLANK_VSYNCING    : %s\n",(vblank.flags&FB_VBLANK_VSYNCING)   ?"TRUE":"FALSE");
+        printf("    FB_VBLANK_HAVE_VSYNC  : %s\n",(vblank.flags&FB_VBLANK_HAVE_VSYNC) ?"TRUE":"FALSE");
+        printf("  count  : %d\n", vblank.count );    
+        printf("  vcount : %d\n", vblank.vcount );    
+        printf("  hcount : %d\n", vblank.hcount );    
+    }
+    printf("-------------------------------------\n");
+
+    struct fb_fix_screeninfo fscreeninfo;
+
+    int get_fscreeninfo_error = ioctl(fb_file, FBIOGET_FSCREENINFO, (unsigned long)&fscreeninfo);
+
+    if ( get_fscreeninfo_error == -1 )
+    {
+        printf("Warning: FBIOGET_FSCREENINFO Failed\n");
+    }
+    else
+    {
+       printf("FBIOGET_FSCREENINFO:\n");
+       printf("  id          : \"" "%c%c%c%c" "%c%c%c%c" "%c%c%c%c" "%c%c%c%c" "\"\n",
+              fscreeninfo.id[0],  fscreeninfo.id[1],  fscreeninfo.id[2],  fscreeninfo.id[3],
+              fscreeninfo.id[4],  fscreeninfo.id[5],  fscreeninfo.id[6],  fscreeninfo.id[7],
+              fscreeninfo.id[8],  fscreeninfo.id[9],  fscreeninfo.id[10], fscreeninfo.id[11],
+              fscreeninfo.id[12], fscreeninfo.id[13], fscreeninfo.id[14], fscreeninfo.id[15] );
+       if ( sizeof(unsigned long) == 4 )
+       {
+           printf("  smem_start  : 0x%08x\n", (unsigned int)fscreeninfo.smem_start);
+       }
+       else if ( sizeof(unsigned long) == 8 )
+       {
+           union UL64 { uint32_t u32[2]; uint64_t u64; } smem_start = {.u64=fscreeninfo.smem_start};
+           printf("  smem_start  : 0x%08x_%08x\n",smem_start.u32[1],smem_start.u32[0]);
+       }
+       else
+       {
+          printf("WTF! sizeof(unsigned long) = %d\n",sizeof(unsigned long));
+       }
+       printf("  smem_len    : %u\n", fscreeninfo.smem_len);
+       printf("  type        : ");
+       switch (fscreeninfo.type)
+       {
+           case FB_TYPE_PACKED_PIXELS:      printf("FB_TYPE_PACKED_PIXELS (0)\n");      break;
+           case FB_TYPE_PLANES:             printf("FB_TYPE_PLANES (1)\n");             break;
+           case FB_TYPE_INTERLEAVED_PLANES: printf("FB_TYPE_INTERLEAVED_PLANES (2)\n"); break;
+           case FB_TYPE_TEXT:               printf("FB_TYPE_TEXT (3)\n");               break;
+           case FB_TYPE_VGA_PLANES:         printf("FB_TYPE_VGA_PLANES (4)\n");         break;
+           default:                         printf("UNKNOWN (See /usr/include/linux/fb.h)\n");
+       }
+       printf("  type_aux    : ");
+       if ( fscreeninfo.type == FB_TYPE_TEXT )
+       {
+           switch (fscreeninfo.type_aux)
+           {
+               case FB_AUX_TEXT_MDA:        printf("FB_AUX_TEXT_MDA (0)\n");         break;
+               case FB_AUX_TEXT_CGA:        printf("FB_AUX_TEXT_CGA (1)\n");         break;
+               case FB_AUX_TEXT_S3_MMIO:    printf("FB_AUX_TEXT_S3_MMIO (2)\n");     break;
+               case FB_AUX_TEXT_MGA_STEP16: printf("FB_AUX_TEXT_MGA_STEP16 (3)\n");  break;
+               case FB_AUX_TEXT_MGA_STEP8:  printf("FB_AUX_TEXT_MGA_STEP8 (4)\n");   break;
+               default:                     printf("UNKNOWN (See /usr/include/linux/fb.h)\n");
+           }
+       }
+       else if ( fscreeninfo.type == FB_TYPE_INTERLEAVED_PLANES )
+       {
+           switch (fscreeninfo.type_aux)
+           {
+               case FB_AUX_VGA_PLANES_VGA4: printf("FB_AUX_VGA_PLANES_VGA4 (0)\n"); break;
+               case FB_AUX_VGA_PLANES_CFB4: printf("FB_AUX_VGA_PLANES_CFB4 (1)\n"); break;
+               case FB_AUX_VGA_PLANES_CFB8: printf("FB_AUX_VGA_PLANES_CFB8 (2)\n"); break;
+               default:                     printf("UNKNOWN (See /usr/include/linux/fb.h)\n");
+           }
+       }
+       else
+       {
+           printf("N/A\n");
+       }
+ 
+       printf("  visual      : ");
+       switch (fscreeninfo.visual)
+       {
+           case FB_VISUAL_MONO01:             printf("FB_VISUAL_MONO01 (0)\n");             break;
+           case FB_VISUAL_MONO10:             printf("FB_VISUAL_MONO10 (1)\n");             break;
+           case FB_VISUAL_TRUECOLOR:          printf("FB_VISUAL_TRUECOLOR (2)\n");          break;
+           case FB_VISUAL_PSEUDOCOLOR:        printf("FB_VISUAL_PSEUDOCOLOR (3)\n");        break;
+           case FB_VISUAL_DIRECTCOLOR:        printf("FB_VISUAL_DIRECTCOLOR (4)\n");        break;
+           case FB_VISUAL_STATIC_PSEUDOCOLOR: printf("FB_VISUAL_STATIC_PSEUDOCOLOR (5)\n"); break;
+           default:                           printf("UNKNOWN (See /usr/include/linux/fb.h)\n");
+       }
+
+       printf("  xpanstep    : %u\n", fscreeninfo.xpanstep);
+       printf("  ypanstep    : %u\n", fscreeninfo.ypanstep);
+       printf("  ywrapstep   : %u\n", fscreeninfo.ywrapstep);
+       printf("  line_length : %u\n", fscreeninfo.line_length);
+       if ( sizeof(unsigned long) == 4 )
+       {
+           printf("  mmio_start  : 0x%08x\n", (unsigned int)fscreeninfo.mmio_start);
+       }
+       else if ( sizeof(unsigned long) == 8 )
+       {
+           union UL64 { uint32_t u32[2]; uint64_t u64; } mmio_start = {.u64=fscreeninfo.mmio_start};
+           printf("  mmio_start  : 0x%08x_%08x\n",mmio_start.u32[1],mmio_start.u32[0]);
+       }
+       else
+       {
+          printf("WTF! sizeof(unsigned long) = %d\n",sizeof(unsigned long));
+       }
+       printf("  mmio_len    : %u\n", fscreeninfo.mmio_len);
+       printf("  accel       : ");
+       switch (fscreeninfo.accel)
+       {
+           case FB_ACCEL_NONE:                printf("FB_ACCEL_NONE (0)\n");                     break;
+           case FB_ACCEL_ATARIBLITT:          printf("FB_ACCEL_ATARIBLITT (1)\n");               break;
+           case FB_ACCEL_AMIGABLITT:          printf("FB_ACCEL_AMIGABLITT (2)\n");               break;
+           case FB_ACCEL_S3_TRIO64:           printf("FB_ACCEL_S3_TRIO64 (3)\n");                break;
+           case FB_ACCEL_NCR_77C32BLT:        printf("FB_ACCEL_NCR_77C32BLT (4)\n");             break;
+           case FB_ACCEL_S3_VIRGE:            printf("FB_ACCEL_S3_VIRGE (5)\n");                 break;
+           case FB_ACCEL_ATI_MACH64GX:        printf("FB_ACCEL_ATI_MACH64GX (6)\n");             break;
+           case FB_ACCEL_DEC_TGA:             printf("FB_ACCEL_DEC_TGA (7)\n");                  break;
+           case FB_ACCEL_ATI_MACH64CT:        printf("FB_ACCEL_ATI_MACH64CT (8)\n");             break;
+           case FB_ACCEL_ATI_MACH64VT:        printf("FB_ACCEL_ATI_MACH64VT (9)\n");             break;
+           case FB_ACCEL_ATI_MACH64GT:        printf("FB_ACCEL_ATI_MACH64GT (10)\n");            break;
+           case FB_ACCEL_SUN_CREATOR:         printf("FB_ACCEL_SUN_CREATOR (11)\n");             break;
+           case FB_ACCEL_SUN_CGSIX:           printf("FB_ACCEL_SUN_CGSIX (12)\n");               break;
+           case FB_ACCEL_SUN_LEO:             printf("FB_ACCEL_SUN_LEO (13)\n");                 break;
+           case FB_ACCEL_IMS_TWINTURBO:       printf("FB_ACCEL_IMS_TWINTURBO (14)\n");           break;
+           case FB_ACCEL_3DLABS_PERMEDIA2:    printf("FB_ACCEL_3DLABS_PERMEDIA2 (15)\n");        break;
+           case FB_ACCEL_MATROX_MGA2064W:     printf("FB_ACCEL_MATROX_MGA2064W (16)\n");         break;
+           case FB_ACCEL_MATROX_MGA1064SG:    printf("FB_ACCEL_MATROX_MGA1064SG (17)\n");        break;
+           case FB_ACCEL_MATROX_MGA2164W:     printf("FB_ACCEL_MATROX_MGA2164W (18)\n");         break;
+           case FB_ACCEL_MATROX_MGA2164W_AGP: printf("FB_ACCEL_MATROX_MGA2164W_AGP (19)\n");     break;
+           case FB_ACCEL_MATROX_MGAG100:      printf("FB_ACCEL_MATROX_MGAG100 (20)\n");          break;
+           case FB_ACCEL_MATROX_MGAG200:      printf("FB_ACCEL_MATROX_MGAG200 (21)\n");          break;
+           case FB_ACCEL_SUN_CG14:            printf("FB_ACCEL_SUN_CG14 (22)\n");                break;
+           case FB_ACCEL_SUN_BWTWO:           printf("FB_ACCEL_SUN_BWTWO (23)\n");               break;
+           case FB_ACCEL_SUN_CGTHREE:         printf("FB_ACCEL_SUN_CGTHREE (24)\n");             break;
+           case FB_ACCEL_SUN_TCX:             printf("FB_ACCEL_SUN_TCX (25)\n");                 break;
+           case FB_ACCEL_MATROX_MGAG400:      printf("FB_ACCEL_MATROX_MGAG400 (26)\n");          break;
+           case FB_ACCEL_NV3:                 printf("FB_ACCEL_NV3 (27)\n");                     break;
+           case FB_ACCEL_NV4:                 printf("FB_ACCEL_NV4 (28)\n");                     break;
+           case FB_ACCEL_NV5:                 printf("FB_ACCEL_NV5 (29)\n");                     break;
+           case FB_ACCEL_CT_6555x:            printf("FB_ACCEL_CT_6555x (30)\n");                break;
+           case FB_ACCEL_3DFX_BANSHEE:        printf("FB_ACCEL_3DFX_BANSHEE (31)\n");            break;
+           case FB_ACCEL_ATI_RAGE128:         printf("FB_ACCEL_ATI_RAGE128 (32)\n");             break;
+           case FB_ACCEL_IGS_CYBER2000:       printf("FB_ACCEL_IGS_CYBER2000 (33)\n");           break;
+           case FB_ACCEL_IGS_CYBER2010:       printf("FB_ACCEL_IGS_CYBER2010 (34)\n");           break;
+           case FB_ACCEL_IGS_CYBER5000:       printf("FB_ACCEL_IGS_CYBER5000 (35)\n");           break;
+           case FB_ACCEL_SIS_GLAMOUR:         printf("FB_ACCEL_SIS_GLAMOUR (36)\n");             break;
+           default:                           printf("UNKNOWN (See /usr/include/linux/fb.h)\n");
+       }
+    }
+    printf("-------------------------------------\n");
+
+    struct ps3fb_ioctl_res res;
+
+    int ps3_screeninfo_error = ioctl(fb_file, PS3FB_IOCTL_SCREENINFO, (unsigned long)&res);
+    
+    if ( ps3_screeninfo_error == -1 )
+    {
+        printf("Warning: PS3FB_IOCTL_SCREENINFO Failed\n");
+    }
+    else
+    {
+        printf("PS3FB_IOCTL_SCREENINFO:\n");
+        printf("    xres        : %u\n",res.xres);
+        printf("    yres        : %u\n",res.yres);
+        printf("    xoff        : %u\n",res.xoff);
+        printf("    yoff        : %u\n",res.yoff);
+        printf("    num_frames  : %u\n",res.num_frames);
+    }
+    printf("-------------------------------------\n");
+
+    int close_fb_error = close( fb_file );
+
+    if ( close_fb_error == -1 )
+    {
+        printf("Warning: Could not close file handle used for /dev/fb0\n");
+    }
+
+    return (0);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/old/framebuffer/fb_test.c	Fri Oct 01 22:01:53 2010 +0900
@@ -0,0 +1,198 @@
+// fb_test.c 
+// Simple test application. Draw something to the frame buffer. 
+//
+// Copyright (c) 2006, Mike Acton <macton@cellperformance.com>
+// 
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
+// documentation files (the "Software"), to deal in the Software without restriction, including without
+// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or substantial
+// portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
+// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
+// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "cp_vt.h"
+#include "cp_fb.h"
+
+void write_hline_gouraud_ABGR8888( int32_t x0, int32_t x1, uint32_t left_rgba, uint32_t right_rgba, void* dest_buffer, uint16_t stride );
+
+int 
+main( void )
+{
+    cp_vt vt;
+    cp_fb fb;
+
+    cp_vt_open_graphics(&vt);
+    cp_fb_open(&fb);
+
+    uint32_t frame_ndx        = 0;
+    float    sprite_t         = 0.0f;
+    float    sprite_prev_t[2] = { 0.0f, 0.0f }; 
+
+    // A little example display.
+ 
+    for (uint32_t y_last = 1; y_last < fb.h; y_last++)
+    {
+        uint32_t* const restrict frame_top = (uint32_t*)fb.draw_addr[ frame_ndx ];
+
+        // Clear the background
+
+        memset( frame_top, 0x00, fb.h * fb.stride * 4 );
+
+        // Draw a rectangle that grows from top to bottom
+
+        for (uint32_t y = 0; y < y_last; y++ )
+        {
+            uint32_t* const restrict next_line = frame_top + ( fb.stride * y );
+
+            write_hline_gouraud_ABGR8888( 0,       64-1,      0x00ff0000, 0x00f0f000, next_line, fb.w );
+            write_hline_gouraud_ABGR8888( 64,      fb.w-64-1, 0x0000ff00, 0x000000ff, next_line, fb.w );
+            write_hline_gouraud_ABGR8888( fb.w-64, fb.w-1,    0x00ff00ff, 0x0000f0f0, next_line, fb.w );
+        }
+
+        // Draw a little sprite on a sine wave. 
+
+        sprite_t                    += 0.08f; // Update position
+        sprite_prev_t [ frame_ndx ]  = sprite_t; 
+
+        {
+            float    sprite_amp    = sinf( sprite_t );
+            uint32_t sprite_left   = (uint32_t)(sprite_t * 0.03f * (float)fb.w);
+            uint32_t sprite_top    = (fb.h>>1) + (uint32_t)(sprite_amp * (float)((fb.h-128)>>1));
+            uint32_t sprite_right  = sprite_left + 64;
+            uint32_t sprite_bottom = sprite_top  + 64;
+            uint32_t sprite_middle = sprite_left + (( sprite_right - sprite_left ) >> 1);
+            uint32_t sprite_cr      = ( (uint32_t)(sprite_amp * 127.0f) + 128 ) & 0x000000ff;
+            uint32_t sprite_cg      = ( (uint32_t)(sprite_amp * 127.0f) + 128 ) & 0x000000ff;
+            uint32_t sprite_cb      = ( (uint32_t)(sprite_amp * 127.0f) + 128 ) & 0x000000ff;
+            uint32_t sprite_crgb    = sprite_cr | ( sprite_cg << 8 ) | ( sprite_cb << 16 );
+
+            for (uint32_t y = sprite_top;y < sprite_bottom;y++)
+            {
+                uint32_t* const restrict next_line = frame_top + ( fb.stride * y );
+
+                write_hline_gouraud_ABGR8888( sprite_left,   sprite_middle-1, 0x007f1e00,  sprite_crgb, next_line, fb.w );
+                write_hline_gouraud_ABGR8888( sprite_middle, sprite_right-1,  sprite_crgb, 0x001e7f00,  next_line, fb.w );
+            }
+
+        }
+
+        // At the vsync, the previous frame is finished sending to the CRT
+        cp_fb_wait_vsync( &fb );
+
+        // Send the frame just drawn to the CRT by the next vblank
+        cp_fb_flip( &fb, frame_ndx );
+
+        frame_ndx  = frame_ndx ^ 0x01;
+    }
+
+    cp_vt_close(&vt);
+    cp_fb_close(&fb);
+
+    return (0);
+}
+
+void 
+write_hline_gouraud_ABGR8888( int32_t x0, int32_t x1, uint32_t left_rgba, uint32_t right_rgba, void* dest_buffer, uint16_t width )
+{
+  uint32_t left_r;
+  uint32_t left_g;
+  uint32_t left_b;
+  uint32_t left_a;
+
+  uint32_t step_r;
+  uint32_t step_g;
+  uint32_t step_b;
+  uint32_t step_a;
+
+  if ( (x1-x0+1) == 0 )
+  {
+    return;
+  }
+
+  /* Setup rgbas */
+  {
+    uint32_t right_r;
+    uint32_t right_g;
+    uint32_t right_b;
+    uint32_t right_a;
+    uint32_t step_scale;
+
+    left_r     = ( ( left_rgba       ) & 0x000000ff );
+    left_g     = ( ( left_rgba >> 8  ) & 0x000000ff );
+    left_b     = ( ( left_rgba >> 16 ) & 0x000000ff );
+    left_a     = ( ( left_rgba >> 24 ) & 0x000000ff );
+
+    right_r    = ( ( right_rgba       ) & 0x000000ff );
+    right_g    = ( ( right_rgba >> 8  ) & 0x000000ff );
+    right_b    = ( ( right_rgba >> 16 ) & 0x000000ff );
+    right_a    = ( ( right_rgba >> 24 ) & 0x000000ff );
+
+    step_scale = (1<<16) / (x1-x0+1);
+    step_r     = ( ( right_r - left_r ) * step_scale );
+    step_g     = ( ( right_g - left_g ) * step_scale );
+    step_b     = ( ( right_b - left_b ) * step_scale );
+    step_a     = ( ( right_a - left_a ) * step_scale );
+
+    left_r   <<= 16;
+    left_g   <<= 16;
+    left_b   <<= 16;
+    left_a   <<= 16;
+
+    left_r    += (1<<16)>>1;
+    left_g    += (1<<16)>>1;
+    left_b    += (1<<16)>>1;
+    left_a    += (1<<16)>>1;
+  }
+
+  /* Write to buffer */
+  {
+    uint32_t* restrict dest_pixel;
+    int32_t            x;
+
+    if ( x0 < 0 )
+    {
+      left_r += step_r * (-x0);
+      left_g += step_g * (-x0);
+      left_b += step_b * (-x0);
+      left_a += step_a * (-x0);
+      x0 = 0;
+    }
+
+    if ( x1 >= (int32_t)width )
+    {
+      x1 = width-1;
+    }
+
+    dest_pixel = (uint32_t*)dest_buffer + x0;
+
+    for (x=x0;x<=x1;x++)
+    {
+      uint32_t rgba;
+
+      rgba  = ( ( left_b >> 16 ) & 0x000000ff );
+      rgba |= ( ( left_g >> 16 ) & 0x000000ff ) << 8;
+      rgba |= ( ( left_r >> 16 ) & 0x000000ff ) << 16;
+      rgba |= ( ( left_a >> 16 ) & 0x000000ff ) << 24;
+
+      *dest_pixel = rgba;
+      dest_pixel++;
+
+      left_r += step_r;
+      left_g += step_g;
+      left_b += step_b;
+      left_a += step_a;
+    }
+  }
+}