Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

linux_glut.cpp

Go to the documentation of this file.
00001 /*        Copyright (C) 2000,2001,2002  Sony Computer Entertainment America
00002           
00003           This file is subject to the terms and conditions of the GNU Lesser
00004           General Public License Version 2.1. See the file "COPYING" in the
00005           main directory of this archive for more details.                             */
00006 
00007 #include <stdlib.h>
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include <linux/ps2/gs.h>
00011 #include <sys/ioctl.h>
00012 // for allocating memory with the ps2stuff kernel module
00013 #include <sys/mman.h>
00014 
00015 #include "ps2gs.h"
00016 #include "ps2dma.h"
00017 #include "ps2vpu.h"
00018 #include "ps2vpufile.h"
00019 
00020 
00021 #include "sjoy.h"
00022 
00023 #include "GL/glut.h"
00024 #include "GL/ps2gl.h"
00025 
00026 #include "ps2s/timer.h"
00027 #include "ps2s/gs.h"
00028 #include "ps2s/packet.h"
00029 #include "ps2s/displayenv.h"
00030 
00031 #include "ps2gl/debug.h"
00032 
00033 // #include "pads.h"
00034 
00035 struct ps2_vpu_struct {
00036         int fd;
00037         int vpu;
00038         unsigned int mapsize;
00039         void *text;
00040         unsigned int text_size;
00041         void *data;
00042         unsigned int data_size;
00043 };
00044 
00045 /********************************************
00046  * some function pointer types
00047  */
00048 
00049 typedef void (* tFunctionPtr_ii)        (int, int);
00050 typedef void (* tFunctionPtr_ucii)      (unsigned char, int, int);
00051 typedef void (* tFunctionPtr_iii)       (int, int, int);
00052 typedef void (* tFunctionPtr)           (void);
00053 typedef void (* tFunctionPtr_i)         (int);
00054 
00055 /********************************************
00056  * local functions
00057  */
00058 
00059 static void initGsMemory();
00060 static bool doPads( int frameCount );
00061 static void parse_cl( int *argcp, char **argv );
00062 
00063 /********************************************
00064  * local data
00065  */
00066 
00067 tFunctionPtr DisplayFunc = NULL;
00068 tFunctionPtr_ii ReshapeFunc = NULL;
00069 tFunctionPtr_ucii KeyboardFunc = NULL;
00070 tFunctionPtr_i VisibilityFunc = NULL;
00071 tFunctionPtr IdleFunc = NULL;
00072 tFunctionPtr_iii SpecialFunc = NULL;
00073 
00074 static CEETimer *Timer2, *Timer3;
00075 //  static char default_module_path[] = "host0:/usr/local/sce/iop/modules";
00076 //  static char *module_path = '\0';
00077 
00078 int g_inter;
00079 int g_out_mode;
00080 int g_ff_mode;
00081 int g_resolution;
00082 int g_refresh_rate;
00083 int g_psm;
00084 int g_zpsm;
00085 int g_zbits;
00086 
00087 int g_fd_gs;
00088 ps2_vpu *g_vpu0, *g_vpu1;
00089 
00090 typedef enum { eNtsc, eVesa0 } screen_mode_t;
00091 screen_mode_t screen_mode = eVesa0;
00092 
00093 int release(void)
00094 {
00095    if (g_vpu1) {
00096       ps2_vpu_close(g_vpu1);
00097       g_vpu1 = NULL;
00098    }
00099         
00100    if (g_vpu0) {
00101       ps2_vpu_close(g_vpu0);
00102       g_vpu0 = NULL;
00103    }
00104         
00105    if (g_fd_gs >= 0) {
00106       ps2_gs_close();
00107       g_fd_gs = -1;
00108    }
00109         
00110    return PS2_GS_VC_REL_SUCCESS;
00111 }
00112 
00113 int acquire(void)
00114 {
00115    g_fd_gs = ps2_gs_open(-1);
00116    g_vpu0 = ps2_vpu_open(0);
00117    g_vpu1 = ps2_vpu_open(1);
00118         
00119    if (g_fd_gs < 0 || g_vpu0 == NULL || g_vpu1 == NULL) {
00120       release();
00121       return PS2_GS_VC_ACQ_FAILURE;
00122    }
00123         
00124    ps2_vpu_reset(g_vpu1);
00125    ps2_vpu_reset(g_vpu0);
00126         
00127    ps2_gs_reset(0, g_inter, g_out_mode, g_ff_mode, g_resolution,
00128                 g_refresh_rate);
00129         
00130    return PS2_GS_VC_ACQ_SUCCESS;
00131 }
00132 
00133 /********************************************
00134  * glut implementation (loosely speaking..)
00135  */
00136 
00155 // it doesn't get much lamer than this...
00156 extern "C" int setcrtmode(int argc, char **argv, int gs_fd);
00157 
00158 #   include <unistd.h>
00159 #   include <sys/stat.h>
00160 #   include <fcntl.h>
00161 #   include <errno.h>
00162 #include <string.h>
00163 
00164 int Ps2stuffDeviceFd = -1;
00165 bool WaitForVsync = true;
00166 
00174 void glutInit(int *argcp, char **argv)
00175 {
00176    parse_cl( argcp, argv );
00177 
00178    if ( screen_mode == eVesa0 ) {
00179       printf("vesa0 mode\n");
00180       g_inter = PS2_GS_NOINTERLACE;
00181       g_out_mode = PS2_GS_VESA;
00182       g_ff_mode = PS2_GS_FRAME;
00183       g_resolution = PS2_GS_640x480;
00184    }
00185    else if ( screen_mode == eNtsc ) {
00186       printf("ntsc1 mode\n");
00187       g_inter = PS2_GS_NOINTERLACE;
00188       g_out_mode = PS2_GS_NTSC;
00189       g_ff_mode = PS2_GS_FRAME;
00190       g_resolution = PS2_GS_640x480;
00191    }
00192 
00193    g_refresh_rate = PS2_GS_60Hz;
00194    g_psm = PS2_GS_PSMCT32;
00195    g_zpsm = PS2_GS_PSMZ32;
00196    g_zbits = 32;
00197         
00198    ps2_gs_vc_graphicsmode();
00199         
00200    g_fd_gs = ps2_gs_open(-1);
00201    g_vpu0 = ps2_vpu_open(0); // must be opened for vpu1...
00202    g_vpu1 = ps2_vpu_open(1);
00203 
00204    Ps2stuffDeviceFd = open( "/dev/ps2stuff", O_RDWR );
00205    if ( Ps2stuffDeviceFd < 0 ) {
00206      fprintf( stderr, "Couldn't open /dev/ps2stuff: %s\n", strerror(errno) );
00207      exit(-1);
00208    }
00209 
00210    ioctl( Ps2stuffDeviceFd, PS2STUFF_IOCTMEMRESET );
00211 
00212    // these are static, so they should be ok to call before
00213    // pglInit..
00214    CDmaPacket::InitFileDescriptors( g_fd_gs, g_vpu0->fd, g_vpu1->fd, Ps2stuffDeviceFd );
00215    GS::CDisplayEnv::InitGsFd( g_fd_gs );
00216 
00217    ps2_gs_reset(0, g_inter, g_out_mode, g_ff_mode, g_resolution,
00218                 g_refresh_rate);
00219         
00220    ps2_gs_start_display(1);
00221         
00222    ps2_gs_vc_enablevcswitch(acquire, release);
00223         
00224    ps2_gs_sync_v(0);
00225         
00226    // does the ps2gl library need to be initialized?
00227 
00228    if ( ! pglHasLibraryBeenInitted() ) {
00229       mWarn( "ps2gl library has not been initialized by the user; using default values." );
00230       int immBufferVertexSize = 8 * 1024;
00231       pglInit( immBufferVertexSize, 1000 );
00232    }
00233 
00234    // does gs memory need to be initialized?
00235 
00236    if ( ! pglHasGsMemBeenInitted() ) {
00237       mWarn("GS memory has not been allocated by the user; using default values.");
00238       initGsMemory();
00239    }
00240 
00241    // init the timing system
00242 
00243    Timer2 = new CEETimer( CEETimer::Timer2 );
00244 //     Timer2->SetResolution( CEETimer::BusClock_256th );
00245 //     Timer3 = new CEETimer( CEETimer::Timer3 );
00246 //     Timer3->SetResolution( CEETimer::BusClock_16th );
00247    mInitTimers( Timer2, CEETimer::BusClock_256th );
00248 
00249    // open the pads
00250    sjoy_open();
00251 }
00252 
00256 void glutDisplayFunc(void (*func)(void))
00257 {
00258    DisplayFunc = func;
00259 }
00260 
00266 void glutReshapeFunc(void (*func)(int width, int height))
00267 {
00268    ReshapeFunc = func;
00269 }
00270 
00276 void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))
00277 {
00278    KeyboardFunc = func;
00279 }
00280 
00286 void glutVisibilityFunc(void (*func)(int state))
00287 {
00288    VisibilityFunc = func;
00289 }
00290 
00295 void glutIdleFunc(void (*func)(void))
00296 {
00297    IdleFunc = func;
00298 }
00299 
00305 void glutSpecialFunc(void (*func)(int key, int x, int y))
00306 {
00307    SpecialFunc = func;
00308 }
00309 
00314 void glutMainLoop( void )
00315 {
00316    mErrorIf( DisplayFunc == NULL, "ps2glut:  No display function!" );
00317 
00318    if ( ReshapeFunc )
00319       ReshapeFunc( 640, 480 );
00320 
00321    if ( VisibilityFunc )
00322       VisibilityFunc( GLUT_VISIBLE );
00323 
00324    int frameCount = 0;
00325 
00326    while(1) {
00327       mUpdateTimers();
00328 
00329       mStartTimer("frame time");
00330 
00331       // ps2_gs_vc_lock();
00332 
00333       bool printTimes = doPads( frameCount );
00334 
00335       if ( DisplayFunc ) {
00336          mStartTimer("DisplayFunc()");
00337          pglBeginGeometry();
00338          DisplayFunc();
00339          pglEndGeometry();
00340          mStopTimer("DisplayFunc()");
00341       }
00342 
00343       if ( IdleFunc ) {
00344          mStartTimer("IdleFunc()");
00345          IdleFunc();
00346          mStopTimer("IdleFunc()");
00347       }
00348 
00349       mStartTimer("wait for vu1");
00350       pglFinishRenderingGeometry( PGL_DONT_FORCE_IMMEDIATE_STOP );
00351       mStopTimer("wait for vu1");
00352 
00353       mStopTimer("frame time");
00354 
00355       if ( printTimes ) {
00356          mDisplayTimers();
00357          printTimes = false;
00358       }
00359 
00360       if ( WaitForVsync )
00361          pglWaitForVSync();
00362 
00363       pglSwapBuffers();
00364 
00365       pglRenderGeometry();
00366 
00367       frameCount++;
00368 
00369       // ps2_gs_vc_unlock();
00370    }
00371 }
00372  // glut_api
00374 
00375 static void
00376 parse_cl( int *argcp, char **argv )
00377 {
00378    for ( int i = 0; i < *argcp; i++ ) {
00379       bool found = false;
00380 
00381       if ( strstr(argv[i], "-ntsc1") == argv[i] ) {
00382          screen_mode = eNtsc;
00383          found = true;
00384       }
00385       else if ( strstr(argv[i], "-vesa0") == argv[i] ) {
00386          screen_mode = eVesa0;
00387          found = true;
00388       }
00389 
00390       if ( found ) argv[i] = NULL;
00391    }
00392 
00393    // fix up argv
00394 
00395    int numArgs = *argcp;
00396    for ( int i = 0; i < numArgs; i++ ) {
00397       if ( argv[i] == NULL ) {
00398          // move everything after left one
00399          for ( int j = i; j < numArgs - 1; j++ )
00400             argv[j] = argv[j+1];
00401          *argcp -= 1;
00402       }
00403    }
00404 }
00405 
00406 static bool
00407 doPads( int frameCount )
00408 {
00409    static int paddata = 0;
00410 
00411    sjoy_poll();
00412    paddata = sjoy_get_ps2_button(0);
00413 
00414    bool printTimes = ( paddata & SJOY_PS2_START );
00415 
00416    if ( SpecialFunc ) {
00417       if ( (frameCount % 15) == 0 ) {
00418          if ( paddata & SJOY_PS2_L_UP ) {
00419             SpecialFunc( GLUT_KEY_UP, 0, 0 );
00420          }
00421          if ( paddata & SJOY_PS2_L_DOWN ) {
00422             SpecialFunc( GLUT_KEY_DOWN, 0, 0 );
00423          }
00424          if ( paddata & SJOY_PS2_L_RIGHT ) {
00425             SpecialFunc( GLUT_KEY_RIGHT, 0, 0 );
00426          }
00427          if ( paddata & SJOY_PS2_L_LEFT ) {
00428             SpecialFunc( GLUT_KEY_LEFT, 0, 0 );
00429          }
00430 
00431          if ( paddata & SJOY_PS2_L1 ) {
00432             SpecialFunc( GLUT_KEY_HOME, 0, 0 );
00433          }
00434          if ( paddata & SJOY_PS2_L2 ) {
00435             SpecialFunc( GLUT_KEY_END, 0, 0 );
00436          }
00437 
00438          if ( paddata & SJOY_PS2_R1 ) {
00439             WaitForVsync = ! WaitForVsync;
00440             SpecialFunc( GLUT_KEY_PAGE_UP, 0, 0 );
00441          }
00442          if ( paddata & SJOY_PS2_R2 ) {
00443             SpecialFunc( GLUT_KEY_PAGE_DOWN, 0, 0 );
00444          }
00445       }
00446    }
00447 
00448    if ( KeyboardFunc ) {
00449       if ( paddata & SJOY_PS2_R_UP ) {
00450          KeyboardFunc( '8', 0, 0 );
00451       }
00452       if ( paddata & SJOY_PS2_R_DOWN ) {
00453          KeyboardFunc( '2', 0, 0 );
00454       }
00455       if ( paddata & SJOY_PS2_R_LEFT ) {
00456          KeyboardFunc( '4', 0, 0 );
00457       }
00458       if ( paddata & SJOY_PS2_R_RIGHT ) {
00459          KeyboardFunc( '6', 0, 0 );
00460       }
00461    }
00462 
00463    return printTimes;
00464 }
00465 
00466 
00467 void glutInitDisplayMode(unsigned int mode)
00468 {
00469    mNotImplemented( );
00470 }
00471 
00472 void glutInitWindowPosition( int x, int y )
00473 {
00474    mNotImplemented( );
00475 }
00476 
00477 void glutInitWindowSize( int x, int y )
00478 {
00479    mNotImplemented( );
00480 }
00481 
00482 int glutCreateWindow(const char *title)
00483 {
00484    mNotImplemented( );
00485 
00486    return 1;
00487 }
00488 
00489 void glutPostRedisplay(void)
00490 {
00491    // mNotImplemented( );
00492 }
00493 
00494 void glutSwapBuffers( void )
00495 {
00496 }
00497 
00498 int glutGet(GLenum type)
00499 {
00500    mNotImplemented( );
00501    return 0;
00502 }
00503 
00504 void*
00505 pglutAllocDmaMem( unsigned int num_bytes )
00506 {
00507    // use the ps2stuff kernel module to allocate
00508    return mmap(0, num_bytes,
00509                PROT_READ | PROT_WRITE,
00510                MAP_SHARED, Ps2stuffDeviceFd,
00511                0 );
00512 }
00513 
00514 void
00515 pglutFreeDmaMem( void *mem )
00516 {
00517    // use the ps2stuff kernel module to allocate
00518    munmap( mem, 0 );
00519 }
00520 
00521 /********************************************
00522  * local function definitions
00523  */
00524 
00525 static void
00526 initGsMemory()
00527 {
00528    // frame and depth buffer
00529    pgl_slot_handle_t frame_slot_0, frame_slot_1, depth_slot;
00530    frame_slot_0 = pglAddGsMemSlot( 0, 150, GS::kPsm32 );
00531    frame_slot_1 = pglAddGsMemSlot( 150, 150, GS::kPsm32 );
00532    depth_slot = pglAddGsMemSlot( 300, 150, GS::kPsmz24 );
00533    // lock these slots so that they aren't allocated by the memory manager
00534    pglLockGsMemSlot( frame_slot_0 );
00535    pglLockGsMemSlot( frame_slot_1 );
00536    pglLockGsMemSlot( depth_slot );
00537 
00538    // ntsc or vesa?
00539 
00540    // default to vesa
00541    int fb_height = 480, interlace = PGL_NONINTERLACED;
00542 
00543    if ( screen_mode == eNtsc ) {
00544       fb_height = 224;
00545       interlace = PGL_INTERLACED;
00546    }
00547 
00548    // create gs memory area objects to use for frame and depth buffers
00549    pgl_area_handle_t frame_area_0, frame_area_1, depth_area;
00550    frame_area_0 = pglCreateGsMemArea( 640, fb_height, GS::kPsm24 );
00551    frame_area_1 = pglCreateGsMemArea( 640, fb_height, GS::kPsm24 );
00552    depth_area = pglCreateGsMemArea( 640, fb_height, GS::kPsmz24 );
00553    // bind the areas to the slots we created above
00554    pglBindGsMemAreaToSlot( frame_area_0, frame_slot_0 );
00555    pglBindGsMemAreaToSlot( frame_area_1, frame_slot_1 );
00556    pglBindGsMemAreaToSlot( depth_area, depth_slot );
00557 
00558    // draw to the new areas...
00559    pglSetDrawBuffers( interlace, frame_area_0, frame_area_1, depth_area );
00560    // ...and display from them
00561    pglSetDisplayBuffers( interlace, frame_area_0, frame_area_1 );
00562 
00563    // 32 bit
00564 
00565    // 64x32
00566    pglAddGsMemSlot( 450, 1, GS::kPsm32 );
00567    pglAddGsMemSlot( 451, 1, GS::kPsm32 );
00568    // 64x64
00569    pglAddGsMemSlot( 452, 2, GS::kPsm32 );
00570    pglAddGsMemSlot( 454, 2, GS::kPsm32 );
00571    // 128x128
00572    pglAddGsMemSlot( 456, 8, GS::kPsm32 );
00573    pglAddGsMemSlot( 464, 8, GS::kPsm32 );
00574    pglAddGsMemSlot( 472, 8, GS::kPsm32 );
00575    // 256x256
00576    pglAddGsMemSlot( 480, 32, GS::kPsm32 );
00577 
00578    pglPrintGsMemAllocation();
00579 }

ps2gl version cvs