Mercurial > hg > Members > kono > Cerium
view Renderer/Engine/viewer.cc @ 737:50220f219341
merge
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 27 Dec 2009 20:49:38 +0900 |
parents | 6222ef073236 716d8bd95503 |
children | 307152e225a4 |
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" #include "Application.h" #include "lindaapi.h" #include "global_alloc.h" static void post2runLoop(SchedTask *s,void *viewer,void *s1); static void post2runDraw(SchedTask *s,void *viewer,void *s1); static void post2speRendering(SchedTask *s,void *viewer,void *s1); static void post2speDraw(SchedTask *s,void *viewer,void *s1); static void post2runMoveDrawLoop(SchedTask *s,void *viewer,void *s1); /* measure for FPS (Frame Per Second) */ int start_time; int this_time; int frames; // static void post2speRunLoop(void *viewer); //static void post2runMove(void *viewer); //static void post2exchange_sgroot(void *viewer); //static void post2speRunLoop(void *viewer); //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(TaskManager *m, ViewerDevice *vd, int b, int w, int h, int _num) { bpp = b; width = w; height = h; spe_num = _num; manager = m; dev = vd; pixels = dev->video_init(manager, b, w, h); } 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::run_init(TaskManager *manager, Application *app) { this->manager = manager; start_time = get_ticks(); this_time = 0; frames = 0; sgroot = new SceneGraphRoot(this->width, this->height); sgroot->tmanager = manager; int size = sizeof(float)*4; light_xyz = (float *)manager->allocate(size); light_xyz[0] = 0.0f; light_xyz[1] = 0.0f; light_xyz[2] = 0.0f; light_xyz[3] = 0.0f; HTaskPtr data_load; data_load = manager->create_task(DataLoad); data_load->set_param(0,(memaddr)size); data_load->set_param(1,(memaddr)Light); data_load->set_cpu((CPU_TYPE)((int)SPE_0)); data_load->spawn(); for(int i = 1; i < spe_num; i++) { data_load = manager->create_task(DataLoad); 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(); } MainLoop *mainloop = app->init(this, this->width, this->height); mainloop->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(Dummy); // ここは、Iterator を用意するべきだよね for (int i = 0; i < spe_num; i++) { task_tex = manager->create_task(LoadTexture); task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i)); task_next->wait_for(task_tex); task_tex->spawn(); } return task_next; } 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(SchedTask *m, void *viewer_, void *arg) { Viewer *viewer = (Viewer*)viewer_; // 同じ PPE 上なので sgroot(ポインタ) を set_param で送る。 //HTaskPtr send_key_task = viewer->manager->create_task(SendKey); //send_key_task->set_param((int)sgroot); // set input data -> viewer keyPtr viewer->getKey(); HTaskPtr update_key = viewer->manager->create_task(UpdateKey); update_key->add_inData(viewer->keyPtr, sizeof(key_stat)); update_key->set_cpu(SPE_0); update_key->spawn(); /* TASK_MOVE は外から引数で取ってくるべき */ //HTaskPtr move_task = viewer->manager->create_task(viewer->app->move_taskid); HTaskPtr move_task = viewer->manager->create_task(Move); //move_task->set_param(sgroot); //HTaskPtr draw_task = viewer->manager->create_task(Draw); /* rendering task test */ HTaskPtr draw_task = viewer->manager->create_task(Dummy); HTaskPtr draw_dummy = viewer->manager->create_task(Dummy); HTaskPtr switch_task = viewer->manager->create_task(Switch); viewer->draw_dummy = draw_dummy; switch_task->wait_for(draw_dummy); draw_task->set_post(post2speRendering, (void*)viewer, 0); 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, 0); switch_task->spawn(); } void Viewer::mainLoop() { HTaskPtr task_next = initLoop(); task_next->set_post(&post2runLoop, (void *)this, 0); // set_post(function(this->run_loop()), NULL) task_next->spawn(); } void Viewer::run_loop(HTaskPtr task_next) { dev->clear_screen(); bool quit_flg; quit_flg = quit_check(); if (quit_flg == true) { this_time = get_ticks(); run_finish(); return; } dev->clean_pixels(); for (int i = 1; i <= spackList_length; i++) { spackList[i-1].reinit(i*split_screen_h); } sgroot->updateControllerState(); sgroot->allExecute(width, height); light_xyz_stock = sgroot->getLightVector(); //sgroot->checkRemove(); // ここから下は Rendering という関数にする rendering(task_next); } void Viewer::run_collision() { } void post2rendering(SchedTask *s, void *viewer_, void *arg) { Viewer *viewer = (Viewer *)viewer_; HTaskPtr task_next = viewer->manager->create_task(Dummy); viewer->rendering(task_next); } void Viewer::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 が Viewer::run_draw() を呼ぶ } static void post2runLoop(SchedTask *s, void *viewer_, void *arg) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(Dummy); viewer->run_loop(task_next); psx_sync_n(); } static void post2runDraw(SchedTask *s, void *viewer_, void *arg) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(Dummy); viewer->run_draw(task_next); } void Viewer::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 が Viewer::run_loop() を呼ぶ frames++; } static void post2speRendering(SchedTask *s, void *viewer_, void *arg) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(Dummy); viewer->spe_rendering(task_next); } void Viewer::spe_rendering(HTaskPtr task_next) { common_rendering(task_next, sgroot); this->draw_dummy->wait_for(task_next); task_next->set_post(post2speDraw, (void*)this, 0); task_next->spawn(); } static void post2speDraw(SchedTask *s, void *viewer_, void *arg) { Viewer *viewer = (Viewer*)viewer_; HTaskPtr task_next = viewer->manager->create_task(Dummy); viewer->spe_draw(task_next); } void Viewer::spe_draw(HTaskPtr task_next) { common_draw(task_next); this->draw_dummy->wait_for(task_next); task_next->spawn(); this->draw_dummy->spawn(); frames++; } void Viewer::common_rendering(HTaskPtr task_next, SceneGraphRoot *sgroot) { 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(); } void Viewer::common_draw(HTaskPtr task_next) { HTaskPtr task_draw; //task_next = manager->create_task(Dummy); //task_next->set_post(post2runLoop, (void*)this); //Light info update HTaskPtr data_update; HTaskPtr data_update_wait; int size = sizeof(float)*4; light_xyz[0] = light_xyz_stock[0]; light_xyz[1] = light_xyz_stock[1]; light_xyz[2] = light_xyz_stock[2]; light_xyz[3] = light_xyz_stock[3]; 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++) { data_update = manager->create_task(DataUpdate); data_update->add_inData(light_xyz,sizeof(float)*size); data_update->set_param(0,size); data_update->set_param(1,Light); data_update->set_cpu((CPU_TYPE)((int)SPE_0 + i)); data_update_wait->wait_for(data_update); data_update->spawn(); } data_update_wait->spawn(); 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(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->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; } } } } void Viewer::run_finish() { dev->free_device(); if (this_time != start_time) { printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0); } delete sgroot; // delete sgroot_2; quit(); } /* end */