diff Renderer/test_render/viewer.cpp @ 283:55ea4465b1a2

fix test_render
author e065746@localhost.localdomain
date Fri, 05 Jun 2009 16:49:12 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Renderer/test_render/viewer.cpp	Fri Jun 05 16:49:12 2009 +0900
@@ -0,0 +1,388 @@
+#include <SDL.h>
+#include "viewer.h"
+#include "viewer_types.h"
+#include "SceneGraph.h"
+#include "SceneGraphRoot.h"
+#include "scene_graph_pack.h"
+#include "sys.h"
+#include "Func.h"
+#include "error.h"
+#include "TaskManager.h"
+#include <wchar.h>
+#include "Pad.h"
+
+
+extern void post2runLoop(void *);
+extern void post2runDraw(void *);
+
+/* measure for FPS (Frame Per Second) */
+int start_time;
+int this_time;
+int frames;
+
+SceneGraphRootPtr sgroot;
+
+/* Data Pack sent to Other CPUs (ex. SPE) */
+SceneGraphPack *sgpack;
+PolygonPack *ppack;
+SpanPackPtr spackList;
+SpanPackPtr *spackList_ptr;
+
+int spackList_length;
+int spackList_length_align;
+
+/**
+ *
+ */
+
+Viewer::Viewer(int b, int w, int h, int _num)
+{
+    bpp = b;
+    width = w;
+    height = h;
+    spe_num = _num;
+}
+
+int
+Viewer::get_ticks(void)
+{
+    int time;
+    time = SDL_GetTicks();
+    return time;
+}
+
+bool
+Viewer::quit_check(void)
+{
+    SDL_Event event;
+
+    while(SDL_PollEvent(&event)) {
+	if (event.type==SDL_QUIT) {
+	    return true;
+	}
+    }
+
+    Uint8 *keys=SDL_GetKeyState(NULL);
+
+    if (keys[SDLK_q] == SDL_PRESSED) {
+	return true;
+    }
+
+    return false;
+}
+
+void
+Viewer::quit(void)
+{
+    SDL_Quit();
+}
+
+void
+Viewer::swap_buffers(void)
+{
+    SDL_GL_SwapBuffers();
+}
+
+extern void node_init(void);
+extern void create_cube_split(int);
+extern void panel_init(int);
+extern void universe_init(void);
+extern void ieshoot_init(void);
+extern void ball_bound_init(int, int);
+extern void lcube_init(int, int);
+extern void direction_init(void);
+extern void init_position(int, int);
+extern void vacuum_init(int w, int h);
+extern void untitled_init(void);
+void
+Viewer::run_init(const char *xml, int sg_number)
+{
+    HTaskPtr task_next;
+    HTaskPtr task_tex;
+
+    start_time = get_ticks();
+    this_time  = 0;
+    frames     = 0;
+
+    sgroot = new SceneGraphRoot(this->width, this->height);
+    //sgroot->createFromXMLFile(xml);
+
+    switch (sg_number) {
+    case 0:
+    case 1:
+	create_cube_split(sg_number);
+	break;
+    case 2:
+    case 3:
+    case 4:
+	panel_init(sg_number);
+	break;
+    case 5:
+	universe_init();
+	break;
+    case 6:
+	ieshoot_init();
+	break;
+    case 7:
+	ball_bound_init(this->width, this->height);
+	break;
+    case 8:
+	lcube_init(this->width, this->height);
+	break;
+    case 9:
+	direction_init();
+	break;
+    case 10:
+	init_position(this->width, this->height);
+	break;
+    case 11:
+	vacuum_init(this->width, this->height);
+	break;
+    case 12:
+        untitled_init();
+        break;
+    default:
+	node_init();
+	break;
+    }
+
+    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);
+
+    /**
+     * 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(TASK_DUMMY);
+
+
+#if 0
+    // 諸事情で、今は SceneGraphPack を作らずに
+    // そのまま SceneGraph でやっています
+    HTaskPtr task_sgp;
+    task_sgp = manager->create_task(TASK_CREATE_SGP);
+    task_sgp->add_param((uint32)scene_graph);
+    task_sgp->add_param((uint32)sgpack);
+    task_next->wait_for(task_sgp);
+    task_sgp->spawn();
+#endif
+
+    for (int i = 0; i < spe_num; i++) {
+	task_tex = manager->create_task(TASK_INIT_TEXTURE);
+	/* 
+	 * ここはもう少しわかりやすい使い方がいいかもしれぬ。こんなもん?
+	*/
+	task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i));
+	task_next->wait_for(task_tex);
+	task_tex->spawn();
+    }
+
+    task_next->set_post(&post2runLoop, NULL); // set_post(function(this->run_loop()), NULL)
+    task_next->spawn(); 
+    // TASK_INIT_TEXTURE が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ 
+}
+
+void
+Viewer::run_loop(void)
+{
+    HTaskPtr task_create_pp  = NULL;
+    HTaskPtr task_create_sp  = NULL;
+    HTaskPtr task_next;
+    bool quit_flg;
+
+    quit_flg = quit_check();
+
+    if (quit_flg == true) {
+	this_time = get_ticks();
+	run_finish();
+	return;
+    }
+
+    clean_pixels();
+
+    for (int i = 1; i <= spackList_length; i++) {
+	spackList[i-1].reinit(i*split_screen_h);
+    }
+
+    task_next = manager->create_task(TASK_DUMMY);
+
+
+#if 0
+    // SceneGraphPack の update
+    HTaskPtr task_update_sgp = NULL;
+    task_update_sgp = manager->create_task(TASK_UPDATE_SGP);
+    task_update_sgp->add_inData(sgpack, sizeof(SceneGraphPack));
+    task_update_sgp->add_outData(sgpack, sizeof(SceneGraphPack));
+    task_update_sgp->add_param(width);
+    task_update_sgp->add_param(height);
+    task_next->wait_for(task_update_sgp);
+    task_update_sgp->spawn();
+#else
+    sgroot->updateControllerState();
+    sgroot->allExecute(width, height);
+    //sgroot->checkRemove();
+#endif
+
+#if 0
+    // SceneGraphPack(配列) -> PolygonPack
+    task_create_pp = manager->create_task(TASK_CREATE_PP);
+    task_create_pp->add_inData(sgpack, sizeof(SceneGraphPack));
+    task_create_pp->add_param((uint32)ppack);
+#else
+    // SceneGraph(木構造) -> PolygonPack
+    task_create_pp = manager->create_task(TASK_CREATE_PP2);
+    task_create_pp->add_param((uint32)sgroot->getDrawSceneGraph());
+    task_create_pp->add_param((uint32)ppack);
+#endif
+    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;
+
+	task_create_sp = manager->create_task(TASK_CREATE_SPAN);
+	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_param(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->add_param(index_start*split_screen_h + 1);
+	task_create_sp->add_param(index_end*split_screen_h);
+
+	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();
+    
+    // Barrier 同期
+    task_next->set_post(post2runDraw, NULL); // set_post(function(this->run_draw()), NULL)
+    task_next->spawn();
+    // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が Viewer::run_draw() を呼ぶ     
+}
+
+void
+Viewer::run_draw(void)
+{
+    HTaskPtr task_next;
+    HTaskPtr task_draw;
+    
+    task_next = manager->create_task(TASK_DUMMY);
+    
+    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;
+
+	while (startx < this->width) {
+	    if (spack->info.size > 0) {
+		// Draw SpanPack
+		task_draw = manager->create_task(TASK_DRAW_SPAN);
+		task_draw->add_inData(spack, sizeof(SpanPack));
+		
+		task_draw->add_param(
+		    (uint32)&pixels[(startx-1) + this->width*(starty-1)]);
+		task_draw->add_param(this->width);
+	    } else {
+#if 0
+		//break;
+		// Draw Background (現在は塗りつぶし)
+		task_draw = manager->create_task(TASK_DRAW_BACK);
+		task_draw->add_param(0xffffffff);
+
+		for (int k = 0; k < rangey; k++) {
+		    task_draw->add_outData(
+			&pixels[(startx-1)+this->width*(k+starty-1)],
+			(endx - startx + 1)*sizeof(int));
+		}
+#else
+		memset(&pixels[(startx-1)+this->width*(starty-1)],
+		       0, (this->width)*sizeof(int)*rangey);
+		//wmemset((wchar_t*)&pixels[(startx-1)+this->width*(starty-1)],
+		//0xFFFFFFFF, (this->width)*sizeof(int)*rangey/sizeof(wchar_t));
+		break;
+#endif
+	    }
+
+	    task_draw->add_param(startx);
+	    task_draw->add_param(endx);
+	    task_draw->add_param(rangey);
+	    task_draw->set_cpu(SPE_ANY);
+	    task_next->wait_for(task_draw);
+	    task_draw->spawn();
+
+	    startx += split_screen_w;
+	    endx += split_screen_w;
+
+	    if (endx > this->width) {
+		endx = this->width;
+	    }
+	}
+    }
+
+    task_next->set_post(post2runLoop, NULL); // set_post(function(this->run_loop()), NULL)
+    task_next->spawn();
+    // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ     
+
+    frames++;
+}
+
+void
+Viewer::run_finish(void)
+{
+    if (this_time != start_time) {
+	printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0);
+    }
+
+    delete sgroot;
+
+    quit();
+}