comparison Renderer/Engine/viewer.cc @ 507:735f76483bb2

Reorganization..
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 12 Oct 2009 09:39:35 +0900
parents
children 8148c81d2660
comparison
equal deleted inserted replaced
506:1d4a8a86f26b 507:735f76483bb2
1 #include <SDL.h>
2 #include "viewer.h"
3 #include "viewer_types.h"
4 #include "SceneGraph.h"
5 #include "SceneGraphRoot.h"
6 #include "scene_graph_pack.h"
7 #include "sys.h"
8 #include "Func.h"
9 #include "error.h"
10 #include "TaskManager.h"
11 #include <wchar.h>
12 #include "Pad.h"
13
14 static void post2runLoop(void *viewer);
15 static void post2runDraw(void *viewer);
16 static void post2speRendering(void *viewer);
17 static void post2speDraw(void *viewer);
18 // static void post2speRunLoop(void *viewer);
19 //static void post2runMove(void *viewer);
20 //static void post2exchange_sgroot(void *viewer);
21 //static void post2speRunLoop(void *viewer);
22 static void post2runMoveDrawLoop(void *viewer);
23
24 /* measure for FPS (Frame Per Second) */
25 int start_time;
26 int this_time;
27 int frames;
28
29 SceneGraphRootPtr sgroot;
30 //SceneGraphRootPtr sgroot_2;
31
32 /* Data Pack sent to Other CPUs (ex. SPE) */
33 SceneGraphPack *sgpack;
34 PolygonPack *ppack;
35 SpanPackPtr spackList;
36 SpanPackPtr *spackList_ptr;
37
38 int spackList_length;
39 int spackList_length_align;
40
41 /**
42 *
43 */
44
45 Viewer::Viewer(int b, int w, int h, int _num)
46 {
47 bpp = b;
48 width = w;
49 height = h;
50 spe_num = _num;
51 }
52
53 int
54 Viewer::get_ticks(void)
55 {
56 int time;
57 time = SDL_GetTicks();
58 return time;
59 }
60
61 bool
62 Viewer::quit_check(void)
63 {
64 SDL_Event event;
65
66 while(SDL_PollEvent(&event)) {
67 if (event.type==SDL_QUIT) {
68 return true;
69 }
70 }
71
72 Uint8 *keys=SDL_GetKeyState(NULL);
73
74 if (keys[SDLK_q] == SDL_PRESSED) {
75 return true;
76 }
77
78 return false;
79 }
80
81 void
82 Viewer::quit(void)
83 {
84 SDL_Quit();
85 }
86
87 void
88 Viewer::swap_buffers(void)
89 {
90 SDL_GL_SwapBuffers();
91 }
92
93 extern void node_init(TaskManager *manager);
94 extern void create_cube_split(TaskManager *manager, int);
95 extern void panel_init(TaskManager *manager, int bg);
96 extern void universe_init(TaskManager *manager);
97 extern void ieshoot_init(TaskManager *manager);
98 extern void ball_bound_init(TaskManager *manager, int, int);
99 extern void lcube_init(TaskManager *manager, int, int);
100 extern void direction_init(TaskManager *manager);
101 extern void init_position(TaskManager *manager, int, int);
102 extern void vacuum_init(TaskManager *manager, int w, int h);
103 extern void untitled_init(TaskManager *manager);
104 extern void chain_init(TaskManager *manager, int w, int h);
105 extern void chain_old_init(TaskManager *manager, int w, int h);
106 extern void boss1_init(TaskManager *manager, int w, int h);
107 extern void init_gaplant(TaskManager *manager, int w, int h);
108 extern void vacuum_init2(TaskManager *manager, int w, int h);
109
110 void
111 Viewer::run_init(TaskManager *manager, const char *xml, int sg_number)
112 {
113 this->manager = manager;
114
115 start_time = get_ticks();
116 this_time = 0;
117 frames = 0;
118
119 sgroot = new SceneGraphRoot(this->width, this->height);
120 // sgroot_2 = new SceneGraphRoot(this->width, this->height);
121 //sgroot->createFromXMLFile(xml);
122 // ここの switch は application->init(this, manager, sg_no); になるべき
123 switch (sg_number) {
124 case 0:
125 case 1:
126 create_cube_split(manager, sg_number);
127 break;
128 case 2:
129 case 3:
130 case 4:
131 panel_init(manager, sg_number);
132 break;
133 case 5:
134 universe_init(manager);
135 break;
136 case 6:
137 ieshoot_init(manager);
138 break;
139 case 7:
140 ball_bound_init(manager, this->width, this->height);
141 break;
142 case 8:
143 lcube_init(manager, this->width, this->height);
144 break;
145 case 9:
146 direction_init(manager);
147 break;
148 case 10:
149 init_position(manager, this->width, this->height);
150 break;
151 case 11:
152 // vacuum_init(manager, this->width, this->height);
153 break;
154 case 12:
155 untitled_init(manager);
156 break;
157 case 13:
158 boss1_init(manager, this->width, this->height);
159 break;
160 case 14:
161 init_gaplant(manager, this->width, this->height);
162 break;
163 case 15:
164 vacuum_init2(manager, this->width, this->height);
165 break;
166 case 16:
167 app = new Chain();
168 app->init(manager, this->width, this->height);
169 speLoop();
170 return;
171 break;
172 case 17:
173 chain_old_init(manager, this->width, this->height);
174 break;
175 default:
176 node_init(manager);
177 break;
178 }
179
180 mainLoop();
181 }
182
183
184 HTaskPtr
185 Viewer::initLoop()
186 {
187 HTaskPtr task_next;
188 HTaskPtr task_tex;
189
190 sgpack = (SceneGraphPack*)manager->allocate(sizeof(SceneGraphPack));
191 sgpack->init();
192 ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack));
193
194 spackList_length = (this->height + split_screen_h - 1) / split_screen_h;
195 spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*spackList_length);
196
197 /**
198 * SPU に送る address list は 16 バイト倍数でないといけない。
199 * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような
200 * length_align を求めている。はみ出した部分は使われない
201 * (ex) spackList_length が 13 の場合
202 * spackList_length_align = 16;
203 * 実際に送るデータは64バイトになるのでOK
204 * 14,15,16 の部分は何も入らない。
205 */
206 spackList_length_align = (spackList_length + 3)&(~3);
207
208 /* 各 SPU が持つ、SpanPack の address list */
209 spackList_ptr =
210 (SpanPack**)manager->allocate(sizeof(SpanPack*)*spackList_length_align);
211
212 for (int i = 0; i < spackList_length; i++) {
213 spackList_ptr[i] = &spackList[i];
214 }
215
216 for (int i = 1; i <= spackList_length; i++) {
217 spackList[i-1].init(i*split_screen_h);
218 }
219
220 task_next = manager->create_task(TASK_DUMMY);
221
222 for (int i = 0; i < spe_num; i++) {
223 task_tex = manager->create_task(TASK_INIT_TEXTURE);
224 /*
225 * ここはもう少しわかりやすい使い方がいいかもしれぬ。こんなもん?
226 */
227 task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i));
228 task_next->wait_for(task_tex);
229 task_tex->spawn();
230 }
231
232 return task_next;
233 }
234
235 /* Loop って言っても1回しか実行されない */
236 void
237 Viewer::speLoop()
238 {
239 HTaskPtr task_next = initLoop();
240 // key の情報を格納する領域を確保する (global_alloc(KEY_STATUS))
241 HTaskPtr init_key_task = manager->create_task(INIT_KEY_TASK);
242 init_key_task->set_cpu(SPE_0);
243 init_key_task->spawn();
244
245 // SPE に送信する KEY_STATUS の領域確保
246 key_stat *key = (key_stat*)manager->allocate(sizeof(key_stat));
247 this->keyPtr = key;
248
249 // post2runLoop は旧バージョン用なので post2speRunLoop の様なものを別につくるべき
250 //task_next->set_post(post2speRunLoop, (void*)this); // set_post(function(this->run_loop()), NULL)
251 //task_next->spawn();
252 // TASK_INIT_TEXTURE が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ
253
254 /* test */
255
256 HTaskPtr task_switch = manager->create_task(TASK_SWITCH);
257 task_switch->wait_for(task_next);
258 task_switch->set_post(post2runMoveDrawLoop, (void*)this);
259 task_switch->spawn();
260 }
261
262 void
263 Viewer::getKey()
264 {
265 Pad *pad = sgroot->getController();
266 if (pad->right.isHold()) {
267 keyPtr->right = HOLD;
268 } else if (pad->right.isPush()) {
269 keyPtr->right = PUSH;
270 } else {
271 keyPtr->right = NONE;
272 }
273
274 if (pad->left.isHold()) {
275 keyPtr->left = HOLD;
276 } else if (pad->left.isPush()) {
277 keyPtr->left = PUSH;
278 } else {
279 keyPtr->left = NONE;
280 }
281
282 if (pad->up.isHold()) {
283 keyPtr->up = HOLD;
284 } else if (pad->up.isPush()) {
285 keyPtr->up = PUSH;
286 } else {
287 keyPtr->up = NONE;
288 }
289
290 if (pad->down.isHold()) {
291 keyPtr->down = HOLD;
292 } else if (pad->down.isPush()) {
293 keyPtr->down = PUSH;
294 } else {
295 keyPtr->down = NONE;
296 }
297
298 if (pad->circle.isHold()) {
299 keyPtr->circle = HOLD;
300 } else if (pad->circle.isPush()) {
301 keyPtr->circle = PUSH;
302 } else {
303 keyPtr->circle = NONE;
304 }
305 }
306
307 static void
308 post2runMoveDrawLoop(void *viewer_)
309 {
310 Viewer *viewer = (Viewer*)viewer_;
311
312 // 同じ PPE 上なので sgroot(ポインタ) を add_param で送る。
313 //HTaskPtr send_key_task = viewer->manager->create_task(SEND_KEY);
314 //send_key_task->add_param((int)sgroot);
315 // set input data -> viewer keyPtr
316 viewer->getKey();
317 HTaskPtr update_key = viewer->manager->create_task(UPDATE_KEY);
318 update_key->add_inData(viewer->keyPtr, sizeof(key_stat));
319 update_key->set_cpu(SPE_0);
320 update_key->spawn();
321
322 /* TASK_MOVE は外から引数で取ってくるべき */
323 //HTaskPtr move_task = viewer->manager->create_task(viewer->app->move_taskid);
324 HTaskPtr move_task = viewer->manager->create_task(TASK_MOVE);
325 //move_task->add_param(sgroot);
326
327 //HTaskPtr draw_task = viewer->manager->create_task(TASK_DRAW);
328
329 /* rendering task test */
330 HTaskPtr draw_task = viewer->manager->create_task(TASK_DUMMY);
331 HTaskPtr draw_dummy = viewer->manager->create_task(TASK_DUMMY);
332
333 HTaskPtr switch_task = viewer->manager->create_task(TASK_SWITCH);
334 viewer->draw_dummy = draw_dummy;
335 switch_task->wait_for(draw_dummy);
336 draw_task->set_post(post2speRendering, (void*)viewer);
337
338 switch_task->wait_for(move_task);
339 switch_task->wait_for(draw_task);
340 move_task->spawn();
341 draw_task->spawn();
342
343 switch_task->set_post(post2runMoveDrawLoop, (void*)viewer);
344 switch_task->spawn();
345
346 }
347
348 #if 0
349 static void
350 post2speRunLoop(void *viewer_)
351 {
352 Viewer *viewer = (Viewer *)viewer_;
353 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
354 viewer->run_move(task_next);
355 }
356 #endif
357
358 void
359 Viewer::mainLoop()
360 {
361 HTaskPtr task_next = initLoop();
362
363 task_next->set_post(&post2runLoop, (void *)this); // set_post(function(this->run_loop()), NULL)
364 task_next->spawn();
365 }
366
367 #if 0
368 void
369 post2runMove(void *viewer_)
370 {
371 Viewer *viewer = (Viewer*)viewer_;
372 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
373 viewer->run_move(task_next);
374 }
375 #endif
376
377
378 void
379 Viewer::run_move(HTaskPtr task_next)
380 {
381 sgroot->updateControllerState();
382 sgroot->allExecute(width, height);
383 }
384
385 void
386 Viewer::run_collision()
387 {
388 }
389
390 void
391 post2rendering(void *viewer_)
392 {
393 Viewer *viewer = (Viewer *)viewer_;
394 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
395 viewer->rendering(task_next);
396 }
397
398 void
399 Viewer::rendering(HTaskPtr task_next)
400 {
401 #if 0
402 HTaskPtr task_create_pp = manager->create_task(TASK_CREATE_PP2);
403
404 // SceneGraph(木構造) -> PolygonPack
405
406 task_create_pp->add_param((uint32)sgroot->getDrawSceneGraph());
407 task_create_pp->add_param((uint32)ppack);
408
409 task_next->wait_for(task_create_pp);
410
411 int range_base = spe_num;
412 // 切り上げのつもり
413 int range = (spackList_length + range_base - 1) / range_base;
414
415 for (int i = 0; i < range_base; i++) {
416 int index_start = range*i;
417 int index_end = (index_start + range >= spackList_length)
418 ? spackList_length : index_start + range;
419
420 HTaskPtr task_create_sp = manager->create_task(TASK_CREATE_SPAN);
421 task_create_sp->add_inData(ppack, sizeof(PolygonPack));
422 task_create_sp->add_inData(spackList_ptr,
423 sizeof(SpanPack*)*spackList_length_align);
424 task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack));
425
426 task_create_sp->add_param(index_start);
427
428 /**
429 * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲
430 * [ 1.. 80] [ 81..160] [161..240]
431 * [241..320] [321..400] [401..480]
432 *
433 * ex. screen_height が 1080, spenum が 5 の場合、
434 * [ 1..216] [217..432] [433..648]
435 * [649..864] [865..1080]
436 */
437 task_create_sp->add_param(index_start*split_screen_h + 1);
438 task_create_sp->add_param(index_end*split_screen_h);
439
440 task_next->wait_for(task_create_sp);
441 task_create_sp->wait_for(task_create_pp);
442
443 task_create_sp->set_cpu(SPE_ANY);
444 task_create_sp->spawn();
445 }
446
447 task_create_pp->spawn();
448 #else
449 common_rendering(task_next);
450 #endif
451
452 // Barrier 同期
453 // run_draw() を呼ぶ post2runDraw
454 task_next->set_post(post2runDraw, (void*)this); // set_post(function(this->run_draw()), NULL)
455 task_next->spawn();
456
457 // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が Viewer::run_draw() を呼ぶ
458 }
459
460 static void
461 post2runLoop(void *viewer_)
462 {
463 Viewer *viewer = (Viewer*)viewer_;
464 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
465 viewer->run_loop(task_next);
466
467 }
468
469 void
470 Viewer::run_loop(HTaskPtr task_next)
471 {
472 bool quit_flg;
473 quit_flg = quit_check();
474 if (quit_flg == true) {
475 this_time = get_ticks();
476 run_finish();
477 return;
478 }
479
480 clean_pixels();
481
482 for (int i = 1; i <= spackList_length; i++) {
483 spackList[i-1].reinit(i*split_screen_h);
484 }
485
486 //run_move(task_next);
487 sgroot->updateControllerState();
488 sgroot->allExecute(width, height);
489 //sgroot->checkRemove();
490
491 // ここから下は Rendering という関数にする
492 rendering(task_next);
493 }
494
495 static void
496 post2runDraw(void *viewer_)
497 {
498 Viewer *viewer = (Viewer*)viewer_;
499 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
500 viewer->run_draw(task_next);
501
502 }
503
504 void
505 Viewer::run_draw(HTaskPtr task_next) // 引数に post2runLoop を入れるようにする
506 {
507 #if 0
508 HTaskPtr task_draw;
509
510 //task_next = manager->create_task(TASK_DUMMY);
511 //task_next->set_post(post2runLoop, (void*)this);
512
513 ppack->clear();
514 for (int i = 0; i < spackList_length; i++) {
515 SpanPack *spack = &spackList[i];
516 int startx = 1;
517 int endx = split_screen_w;
518
519 int starty = spack->info.y_top - split_screen_h + 1;
520 //int endy = spack->info.y_top;
521 int rangey = (starty + split_screen_h - 1 > this->height)
522 ? this->height - starty + 1 : split_screen_h;
523
524 while (startx < this->width) {
525 if (spack->info.size > 0) {
526 // Draw SpanPack
527 task_draw = manager->create_task(TASK_DRAW_SPAN);
528 task_draw->add_inData(spack, sizeof(SpanPack));
529
530 task_draw->add_param(
531 (uint32)&pixels[(startx-1) + this->width*(starty-1)]);
532 task_draw->add_param(this->width);
533 } else {
534 // 7.7.3 SL1 Data Cache Range Set to Zero コマンド
535 // を使って、DMAでclearするべき... ということは、
536 // それもSPEでやる方が良い?
537 memset(&pixels[(startx-1)+this->width*(starty-1)],
538 0, (this->width)*sizeof(int)*rangey);
539 break;
540 }
541
542 task_draw->add_param(startx);
543 task_draw->add_param(endx);
544 task_draw->add_param(rangey);
545 task_draw->set_cpu(SPE_ANY);
546 task_next->wait_for(task_draw);
547 task_draw->spawn();
548
549 startx += split_screen_w;
550 endx += split_screen_w;
551
552 if (endx > this->width) {
553 endx = this->width;
554 }
555 }
556 }
557 #else
558 common_draw(task_next);
559 #endif
560
561 task_next->set_post(post2runLoop, (void*)this); // set_post(function(this->run_loop()), NULL)
562 task_next->spawn();
563 // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ
564
565 frames++;
566 }
567
568 void
569 Viewer::run_finish(void)
570 {
571 if (this_time != start_time) {
572 printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0);
573 }
574
575 delete sgroot;
576 // delete sgroot_2;
577 quit();
578 }
579
580 static void
581 post2speRendering(void *viewer_)
582 {
583 Viewer *viewer = (Viewer*)viewer_;
584 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
585 viewer->spe_rendering(task_next);
586 }
587
588 void
589 Viewer::spe_rendering(HTaskPtr task_next)
590 {
591 common_rendering(task_next);
592
593 this->draw_dummy->wait_for(task_next);
594 task_next->set_post(post2speDraw, (void*)this);
595 task_next->spawn();
596
597 }
598
599 static void
600 post2speDraw(void *viewer_)
601 {
602 Viewer *viewer = (Viewer*)viewer_;
603 HTaskPtr task_next = viewer->manager->create_task(TASK_DUMMY);
604 viewer->spe_draw(task_next);
605 }
606
607 void
608 Viewer::spe_draw(HTaskPtr task_next)
609 {
610 common_draw(task_next);
611
612 this->draw_dummy->wait_for(task_next);
613 task_next->spawn();
614 this->draw_dummy->spawn();
615
616 frames++;
617 }
618
619 void
620 Viewer::common_rendering(HTaskPtr task_next)
621 {
622 HTaskPtr task_create_pp = manager->create_task(TASK_CREATE_PP2);
623
624 // SceneGraph(木構造) -> PolygonPack
625
626 task_create_pp->add_param((uint32)sgroot->getDrawSceneGraph());
627 task_create_pp->add_param((uint32)ppack);
628
629 task_next->wait_for(task_create_pp);
630
631 int range_base = spe_num;
632 // 切り上げのつもり
633 int range = (spackList_length + range_base - 1) / range_base;
634
635 for (int i = 0; i < range_base; i++) {
636 int index_start = range*i;
637 int index_end = (index_start + range >= spackList_length)
638 ? spackList_length : index_start + range;
639
640 HTaskPtr task_create_sp = manager->create_task(TASK_CREATE_SPAN);
641 task_create_sp->add_inData(ppack, sizeof(PolygonPack));
642 task_create_sp->add_inData(spackList_ptr,
643 sizeof(SpanPack*)*spackList_length_align);
644 task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack));
645
646 task_create_sp->add_param(index_start);
647
648 /**
649 * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲
650 * [ 1.. 80] [ 81..160] [161..240]
651 * [241..320] [321..400] [401..480]
652 *
653 * ex. screen_height が 1080, spenum が 5 の場合、
654 * [ 1..216] [217..432] [433..648]
655 * [649..864] [865..1080]
656 */
657 task_create_sp->add_param(index_start*split_screen_h + 1);
658 task_create_sp->add_param(index_end*split_screen_h);
659
660 task_next->wait_for(task_create_sp);
661 task_create_sp->wait_for(task_create_pp);
662
663 task_create_sp->set_cpu(SPE_ANY);
664 task_create_sp->spawn();
665 }
666
667 task_create_pp->spawn();
668 }
669
670 void
671 Viewer::common_draw(HTaskPtr task_next)
672 {
673 HTaskPtr task_draw;
674
675 //task_next = manager->create_task(TASK_DUMMY);
676 //task_next->set_post(post2runLoop, (void*)this);
677
678 ppack->clear();
679 for (int i = 0; i < spackList_length; i++) {
680 SpanPack *spack = &spackList[i];
681 int startx = 1;
682 int endx = split_screen_w;
683
684 int starty = spack->info.y_top - split_screen_h + 1;
685 //int endy = spack->info.y_top;
686 int rangey = (starty + split_screen_h - 1 > this->height)
687 ? this->height - starty + 1 : split_screen_h;
688
689 while (startx < this->width) {
690 if (spack->info.size > 0) {
691 // Draw SpanPack
692 task_draw = manager->create_task(TASK_DRAW_SPAN);
693 task_draw->add_inData(spack, sizeof(SpanPack));
694
695 task_draw->add_param(
696 (uint32)&pixels[(startx-1) + this->width*(starty-1)]);
697 task_draw->add_param(this->width);
698 } else {
699 // 7.7.3 SL1 Data Cache Range Set to Zero コマンド
700 // を使って、DMAでclearするべき... ということは、
701 // それもSPEでやる方が良い?
702 memset(&pixels[(startx-1)+this->width*(starty-1)],
703 0, (this->width)*sizeof(int)*rangey);
704 break;
705 }
706
707 task_draw->add_param(startx);
708 task_draw->add_param(endx);
709 task_draw->add_param(rangey);
710 task_draw->set_cpu(SPE_ANY);
711 task_next->wait_for(task_draw);
712 task_draw->spawn();
713
714 startx += split_screen_w;
715 endx += split_screen_w;
716
717 if (endx > this->width) {
718 endx = this->width;
719 }
720 }
721 }
722 }
723
724 /* end */