# HG changeset patch # User Shinji KONO # Date 1285938113 -32400 # Node ID eb704fa22d05cc61810e2ebeb244db0295e4406d # Parent 537d7aa245754edc5315118fe00291e0a355580d add frame buffer utitilties diff -r 537d7aa24575 -r eb704fa22d05 old/framebuffer/cp_fb.c --- /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 +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 ); +} diff -r 537d7aa24575 -r eb704fa22d05 old/framebuffer/cp_fb.h --- /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 +// +// 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 */ + diff -r 537d7aa24575 -r eb704fa22d05 old/framebuffer/fb_info.c --- /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 +// +// 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 +#include +#include +#include +#include +#include +#include + +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); +} + diff -r 537d7aa24575 -r eb704fa22d05 old/framebuffer/fb_test.c --- /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 +// +// 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 +#include +#include +#include +#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; + } + } +}