283
|
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
|
|
15 extern void post2runLoop(void *);
|
|
16 extern void post2runDraw(void *);
|
|
17
|
|
18 /* measure for FPS (Frame Per Second) */
|
|
19 int start_time;
|
|
20 int this_time;
|
|
21 int frames;
|
|
22
|
|
23 SceneGraphRootPtr sgroot;
|
|
24
|
|
25 /* Data Pack sent to Other CPUs (ex. SPE) */
|
|
26 SceneGraphPack *sgpack;
|
|
27 PolygonPack *ppack;
|
|
28 SpanPackPtr spackList;
|
|
29 SpanPackPtr *spackList_ptr;
|
|
30
|
|
31 int spackList_length;
|
|
32 int spackList_length_align;
|
|
33
|
|
34 /**
|
|
35 *
|
|
36 */
|
|
37
|
|
38 Viewer::Viewer(int b, int w, int h, int _num)
|
|
39 {
|
|
40 bpp = b;
|
|
41 width = w;
|
|
42 height = h;
|
|
43 spe_num = _num;
|
|
44 }
|
|
45
|
|
46 int
|
|
47 Viewer::get_ticks(void)
|
|
48 {
|
|
49 int time;
|
|
50 time = SDL_GetTicks();
|
|
51 return time;
|
|
52 }
|
|
53
|
|
54 bool
|
|
55 Viewer::quit_check(void)
|
|
56 {
|
|
57 SDL_Event event;
|
|
58
|
|
59 while(SDL_PollEvent(&event)) {
|
|
60 if (event.type==SDL_QUIT) {
|
|
61 return true;
|
|
62 }
|
|
63 }
|
|
64
|
|
65 Uint8 *keys=SDL_GetKeyState(NULL);
|
|
66
|
|
67 if (keys[SDLK_q] == SDL_PRESSED) {
|
|
68 return true;
|
|
69 }
|
|
70
|
|
71 return false;
|
|
72 }
|
|
73
|
|
74 void
|
|
75 Viewer::quit(void)
|
|
76 {
|
|
77 SDL_Quit();
|
|
78 }
|
|
79
|
|
80 void
|
|
81 Viewer::swap_buffers(void)
|
|
82 {
|
|
83 SDL_GL_SwapBuffers();
|
|
84 }
|
|
85
|
|
86 extern void node_init(void);
|
|
87 extern void create_cube_split(int);
|
|
88 extern void panel_init(int);
|
|
89 extern void universe_init(void);
|
|
90 extern void ieshoot_init(void);
|
|
91 extern void ball_bound_init(int, int);
|
|
92 extern void lcube_init(int, int);
|
|
93 extern void direction_init(void);
|
|
94 extern void init_position(int, int);
|
|
95 extern void vacuum_init(int w, int h);
|
|
96 extern void untitled_init(void);
|
|
97 void
|
|
98 Viewer::run_init(const char *xml, int sg_number)
|
|
99 {
|
|
100 HTaskPtr task_next;
|
|
101 HTaskPtr task_tex;
|
|
102
|
|
103 start_time = get_ticks();
|
|
104 this_time = 0;
|
|
105 frames = 0;
|
|
106
|
|
107 sgroot = new SceneGraphRoot(this->width, this->height);
|
|
108 //sgroot->createFromXMLFile(xml);
|
|
109
|
|
110 switch (sg_number) {
|
|
111 case 0:
|
|
112 case 1:
|
|
113 create_cube_split(sg_number);
|
|
114 break;
|
|
115 case 2:
|
|
116 case 3:
|
|
117 case 4:
|
|
118 panel_init(sg_number);
|
|
119 break;
|
|
120 case 5:
|
|
121 universe_init();
|
|
122 break;
|
|
123 case 6:
|
|
124 ieshoot_init();
|
|
125 break;
|
|
126 case 7:
|
|
127 ball_bound_init(this->width, this->height);
|
|
128 break;
|
|
129 case 8:
|
|
130 lcube_init(this->width, this->height);
|
|
131 break;
|
|
132 case 9:
|
|
133 direction_init();
|
|
134 break;
|
|
135 case 10:
|
|
136 init_position(this->width, this->height);
|
|
137 break;
|
|
138 case 11:
|
|
139 vacuum_init(this->width, this->height);
|
|
140 break;
|
|
141 case 12:
|
|
142 untitled_init();
|
|
143 break;
|
|
144 default:
|
|
145 node_init();
|
|
146 break;
|
|
147 }
|
|
148
|
|
149 sgpack = (SceneGraphPack*)manager->allocate(sizeof(SceneGraphPack));
|
|
150 sgpack->init();
|
|
151 ppack = (PolygonPack*)manager->allocate(sizeof(PolygonPack));
|
|
152
|
|
153 spackList_length = (this->height + split_screen_h - 1) / split_screen_h;
|
|
154 spackList = (SpanPack*)manager->allocate(sizeof(SpanPack)*spackList_length);
|
|
155
|
|
156 /**
|
|
157 * SPU に送る address list は 16 バイト倍数でないといけない。
|
|
158 * spackList_length*sizeof(SpanPack*) が 16 バイト倍数になるような
|
|
159 * length_align を求めている。はみ出した部分は使われない
|
|
160 * (ex) spackList_length が 13 の場合
|
|
161 * spackList_length_align = 16;
|
|
162 * 実際に送るデータは64バイトになるのでOK
|
|
163 * 14,15,16 の部分は何も入らない。
|
|
164 */
|
|
165 spackList_length_align = (spackList_length + 3)&(~3);
|
|
166
|
|
167 /* 各 SPU が持つ、SpanPack の address list */
|
|
168 spackList_ptr =
|
|
169 (SpanPack**)manager->allocate(sizeof(SpanPack*)*spackList_length_align);
|
|
170
|
|
171 for (int i = 0; i < spackList_length; i++) {
|
|
172 spackList_ptr[i] = &spackList[i];
|
|
173 }
|
|
174
|
|
175 for (int i = 1; i <= spackList_length; i++) {
|
|
176 spackList[i-1].init(i*split_screen_h);
|
|
177 }
|
|
178
|
|
179 task_next = manager->create_task(TASK_DUMMY);
|
|
180
|
|
181
|
|
182 #if 0
|
|
183 // 諸事情で、今は SceneGraphPack を作らずに
|
|
184 // そのまま SceneGraph でやっています
|
|
185 HTaskPtr task_sgp;
|
|
186 task_sgp = manager->create_task(TASK_CREATE_SGP);
|
|
187 task_sgp->add_param((uint32)scene_graph);
|
|
188 task_sgp->add_param((uint32)sgpack);
|
|
189 task_next->wait_for(task_sgp);
|
|
190 task_sgp->spawn();
|
|
191 #endif
|
|
192
|
|
193 for (int i = 0; i < spe_num; i++) {
|
|
194 task_tex = manager->create_task(TASK_INIT_TEXTURE);
|
|
195 /*
|
|
196 * ここはもう少しわかりやすい使い方がいいかもしれぬ。こんなもん?
|
|
197 */
|
|
198 task_tex->set_cpu((CPU_TYPE)((int)SPE_0 + i));
|
|
199 task_next->wait_for(task_tex);
|
|
200 task_tex->spawn();
|
|
201 }
|
|
202
|
|
203 task_next->set_post(&post2runLoop, NULL); // set_post(function(this->run_loop()), NULL)
|
|
204 task_next->spawn();
|
|
205 // TASK_INIT_TEXTURE が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ
|
|
206 }
|
|
207
|
|
208 void
|
|
209 Viewer::run_loop(void)
|
|
210 {
|
|
211 HTaskPtr task_create_pp = NULL;
|
|
212 HTaskPtr task_create_sp = NULL;
|
|
213 HTaskPtr task_next;
|
|
214 bool quit_flg;
|
|
215
|
|
216 quit_flg = quit_check();
|
|
217
|
|
218 if (quit_flg == true) {
|
|
219 this_time = get_ticks();
|
|
220 run_finish();
|
|
221 return;
|
|
222 }
|
|
223
|
|
224 clean_pixels();
|
|
225
|
|
226 for (int i = 1; i <= spackList_length; i++) {
|
|
227 spackList[i-1].reinit(i*split_screen_h);
|
|
228 }
|
|
229
|
|
230 task_next = manager->create_task(TASK_DUMMY);
|
|
231
|
|
232
|
|
233 #if 0
|
|
234 // SceneGraphPack の update
|
|
235 HTaskPtr task_update_sgp = NULL;
|
|
236 task_update_sgp = manager->create_task(TASK_UPDATE_SGP);
|
|
237 task_update_sgp->add_inData(sgpack, sizeof(SceneGraphPack));
|
|
238 task_update_sgp->add_outData(sgpack, sizeof(SceneGraphPack));
|
|
239 task_update_sgp->add_param(width);
|
|
240 task_update_sgp->add_param(height);
|
|
241 task_next->wait_for(task_update_sgp);
|
|
242 task_update_sgp->spawn();
|
|
243 #else
|
|
244 sgroot->updateControllerState();
|
|
245 sgroot->allExecute(width, height);
|
|
246 //sgroot->checkRemove();
|
|
247 #endif
|
|
248
|
|
249 #if 0
|
|
250 // SceneGraphPack(配列) -> PolygonPack
|
|
251 task_create_pp = manager->create_task(TASK_CREATE_PP);
|
|
252 task_create_pp->add_inData(sgpack, sizeof(SceneGraphPack));
|
|
253 task_create_pp->add_param((uint32)ppack);
|
|
254 #else
|
|
255 // SceneGraph(木構造) -> PolygonPack
|
|
256 task_create_pp = manager->create_task(TASK_CREATE_PP2);
|
|
257 task_create_pp->add_param((uint32)sgroot->getDrawSceneGraph());
|
|
258 task_create_pp->add_param((uint32)ppack);
|
|
259 #endif
|
|
260 task_next->wait_for(task_create_pp);
|
|
261
|
|
262 int range_base = spe_num;
|
|
263 // 切り上げのつもり
|
|
264 int range = (spackList_length + range_base - 1) / range_base;
|
|
265
|
|
266 for (int i = 0; i < range_base; i++) {
|
|
267 int index_start = range*i;
|
|
268 int index_end = (index_start + range >= spackList_length)
|
|
269 ? spackList_length : index_start + range;
|
|
270
|
|
271 task_create_sp = manager->create_task(TASK_CREATE_SPAN);
|
|
272 task_create_sp->add_inData(ppack, sizeof(PolygonPack));
|
|
273 task_create_sp->add_inData(spackList_ptr,
|
|
274 sizeof(SpanPack*)*spackList_length_align);
|
|
275 task_create_sp->add_inData(&spackList[index_start], sizeof(SpanPack));
|
|
276
|
|
277 task_create_sp->add_param(index_start);
|
|
278
|
|
279 /**
|
|
280 * ex. screen_height が 480, spenum が 6 の場合、各SPEのy担当範囲
|
|
281 * [ 1.. 80] [ 81..160] [161..240]
|
|
282 * [241..320] [321..400] [401..480]
|
|
283 *
|
|
284 * ex. screen_height が 1080, spenum が 5 の場合、
|
|
285 * [ 1..216] [217..432] [433..648]
|
|
286 * [649..864] [865..1080]
|
|
287 */
|
|
288 task_create_sp->add_param(index_start*split_screen_h + 1);
|
|
289 task_create_sp->add_param(index_end*split_screen_h);
|
|
290
|
|
291 task_next->wait_for(task_create_sp);
|
|
292 task_create_sp->wait_for(task_create_pp);
|
|
293
|
|
294 task_create_sp->set_cpu(SPE_ANY);
|
|
295 task_create_sp->spawn();
|
|
296 }
|
|
297
|
|
298 task_create_pp->spawn();
|
|
299
|
|
300 // Barrier 同期
|
|
301 task_next->set_post(post2runDraw, NULL); // set_post(function(this->run_draw()), NULL)
|
|
302 task_next->spawn();
|
|
303 // TASK_CREATE_SPAN が全て終わったら DUMMY_TASK が Viewer::run_draw() を呼ぶ
|
|
304 }
|
|
305
|
|
306 void
|
|
307 Viewer::run_draw(void)
|
|
308 {
|
|
309 HTaskPtr task_next;
|
|
310 HTaskPtr task_draw;
|
|
311
|
|
312 task_next = manager->create_task(TASK_DUMMY);
|
|
313
|
|
314 ppack->clear();
|
|
315 for (int i = 0; i < spackList_length; i++) {
|
|
316 SpanPack *spack = &spackList[i];
|
|
317 int startx = 1;
|
|
318 int endx = split_screen_w;
|
|
319
|
|
320 int starty = spack->info.y_top - split_screen_h + 1;
|
|
321 //int endy = spack->info.y_top;
|
|
322 int rangey = (starty + split_screen_h - 1 > this->height)
|
|
323 ? this->height - starty + 1 : split_screen_h;
|
|
324
|
|
325 while (startx < this->width) {
|
|
326 if (spack->info.size > 0) {
|
|
327 // Draw SpanPack
|
|
328 task_draw = manager->create_task(TASK_DRAW_SPAN);
|
|
329 task_draw->add_inData(spack, sizeof(SpanPack));
|
|
330
|
|
331 task_draw->add_param(
|
|
332 (uint32)&pixels[(startx-1) + this->width*(starty-1)]);
|
|
333 task_draw->add_param(this->width);
|
|
334 } else {
|
|
335 #if 0
|
|
336 //break;
|
|
337 // Draw Background (現在は塗りつぶし)
|
|
338 task_draw = manager->create_task(TASK_DRAW_BACK);
|
|
339 task_draw->add_param(0xffffffff);
|
|
340
|
|
341 for (int k = 0; k < rangey; k++) {
|
|
342 task_draw->add_outData(
|
|
343 &pixels[(startx-1)+this->width*(k+starty-1)],
|
|
344 (endx - startx + 1)*sizeof(int));
|
|
345 }
|
|
346 #else
|
|
347 memset(&pixels[(startx-1)+this->width*(starty-1)],
|
|
348 0, (this->width)*sizeof(int)*rangey);
|
|
349 //wmemset((wchar_t*)&pixels[(startx-1)+this->width*(starty-1)],
|
|
350 //0xFFFFFFFF, (this->width)*sizeof(int)*rangey/sizeof(wchar_t));
|
|
351 break;
|
|
352 #endif
|
|
353 }
|
|
354
|
|
355 task_draw->add_param(startx);
|
|
356 task_draw->add_param(endx);
|
|
357 task_draw->add_param(rangey);
|
|
358 task_draw->set_cpu(SPE_ANY);
|
|
359 task_next->wait_for(task_draw);
|
|
360 task_draw->spawn();
|
|
361
|
|
362 startx += split_screen_w;
|
|
363 endx += split_screen_w;
|
|
364
|
|
365 if (endx > this->width) {
|
|
366 endx = this->width;
|
|
367 }
|
|
368 }
|
|
369 }
|
|
370
|
|
371 task_next->set_post(post2runLoop, NULL); // set_post(function(this->run_loop()), NULL)
|
|
372 task_next->spawn();
|
|
373 // TASK_DRAW_SPAN が全て終わったら DUMMY_TASK が Viewer::run_loop() を呼ぶ
|
|
374
|
|
375 frames++;
|
|
376 }
|
|
377
|
|
378 void
|
|
379 Viewer::run_finish(void)
|
|
380 {
|
|
381 if (this_time != start_time) {
|
|
382 printf("%f FPS\n", (((float)frames)/(this_time-start_time))*1000.0);
|
|
383 }
|
|
384
|
|
385 delete sgroot;
|
|
386
|
|
387 quit();
|
|
388 }
|