Mercurial > hg > Members > kono > Cerium
changeset 987:5eb651827ae3 akira
merge
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 02 Oct 2010 03:19:33 +0900 |
parents | ac437c3cf766 (diff) eb704fa22d05 (current diff) |
children | 0b6f8c82625a |
files | |
diffstat | 31 files changed, 1631 insertions(+), 166 deletions(-) [+] |
line wrap: on
line diff
--- a/Renderer/Engine/Makefile.cell Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/Makefile.cell Sat Oct 02 03:19:33 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 += -D__CERIUM_CELL__ -Drestrict=__restrict__ `sdl-config --cflags` `xml2-config --cflags` LIBS += `sdl-config --libs` -lSDL_image -lGL `xml2-config --libs` .SUFFIXES: .cc .o
--- a/Renderer/Engine/SgChange.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/SgChange.cc Sat Oct 02 03:19:33 2010 +0900 @@ -24,12 +24,7 @@ extern int frames; /* Data Pack sent to Other CPUs (ex. SPE) */ -extern SceneGraphPack *sgpack; -extern SpanPackPtr spackList; -extern SpanPackPtr *spackList_ptr; - -extern int spackList_length; -extern int spackList_length_align; +extern RederingData r[2]; void SgChange::run_init() @@ -95,15 +90,15 @@ bool quit_flg; quit_flg = viewer->quit_check(); if (quit_flg == true) { - this_time = viewer->get_ticks(); + // this_time = viewer->get_ticks(); viewer->run_finish(); return; } viewer->dev->clean_pixels(); - for (int i = 1; i <= spackList_length; i++) { - spackList[i-1].reinit(i*split_screen_h); + for (int i = 1; i <= r[spi].spackList_length; i++) { + r[spi].spackList[i-1].reinit(i*split_screen_h); } sgroot_A->updateControllerState();
--- a/Renderer/Engine/ViewerDevice.h Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/ViewerDevice.h Sat Oct 02 03:19:33 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 Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/fb.h Sat Oct 02 03:19:33 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 Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/main.cc Sat Oct 02 03:19:33 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,10 @@ 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; + } else if (strcmp(argv[i+1], "sdl") == 0) { + vtype = VTYPE_SDL; } i++; } @@ -76,6 +81,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 Sat Oct 02 03:19:33 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 Sat Oct 02 03:19:33 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 Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,287 @@ +// 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; + +#if 0 + 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; +#endif + + // 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 Sat Oct 02 03:19:33 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/spe/DataAllocate.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/spe/DataAllocate.cc Sat Oct 02 03:19:33 2010 +0900 @@ -10,14 +10,16 @@ run(SchedTask *s, void *rbuf, void *wbuf) { - void *idata = s->get_input(rbuf, 0); - long size = (long)s->get_param(0); - long load_id = (long)s->get_param(1); + int count = (int)s->get_input(rbuf, 0); + for(int i=0;i<count;i++) { + void *idata = s->get_input(rbuf, i); + long size = (long)s->get_param(i*2+1); + long load_id = (long)s->get_param(i*2+2); - void *buff = s->global_alloc(load_id, size); - - if (idata != NULL) { - memcpy(buff,idata,size); + void *buff = s->global_alloc(load_id, size); + if (idata != NULL) { + memcpy(buff,idata,size); + } } return 0;
--- a/Renderer/Engine/spe/DataUpdate.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/spe/DataUpdate.cc Sat Oct 02 03:19:33 2010 +0900 @@ -10,12 +10,14 @@ run(SchedTask *s, void *rbuf, void *wbuf) { - void *idata = (void*)s->get_input(rbuf, 0); - long size = (long)s->get_param(0); - long load_id = (long)s->get_param(1); - void *global_data = (void*)s->global_get(load_id); - - memcpy(global_data,idata,size); + long count = (long)s->get_param(0); + long id_base = (long)s->get_param(1); + for(int i=0; i<count; i++) { + void *idata = (void*)s->get_input(rbuf, i); + long size = (long)s->get_inputSize(i); + void *global_data = (void*)s->global_get(id_base+i); + memcpy(global_data,idata,size); + } return 0; }
--- a/Renderer/Engine/spe/Load_Texture.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/spe/Load_Texture.cc Sat Oct 02 03:19:33 2010 +0900 @@ -21,7 +21,7 @@ MemList *ml = smanager->createMemList(sizeof(uint32) * TEXTURE_BLOCK_SIZE, MAX_TILE); smanager->global_set(GLOBAL_TILE_LIST, (void *)ml); - smanager->printf("%d\n",GLOBAL_TILE_LIST); + // smanager->printf("%d\n",GLOBAL_TILE_LIST); return 0; }
--- a/Renderer/Engine/task/DataAllocate.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/task/DataAllocate.cc Sat Oct 02 03:19:33 2010 +0900 @@ -10,15 +10,17 @@ run(SchedTask *s, void *rbuf, void *wbuf) { - long size = (long)s->get_param(0); - long load_id = (long)s->get_param(1); - - //printf("size %d",sizeof(float)*length); + int count = (int)s->get_input(rbuf, 0); + for(int i=0;i<count;i++) { + void *idata = s->get_input(rbuf, i); + long size = (long)s->get_param(i*2+1); + long load_id = (long)s->get_param(i*2+2); - s->global_alloc(load_id, size); - - //MemList *ml = s->createMemList(length,length); - //s->global_set(load_id, (void *)ml); + void *buff = s->global_alloc(load_id, size); + if (idata != NULL) { + memcpy(buff,idata,size); + } + } return 0; }
--- a/Renderer/Engine/task/DataUpdate.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/task/DataUpdate.cc Sat Oct 02 03:19:33 2010 +0900 @@ -9,12 +9,15 @@ static int run(SchedTask *s, void *rbuf, void *wbuf) { - void *idata = (void*)s->get_input(rbuf, 0); - long size = (long)s->get_param(0); - long load_id = (long)s->get_param(1); - void *global_data = (void*)s->global_get(load_id); - - memcpy(global_data,idata,size); + + long count = (long)s->get_param(0); + long id_base = (long)s->get_param(1); + for(int i=0; i<count; i++) { + void *idata = (void*)s->get_input(rbuf, i); + long size = (long)s->get_inputSize(i); + void *global_data = (void*)s->global_get(id_base+i); + memcpy(global_data,idata,size); + } return 0; }
--- a/Renderer/Engine/viewer.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewer.cc Sat Oct 02 03:19:33 2010 +0900 @@ -20,8 +20,8 @@ static void post2runMoveDrawLoop(SchedTask *s,void *viewer,void *s1); /* measure for FPS (Frame Per Second) */ -int start_time; -int this_time; +static int start_time; +static int this_time; int frames; // static void post2speRunLoop(void *viewer); //static void post2runMove(void *viewer); @@ -31,14 +31,10 @@ //SceneGraphRootPtr sgroot_2; /* Data Pack sent to Other CPUs (ex. SPE) */ -SceneGraphPack *sgpack; -PolygonPack *ppack; -SpanPackPtr spackList; -SpanPackPtr *spackList_ptr; -int spackList_length; -int spackList_length_align; +RederingData r[2]; +int ppi, spi; /** * @@ -98,10 +94,6 @@ { this->manager = manager; - start_time = get_ticks(); - this_time = 0; - frames = 0; - if (spe_num == 0) spe_num = 1; sgroot = new SceneGraphRoot(this->width, this->height); @@ -121,29 +113,24 @@ for(int i = 0; i < spe_num; i++) { - - HTaskPtr data_load = manager->create_task(DataAllocate); - data_load->set_param(0,(memaddr)size); - data_load->set_param(1,(memaddr)Light); + HTaskPtr data_load = manager->create_task(DataAllocate); + data_load->set_param(0,(memaddr)3); // num of allocate block + data_load->set_param(0,(memaddr)(sizeof(float)*4*light_num)); // 1st allocate size + data_load->set_param(1,(memaddr)Light); // 1st id + data_load->set_param(0,(memaddr)(light_num * sizeof(int))); // 2nd size + data_load->set_param(1,(memaddr)LightSwitch); // 2nd id + data_load->set_param(0,(memaddr)16); // 3rd size + data_load->set_param(1,(memaddr)LightSysSwitch); // 3rd id data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); data_load->spawn(); } - size = light_num * sizeof(int); light_switch = (int*)manager->allocate(size); for (int i = 0; i < light_num; i++) { light_switch[i] = 0; } - for(int i = 0; i < spe_num; i++) { - HTaskPtr data_load = manager->create_task(DataAllocate); - data_load->set_param(0,(memaddr)size); - data_load->set_param(1,(memaddr)LightSwitch); - data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); - data_load->spawn(); - } - size = 16; // LightSysSwitch は 4byte. 残り 12byte は DMA転送の為のパディング light_sysswitch = (int*)manager->allocate(size); @@ -152,14 +139,10 @@ light_sysswitch[i] = 0; } - for(int i = 0; i < spe_num; i++) { - HTaskPtr data_load = manager->create_task(DataAllocate); - data_load->set_param(0,(memaddr)size); - data_load->set_param(1,(memaddr)LightSysSwitch); - data_load->set_cpu((CPU_TYPE)((int)SPE_0 + i)); - data_load->spawn(); - } - + start_time = get_ticks(); + this_time = 0; + frames = 0; + MainLoop *mainloop = app->init(this, this->width, this->height); mainloop->mainLoop(); } @@ -171,43 +154,43 @@ HTaskPtr task_next; HTaskPtr task_tex; - sgpack = (SceneGraphPack*)manager->allocate(sizeof(SceneGraphPack)); - sgpack->init(); - ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack)); + for(int i=0;i<2;i++) { + r[i].ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack)); - spackList_length = (this->height + split_screen_h - 1) / split_screen_h; - spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*spackList_length); - // printf("spackList %0lx height %d\n",(unsigned long)spackList, this->height); + r[i].spackList_length = (this->height + split_screen_h - 1) / split_screen_h; + r[i].spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*r[i].spackList_length); + // printf("spackList %0lx height %d\n",(unsigned long)r[i].spackList, this->height); - /** - * SPU に送る address list は 16 バイト倍数でないといけない。 - * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような - * length_align を求めている。はみ出した部分は使われない - * (ex) spackList_length が 13 の場合 - * spackList_length_align = 16; - * 実際に送るデータは64バイトになるのでOK - * 14,15,16 の部分は何も入らない。 - */ - spackList_length_align = (spackList_length + 3)&(~3); + /** + * SPU に送る address list は 16 バイト倍数でないといけない。 + * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような + * length_align を求めている。はみ出した部分は使われない + * (ex) spackList_length が 13 の場合 + * spackList_length_align = 16; + * 実際に送るデータは64バイトになるのでOK + * 14,15,16 の部分は何も入らない。 + */ + r[i].spackList_length_align = (r[i].spackList_length + 3)&(~3); - /* 各 SPU が持つ、SpanPack の address list */ - spackList_ptr = - (SpanPack**)manager->allocate(sizeof(SpanPack*)*spackList_length_align); + /* 各 SPU が持つ、SpanPack の address list */ + r[i].spackList_ptr = + (SpanPack**)manager->allocate(sizeof(SpanPack*)*r[i].spackList_length_align); - for (int i = 0; i < spackList_length; i++) { - spackList_ptr[i] = &spackList[i]; - } + for (int j = 0; i < r[i].spackList_length; i++) { + r[i].spackList_ptr[j] = &r[i].spackList[j]; + } - for (int i = 1; i <= spackList_length; i++) { - spackList[i-1].init(i*split_screen_h); + for (int j = 1; j <= r[i].spackList_length; i++) { + r[i].spackList[j-1].init(j*split_screen_h); + } } task_next = manager->create_task(Dummy,0,0,0,0); // ここは、Iterator を用意するべきだよね - for (int i = 0; i < spe_num; i++) { + for (int j = 0; j < spe_num; j++) { task_tex = manager->create_task(LoadTexture,0,0,0,0); - task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i)); + task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + j)); task_next->wait_for(task_tex); task_tex->spawn(); } @@ -327,10 +310,7 @@ } dev->clean_pixels(); - - for (int i = 1; i <= spackList_length; i++) { - spackList[i-1].reinit(i*split_screen_h); - } + pixels = dev->flip_screen(pixels); /* ここでGameTaskの終了を待つTaskを生成しておく */ sgroot->wait_game_task = manager->create_task(Dummy,0,0,0,0); @@ -710,7 +690,7 @@ // SceneGraph(木構造) -> PolygonPack task_create_pp->set_param(0,(memaddr)sgroot->getDrawSceneGraph()); - task_create_pp->set_param(1,(memaddr)ppack); + task_create_pp->set_param(1,(memaddr)r[ppi].ppack); /* GameTaskの終了を待ってからポリゴンを作る */ task_create_pp->wait_for(game_task); @@ -721,12 +701,12 @@ int range_base = spe_num; // 切り上げのつもり - int range = (spackList_length + range_base - 1) / range_base; + int range = (r[spi].spackList_length + range_base - 1) / range_base; for (int i = 0; i < range_base; i++) { int index_start = range*i; - int index_end = (index_start + range >= spackList_length) - ? spackList_length : index_start + range; + int index_end = (index_start + range >= r[spi].spackList_length) + ? r[spi].spackList_length : index_start + range; HTaskPtr task_create_sp = manager->create_task(CreateSpan); @@ -745,10 +725,10 @@ task_create_sp->set_param(1,index_start*split_screen_h + 1); task_create_sp->set_param(2,index_end*split_screen_h); - task_create_sp->add_inData(ppack, sizeof(PolygonPack)); - task_create_sp->add_inData(spackList_ptr, - sizeof(SpanPack*)*spackList_length_align); - task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack)); + task_create_sp->add_inData(r[ppi].ppack, sizeof(PolygonPack)); + task_create_sp->add_inData(r[spi].spackList_ptr, + sizeof(SpanPack*)*r[spi].spackList_length_align); + task_create_sp->add_inData(&r[spi].spackList[index_start], sizeof(SpanPack)); task_next->wait_for(task_create_sp); task_create_sp->wait_for(task_create_pp); @@ -761,24 +741,6 @@ game_task->spawn(); } -HTaskPtr -Viewer::update_task_create(void *data, int size, - int load_id, int spe_id, HTaskPtr wait) -{ - - HTaskPtr data_update = manager->create_task(DataUpdate); - data_update->add_inData(data,size); - data_update->set_param(0,size); - data_update->set_param(1,load_id); - data_update->set_cpu((CPU_TYPE)(spe_id)); - if (wait != NULL) { - wait->wait_for(data_update); - } - data_update->spawn(); - - return data_update; - -} void Viewer::common_draw(HTaskPtr task_next) @@ -789,8 +751,6 @@ //Light info update - //HTaskPtr data_update; - HTaskPtr data_update_wait; int light_num = 4; int size = sizeof(float)*4*light_num; //xyz+alpha(4) * light_num(4) int light_size = size / sizeof(float); @@ -804,33 +764,25 @@ } light_sysswitch[0] = light_sysswitch_stock; - - data_update_wait = manager->create_task(DataUpdate); - data_update_wait->add_inData(light_xyz,size); - data_update_wait->set_param(0,size); - data_update_wait->set_param(1,Light); - data_update_wait->set_cpu((CPU_TYPE)((int)SPE_0)); - - for (int i = 1; i < spe_num; i++) { - update_task_create(light_xyz,size,Light,(int)SPE_0+i,data_update_wait); + + + HTask *data_update_wait = 0; + for (int i = 0; i < spe_num; i++) { + data_update_wait = manager->create_task(DataUpdate); + data_update_wait->set_param(0,3); + data_update_wait->set_param(1,Light); // GlobalSet ID base + data_update_wait->set_inData(0,light_xyz,size); // Light + data_update_wait->set_inData(1,light_switch,light_num * sizeof(int)); // LightSwitch = Light+1 + data_update_wait->set_inData(2,light_sysswitch,16); // LightSysSwitch = Light+2 + data_update_wait->set_cpu((CPU_TYPE)(SPE_0+i)); + data_update_wait->spawn(); } - size = light_num * sizeof(int); - - for (int i = 0; i < spe_num; i++) { - update_task_create(light_switch,size,LightSwitch,(int)SPE_0+i,data_update_wait); - } - - size = 16; // LightSysSwitch は 4byte. 残り 12byte は DMA転送の為のパディング + ppi ^= 1; + r[ppi].ppack->clear(); - for (int i = 0; i < spe_num; i++) { - update_task_create(light_sysswitch,size,LightSysSwitch,(int)SPE_0+i,data_update_wait); - } - - ppack->clear(); - - for (int i = 0; i < spackList_length; i++) { - SpanPack *spack = &spackList[i]; + for (int i = 0; i < r[spi].spackList_length; i++) { + SpanPack *spack = &r[spi].spackList[i]; int startx = 1; int endx = split_screen_w; @@ -880,7 +832,6 @@ task_draw_array->spawn_task_array(task_draw->next()); task_draw_array->set_cpu(SPE_ANY); task_next->wait_for(task_draw_array); - task_draw_array->wait_for(data_update_wait); task_draw_array->spawn(); @@ -929,7 +880,6 @@ task_draw->set_cpu(SPE_ANY); task_next->wait_for(task_draw); - task_draw->wait_for(data_update_wait); task_draw->spawn(); startx += split_screen_w; @@ -942,14 +892,22 @@ #endif } + spi ^= 1; + for (int i = 1; i <= r[spi].spackList_length; i++) { + r[spi].spackList[i-1].reinit(i*split_screen_h); + } - data_update_wait->spawn(); + if (profile) { - if (frames % 1000 == 999) { - manager->show_profile(); + if (frames % 50 == 49) { + manager->show_profile(); + this_time = get_ticks(); + if (this_time != start_time) { + printf("\n%f FPS\n", ((((float)frames)*1000.0)/(this_time-start_time))); + start_time = this_time; frames = 0; + } } } - } void
--- a/Renderer/Engine/viewer.h Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewer.h Sat Oct 02 03:19:33 2010 +0900 @@ -16,6 +16,19 @@ class Application; +typedef struct rendering_data { + PolygonPack *ppack; + SpanPackPtr spackList; + SpanPackPtr *spackList_ptr; + + int spackList_length; + int spackList_length_align; +} RederingData ; + +extern RederingData r[2]; + +extern int ppi, spi; + class Viewer : public MainLoop { public:
--- a/Renderer/Engine/viewerFB.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewerFB.cc Sat Oct 02 03:19:33 2010 +0900 @@ -1,6 +1,10 @@ #include "viewerFB.h" #include "fb.h" #include <stdio.h> +#if 0 +#include <asm/ps3fb.h> +#endif + #define default_sdl_flag SDL_INIT_TIMER | SDL_INIT_JOYSTICK @@ -65,12 +69,20 @@ } send_current_information("The framebuffer device was mapped !"); +#if 0 + // Take control of frame buffer from kernel + ioctl(fd_framebuffer, PS3FB_IOCTL_ON, 0); + int field_ndx = 0; + ioctl(fd_framebuffer , PS3FB_IOCTL_FSEL, &field_ndx ); +#endif + + printf("fb: 0x%x \n", (unsigned int)fbptr); info.xres = xres; 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 +119,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 Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,100 @@ +#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 Sat Oct 02 03:19:33 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
--- a/Renderer/Engine/viewerSDL.cc Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewerSDL.cc Sat Oct 02 03:19:33 2010 +0900 @@ -3,6 +3,8 @@ #include "TaskManager.h" #include "viewer_types.h" +#define UGA 1 + extern void post2runLoop(void *); #define default_sdl_flag SDL_INIT_TIMER | SDL_INIT_JOYSTICK @@ -21,7 +23,7 @@ exit(1); } - screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE); + screen = SDL_SetVideoMode(width, height, bpp, SDL_HWSURFACE); if (screen == NULL) { fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError()); SDL_Quit(); @@ -45,14 +47,28 @@ ViewerSDL::clean_pixels() { //bzero(pixels, sizeof(int)*width*height); +#if !UGA SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0)); +#endif } void ViewerSDL::clear_screen() { +#if !UGA SDL_BlitSurface(bitmap, NULL, screen, NULL); SDL_UpdateRect(screen, 0, 0, 0, 0); +#endif +} + +uint32_t * +ViewerSDL::flip_screen(uint32_t *old) +{ +#if UGA + SDL_BlitSurface(bitmap,NULL,screen,NULL); + SDL_UpdateRect(screen,0,0,0,0); +#endif + return old; } void
--- a/Renderer/Engine/viewerSDL.h Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewerSDL.h Sat Oct 02 03:19:33 2010 +0900 @@ -17,6 +17,8 @@ void clean_pixels(); void clear_screen(); void free_device(); + uint32_t* flip_screen(uint32_t *); + }; #endif
--- a/Renderer/Engine/viewer_types.h Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Engine/viewer_types.h Sat Oct 02 03:19:33 2010 +0900 @@ -13,6 +13,7 @@ enum video_type { VTYPE_SDL, VTYPE_FB, + VTYPE_PS3, VTYPE_GL };
--- a/Renderer/Test/Makefile.cell Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Test/Makefile.cell Sat Oct 02 03:19:33 2010 +0900 @@ -14,7 +14,7 @@ %.pb.cc: $(PROTODIR)/%.proto $(PROTO) $(PROTOFLAGS) $< -ALL = spe-main ball_bound boss1_action direction gaplant ieshoot node panel universe untitled vacuum dynamic viewer SgRootChange property_test create_task property_universe chain_old property_chain aquarium init_aquarium +ALL = spe-main ball_bound boss1_action direction gaplant ieshoot node panel universe untitled vacuum dynamic viewer SgRootChange property_test create_task property_universe chain_old property_chain aquarium network init_aquarium all: $(ALL) @@ -108,6 +108,10 @@ aquarium : $(AQUARIUM_OBJ) $(CC) -o $@ $? $(LIBS) $(PROTOLIBS) +NETWORK_OBJ = network_game.pb.o network.o +network : $(NETWORK_OBJ) + $(CC) -o $@ $? $(LIBS) $(PROTOLIBS) + INIT_AQUARIUM_OBJ = aquarium.pb.o init_aquarium.o init_aquarium : $(INIT_AQUARIUM_OBJ) $(CC) -o $@ $? $(LIBS) $(PROTOLIBS)
--- a/Renderer/Test/Makefile.macosx Fri Oct 01 22:01:53 2010 +0900 +++ b/Renderer/Test/Makefile.macosx Sat Oct 02 03:19:33 2010 +0900 @@ -13,7 +13,7 @@ %.pb.cc: $(PROTODIR)/%.proto $(PROTO) $(PROTOFLAGS) $< -ALL = ball_bound boss1_action direction gaplant ieshoot node panel universe untitled vacuum property_test send_linda dynamic writer chain_old SgRootChange viewer aquarium init_aquarium test_linda +ALL = ball_bound boss1_action direction gaplant ieshoot node panel universe untitled vacuum property_test send_linda dynamic writer chain_old SgRootChange viewer aquarium network init_aquarium test_linda oFLAGS=-g -O2 CFLAGt=-g -O2 @@ -91,6 +91,10 @@ aquarium : $(AQUARIUM_OBJ) $(CC) -o $@ $? $(LIBS) $(PROTOLIBS) +NETWORK_OBJ = network_game.pb.o network.o +network : $(NETWORK_OBJ) + $(CC) -o $@ $? $(LIBS) $(PROTOLIBS) + INIT_AQUARIUM_OBJ = aquarium.pb.o init_aquarium.o init_aquarium : $(INIT_AQUARIUM_OBJ) $(CC) -o $@ $? $(LIBS) $(PROTOLIBS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Test/network.cc Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,293 @@ +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#include "SceneGraphRoot.h" +#include "lindaapi.h" +#include "network.h" +#include "network_game.pb.h" + +#define GET_SERIAL_ID 65535 + +int NetworkGame::last_player_id = 0; + +Viewer *NetworkGame::sgroot; +linda_t NetworkGame::linda_addr = { "localhost", 10000 }; +int NetworkGame::linda; +int NetworkGame::serial_id; +int NetworkGame::width; +int NetworkGame::start_x; +char *NetworkGame::xml_file_name; + +const char *usr_help_str = "Usage: ./network -linda LINDA_SERVER_NAME\n"; +void TMend(TaskManager *manager); + +extern void task_initialize(); +extern int init(TaskManager *manager, int argc, char *argv[]); +extern Application * +application() { + return new NetworkGame(); +} + +static void +null_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) +{ +} +static void +null_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree) +{ +} + +void +NetworkGame::update_last_player_id() { + last_player_id++; + if (last_player_id == serial_id) + last_player_id++; +} + +void +NetworkGame::set_position(SceneGraphPtr node, unsigned char *reply) { + network_game::Position *pos = new network_game::Position(); + pos->ParseFromArray(reply + LINDA_HEADER_SIZE, psx_get_datalength(reply)); + node->xyz[0] = pos->x(); + node->xyz[1] = pos->y(); + node->angle[0] = pos->angle_x(); + node->angle[1] = pos->angle_y(); + delete pos; +} + +static void +update_position_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) +{ + // LindaServerから座標データを取得してオブジェクトに反映させる。 + if (!node->resend_flag || node->seq_rd != node->seq) { + unsigned char *reply_rd = psx_reply(node->seq_rd); + if (reply_rd != NULL) { + NetworkGame::set_position(node, reply_rd); + psx_free(reply_rd); + return; + } + } + unsigned char *reply = psx_reply(node->seq); + if (reply != NULL) { +// NetworkGame::set_position(node, reply); + psx_free(reply); + node->seq = psx_wait_rd(NetworkGame::linda, node->id * 10 + 1); + node->resend_flag = true; + } else if (node->resend_flag) { + node->seq_rd = psx_rd(NetworkGame::linda, node->id * 10 + 1); + node->resend_flag = false; + } +} + +SceneGraphPtr +create_sg(Viewer *viewer, SceneGraphPtr par, unsigned char *data, int len, int serial_id) +{ + SceneGraphPtr child = viewer->sgroot->createSceneGraph(); + viewer->sgroot->createFromXMLmemory(viewer->sgroot->tmanager, child, (char *)data, len); + child->set_move_collision(update_position_move, null_collision); + child->id = serial_id; + child->seq = psx_wait_rd(NetworkGame::linda, serial_id * 10 + 1); + child->seq_rd = psx_rd(NetworkGame::linda, serial_id * 10 + 1); + child->resend_flag = false; + par->addChild(child); + return child; +} + +static void +check_new_player_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h) +{ + unsigned char *reply_rd = psx_reply(node->seq_rd); + if (reply_rd != NULL) { + unsigned char *xml_data = reply_rd + LINDA_HEADER_SIZE; + int xml_len = psx_get_datalength(reply_rd); + create_sg(NetworkGame::sgroot, node, xml_data, xml_len, NetworkGame::last_player_id); + psx_free(reply_rd); + NetworkGame::update_last_player_id(); + int tuple_id = NetworkGame::last_player_id * 10; + node->seq_rd = psx_rd(NetworkGame::linda, tuple_id); + } + // printf("rd id: %d\n", NetworkGame::last_player_id); +} + +void * +file_map(const char *filename, int *size) { + int fd; + void *addr; + struct stat sb; + + if ((fd = open(filename, O_RDONLY)) == -1) { + fprintf(stderr, "Can't open %s\n", filename); + perror(NULL); + } + if (fstat(fd, &sb) == -1) { + fprintf(stderr, "Can't fstat %s\n", filename); + perror(NULL); + } + *size = sb.st_size; + addr = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fd, 0); + if (addr == MAP_FAILED) { + perror("mmap error\n"); + exit(EXIT_FAILURE); + } + close(fd); + + return addr; +} + +void callback_free(unsigned char *tuple, void *arg) { + psx_free(tuple); +} + +void +NetworkGame::send_position(SceneGraphPtr node) { + int pos_id = serial_id * 10 + 1; + psx_callback_in(linda, pos_id, callback_free, NULL); + network_game::Position *pos = new network_game::Position(); + pos->set_x(node->xyz[0]); + pos->set_y(node->xyz[1]); + pos->set_angle_x(node->angle[0]); + pos->set_angle_y(node->angle[1]); + int size = pos->ByteSize(); + unsigned char *msg = (unsigned char *) sgroot->manager->allocate(sizeof(char) * size); + pos->SerializeToArray(msg, size); // 更新したデータを再度シリアライズ + delete pos; + psx_out(linda, pos_id, msg, size); +} + +void +my_move(SceneGraphPtr node, void *sgroot_, int w, int h) +{ + SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_; + Pad *pad = sgroot->getController(); + int flag = 0; + if (pad->right.isHold() || pad->left.isHold()) { + if (pad->right.isHold()) { + node->xyz[0] += 5.0f; + sgroot->camera->xyz[0] = node->xyz[0]; +// node->angle[1] = 0.0f; + flag = 1; + } else if (pad->left.isHold()) { + node->xyz[0] -= 5.0f; + sgroot->camera->xyz[0] = node->xyz[0]; +// node->angle[1] = 180.0f; + flag = 1; + } + } + + if (pad->down.isHold() || pad->up.isHold() ) { + if (pad->down.isHold()) { + node->xyz[1] += 5.0f; + sgroot->camera->xyz[1] = node->xyz[1]; + flag = 1; + } else if (pad->up.isHold()) { + node->xyz[1] -= 5.0f; + sgroot->camera->xyz[1] = node->xyz[1]; + flag = 1; + } + } + + /* ここで座標を送信 */ + if (flag || node->resend_flag) { + NetworkGame::send_position(node); + } +} + +void +NetworkGame::create_my_sg(Viewer *viewer, SceneGraphPtr par, int screen_w, int screen_h) +{ + int size; + void *addr = file_map(xml_file_name, &size); + SceneGraphPtr sgp = viewer->createSceneGraph(); + viewer->createFromXMLmemory(sgp, (char *)addr, size); + sgp->set_move_collision(my_move, null_collision); + Camera *camera = viewer->sgroot->camera; + camera->xyz[0] = 0.0; + camera->xyz[1] = 0.0; + + par->addChild(sgp); + sgp->c_xyz[0] = 0.0f; + sgp->c_xyz[1] = 0.0f; + sgp->c_xyz[2] = 0.0f; + + int xml_id = serial_id * 10; + psx_out(linda, xml_id, (unsigned char *)addr, size); + int pos_id = serial_id * 10 + 1; + + network_game::Position *pos = new network_game::Position(); + pos->set_x(0.0f); + pos->set_y(0.0f); + pos->set_angle_x(0.0f); + pos->set_angle_y(0.0f); + unsigned char *msg = (unsigned char *) viewer->manager->allocate(sizeof(unsigned char *) * size); + pos->SerializeToArray(msg, size); + psx_out(linda, pos_id, (unsigned char *)msg, pos->ByteSize()); + delete pos; + sgp->seq = 0; + sgp->resend_flag = 0; +} + +MainLoopPtr +NetworkGame::init(Viewer *sgroot, int screen_w, int screen_h) +{ + this->sgroot = sgroot; + width = screen_w; + linda_connect(); // 接続に合わせて serial_id も取得 +// update_screen_scope(); + SceneGraphPtr parent = sgroot->createSceneGraph(); + parent->set_move_collision(check_new_player_move, null_collision); + + create_my_sg(sgroot, parent, screen_w, screen_h); + update_last_player_id(); + + int tuple_id = NetworkGame::last_player_id * 10; + parent->seq_rd = psx_rd(linda, tuple_id); + sgroot->setSceneData(parent); + return sgroot; +} + +void +NetworkGame::linda_connect() { + init_linda(); // セレクタの初期化 + linda = open_linda_java(linda_addr.hostname, linda_addr.port); + // serial_id の取得 + int seq = psx_in(linda, GET_SERIAL_ID); + unsigned char *data = NULL; + do { + psx_sync_n(); + data = psx_reply(seq); + } while (data == NULL); +// data[LINDA_HEADER_SIZE + psx_get_datalength(data)] = '\0'; + serial_id = atoi((char *)data + LINDA_HEADER_SIZE); + psx_free(data); + printf("Get serial_id: %d\n", serial_id); +} + +int +TMmain(TaskManager *manager, int argc, char *argv[]) +{ + task_initialize(); + manager->set_TMend(TMend); + + for (int i = 0; i < argc; i++) { + if (strcmp(argv[i],"-linda") == 0 && i + 1 <= argc) { + NetworkGame::linda_addr.hostname = argv[i+1]; + } else if (strcmp(argv[i],"-port") == 0 && i + 1 <= argc) { + NetworkGame::linda_addr.port = atoi(argv[i+1]); + } else if (strcmp(argv[i],"-xml") == 0 && i + 1 <= argc) { + NetworkGame::xml_file_name = argv[i+1]; + } + } + return init(manager, argc, argv); +} + +void +TMend(TaskManager *manager) +{ + printf("NetworkGame end\n"); +} + +/* end */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Test/network.h Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,29 @@ +#include <math.h> +#include <stdlib.h> +#include "SceneGraphRoot.h" +#include "Application.h" +#include "MainLoop.h" +typedef struct { + const char *hostname; + int port; +} linda_t; + +class NetworkGame : public Application { +public: + static int last_player_id; + + static Viewer *sgroot; + static linda_t linda_addr; + static int linda; + static int serial_id; + static int start_x; + static int width; + static char *xml_file_name; + static void linda_connect(); + static void update_screen_scope(); + static void send_position(SceneGraphPtr node); + static void set_position(SceneGraphPtr node, unsigned char *reply); + static void update_last_player_id(); + void create_my_sg(Viewer *sgroot, SceneGraphPtr parent, int screen_w, int screen_h); + MainLoopPtr init(Viewer *viewer, int screen_w, int screen_h); +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Renderer/Test/protobuf/network_game.proto Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,8 @@ +package network_game; + +message Position { + required float x = 1; + required float y = 2; + required float angle_x = 3; + required float angle_y = 4; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/old/framebuffer/Makefile Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,14 @@ +all: fb_info fb_test fb_finish + +CC = gcc -std=c99 -O2 -g +fb_info : fb_info.o cp_fb.o cp_vt.o + $(CC) -o $@ $+ + +fb_test : fb_test.o cp_fb.o cp_vt.o -lm + $(CC) -o $@ $+ + +fb_finish : fb_finish.o cp_fb.o cp_vt.o -lm + $(CC) -o $@ $+ + +clean: + rm -f fb_info fb_test fb_finish *.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/old/framebuffer/cp_vt.c Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,286 @@ +// 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; +#if 0 + 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; +#endif + + // 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/old/framebuffer/cp_vt.h Sat Oct 02 03:19:33 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/old/framebuffer/fb_finish.c Sat Oct 02 03:19:33 2010 +0900 @@ -0,0 +1,45 @@ +// 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); + + + cp_vt_close(&vt); + cp_fb_close(&fb); + + return (0); +} +