changeset 922:655e11f6e437

moving OpenGL mode now!
author koba <koba@cr.ie.u-ryukyu.ac.jp>
date Thu, 29 Jul 2010 22:56:58 +0900
parents 58b5bbacb207
children e015a4e5e4b0 651251d56f36
files Renderer/Engine/SceneGraph.cc Renderer/Engine/main.cc Renderer/Engine/viewer.h Renderer/Engine/viewerGL.cc Renderer/Engine/viewerGL.h Renderer/Engine/viewer_types.h
diffstat 6 files changed, 1081 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/Renderer/Engine/SceneGraph.cc	Mon Jul 26 00:39:15 2010 +0900
+++ b/Renderer/Engine/SceneGraph.cc	Thu Jul 29 22:56:58 2010 +0900
@@ -464,6 +464,7 @@
         texture_image = converted;
     }
 
+    this->texture_image = texture_image;
     return texture_image;
 }
 
--- a/Renderer/Engine/main.cc	Mon Jul 26 00:39:15 2010 +0900
+++ b/Renderer/Engine/main.cc	Thu Jul 29 22:56:58 2010 +0900
@@ -2,6 +2,7 @@
 #include "viewer.h"
 #include "viewerSDL.h"
 #include "viewerFB.h"
+#include "viewerGL.h"
 #include "Application.h"
 
 /* prototype */
@@ -52,6 +53,8 @@
 		vtype = VTYPE_SDL;
 	    } else if (strcmp(argv[i+1], "fb") == 0) {
 		vtype = VTYPE_FB;
+	    } else if  (strcmp(argv[i+1], "gl") == 0) {
+	      vtype = VTYPE_GL;
 	    }
 	    i++;
 	}
@@ -67,7 +70,9 @@
     } else if (vtype == VTYPE_FB) {
 	ViewerDevice *dev = new ViewerFB(manager);
 	screen = new Viewer(manager, dev, bpp, width, height, spenum);
-    }else{
+    } else if (vtype == VTYPE_GL) {
+        screen = new cViewerGL(manager, bpp, width, height, spenum);
+    } else {
 	ViewerDevice *dev = new ViewerSDL(manager);
 	screen = new Viewer(manager, dev, bpp, width, height, spenum);
     }
--- a/Renderer/Engine/viewer.h	Mon Jul 26 00:39:15 2010 +0900
+++ b/Renderer/Engine/viewer.h	Thu Jul 29 22:56:58 2010 +0900
@@ -19,7 +19,7 @@
 class Viewer : public MainLoop {
 
 public:
-
+    Viewer(){};
     Viewer(TaskManager *manager, ViewerDevice *dev, int bpp, int width, int height, int spenum);
 
     virtual ~Viewer() {}
@@ -64,7 +64,7 @@
 
     void clean_pixels() {}
 
-    void run_init(TaskManager *manager, Application *app);
+    virtual void run_init(TaskManager *manager, Application *app);
     void run_loop(HTaskPtr task_next);
     void run_draw(HTaskPtr task_next);
     void run_finish();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Renderer/Engine/viewerGL.cc	Thu Jul 29 22:56:58 2010 +0900
@@ -0,0 +1,1019 @@
+#include "viewerGL.h"
+#include "Func.h"
+#include "TaskManager.h"
+#include "lindaapi.h"
+#include "viewer_types.h"
+
+
+static void
+ApplyMatrix(float *v, float *m)
+{
+  float t[4];
+
+  t[0] = v[0];
+  t[1] = v[1];
+  t[2] = v[2];
+  t[3] = v[3];
+
+  for (int i = 0; i < 4; i++) {
+    v[i] = t[0]*m[i] + t[1]*m[i+4] + t[2]*m[i+8] + t[3]*m[i+12];
+  }
+}
+
+static void
+ApplyNormalMatrix(float *v, float *m)
+{
+  float t[4];
+
+  t[0] = v[0];
+  t[1] = v[1];
+  t[2] = v[2];
+
+  for (int i = 0; i < 3; i++) {
+    v[i] = t[0]*m[i] + t[1]*m[i+4] + t[2]*m[i+8];
+  }
+}
+
+
+int power_of_two(int input)
+{
+  int value = 1;
+
+  while ( value < input )
+    {
+      value <<= 1;
+    }
+  return value;
+}
+
+cViewerGL::cViewerGL(TaskManager *m, int b, int w, int h, int _num)
+{
+  spe_num = _num;
+  manager = m;
+
+  video_init(b, w, h);
+}
+
+void
+cViewerGL::video_init(int bpp, int width, int height)
+{
+  int rgb_size[3];
+  Uint32 sdl_flag = SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK;
+  Uint32 video_flag = SDL_OPENGL;
+  int value = 1;
+
+  if (SDL_Init(sdl_flag) < 0) {
+    fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError());
+    exit(1);
+  }
+
+  /* See if we should detect the display depth */
+  if ( bpp == 0 )
+    {
+      if ( SDL_GetVideoInfo()->vfmt->BitsPerPixel <= 8 )
+        {
+          bpp = 8;
+        }
+      else
+        {
+          bpp = 32;
+        }
+    }
+
+  /* Initialize the bpp */
+  switch (bpp)
+    {
+    case 8:
+      rgb_size[0] = 3;
+      rgb_size[1] = 3;
+      rgb_size[2] = 2;
+      break;
+    case 15:
+    case 16:
+      rgb_size[0] = 5;
+      rgb_size[1] = 5;
+      rgb_size[2] = 5;
+      break;
+    default:
+      rgb_size[0] = 8;
+      rgb_size[1] = 8;
+      rgb_size[2] = 8;
+      break;
+    }
+  
+  screen = SDL_SetVideoMode(width, height, bpp, video_flag);
+  if (screen == NULL) {
+    fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError());
+    SDL_Quit();
+    exit(1);
+  }
+  this->width = screen->w;
+  this->height = screen->h;
+  this->bpp = screen->format->BitsPerPixel;
+
+  //各パラメータがちゃんと取れているか確認
+  printf("Screen BPP: %d\n", SDL_GetVideoSurface()->format->BitsPerPixel);
+  printf("\n");
+  printf( "Vendor     : %s\n", glGetString( GL_VENDOR ) );
+  printf( "Renderer   : %s\n", glGetString( GL_RENDERER ) );
+  printf( "Version    : %s\n", glGetString( GL_VERSION ) );
+  printf( "Extensions : %s\n", glGetString( GL_EXTENSIONS ) );
+  printf("\n");
+
+  SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &value );
+  printf( "SDL_GL_RED_SIZE: requested %d, got %d\n", rgb_size[0],value);
+  SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &value );
+  printf( "SDL_GL_GREEN_SIZE: requested %d, got %d\n", rgb_size[1],value);
+  SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &value );
+  printf( "SDL_GL_BLUE_SIZE: requested %d, got %d\n", rgb_size[2],value);
+  SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &value );
+  printf( "SDL_GL_DEPTH_SIZE: requested %d, got %d\n", bpp, value );
+  SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &value );
+  printf( "SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value );
+
+  //OpenGLの設定
+  glViewport( 0, 0, width, height );
+  glMatrixMode( GL_PROJECTION );
+  glLoadIdentity( );
+
+  glOrtho( -1000.0, 1000.0, 1000.0, -1000.0, -1000.0, 1000.0 );
+
+  glMatrixMode( GL_MODELVIEW );
+  glLoadIdentity( );
+
+  glEnable(GL_DEPTH_TEST);
+  glDepthFunc(GL_LESS);
+  glShadeModel(GL_SMOOTH);
+
+  /* 多分使わない
+     p = (Uint32*)manager->allocate(screen->pitch*height);
+     bitmap = SDL_CreateRGBSurfaceFrom((void *)p,
+     screen->w, screen->h,
+     screen->format->BitsPerPixel,
+     screen->pitch,
+     redMask, greenMask, blueMask, alphaMask);
+  
+     return p;
+  */
+}
+
+void
+cViewerGL::clean_pixels()
+{
+  //  SDL_FillRect(screen,NULL,SDL_MapRGB(screen->format,0,0,0));
+
+  glClearColor( 0.0, 0.0, 0.0, 1.0 );
+  glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void
+cViewerGL::clear_screen()
+{
+  //  SDL_BlitSurface(bitmap, NULL, screen, NULL);
+  //  SDL_UpdateRect(screen, 0, 0, 0, 0);  
+  GLenum gl_error;
+  char* sdl_error;
+
+  SDL_GL_SwapBuffers( );
+
+  /* Check for error conditions. */
+  gl_error = glGetError( );
+
+  if( gl_error != GL_NO_ERROR )
+    {
+      fprintf( stderr, "OpenGL error: %d\n", gl_error );
+    }
+
+  sdl_error = SDL_GetError( );
+
+  if( sdl_error[0] != '\0' )
+    {
+      fprintf(stderr, "SDL error '%s'\n", sdl_error);
+      SDL_ClearError();
+    }
+}
+
+#if 0
+void
+cViewerGL::free_device()
+{
+  free(bitmap->pixels);
+  SDL_FreeSurface(bitmap);
+}
+#endif
+
+void
+cViewerGL::pickup_vertex()
+{
+  SDL_Surface* texture;
+  float xyz1[4], xyz2[4], xyz3[4];
+  float tex_xy1[2], tex_xy2[2], tex_xy3[2];
+  float normal1[4],normal2[4],normal3[4];
+  GLuint image;
+
+  SceneGraphPtr sg_top = sgroot->getDrawSceneGraph();
+  SceneGraphPtr sg = sg_top;
+
+  while (sg) {
+    if (sg->flag_drawable) {
+      texture = sg->texture_image;
+      image = SDL_GL_LoadTexture(texture);
+
+      glEnable(GL_TEXTURE_2D);
+      glBindTexture(GL_TEXTURE_2D, image);
+      glBegin( GL_TRIANGLES);
+      for (int i = 0; i < sg->size; i += 3) {
+	xyz1[0] = sg->coord_xyz[(i+0)*3];
+	xyz1[1] = sg->coord_xyz[(i+0)*3+1];
+	xyz1[2] = sg->coord_xyz[(i+0)*3+2]*-1.0f;
+	xyz1[3] = 1.0f;
+	
+	xyz2[0] = sg->coord_xyz[(i+1)*3];
+	xyz2[1] = sg->coord_xyz[(i+1)*3+1];
+	xyz2[2] = sg->coord_xyz[(i+1)*3+2]*-1.0f;
+	xyz2[3] = 1.0f;
+	
+	xyz3[0] = sg->coord_xyz[(i+2)*3];
+	xyz3[1] = sg->coord_xyz[(i+2)*3+1];
+	xyz3[2] = sg->coord_xyz[(i+2)*3+2]*-1.0f;
+	xyz3[3] = 1.0f;
+
+	// sg->matrix = 回転行列*透視変換行列
+	ApplyMatrix(xyz1, sg->matrix);
+	ApplyMatrix(xyz2, sg->matrix);
+	ApplyMatrix(xyz3, sg->matrix);
+
+	xyz1[0] /= xyz1[2];
+	xyz1[1] /= xyz1[2];
+	xyz2[0] /= xyz2[2];
+	xyz2[1] /= xyz2[2];
+	xyz3[0] /= xyz3[2];
+	xyz3[1] /= xyz3[2];
+	
+	tex_xy1[0] = sg->coord_tex[(i+0)*3];
+	tex_xy1[1] = sg->coord_tex[(i+0)*3+1];
+      	tex_xy2[0] = sg->coord_tex[(i+1)*3];
+	tex_xy2[1] = sg->coord_tex[(i+1)*3+1];
+	tex_xy3[0] = sg->coord_tex[(i+2)*3];
+	tex_xy3[1] = sg->coord_tex[(i+2)*3+1];
+	
+	normal1[0] = sg->normal[(i+0)*3];
+	normal1[1] = sg->normal[(i+0)*3+1];
+	normal1[2] = sg->normal[(i+0)*3+2]*-1.0f;
+	normal1[3] = 0.0f;
+
+	normal2[0] = sg->normal[(i+1)*3];
+	normal2[1] = sg->normal[(i+1)*3+1];
+	normal2[2] = sg->normal[(i+1)*3+2]*-1.0f;
+	normal2[3] = 0.0f;
+
+	normal3[0] = sg->normal[(i+2)*3];
+	normal3[1] = sg->normal[(i+2)*3+1];
+	normal3[2] = sg->normal[(i+2)*3+2]*-1.0f;
+	normal3[3] = 0.0f;
+
+	ApplyNormalMatrix(normal1,sg->real_matrix);
+	ApplyNormalMatrix(normal2,sg->real_matrix);
+	ApplyNormalMatrix(normal3,sg->real_matrix);
+
+	normal1[0] /= normal1[2];
+	normal1[1] /= normal1[2];
+	
+	normal2[0] /= normal2[2];
+	normal2[1] /= normal2[2];
+	
+	normal3[0] /= normal3[2];
+	normal3[1] /= normal3[2];
+
+	//	if (sg->texture_image != NULL) {
+
+	  
+	  obj_draw(xyz1, tex_xy1, normal1);
+	  obj_draw(xyz2, tex_xy2, normal2);
+	  obj_draw(xyz3, tex_xy3, normal3);
+	  
+
+	  //}
+	/*
+	  triangle->tex_info.addr   = sg->texture_info.pixels;
+	  triangle->tex_info.width  = sg->texture_info.t_w;
+	  triangle->tex_info.height = sg->texture_info.t_h;
+	  triangle->tex_info.scale_max = sg->texture_info.scale_max;
+	*/
+      }
+      glEnd( );
+      glDisable(GL_TEXTURE_2D);
+    }
+   
+    if (sg->children != NULL) {
+      sg = sg->children;
+    } else if (sg->brother != NULL) {
+      sg = sg->brother;
+    } else {
+      while (sg) {
+	if (sg->brother != NULL) {
+	  sg = sg->brother;
+	  break;
+	} else {
+	  if (sg->parent == NULL) {
+	    sg = NULL;
+	    break;
+	  } else {
+	    sg = sg->parent;
+	  }
+	}
+      }
+    }
+
+  }
+}
+
+void
+cViewerGL::obj_draw(float *xyz, float *tex_xyz, float *normal_xyz)
+{  
+  glTexCoord2f(tex_xyz[0], tex_xyz[1]);
+  glVertex3f(xyz[0], xyz[1], xyz[2]);
+  glNormal3f(normal_xyz[0], normal_xyz[1], normal_xyz[2]);
+}
+void
+cViewerGL::run_init(TaskManager *manager, Application *app)
+{
+  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);
+  sgroot->tmanager = manager;
+  
+  int light_num = 4;
+  int size = sizeof(float)*4*light_num; //xyz+alfa(4) * light_num(4)
+  int light_size = size / sizeof(float);
+
+  light_xyz_stock = (float *)manager->allocate(size);
+  light_xyz = (float *)manager->allocate(size);
+
+  for (int i = 0; i < light_size ; i++) {
+    light_xyz[i] = 0.0f;
+  }
+
+  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);
+    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);
+
+  for (unsigned int i = 0; i < size / sizeof(int); i++) {
+    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();
+  }
+    
+  MainLoop *mainloop = app->init(this, this->width, this->height);
+  mainloop->mainLoop();
+}
+
+#if 0
+  HTaskPtr
+  cViewerGL::initLoop()
+  {
+  HTaskPtr task_next;
+  HTaskPtr task_tex;
+
+  sgpack = (SceneGraphPack*)manager->allocate(sizeof(SceneGraphPack));
+  sgpack->init();
+  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 %0x height %d\n",(unsigned int)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 が持つ、SpanPack の address list */
+spackList_ptr =
+  (SpanPack**)manager->allocate(sizeof(SpanPack*)*spackList_length_align);
+
+for (int i = 0; i < spackList_length; i++) {
+  spackList_ptr[i] = &spackList[i];
+ }
+
+for (int i = 1; i <= spackList_length; i++) {
+  spackList[i-1].init(i*split_screen_h);
+ }
+
+task_next = manager->create_task(Dummy,0,0,0,0);
+
+// ここは、Iterator を用意するべきだよね
+for (int i = 0; i < spe_num; i++) {
+  task_tex = manager->create_task(LoadTexture,0,0,0,0);
+  task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i));
+  task_next->wait_for(task_tex);
+  task_tex->spawn();
+ }
+
+return task_next;
+}
+#endif
+
+void
+cViewerGL::mainLoop()
+{
+  while(1) {
+    run_loop();
+  }
+}
+
+GLuint
+cViewerGL::SDL_GL_LoadTexture(SDL_Surface *surface)
+{
+  GLuint texture;
+  GLfloat texcoord[4];
+  int w, h;
+  SDL_Surface *image;
+  SDL_Rect area;
+  Uint32 saved_flags;
+  Uint8  saved_alpha;
+
+  /* Use the surface width and height expanded to powers of 2 */
+  w = power_of_two(surface->w);
+  h = power_of_two(surface->h);
+  texcoord[0] = 0.0f;                     /* Min X */
+  texcoord[1] = 0.0f;                     /* Min Y */
+  texcoord[2] = (GLfloat)surface->w / w;  /* Max X */
+  texcoord[3] = (GLfloat)surface->h / h;  /* Max Y */
+
+  image = SDL_CreateRGBSurface(
+                               SDL_SWSURFACE,
+                               w, h,
+                               32,
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
+                               0x000000FF, 
+                               0x0000FF00, 
+                               0x00FF0000, 
+                               0xFF000000
+#else
+                               0xFF000000,
+                               0x00FF0000, 
+                               0x0000FF00, 
+                               0x000000FF
+#endif
+                               );
+  if ( image == NULL )
+    {
+      return 0;
+    }
+
+  /* Save the alpha blending attributes */
+  saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
+  saved_alpha = surface->format->alpha;
+  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA )
+    {
+      SDL_SetAlpha(surface, 0, 0);
+    }
+  /* Copy the surface into the GL texture image */
+  area.x = 0;
+  area.y = 0;
+  area.w = surface->w;
+  area.h = surface->h;
+  SDL_BlitSurface(surface, &area, image, &area);
+
+  /* Restore the alpha blending attributes */
+  if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA )
+    {
+      SDL_SetAlpha(surface, saved_flags, saved_alpha);
+    }
+
+  /* Create an OpenGL texture for the image */
+  glGenTextures(1, &texture);
+  glBindTexture(GL_TEXTURE_2D, texture);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexImage2D(GL_TEXTURE_2D,
+               0,
+               GL_RGBA,
+               w, h,
+               0,
+               GL_RGBA,
+               GL_UNSIGNED_BYTE,
+               image->pixels);
+  SDL_FreeSurface(image); /* No longer needed */
+
+  return texture;
+}
+
+void
+cViewerGL::run_loop()
+{
+  clear_screen();
+
+  bool quit_flg;
+  quit_flg = quit_check();
+  if (quit_flg == true) {
+    this_time = get_ticks();
+    run_finish();
+    return;
+  }
+
+  clean_pixels();
+
+  sgroot->updateControllerState();
+  sgroot->allExecute(width, height);
+  light_xyz_stock = sgroot->getLightVector();
+  light_switch_stock = sgroot->getLightSwitch();
+  light_sysswitch_stock = sgroot->getLightSysSwitch();
+  pickup_vertex();
+  
+  psx_sync_n();
+  frames++;
+  //  rendering(task_next);
+}
+
+
+#if 0 //要らないハズ
+void
+cViewerGL::run_collision()
+{
+}
+
+void
+post2rendering(SchedTask *s, void *viewer_, void *arg)
+{
+  Viewer *viewer = (Viewer *)viewer_;
+  HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0);
+  viewer->rendering(task_next);
+}
+
+void 
+cViewerGL::rendering(HTaskPtr task_next)
+{
+  common_rendering(task_next, sgroot);
+    
+  // Barrier 同期
+  // run_draw() を呼ぶ post2runDraw
+  task_next->set_post(post2runDraw, (void*)this, 0); // set_post(function(this->run_draw()), NULL)
+  task_next->spawn();
+
+  // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が cViewerGL::run_draw() を呼ぶ
+}
+
+static void 
+post2runDraw(SchedTask *s, void *viewer_, void *arg)
+{
+  Viewer *viewer = (Viewer*)viewer_;
+  HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0);
+  viewer->run_draw(task_next);
+
+}
+
+void
+cViewerGL::run_draw(HTaskPtr task_next) // 引数に post2runLoop を入れるようにする
+{
+  common_draw(task_next);
+
+  task_next->set_post(post2runLoop, (void*)this, 0); // set_post(function(this->run_loop()), NULL)
+  task_next->spawn();
+  // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が cViewerGL::run_loop() を呼ぶ    
+
+
+}
+
+
+static void
+post2speRendering(SchedTask *s, void *viewer_, void *arg)
+{
+  Viewer *viewer = (Viewer*)viewer_;
+  HTaskPtr task_next = viewer->manager->create_task(Dummy,0,0,0,0);
+  viewer->spe_rendering(task_next);
+}
+
+#if SPE_CREATE_POLYGON
+
+void
+cViewerGL::create_pp_task(SceneGraphPtr sg, PolygonPackPtr pp_cur, HTaskPtr create_pp_wait,
+			  int &pp_index, int &sg_index, int tri_num) 
+{
+
+  HTaskPtr create_pp = manager->create_task(CreatePolygon);
+  create_pp->set_inData(0, &sg->tri_pack[sg_index], sizeof(TrianglePack)*tri_num);
+  create_pp->set_inData(1, sg->texture_info, sizeof(texture_list));
+  create_pp->set_inData(2, sg->sg_matrix, sizeof(float)*32); //わーい、マジックナンバー
+  create_pp->set_outData(0, &pp_cur->tri[pp_index], sizeof(TrianglePack)*tri_num);
+  create_pp->set_param(0, (memaddr)tri_num);
+  //create_pp->set_cpu(SPE_ANY);
+  create_pp_wait->wait_for(create_pp);
+  create_pp->spawn();
+
+  pp_index += tri_num;
+  sg_index += tri_num;
+}
+
+#endif
+
+void
+cViewerGL::common_rendering(HTaskPtr task_next, SceneGraphRoot *sgroot)
+{
+
+#if SPE_CREATE_POLYGON
+
+  SceneGraphPtr sg = sgroot->getDrawSceneGraph();
+  PolygonPackPtr pp_cur = ppack;
+  HTaskPtr create_pp_wait = manager->create_task(Dummy);
+  int pp_index = 0;
+
+  pp_cur->init();
+
+  task_next->wait_for(create_pp_wait);
+
+  while (sg) {
+    
+    if (sg->flag_drawable) {
+
+      int sum_size = sg->size;
+      int tri_cur_num = MAX_SIZE_TRIANGLE;
+      int sg_index = 0;
+
+      while (sum_size) {
+	
+	tri_cur_num -= sg->size/3;
+	
+	if (tri_cur_num < 0) {
+	    
+	  tri_cur_num = MAX_SIZE_TRIANGLE;
+	  create_pp_task(sg, pp_cur, create_pp_wait,
+			 pp_index, sg_index, tri_cur_num);
+	     
+	  PolygonPackPtr next = (PolygonPackPtr)manager->allocate(sizeof(PolygonPack));
+	  next->init();
+
+	  pp_cur->next = next;
+	  pp_cur       = next;
+	  pp_index = 0;
+	      
+	} else {
+	  
+	  create_pp_task(sg, pp_cur, create_pp_wait,
+			 pp_index, sg_index, tri_cur_num);
+
+	}
+
+	sum_size -= tri_cur_num*3;
+
+      }
+      
+      
+    }
+    
+    
+    
+    if (sg->children != NULL) {
+      sg = sg->children;
+    } else if (sg->brother != NULL) {
+      sg = sg->brother;
+    } else {
+      while (sg) {
+	if (sg->brother != NULL) {
+	  sg = sg->brother;
+	  break;
+	} else {
+	  if (sg->parent == NULL) {
+	    sg = NULL;
+	    break;
+	  } else {
+	    sg = sg->parent;
+	  }
+	}
+      }
+    } 
+  }
+  
+
+  int  range_base = spe_num;
+  
+  // 切り上げのつもり
+  int range = (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;
+    
+    HTaskPtr task_create_sp = manager->create_task(CreateSpan);
+    
+    task_create_sp->set_param(0,index_start);
+    
+    /**
+     * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲
+     *   [  1.. 80] [ 81..160] [161..240]
+     *   [241..320] [321..400] [401..480]
+     *
+     * ex. screen_height が 1080, spenum が 5 の場合、
+     *   [  1..216] [217..432] [433..648]
+     *   [649..864] [865..1080]
+     */
+    
+    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_next->wait_for(task_create_sp);
+    task_create_sp->wait_for(create_pp_wait);
+    
+    task_create_sp->set_cpu(SPE_ANY);
+    task_create_sp->spawn();
+  }
+  
+#else
+
+  HTaskPtr task_create_pp = manager->create_task(CreatePolygonFromSceneGraph);
+
+  // SceneGraph(木構造) -> PolygonPack
+
+  task_create_pp->set_param(0,(memaddr)sgroot->getDrawSceneGraph());
+  task_create_pp->set_param(1,(memaddr)ppack);
+
+  task_next->wait_for(task_create_pp);
+
+  int  range_base = spe_num;
+
+  // 切り上げのつもり
+  int range = (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;
+
+    HTaskPtr task_create_sp = manager->create_task(CreateSpan);
+
+    task_create_sp->set_param(0,index_start);
+	
+    /**
+     * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲
+     *   [  1.. 80] [ 81..160] [161..240]
+     *   [241..320] [321..400] [401..480]
+     *
+     * ex. screen_height が 1080, spenum が 5 の場合、
+     *   [  1..216] [217..432] [433..648]
+     *   [649..864] [865..1080]
+     */
+
+    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_next->wait_for(task_create_sp);
+    task_create_sp->wait_for(task_create_pp);
+
+    task_create_sp->set_cpu(SPE_ANY);
+    task_create_sp->spawn();
+  }
+
+  task_create_pp->spawn();
+
+#endif
+
+}
+
+HTaskPtr
+cViewerGL::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
+cViewerGL::common_draw(HTaskPtr task_next)
+{
+
+  //task_next = manager->create_task(Dummy);
+  //task_next->set_post(post2runLoop, (void*)this);
+
+  //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);
+
+  for (int i = 0; i < light_size; i++) {
+    light_xyz[i] = light_xyz_stock[i]; 
+  }
+
+  for (int i = 0; i < light_num; i++) {
+    light_switch[i] = light_switch_stock[i];
+  }
+
+  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);
+  }
+
+  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転送の為のパディング
+
+  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];
+    int startx = 1;
+    int endx = split_screen_w;
+
+    int starty = spack->info.y_top - split_screen_h + 1;
+    //int endy = spack->info.y_top;
+    int rangey = (starty + split_screen_h - 1 > this->height)
+      ? this->height - starty + 1 : split_screen_h;
+
+#if 1
+
+    if(spack->info.size > 0) {
+
+      int array_task_num = (this->width + split_screen_w - 1) / split_screen_w;
+      HTaskPtr task_draw_array = manager->create_task_array(DrawSpan, array_task_num, 6, 1, rangey);
+      Task *task_draw = 0;
+	  
+      while (startx < this->width) {
+	    
+	// Draw SpanPack
+	    
+	task_draw = task_draw_array->next_task_array(DrawSpan,task_draw);
+	task_draw->set_param(0,(memaddr)&pixels[(startx-1) + this->width*(starty-1)]);
+	task_draw->set_param(1,this->width);
+	task_draw->set_param(2,startx);
+	task_draw->set_param(3,endx);
+	task_draw->set_param(4,rangey);
+	task_draw->set_param(5,spack->info.size);
+	    
+	task_draw->set_inData(0,spack, sizeof(SpanPack));
+	    
+	for (int i = 0; i < rangey; i++) {
+	  task_draw->set_outData(i,
+				 &pixels[(startx-1) + this->width*(starty-1 + i) ],
+				 (endx-startx+1)*sizeof(int));
+	}
+	    
+	startx += split_screen_w;
+	endx += split_screen_w;
+	    
+	if (endx > this->width) {
+	  endx = this->width;
+	}
+	    
+      }	
+	  
+      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();
+
+    } else {
+	  
+      memset(&pixels[(startx-1)+this->width*(starty-1)],
+	     0, (this->width)*sizeof(int)*rangey);
+
+    }
+
+#else
+
+    HTaskPtr task_draw;
+
+    while (startx < this->width) {
+      if (spack->info.size > 0) {
+	// Draw SpanPack
+	task_draw = manager->create_task(DrawSpan);
+
+	task_draw->set_param(0,
+			     (memaddr)&pixels[(startx-1) + this->width*(starty-1)]);
+	task_draw->set_param(1,this->width);
+	task_draw->set_param(2,startx);
+	task_draw->set_param(3,endx);
+	task_draw->set_param(4,rangey);
+	task_draw->set_param(5,spack->info.size);
+
+	task_draw->add_inData(spack, sizeof(SpanPack));
+
+	for (int i = 0; i < rangey; i++) {
+	  task_draw->add_outData(
+				 &pixels[(startx-1) + this->width*(starty-1 + i) ],
+				 (endx-startx+1)*sizeof(int));
+	}
+
+      } else {
+	// 7.7.3 SL1 Data Cache Range Set to Zero コマンド
+	//  を使って、DMAでclearするべき... ということは、
+	// それもSPEでやる方が良い?
+	memset(&pixels[(startx-1)+this->width*(starty-1)],
+	       0, (this->width)*sizeof(int)*rangey);
+	break;
+      }
+
+      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;
+      endx += split_screen_w;
+
+      if (endx > this->width) {
+	endx = this->width;
+      }
+    }
+#endif
+
+  } 
+
+  data_update_wait->spawn();  
+
+}
+#endif
+
+void
+cViewerGL::run_finish()
+{
+  if (this_time != start_time) {
+    printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0);
+  }
+  
+  delete sgroot;
+  quit();
+}
+
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Renderer/Engine/viewerGL.h	Thu Jul 29 22:56:58 2010 +0900
@@ -0,0 +1,52 @@
+/**
+ * OpenGLを用いてレンダリングを行うクラスです。
+ * MacOSX上での高速な動作を目的としたViewerです。
+ * ViewerとViewerDevice 一体型です。
+ * 通常の計算(Move, Collision)はそのままです。
+ * 描画の部分はTaskを使わず、OpenGLで直に記述する予定です。
+ **/
+
+#ifndef INCLUDED_VIEWER_GL
+#define INCLUDED_VIEWER_GL
+
+#include <SDL.h>
+#include <SDL_opengl.h>
+#include "viewer_types.h"
+#include "TaskManager.h"
+#include "KeyStat.h"
+#include "MainLoop.h"
+#include "Application.h"
+#include "SceneGraphRoot.h"
+
+
+class cViewerGL : public Viewer {
+ public:
+  cViewerGL(TaskManager *m, int b, int w, int h, int _num);
+  ~cViewerGL(){};
+  
+  SDL_Surface *screen;
+  //  SDL_Surface *bitmap;
+  
+  /* override function */
+  void video_init(int bpp, int width, int height);
+  void clean_pixels();
+  void clear_screen();
+  //  void free_device();
+  
+  void run_init(TaskManager *manager, Application *app);
+  void run_loop();
+  void run_finish();
+
+  void mainLoop();
+  void pickup_vertex();
+  void obj_draw(float *xyz, float *tex_xyz, float *normal_xyz);
+  GLuint SDL_GL_LoadTexture(SDL_Surface *surface);
+
+ private:
+    /* measure for FPS (Frame Per Second) */
+    int start_time;
+    int this_time;
+    int frames;    
+};
+
+#endif
--- a/Renderer/Engine/viewer_types.h	Mon Jul 26 00:39:15 2010 +0900
+++ b/Renderer/Engine/viewer_types.h	Thu Jul 29 22:56:58 2010 +0900
@@ -13,6 +13,7 @@
 enum video_type {
     VTYPE_SDL,
     VTYPE_FB,
+    VTYPE_GL
 };
 
 #if defined(__LITTLE_ENDIAN__)