0
|
1 #include <stdlib.h>
|
|
2 #include <string.h>
|
|
3 #include "DrawSpan.h"
|
|
4 #include "polygon_pack.h"
|
|
5 #include "task_texture.h"
|
|
6 #include "viewer_types.h"
|
|
7 #include "Func.h"
|
|
8 #include "sys.h"
|
|
9 #include "SchedTask.h"
|
|
10 #include "Tapestry.h"
|
|
11 #include "SpanPack.h"
|
|
12
|
|
13 #if (__LITTLE_ENDIAN__)
|
|
14 #define LITTLEENDIAN 1
|
|
15 #else
|
|
16 #define LITTLEENDIAN 0
|
|
17 #endif
|
|
18
|
|
19 SchedDefineTask(DrawSpan);
|
|
20
|
|
21 #define TEX_LOAD1 0
|
|
22 #define TEX_LOAD2 1
|
|
23 #define SPAN_PACK_LOAD 2
|
|
24 #define FB_STORE 3
|
|
25
|
|
26 typedef struct {
|
|
27 int **linebuf;
|
|
28 float *zRow;
|
|
29 TileListPtr tileList;
|
|
30 int doneWrite;
|
|
31 } G, *Gptr;
|
|
32
|
|
33 static int** linebuf_init(SchedTask *smanager, int width, int height, int rgb);
|
|
34 static float* zRow_init(SchedTask *smanager, int width, int height);
|
|
35 // static TilePtr set_rgb(memaddr addr, int wait_tag);
|
|
36 // static void set_rgbs(memaddr addr, uint32 *max_addr, int wait_tag);
|
|
37 static uint32 get_rgb(int tx, int ty, TilePtr tile);
|
|
38 // static TilePtr isAvailableTile(memaddr addr);
|
|
39 static memaddr getTile(int tx, int ty, int tw, memaddr tex_addr_top);
|
|
40 static int getTexBlock(int tx, int ty, int twidth);
|
|
41
|
|
42 static void updateBuffer(Gptr g, float zpos, int rangex, int loaclx, int localy,
|
|
43 int tex_x, int tex_y, float normal_x, float nomral_x, float normal_z,
|
|
44 TilePtr tile, int world_x, int world_y, float world_z,SchedTask *smanager);
|
|
45
|
|
46 // static void reboot(SpanPackPtr spack, int cur_span_x);
|
|
47
|
|
48 static int drawDot1(SchedTask *smanager, Gptr g, SpanPtr span, int startx, int endx, int wait_tag);
|
|
49 //static void drawDot2(SchedTask *smanager, SpanPtr span, int startx, int endx, int js, int wait_tag);
|
|
50 static int drawLine1(SchedTask *smanager, Gptr g, SpanPtr span, int startx, int endx, int wait_tag);
|
|
51 // static void drawLine2(SchedTask *smanager, SpanPtr span, int startx, int endx, int js, int wait_tag);
|
|
52
|
|
53 static int infinity_light_calc(int color,float normal_x, float normal_y, float normal_z,
|
|
54 SchedTask *smanager,int x, int y, float z, int world_x, int world_y, float world_z);
|
|
55
|
|
56
|
|
57 static float
|
|
58 innerProduct1(float *v0, float *v1)
|
|
59 {
|
|
60 return (v0[0]*v1[0] + v0[1]*v1[1] + v0[2]*v1[2]);
|
|
61 }
|
|
62
|
|
63
|
|
64 /**
|
|
65 * テクスチャは、TEXTURE_SPLIT_PIXEL^2 のブロックに分割する
|
|
66 *
|
|
67 * +---+---+---+---+---+---+
|
|
68 * | 0 | 1 | 2 | 3 | 4 | 5 |
|
|
69 * +---+---+---+---+---+---+
|
|
70 * | | | | | |11 |
|
|
71 * +---+---+---+---+---+---+
|
|
72 * | | | | | |17 |
|
|
73 * +---+---+---+---+---+---+
|
|
74 * | | | | | |23 |
|
|
75 * +---+---+---+---+---+---+
|
|
76 * | | | | | |29 |
|
|
77 * +---+---+---+---+---+---+
|
|
78 * | | | | | |35 |
|
|
79 * +---+---+---+---+---+---+
|
|
80 *
|
|
81 * 一辺を TEXTURE_SPLIT とする
|
|
82 * 各ブロックの数字がブロックIDとなる。
|
|
83 */
|
|
84
|
|
85 /**
|
|
86 * テクスチャの座標から、
|
|
87 * テクスチャのどのブロックかを求める
|
|
88 *
|
|
89 * @param[in] tx X coordinates of texture
|
|
90 * @param[in] tx Y coordinates of texture
|
|
91 * @param[in] twidth Width of texture
|
|
92 * @return block ID
|
|
93 */
|
|
94 static int
|
|
95 getTexBlock(int tx, int ty, int twidth)
|
|
96 {
|
|
97 int blockX, blockY;
|
|
98
|
|
99 blockX = tx / TEXTURE_SPLIT_PIXEL;
|
|
100 blockY = ty / TEXTURE_SPLIT_PIXEL;
|
|
101
|
|
102 return blockX + (twidth/TEXTURE_SPLIT_PIXEL)*blockY;
|
|
103 }
|
|
104
|
|
105 /**
|
|
106 * block ID と、テクスチャの TOP address から
|
|
107 * (tx,ty) で使われるテクスチャの Tile addres を求める
|
|
108 *
|
|
109 * @param[in] tx X coordinates of texture
|
|
110 * @param[in] tx Y coordinates of texture
|
|
111 * @param[in] tw Width of texture
|
|
112 * @param[in] tex_addr_top (tx,ty) で使うテクスチャの先頭address
|
|
113 * @return block ID
|
|
114 */
|
|
115 static memaddr
|
|
116 getTile(int tx, int ty, int tw, memaddr tex_addr_top)
|
|
117 {
|
|
118 int block = getTexBlock(tx, ty, tw);
|
|
119 return tex_addr_top + block * TEXTURE_BLOCK_SIZE * sizeof(uint32);
|
|
120 }
|
|
121
|
|
122 /**
|
|
123 * FrameBuffer に書き込む rgb の領域初期化
|
|
124 *
|
|
125 * @param width Width of Buffer
|
|
126 * @param height Height of Buffer
|
|
127 * @param rgb Initial value of RGB at Buffer
|
|
128 * @return Buffer
|
|
129 */
|
|
130 static int **
|
|
131 linebuf_init(SchedTask *smanager, int width, int height, int rgb)
|
|
132 {
|
|
133 int **linebuf = (int**)smanager->allocate(height*sizeof(int*));
|
|
134 for(int h = 0;h<height;h++) {
|
|
135 int *buf = linebuf[h] = (int*)smanager->get_output(h);
|
|
136 for (int i = 0; i < width; i++) {
|
|
137 buf[i] = rgb;
|
|
138 }
|
|
139 }
|
|
140 return linebuf;
|
|
141 }
|
|
142
|
|
143 /**
|
|
144 * Z-Buffer の初期化
|
|
145 *
|
|
146 * @param width Width of Z-Buffer
|
|
147 * @param height Height of Z-Buffer
|
|
148 * @return Z-Buffer
|
|
149 */
|
|
150 static float*
|
|
151 zRow_init(SchedTask *smanager, int width, int height)
|
|
152 {
|
|
153 float *buf = (float*)smanager->allocate(sizeof(float)*width*height);
|
|
154 float def = 65535.0f;
|
|
155
|
|
156 for (int i = 0; i < width*height; i++) {
|
|
157 buf[i] = def;
|
|
158 }
|
|
159
|
|
160 return buf;
|
|
161 }
|
|
162
|
|
163
|
|
164 static uint32
|
|
165 get_rgb(int tx, int ty, TilePtr tile)
|
|
166 {
|
|
167 uint32 *data = (uint32 *)tile->data;
|
|
168 return data[(TEXTURE_SPLIT_PIXEL)*ty+tx];
|
|
169 }
|
|
170
|
|
171
|
|
172
|
|
173 /**
|
|
174 * zRow と Linebuf を更新する
|
|
175 *
|
|
176 * @param zpos 更新する pixel のZ座標
|
|
177 * @param rangex このタスクが処理する描画領域の x の長さ
|
|
178 * @param x pixel の、描画領域内での x 座標
|
|
179 * @param y 〃 の、y 座標
|
|
180 * @param tex_x pixel が使用するテクスチャの、Tile (8x8) 内での x 座標
|
|
181 * @param tex_y 〃 の y 座標
|
|
182 * @param tex_addr テクスチャのアドレス(MainMemory)
|
|
183 */
|
|
184 static void
|
|
185 updateBuffer(Gptr g, float zpos, int rangex, int localx, int localy, int tex_x, int tex_y,
|
|
186 float normal_x, float normal_y, float normal_z, TilePtr tile,
|
|
187 int world_x, int world_y, float world_z, SchedTask *smanager)
|
|
188 {
|
|
189
|
|
190 int color = get_rgb(tex_x, tex_y, tile);
|
|
191 /*下位4bitを抽出*/
|
|
192 #if LITTLEENDIAN
|
|
193 int alpha = color & 0x000000ff;
|
|
194 #else
|
|
195 int alpha = color & 0xff000000;
|
|
196 #endif
|
|
197
|
|
198 //int *light_sysswitch = (int*)smanager->global_get(LightSysSwitch);
|
|
199
|
|
200
|
|
201 /*完全に透けているか判断, 法線ベクトルが奥を向いてるかどうか*/
|
|
202 int flag = (alpha != 0 && normal_z < 0);
|
|
203
|
|
204 //printf("light_sysswitch %d\n",light_sysswitch);
|
|
205
|
|
206 //if ( *light_sysswitch == 1) {
|
|
207 if (flag) {
|
|
208 color = infinity_light_calc(color,normal_x,normal_y,normal_z,
|
|
209 smanager,localx,localy,zpos,
|
|
210 world_x,world_y,world_z);
|
|
211 }
|
|
212 //}
|
|
213
|
|
214 g->zRow[localx + (rangex*localy)] = zpos*flag + g->zRow[localx + (rangex*localy)]*(1-flag);
|
|
215 int *point = &g->linebuf[localy][localx] ;
|
|
216 *point = color*flag + *point *(1-flag);
|
|
217
|
|
218
|
|
219
|
|
220 }
|
|
221
|
|
222 /**
|
|
223 * 長さが 1 の Span の描画 (要するに 1 pixel)
|
|
224 *
|
|
225 * @param span Span
|
|
226 * @param startx 描画開始範囲
|
|
227 * @param endx 描画終了範囲
|
|
228 */
|
|
229 static int
|
|
230 drawDot1(SchedTask *smanager, Gptr g, SpanPtr span, int startx, int endx, int wait_tag)
|
|
231 {
|
|
232 int rangex = endx - startx + 1;
|
|
233
|
|
234 float normal_x = span->normal_x;
|
|
235 float normal_y = span->normal_y;
|
|
236 float normal_z = span->normal_z;
|
|
237
|
|
238
|
|
239 /* span->x に対応する Texture の座標 (tex_xpos, tex_ypos) */
|
|
240 int tex_xpos, tex_ypos;
|
|
241
|
|
242 // span の始点に対応する Texture の座標 (tex1, tey1)
|
|
243 float tex = span->tex_x1;
|
|
244 float tey = span->tex_y1;
|
|
245
|
|
246 // span の始点に対応する z 座標
|
|
247 float zpos = span->start_z;
|
|
248
|
|
249 /* Tile 内での座標 */
|
|
250 int localx = getLocalX(span->x-1);
|
|
251 int localy = getLocalY(span->y-1);
|
|
252
|
|
253 /**
|
|
254 * (tex_xpos, tex_ypos) の、Tile 内(上の図参照)での座標と
|
|
255 * そのブロックのアドレス(MainMemory)
|
|
256 */
|
|
257 int tex_localx;
|
|
258 int tex_localy;
|
|
259 memaddr tex_addr;
|
|
260
|
|
261 if (span->x < startx || endx < span->x) {
|
|
262 return -1;
|
|
263 }
|
|
264
|
|
265 tex_xpos = (int)((span->tex_width-1) * tex);
|
|
266 tex_ypos = (int)((span->tex_height-1) * tey);
|
|
267
|
|
268 if (zpos < g->zRow[localx + (rangex*localy)]) {
|
|
269 tex_addr = getTile(tex_xpos, tex_ypos,
|
|
270 span->tex_width, (memaddr)span->tex_addr);
|
|
271 tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
|
|
272 tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
|
|
273
|
|
274 TilePtr tile = smanager->get_segment(tex_addr,g->tileList);
|
|
275 smanager->wait_segment(tile);
|
|
276
|
|
277 updateBuffer(g, zpos, rangex, localx, localy,
|
|
278 tex_localx, tex_localy,
|
|
279 normal_x,normal_y,normal_z,tile,
|
|
280 span->x, span->y, zpos, smanager);
|
|
281 }
|
|
282
|
|
283 return -1;
|
|
284 }
|
|
285
|
|
286 #if 0
|
|
287 static void
|
|
288 drawDot2(SchedTask *smanager, SpanPtr span, int startx, int end, int js, int wait_tag)
|
|
289 {
|
|
290 //printf("%d\n", js);
|
|
291 }
|
|
292 #endif
|
|
293
|
|
294 /**
|
|
295 * 長さが 1 より大きい Span の描画
|
|
296 *
|
|
297 * 本来の目的として、この関数(drawLine1) では
|
|
298 * : 既に SPE 上に Tile のある pixel だけ描画
|
|
299 * : それ以外は、ここで予め DMA load しておき、
|
|
300 * : drawLine2 で一気に描画する
|
|
301 * ってものだったんだけど、どうも上手く行かなかったので
|
|
302 * 今は drawLine1 で load -> wait -> rendering を全部やってます
|
|
303 * (rendering といっても、rendering buffer に書き込むだけで
|
|
304 * まだ main memory (frame buffer) に dma store してるわけではない)
|
|
305 *
|
|
306 * @param span Span
|
|
307 * @param startx 描画開始範囲
|
|
308 * @param endx 描画終了範囲
|
|
309 * @return 「span のどの位置まで rendering が終わったか」の x 座標
|
|
310 */
|
|
311 static int
|
|
312 drawLine1(SchedTask *smanager, Gptr g, SpanPtr span, int startx, int endx, int wait_tag)
|
|
313 {
|
|
314 int x = span->x;
|
|
315 int rangex = endx - startx + 1;
|
|
316 int x_len = span->length_x;
|
|
317
|
|
318 float normal_x = span->normal_x;
|
|
319 float normal_y = span->normal_y;
|
|
320 float normal_z = span->normal_z;
|
|
321
|
|
322
|
|
323 int js = (x < startx) ? startx - x : 0;
|
|
324 int je = (x + x_len > endx) ? endx - x : x_len;
|
|
325
|
|
326 /* span->x に対応する Texture の座標 (tex_xpos, tex_ypos) */
|
|
327 int tex_xpos, tex_ypos;
|
|
328
|
|
329 // span の始点に対応する座標 (tex1, tey1)
|
|
330 float tex1 = span->tex_x1;
|
|
331 float tey1 = span->tex_y1;
|
|
332
|
|
333 // span の終点に対応する座標 (tex2, tey2)
|
|
334 float tex2 = span->tex_x2;
|
|
335 float tey2 = span->tex_y2;
|
|
336
|
|
337 // span の始点、終点に対応する z 座標
|
|
338 float zpos1 = span->start_z;
|
|
339 float zpos2 = span->end_z;
|
|
340
|
|
341 //spanを右から左に見ていくうちに、zが下がるのか、上がっていくのか。
|
|
342 float z_inclination = (zpos1 - zpos2) / x_len;
|
|
343 float world_z = zpos2;
|
|
344
|
|
345 // Tile 内での座標
|
|
346 int localx, localy = getLocalY(span->y-1);
|
|
347
|
|
348 int ret = je+1;
|
|
349
|
|
350 //for (int j = js; j <= je; j++) {
|
|
351 for (int j = je; j >= js; j--) {
|
|
352 float tex_x, tex_y, tex_z;
|
|
353
|
|
354 world_z += z_inclination;
|
|
355
|
|
356 localx = getLocalX(x-1+j);
|
|
357
|
|
358 tex_z = zpos1*(x_len-1-j)/(x_len-1) + zpos2*j/(x_len-1);
|
|
359
|
|
360 tex_x = tex1*(x_len-1-j)/(x_len-1) + tex2*j/(x_len-1);
|
|
361 tex_y = tey1*(x_len-1-j)/(x_len-1) + tey2*j/(x_len-1);
|
|
362 if (tex_x > 1) tex_x = 1;
|
|
363 if (tex_x < 0) tex_x = 0;
|
|
364 if (tex_y > 1) tex_y = 1;
|
|
365 if (tex_y < 0) tex_y = 0;
|
|
366 tex_xpos = (int)((span->tex_width-1) * tex_x);
|
|
367 tex_ypos = (int)((span->tex_height-1) * tex_y);
|
|
368
|
|
369 if (tex_z < g->zRow[localx + (rangex*localy)]) {
|
|
370 // (tex_xpos, tex_ypos) の、Tile 内(上の図参照)での座標と
|
|
371 // そのブロックのアドレス(MainMemory)
|
|
372 memaddr tex_addr;
|
|
373 int tex_localx;
|
|
374 int tex_localy;
|
|
375
|
|
376 tex_addr = getTile(tex_xpos, tex_ypos,
|
|
377 span->tex_width, (memaddr)span->tex_addr);
|
|
378 tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
|
|
379 tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
|
|
380 TilePtr tile = smanager->get_segment(tex_addr,g->tileList);
|
|
381 smanager->wait_segment(tile);
|
|
382
|
|
383 updateBuffer(g, tex_z, rangex, localx, localy,
|
|
384 tex_localx, tex_localy,
|
|
385 normal_x, normal_y, normal_z, tile,
|
|
386 span->x+j, span->y, world_z, smanager);
|
|
387 }
|
|
388 }
|
|
389
|
|
390 return ret;
|
|
391 }
|
|
392
|
|
393 static int
|
|
394 infinity_light_calc(int color,float normal_x, float normal_y,
|
|
395 float normal_z, SchedTask *smanager, int x, int y, float z,
|
|
396 int world_x, int world_y, float world_z)
|
|
397
|
|
398 {
|
|
399
|
|
400
|
|
401 unsigned char rgb[4];
|
|
402 int light_rgb;
|
|
403 int flag;
|
|
404 float normal_vector[4] = {normal_x,normal_y,normal_z,0};
|
|
405 float light_vector[4];
|
|
406 float inner_product;
|
|
407 float *light_xyz = (float*)smanager->global_get(Light);
|
|
408
|
|
409 normalize(normal_vector, normal_vector);
|
|
410
|
|
411 // 引数で受け取った color の rgb 情報の抜き出し
|
|
412 #if LITTLEENDIAN
|
|
413 rgb[0] = (color & 0xff000000) >> 24;
|
|
414 rgb[1] = (color & 0x00ff0000) >> 16;
|
|
415 rgb[2] = (color & 0x0000ff00) >> 8;
|
|
416 rgb[3] = (color & 0x000000ff);
|
|
417 #else
|
|
418 rgb[3] = (color & 0xff000000) >> 24;
|
|
419 rgb[2] = (color & 0x00ff0000) >> 16;
|
|
420 rgb[1] = (color & 0x0000ff00) >> 8;
|
|
421 rgb[0] = (color & 0x000000ff);
|
|
422 #endif
|
|
423
|
|
424 int tmp_rgb[3] = {0,0,0};
|
|
425 int light_num = 4;
|
|
426 for (int i = 0; i < light_num; i++) {
|
|
427
|
|
428
|
|
429 light_vector[0] = world_x - light_xyz[i*4];
|
|
430 light_vector[1] = world_y - light_xyz[i*4+1];
|
|
431 light_vector[2] = light_xyz[i*4+2] - world_z;
|
|
432 light_vector[3] = light_xyz[i*4+3];
|
|
433
|
|
434 normalize(light_vector, light_vector);
|
|
435
|
|
436 // 法線ベクトルと光源ベクトルとの内積をとる
|
|
437 inner_product = innerProduct1(normal_vector,light_vector);
|
|
438
|
|
439 //printf("inner_product %f\n",inner_product);
|
|
440
|
|
441 // 内積がマイナスの場合は色がない。
|
|
442 flag = (inner_product > 0);
|
|
443
|
|
444 // 内積を rgb にかけていく
|
|
445
|
|
446 tmp_rgb[0] += (unsigned char)(rgb[0]*inner_product*flag);
|
|
447 tmp_rgb[1] += (unsigned char)(rgb[1]*inner_product*flag);
|
|
448 tmp_rgb[2] += (unsigned char)(rgb[2]*inner_product*flag);
|
|
449
|
|
450 }
|
|
451
|
|
452 int rgb_flag[3];
|
|
453 for (int i = 0; i < 3; i++) {
|
|
454 rgb_flag[i] = (tmp_rgb[i] > 255);
|
|
455 }
|
|
456
|
|
457 rgb[0] = tmp_rgb[0]*(1 - rgb_flag[0]) + 255*(rgb_flag[0]);
|
|
458 rgb[1] = tmp_rgb[1]*(1 - rgb_flag[1]) + 255*(rgb_flag[1]);
|
|
459 rgb[2] = tmp_rgb[2]*(1 - rgb_flag[2]) + 255*(rgb_flag[2]);
|
|
460
|
|
461
|
|
462 //計算した rgb を light_rgb にまとめる。
|
|
463 #if LITTLEENDIAN
|
|
464 light_rgb = (rgb[0] << 24) + (rgb[1] << 16) + (rgb[2] << 8) + (rgb[3]);
|
|
465 #else
|
|
466 light_rgb = (rgb[3] << 24) + (rgb[2] << 16) + (rgb[1] << 8) + (rgb[0]);
|
|
467 #endif
|
|
468
|
|
469 return light_rgb;
|
|
470
|
|
471 }
|
|
472
|
|
473
|
|
474 static int
|
|
475 run(SchedTask *smanager, void *rbuf, void *wbuf)
|
|
476 {
|
|
477
|
|
478 //get_param(5) is spack->info.size
|
|
479 if ((long)smanager->get_param(5) == 0) {
|
|
480
|
|
481 int rangex_start = (long)smanager->get_param(2);
|
|
482 int rangex_end = (long)smanager->get_param(3);
|
|
483
|
|
484 int rangex = rangex_end - rangex_start + 1;
|
|
485 int rangey = (long)smanager->get_param(4);
|
|
486
|
|
487 for(int h = 0; h < rangey; h++) {
|
|
488 int *buf = (int*)smanager->get_output(h);
|
|
489 for (int i = 0; i < rangex; i++) {
|
|
490 buf[i] = 0;
|
|
491 }
|
|
492 }
|
|
493
|
|
494 return 0;
|
|
495
|
|
496 }
|
|
497
|
|
498
|
|
499 G g0;
|
|
500 Gptr g = &g0;
|
|
501
|
|
502 SpanPackPtr spack = (SpanPackPtr)smanager->get_input(0);
|
|
503 SpanPackPtr next_spack = (SpanPackPtr)smanager->allocate(sizeof(SpanPack));
|
|
504 SpanPackPtr free_spack = next_spack; // next_spack の free() 用
|
|
505 Span *span;
|
|
506
|
|
507 Span nop_span;
|
|
508 nop_span.length_x = 1;
|
|
509
|
|
510 // uint32 display = (long)smanager->get_param(0);
|
|
511 // int screen_width = (long)smanager->get_param(1);
|
|
512 int rangex_start = (long)smanager->get_param(2);
|
|
513 int rangex_end = (long)smanager->get_param(3);
|
|
514
|
|
515 // このタスクが担当する x の範囲
|
|
516 int rangex = rangex_end - rangex_start + 1;
|
|
517
|
|
518 // y の範囲
|
|
519 int rangey = (long)smanager->get_param(4);
|
|
520 g->tileList = (TileListPtr)smanager->global_get(GLOBAL_TILE_LIST);
|
|
521
|
|
522 g->zRow = zRow_init(smanager, rangex, rangey);
|
|
523 g->linebuf = linebuf_init(smanager, rangex, rangey, 0);
|
|
524
|
|
525 int tl_tag[2] = {TEX_LOAD1, TEX_LOAD2};
|
|
526 int tl_tag_flg1 = 0;
|
|
527 int tl_tag_flg2 = 1;
|
|
528
|
|
529 do {
|
|
530 /**
|
|
531 * SpanPack->next が存在する場合、
|
|
532 * 現在の SpanPack を処理してる間に
|
|
533 * 次の SpanPack の DMA 転送を行う
|
|
534 */
|
|
535 if (spack->next != NULL) {
|
|
536 smanager->dma_load(next_spack, (memaddr)spack->next,
|
|
537 sizeof(SpanPack), SPAN_PACK_LOAD);
|
|
538 } else {
|
|
539 next_spack = NULL;
|
|
540 }
|
|
541
|
|
542 SpanPtr resume_span = &nop_span;
|
|
543
|
|
544 for (int t = 0; t < spack->info.size; t++) {
|
|
545 SpanPtr next_span;
|
|
546
|
|
547 span = &spack->span[t];
|
|
548
|
|
549 if (span->length_x != 1) {
|
|
550 drawLine1(
|
|
551 smanager, g,
|
|
552 span, rangex_start, rangex_end, tl_tag[tl_tag_flg1]);
|
|
553 } else {
|
|
554 drawDot1(
|
|
555 smanager, g,
|
|
556 span, rangex_start, rangex_end, tl_tag[tl_tag_flg1]);
|
|
557 }
|
|
558 next_span = span;
|
|
559
|
|
560 resume_span = next_span;
|
|
561
|
|
562 tl_tag_flg1 ^= 1;
|
|
563 tl_tag_flg2 ^= 1;
|
|
564 }
|
|
565
|
|
566 smanager->dma_wait(SPAN_PACK_LOAD);
|
|
567
|
|
568 SpanPackPtr tmp_spack = spack;
|
|
569 spack = next_spack;
|
|
570 next_spack = tmp_spack;
|
|
571 } while (spack);
|
|
572
|
|
573
|
|
574 free(g->zRow);
|
|
575 free(g->linebuf);
|
|
576
|
|
577 //FINISH:
|
|
578 /**
|
|
579 * goto FINISH; の時は reboot なので
|
|
580 * linebuf, zRow は free() しない
|
|
581 */
|
|
582
|
|
583 free(free_spack);
|
|
584
|
|
585
|
|
586 return 0;
|
|
587 }
|
|
588
|
|
589 /* end */
|