Mercurial > hg > Members > kono > Cerium
changeset 981:a193a851b5e3
add double buffering frame device
author | root@henri.cr.ie.u-ryukyu.ac.jp |
---|---|
date | Thu, 30 Sep 2010 23:54:08 +0900 |
parents | 4ce73df9ac61 |
children | b29547a5b85b |
files | Renderer/Engine/Makefile.cell Renderer/Engine/ViewerDevice.h Renderer/Engine/fb.h Renderer/Engine/main.cc Renderer/Engine/ps3fb/cp_fb.cc Renderer/Engine/ps3fb/cp_fb.h Renderer/Engine/ps3fb/cp_vt.cc Renderer/Engine/ps3fb/cp_vt.h Renderer/Engine/viewer.cc Renderer/Engine/viewerFB.cc Renderer/Engine/viewerPS3.cc Renderer/Engine/viewerPS3.h Renderer/Engine/viewer_types.h old/framebuffer/Makefile |
diffstat | 14 files changed, 736 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/Renderer/Engine/Makefile.cell Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/Makefile.cell Thu Sep 30 23:54:08 2010 +0900 @@ -1,6 +1,6 @@ include ./Makefile.def -SRCS_TMP = $(wildcard *.cc) $(wildcard Application/*.cc) +SRCS_TMP = $(wildcard *.cc) $(wildcard Application/*.cc) $(wildcard ps3fb/*.cc) SRCS_EXCLUDE = # ½ü³° SRCS = $(filter-out $(SRCS_EXCLUDE),$(SRCS_TMP)) OBJS = $(SRCS:.cc=.o) @@ -13,7 +13,7 @@ LIBS += -lCellManager -lspe2 -lpthread -CFLAGS += `sdl-config --cflags` `xml2-config --cflags` +CFLAGS += -Drestrict=__restrict__ `sdl-config --cflags` `xml2-config --cflags` LIBS += `sdl-config --libs` -lSDL_image -lGL `xml2-config --libs` .SUFFIXES: .cc .o
--- a/Renderer/Engine/ViewerDevice.h Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/ViewerDevice.h Thu Sep 30 23:54:08 2010 +0900 @@ -17,6 +17,7 @@ /* override function */ virtual Uint32 *video_init(TaskManager *manager, int bpp, int width, int height) = 0; + virtual Uint32 * flip_screen(Uint32 *v) { return v; } virtual void clean_pixels() = 0; virtual void clear_screen() = 0; virtual void free_device() = 0;
--- a/Renderer/Engine/fb.h Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/fb.h Thu Sep 30 23:54:08 2010 +0900 @@ -12,6 +12,7 @@ #include <sys/ioctl.h> #include <stdlib.h> #include <iostream> +#include "types.h" using namespace std; @@ -23,7 +24,7 @@ typedef struct screen_info { int xres,yres,vbpp,line_len; - char *fbptr; + uint32_t *fbptr[2]; } ScreenInfo , *ScreenInfoPtr;
--- a/Renderer/Engine/main.cc Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/main.cc Thu Sep 30 23:54:08 2010 +0900 @@ -3,6 +3,7 @@ #include "viewerSDL.h" #include "viewerFB.h" #include "viewerGL.h" +#include "viewerPS3.h" #include "Application.h" /* prototype */ @@ -59,6 +60,8 @@ vtype = VTYPE_FB; } else if (strcmp(argv[i+1], "gl") == 0) { vtype = VTYPE_GL; + } else if (strcmp(argv[i+1], "ps3") == 0) { + vtype = VTYPE_PS3; } i++; } @@ -76,6 +79,9 @@ screen = new Viewer(manager, dev, bpp, width, height, spenum); } else if (vtype == VTYPE_GL) { screen = new ViewerGL(manager, bpp, width, height, spenum); + } else if (vtype == VTYPE_PS3) { + ViewerDevice *dev = new ViewerPS3(); + screen = new Viewer(manager, dev, bpp, width, height, spenum); } else { ViewerDevice *dev = new ViewerSDL(manager); screen = new Viewer(manager, dev, bpp, width, height, spenum);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/ps3fb/cp_fb.cc Thu Sep 30 23:54:08 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/Renderer/Engine/ps3fb/cp_fb.h Thu Sep 30 23:54:08 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/Renderer/Engine/ps3fb/cp_vt.cc Thu Sep 30 23:54:08 2010 +0900 @@ -0,0 +1,285 @@ +// cp_vt.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 http://www.linuxjournal.com/article/2597 +// +// "Console ttys are used when the keyboard and monitor are directly connected to the system without running +// the X Window System. Since you can have several virtual consoles, the devices are tty0 through tty63. In +// theory you can have 64 virtual consoles, but most people use only a few. The device /dev/console is +// identical to tty0 and is needed for historical reasons. If your system lets you log in on consoles 1 +// through 6, then when you run X Windows System, X uses console 7, so you'll need /dev/tty1 through /dev/ +// tty7 on your system. I recommend having files up through /dev/tty12. For more information on using +// virtual consoles, see the article Keyboards, Consoles and VT Cruising by John Fisk in the November 1996 +// issue of Linux Journal" + +#include <stdio.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/vt.h> +#include <linux/kd.h> +#include "cp_vt.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_vt_open_graphics(cp_vt* restrict vt) +{ + const char* error_str = NULL; + int error = 0; + + // Open the current tty + + // From http://tldp.org/HOWTO/Text-Terminal-HOWTO-6.html#ss6.3 + // (An excellent overview by David S. Lawyer) + // + // "In Linux the PC monitor is usually called the console and has several device special files associated + // with it: vc/0 (tty0), vc/1 (tty1), vc/2 (tty2), etc. When you log in you are on vc/1. To go to vc/2 + // (on the same screen) press down the 2 keys Alt(left)-F3. For vc/3 use Left Alt-F3, etc. These (vc/1, + // vc/2, vc/3, etc.) are called "virtual terminals". vc/0 (tty0) is just an alias for the current virtual + // terminal and it's where messages from the system are sent. Thus messages from the system will be seen + // on the console (monitor) regardless of which virtual terminal it is displaying." + + const int cur_tty = open( "/dev/tty0", O_RDWR ); + const int open_cur_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); + const char* open_cur_tty_error_str = "Could not open /dev/tty0. Check permissions."; + + error_str = select_error_str( error, error_str, open_cur_tty_error, open_cur_tty_error_str ); + error = error | open_cur_tty_error; + + // From: http://www.linuxjournal.com/article/2783 + // (A little out of date, but a nice primer.) + // + // "VT_GETSTATE returns the state of all VT's in the kernel in the structure: + // + // struct vt_stat { + // ushort v_active; + // ushort v_signal; + // ushort v_state; + // }; + // + // v_active the currently active VT + // v_state mask of all the opened VT's + // + // v_active holds the number of the active VT (starting from 1), while v_state + // holds a mask where there is a 1 for each VT that has been opened by some process. + // Note that VT 0 is always opened in this scenario, since it refers to the current VT. + // + // Bugs: + // The v_signal member is unsupported." + + struct vt_stat vts; + + const int get_state_error = ioctl( cur_tty, VT_GETSTATE, &vts ); + const char* get_state_error_str = "VT_GETSTATE failed on /dev/tty0"; + + error_str = select_error_str( error, error_str, get_state_error, get_state_error_str ); + error = error | get_state_error; + + vt->prev_tty_ndx = vts.v_active; + + // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt + // (Close enough to Linux and a pretty good source of documentation.) + // + // "VT_OPENQRY + // This call is used to find an available VT. The argu- + // ment to the ioctl is a pointer to an integer. The integer + // will be filled in with the number of the first avail- + // able VT that no other process has open (and hence, is + // available to be opened). If there are no available + // VTs, then -1 will be filled in." + + const int open_query_error = ioctl( cur_tty, VT_OPENQRY, &vt->tty_ndx); + const char* open_query_error_str = "No open ttys available"; + + error_str = select_error_str( error, error_str, open_query_error, open_query_error_str ); + error = error | open_query_error; + + const int close_cur_tty_error = close( cur_tty ); + const char* close_cur_tty_error_str = "Could not close parent tty"; + + error_str = select_error_str( error, error_str, close_cur_tty_error, close_cur_tty_error_str ); + error = error | close_cur_tty_error; + + char tty_file_name[11]; + + (void)snprintf( tty_file_name, 11, "/dev/tty%d", vt->tty_ndx ); + + const int tty = open( tty_file_name, O_RDWR ); + const int open_tty_error = (cur_tty >> ((sizeof(int)*8)-1)); + const char* open_tty_error_str = "Could not open tty"; + + error_str = select_error_str( error, error_str, open_tty_error, open_tty_error_str ); + error = error | open_tty_error; + + vt->tty = tty; + + // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt + // (Close enough to Linux and a pretty good source of documentation.) + // + // "VT_ACTIVATE + // This call has the effect of making the VT specified in + // the argument the active VT. The VT manager will cause + // a switch to occur in the same manner as if a hotkey had + // initiated the switch. If the specified VT is not open + // or does not exist the call will fail and errno will be + // set to ENXIO." + // + // "VT_WAITACTIVE + // If the specified VT is already active, this call + // returns immediately. Otherwise, it will sleep until + // the specified VT becomes active, at which point it will + // return." + + + const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->tty_ndx ); + const char* activate_tty_error_str = "Could not activate tty"; + + error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); + error = error | activate_tty_error; + + const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->tty_ndx ); + const char* waitactive_tty_error_str = "Could not switch to tty"; + + error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); + error = error | waitactive_tty_error; + + // From: http://opensolaris.org/os/project/vconsole/vt.7i.txt + // (Close enough to Linux and a pretty good source of documentation.) + // + // "KDSETMODE + // This call is used to set the text/graphics mode to the VT. + // + // KD_TEXT indicates that console text will be displayed on the screen + // with this VT. Normally KD_TEXT is combined with VT_AUTO mode for + // text console terminals, so that the console text display will + // automatically be saved and restored on the hot key screen switches. + // + // KD_GRAPHICS indicates that the user/application, usually Xserver, + // will have direct control of the display for this VT in graphics + // mode. Normally KD_GRAPHICS is combined with VT_PROCESS mode for + // this VT indicating direct control of the display in graphics mode. + // In this mode, all writes to this VT using the write system call are + // ignored, and the user is responsible for saving and restoring the + // display on the hot key screen switches." + + // Save the current VT mode. This is most likely KD_TEXT. + + const int kdgetmode_error = ioctl( vt->tty, KDGETMODE, &vt->prev_kdmode ); + const char* kdgetmode_error_str = "Could not get mode for tty"; + + error_str = select_error_str( error, error_str, kdgetmode_error, kdgetmode_error_str ); + error = error | kdgetmode_error; + + // Set VT to GRAPHICS (user draw) mode + + const int kdsetmode_graphics_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); + const char* kdsetmode_graphics_error_str = "Could not set graphics mode for tty"; + + error_str = select_error_str( error, error_str, kdsetmode_graphics_error, kdsetmode_graphics_error_str ); + error = error | kdsetmode_graphics_error; + + // + // Not bothering with VT_PROCESS, VT_AUTO is fine for our purposes. + // + + // If vt blanking is active, for example when running this program from a remote terminal, + // setting KD_GRAPHICS will not disable the blanking. Reset to KD_TEXT from KD_GRAPHICS will + // force disable blanking. Then return to KD_GRAPHICS for drawing. + // + // Note: KD_TEXT (default) to KD_TEXT will do nothing, so blanking will not be disable unless + // the mode is changing. i.e. the initial set to KD_GRAPHICS above is useful. + + const int kdsetmode_text_error = ioctl( vt->tty, KDSETMODE, KD_TEXT ); + const char* kdsetmode_text_error_str = "Could not set text mode for tty"; + + error_str = select_error_str( error, error_str, kdsetmode_text_error, kdsetmode_text_error_str ); + error = error | kdsetmode_text_error; + + const int kdsetmode_graphics_reset_error = ioctl( vt->tty, KDSETMODE, KD_GRAPHICS ); + const char* kdsetmode_graphics_reset_error_str = "Could not reset graphics mode for tty"; + + error_str = select_error_str( error, error_str, kdsetmode_graphics_reset_error, kdsetmode_graphics_reset_error_str ); + error = error | kdsetmode_graphics_reset_error; + + if ( error == -1 ) + { + printf("ERROR: vt_graphics_open: %s\n",error_str); + return (-1); + } + + return (0); +} + +int +cp_vt_close(cp_vt* restrict vt) +{ + const char* error_str = NULL; + int error = 0; + + // Reset previous mode on tty (likely KD_TEXT) + + const int kdsetmode_error = ioctl( vt->tty, KDSETMODE, vt->prev_kdmode ); + const char* kdsetmode_error_str = "Could not reset previous mode for tty"; + + error_str = select_error_str( error, error_str, kdsetmode_error, kdsetmode_error_str ); + error = error | kdsetmode_error; + + // Restore previous tty + + const int activate_tty_error = ioctl( vt->tty, VT_ACTIVATE, vt->prev_tty_ndx ); + const char* activate_tty_error_str = "Could not activate previous tty"; + + error_str = select_error_str( error, error_str, activate_tty_error, activate_tty_error_str ); + error = error | activate_tty_error; + + const int waitactive_tty_error = ioctl( vt->tty, VT_WAITACTIVE, vt->prev_tty_ndx ); + const char* waitactive_tty_error_str = "Could not switch to previous tty"; + + error_str = select_error_str( error, error_str, waitactive_tty_error, waitactive_tty_error_str ); + error = error | waitactive_tty_error; + + // Close tty + + const int close_tty_error = close( vt->tty ); + const char* close_tty_error_str = "Could not close tty"; + + error_str = select_error_str( error, error_str, close_tty_error, close_tty_error_str ); + error = error | close_tty_error; + + if ( error == -1 ) + { + printf("ERROR: vt_close: %s\n",error_str); + return (-1); + } + + return (0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/ps3fb/cp_vt.h Thu Sep 30 23:54:08 2010 +0900 @@ -0,0 +1,45 @@ +// cp_vt.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_VT_H +#define CP_VT_H + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct cp_vt cp_vt; + +struct cp_vt +{ + int prev_tty_ndx; + int prev_kdmode; + int tty; + int tty_ndx; +}; + +int cp_vt_open_graphics(cp_vt* restrict vt); +int cp_vt_close(cp_vt* restrict vt); + +#if defined(__cplusplus) +} +#endif + +#endif
--- a/Renderer/Engine/viewer.cc Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/viewer.cc Thu Sep 30 23:54:08 2010 +0900 @@ -327,6 +327,7 @@ } dev->clean_pixels(); + pixels = dev->flip_screen(pixels); for (int i = 1; i <= spackList_length; i++) { spackList[i-1].reinit(i*split_screen_h);
--- a/Renderer/Engine/viewerFB.cc Thu Sep 30 22:50:35 2010 +0900 +++ b/Renderer/Engine/viewerFB.cc Thu Sep 30 23:54:08 2010 +0900 @@ -70,7 +70,7 @@ info.yres = yres; info.vbpp = vbpp; info.line_len = line_len; - info.fbptr = fbptr; + info.fbptr[0] = (uint32_t *)fbptr; return info; //munmap(fbptr,screensize); @@ -107,7 +107,7 @@ } screen_info = get_fbdev_addr(); - Uint32 *pixels = (Uint32*) screen_info.fbptr; + Uint32 *pixels = screen_info.fbptr[0]; if (pixels == 0) { fprintf(stderr, "Cannot get frame buffer!\n");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/viewerPS3.cc Thu Sep 30 23:54:08 2010 +0900 @@ -0,0 +1,99 @@ +#include "viewerPS3.h" +#include "fb.h" +#include "types.h" +#include "ps3fb/cp_vt.h" +#include "ps3fb/cp_fb.h" +#include <stdio.h> + +#define default_sdl_flag SDL_INIT_TIMER | SDL_INIT_JOYSTICK + +ViewerPS3::ViewerPS3() {} +ViewerPS3::~ViewerPS3() {} + +#if defined(__linux__) + +#define DEVICE_NAME "/dev/fb0" +#define DIV_BYTE 8 + +ScreenInfo +ViewerPS3::get_fbdev_addr() +{ + ScreenInfo info; + + cp_vt_open_graphics(&vt); + cp_fb_open(&fb); + + info.xres = fb.w; + info.yres = fb.h; + info.vbpp = 32; + info.fbptr[0] = (uint32_t *)fb.draw_addr[ 0 ]; + info.fbptr[1] = (uint32_t *)fb.draw_addr[ 1 ]; + + return info; +} + +#else /* !defined(__linux__) */ +ScreenInfo get_fbdev_addr(void) { + ScreenInfo tmp = {0,0,0,0}; + return tmp; +} +#endif /* defined(__linux__) */ + + +Uint32 * +ViewerPS3::video_init(TaskManager *manager, int bpp, int width, int height) +{ + // Uint32 sdl_flag = default_sdl_flag | SDL_INIT_VIDEO; + Uint32 sdl_flag = default_sdl_flag ; + + if (SDL_Init(sdl_flag) < 0) { + fprintf(stderr,"Couldn't initialize SDL: %s\n",SDL_GetError()); + exit(1); + } + + screen_info = get_fbdev_addr(); + uint32_t *pixels = screen_info.fbptr[frame_ndx]; + + if (pixels == 0) { + fprintf(stderr, "Cannot get frame buffer!\n"); + pixels = (new Uint32[width*height*32/8]); + } + this->width = screen_info.xres; + this->height = screen_info.yres; + this->bpp = screen_info.vbpp; + + return pixels; +} + +void +ViewerPS3::clean_pixels() +{ +} + +void +ViewerPS3::clear_screen() +{ +} + +uint32_t * +ViewerPS3::flip_screen(uint32_t *old) +{ + // 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; + return (uint32_t*)fb.draw_addr[ frame_ndx ]; +} + + +void +ViewerPS3::free_device() +{ + cp_vt_close(&vt); + cp_fb_close(&fb); +} + +/* end */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Engine/viewerPS3.h Thu Sep 30 23:54:08 2010 +0900 @@ -0,0 +1,33 @@ +#ifndef INCLUDED_VIEWER_PS3 +#define INCLUDED_VIEWER_PS3 + +#include "fb.h" +#include "types.h" +#include "ps3fb/cp_vt.h" +#include "ps3fb/cp_fb.h" + +#include "ViewerDevice.h" + +class ViewerPS3 : public ViewerDevice { +public: + ViewerPS3(TaskManager *manager) {}; + ViewerPS3(); + virtual ~ViewerPS3(); + + ScreenInfo screen_info ; + cp_vt vt; + cp_fb fb; + uint32_t frame_ndx; + + ScreenInfo get_fbdev_addr(); + + /* override function */ + uint32_t *video_init(TaskManager *manager, int bpp, int width, int height); + void clean_pixels(void); + void clear_screen(); + void free_device(); + uint32_t* flip_screen(uint32_t *); + +}; + +#endif