Mercurial > hg > Members > kono > Cerium
view TaskManager/Test/test_render/viewer.cc @ 419:9348e49f63cf
merge
author | Hiroki NAKASONE <hiroki@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 23 Sep 2009 21:24:38 +0900 |
parents | 475a01e217cd a71cc69f2343 |
children | 976ca6f00d65 |
line wrap: on
line source
#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" static void post2runLoop(void *viewer); static void post2runDraw(void *viewer); static void post2speRunLoop(void *viewer); //static void post2runMove(void *viewer); //static void post2exchange_sgroot(void *viewer); static void post2speRunLoop(void *viewer); static void post2runMoveDrawLoop(void *viewer); /* measure for FPS (Frame Per Second) */ int start_time; int this_time; int frames; SceneGraphRootPtr sgroot; 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; /** * */ 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(TaskManager *manager); extern void create_cube_split(TaskManager *manager, int); extern void panel_init(TaskManager *manager, int bg); extern void universe_init(TaskManager *manager); extern void ieshoot_init(TaskManager *manager); extern void ball_bound_init(TaskManager *manager, int, int); extern void lcube_init(TaskManager *manager, int, int); extern void direction_init(TaskManager *manager); extern void init_position(TaskManager *manager, int, int); extern void vacuum_init(TaskManager *manager, int w, int h); extern void untitled_init(TaskManager *manager); extern void chain_init(TaskManager *manager, int w, int h); extern void chain_old_init(TaskManager *manager, int w, int h); extern void boss1_init(TaskManager *manager, int w, int h); extern void init_gaplant(TaskManager *manager, int w, int h); extern void vacuum_init2(TaskManager *manager, int w, int h); void Viewer::run_init(TaskManager *manager, const char *xml, int sg_number) { this->manager = manager; start_time = get_ticks(); this_time = 0; frames = 0; sgroot = new SceneGraphRoot(this->width, this->height); sgroot_2 = new SceneGraphRoot(this->width, this->height); //sgroot->createFromXMLFile(xml); switch (sg_number) { case 0: case 1: create_cube_split(manager, sg_number); break; case 2: case 3: case 4: panel_init(manager, sg_number); break; case 5: universe_init(manager); break; case 6: ieshoot_init(manager); break; case 7: ball_bound_init(manager, this->width, this->height); break; case 8: lcube_init(manager, this->width, this->height); break; case 9: direction_init(manager); break; case 10: init_position(manager, this->width, this->height); break; case 11: // vacuum_init(manager, this->width, this->height); break; case 12: untitled_init(manager); break; case 13: boss1_init(manager, this->width, this->height); break; case 14: init_gaplant(manager, this->width, this->height); break; case 15: vacuum_init2(manager, this->width, this->height); break; case 16: chain_init(manager, this->width, this-> height); speLoop(); return; break; case 17: chain_old_init(manager, this->width, this-> height); break; default: node_init(manager); break; } mainLoop(); } HTaskPtr Viewer::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); /** * 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); 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(); } return task_next; } /* Loop って言っても1回しか実行されない */ void Viewer::speLoop() { HTaskPtr task_next = initLoop(); // key の情報を格納する領域を確保する (global_alloc(KEY_STATUS)) HTaskPtr init_key_task = manager->create_task(INIT_KEY_TASK); init_key_task->spawn(); // SPE に送信する KEY_STATUS の領域確保 key_stat *key = (key_stat*)manager->allocate(sizeof(key_stat)); this->keyPtr = key; // post2runLoop は旧バージョン用なので post2speRunLoop の様なものを別につくるべき task_next->set_post(post2speRunLoop, (void*)this); // set_post(function(this->run_loop()), NULL) task_next->spawn(); // TASK_INIT_TEXTURE が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ /* test */ HTaskPtr task_switch = manager->create_task(TASK_SWITCH); task_switch->wait_for(task_next); task_switch->set_post(post2runMoveDrawLoop, (void*)this); task_switch->spawn(); } void Viewer::getKey() { Pad *pad = sgroot->getController(); if (pad->right.isHold()) { keyPtr->right = HOLD; } else if (pad->right.isPush()) { keyPtr->right = PUSH; } else { keyPtr->right = NONE; } if (pad->left.isHold()) { keyPtr->left = HOLD; } else if (pad->left.isPush()) { keyPtr->left = PUSH; } else { keyPtr->left = NONE; } if (pad->up.isHold()) { keyPtr->up = HOLD; } else if (pad->up.isPush()) { keyPtr->up = PUSH; } else { keyPtr->up = NONE; } if (pad->down.isHold()) { keyPtr->down = HOLD; } else if (pad->down.isPush()) { keyPtr->down = PUSH; } else { keyPtr->down = NONE; } if (pad->circle.isHold()) { keyPtr->circle = HOLD; } else if (pad->circle.isPush()) { keyPtr->circle = PUSH; } else { keyPtr->circle = NONE; } } static void post2runMoveDrawLoop(void *viewer_) { Viewer *viewer = (Viewer*)viewer_; // 同じ PPE 上なので sgroot(ポインタ) を add_param で送る。 //HTaskPtr send_key_task = viewer->manager->create_task(SEND_KEY); //send_key_task->add_param((int)sgroot); // set input data -> viewer keyPtr viewer->getKey(); HTaskPtr update_key = viewer->manager->create_task(UPDATE_KEY); update_key->add_inData(viewer->keyPtr, sizeof(key_stat)); update_key->spawn(); HTaskPtr move_task = viewer->manager->create_task(TASK_MOVE); //move_task->add_param(sgroot); HTaskPtr draw_task = viewer->manager->create_task(TASK_DRAW); HTaskPtr switch_task = viewer->manager->create_task(TASK_SWITCH); switch_task->wait_for(move_task); switch_task->wait_for(draw_task); move_task->spawn(); draw_task->spawn(); switch_task->set_post(post2runMoveDrawLoop, (void*)viewer); switch_task->spawn(); } static void post2speRunLoop(void *viewer_) { Viewer *viewer = (Viewer *)viewer_; HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY); viewer->run_move(task_next); } /* void Viewer::spe_run_loop() { 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); } //run_move(task_next); sgroot->updateControllerState(); sgroot->speExecute(width, height); //sgroot->checkRemove(); // ここから下は Rendering という関数にする rendering(task_next); } */ void Viewer::mainLoop() { HTaskPtr task_next = initLoop(); task_next->set_post(&post2runLoop, (void *)this); // set_post(function(this->run_loop()), NULL) task_next->spawn(); // TASK_INIT_TEXTURE が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ } /* static void post2exchange_sgroot(void *viewer_) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY); viewer->exchange_sgroot(task_next); } void Viewer::exchange_sgroot(TaskManager *manager) { SceneGraphRootPtr tmp = sgroot; sgroot = sgroot_2; sgroot_2 = tmp; } */ /* void Viewer::spe_run_move(HTaskPtr task_next) { HTaskPtr move_task = manager->create_task(MOVE_TASK); move_task->add_param(sgroot); task_next->wait_for(move_task); } */ static void post2runMove(void *viewer_) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY); viewer->run_move(task_next); } void Viewer::run_move(HTaskPtr task_next) { sgroot->updateControllerState(); sgroot->allExecute(width, height); } void Viewer::run_collision() { } void Viewer::rendering(HTaskPtr task_next) { HTaskPtr task_create_pp = manager->create_task(TASK_CREATE_PP2); // SceneGraph(木構造) -> PolygonPack task_create_pp->add_param((uint32)sgroot->getDrawSceneGraph()); task_create_pp->add_param((uint32)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(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 同期 // run_draw() を呼ぶ post2runDraw task_next->set_post(post2runDraw, (void*)this); // set_post(function(this->run_draw()), NULL) task_next->spawn(); // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が Viewer::run_draw() を呼ぶ } static void post2runLoop(void *viewer_) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY); viewer->run_loop(task_next); } void Viewer::run_loop(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); } //run_move(task_next); sgroot->updateControllerState(); sgroot->allExecute(width, height); //sgroot->checkRemove(); // ここから下は Rendering という関数にする rendering(task_next); } static void post2runDraw(void *viewer_) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY); viewer->run_draw(task_next); } void Viewer::run_draw(HTaskPtr task_next) // 引数に post2runLoop を入れるようにする { HTaskPtr task_draw; //task_next = manager->create_task(TASK_DUMMY); //task_next->set_post(post2runLoop, (void*)this); 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 { memset(&pixels[(startx-1)+this->width*(starty-1)], 0, (this->width)*sizeof(int)*rangey); break; } 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, (void*)this); // 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; delete sgroot_2; quit(); }