diff TaskManager/Test/test_render/spe/DrawSpan.cpp @ 210:e75f9eb97180 draft

fix DrawSpan
author gongo@localhost.localdomain
date Fri, 30 Jan 2009 14:55:04 +0900
parents de235e3ef9d3
children 53cd9cf3ab99
line wrap: on
line diff
--- a/TaskManager/Test/test_render/spe/DrawSpan.cpp	Fri Jan 30 09:57:32 2009 +0900
+++ b/TaskManager/Test/test_render/spe/DrawSpan.cpp	Fri Jan 30 14:55:04 2009 +0900
@@ -7,11 +7,12 @@
 #include "viewer_types.h"
 #include "Func.h"
 
-#define SPAN_PACK_LOAD 0
-#define TEX_LOAD 1
-#define FB_STORE 2
+SchedDefineTask(DrawSpan);
 
-SchedDefineTask(DrawSpan);
+#define TEX_LOAD1      0
+#define TEX_LOAD2      1
+#define SPAN_PACK_LOAD 2
+#define FB_STORE       3
 
 DrawSpan::~DrawSpan(void)
 {
@@ -140,8 +141,8 @@
 	buf[i] = def;
     }
 #else 
-    vector float init = {0.0f, 0.0f, 0.0f, 0.0f};
-    vector float defi = {def, def, def, def};
+    vector float init = spu_splats(0.0f);
+    vector float defi = spu_splats(def);
 
     for (int i = 0; i < width*height; i += 4) {
 	vector float *out = (vector float *)&buf[i];
@@ -167,10 +168,14 @@
 }
 
 void
-DrawSpan::set_rgb(uint32 *addr)
+DrawSpan::set_rgb(uint32 *addr, int tag)
 {
     TilePtr tile;
 
+    if (isAvailableTile(addr)) {
+	return;
+    }
+
     tile = tileList->nextTile();
     /**
      * FIFO なので、もし前のが残っていれば削除
@@ -179,23 +184,37 @@
     
     tile->texture_addr = addr;
     
-    hash->put(tile->texture_addr, tile);
-    
+    int index = hash->put(tile->texture_addr, tile);
     smanager->dma_load(tile->pixel, (uint32)addr,
-		       sizeof(uint32)*TEXTURE_BLOCK_SIZE, TEX_LOAD);
+		       sizeof(uint32)*TEXTURE_BLOCK_SIZE, tag);
 }
 
+/**
+ * 
+ */
 void
-DrawSpan::set_rgbs(uint32 *addr, uint32 *max_addr)
+DrawSpan::set_rgbs(uint32 *cur_addr, uint32 *max_addr, int wait_tag)
 {
-    uint32 start = (uint32)addr;
-    uint32 end = (uint32)max_addr;
-    int length = (int)end-start;
-    int diff = sizeof(int)*TEXTURE_BLOCK_SIZE;
-    int max_tile = 16;
+    uint32 curp   = (uint32)cur_addr;
+    uint32 maxp   = (uint32)max_addr;
+    uint32 startp = curp;
+    uint32 diff   = sizeof(int)*TEXTURE_BLOCK_SIZE;
+    int length = (int)maxp-(int)curp;
+
+    int cmp = (length < 0);
 
-    for (int i = 0, j = 0; i <= length && j < max_tile; i += diff, j++) {
-	set_rgb((uint32*)(start + i));
+#if 1
+    length += cmp*(-1)*length*2;
+    startp = cmp*maxp + !cmp*curp;
+#else
+    if (length < 0) {
+	length = -length;
+	startp = maxp;
+    }
+#endif
+
+    for (int i = 0; i <= length; i += diff) {
+	set_rgb((uint32*)(startp + i), wait_tag);
     }
 }
 
@@ -269,14 +288,35 @@
 }
 
 /**
+ * zRow と Linebuf を更新する
+ *
+ * @param zpos     更新する pixel のZ座標
+ * @param rangex   このタスクが処理する描画領域の x の長さ
+ * @param x        pixel の、描画領域内での x 座標
+ * @param y        〃 の、y 座標
+ * @param tex_x    pixel が使用するテクスチャの、Tile (8x8) 内での x 座標
+ * @param tex_y    〃 の y 座標
+ * @param tex_addr テクスチャのアドレス(MainMemory)
+ */
+void
+DrawSpan::updateBuffer(float zpos, int rangex, int x, int y,
+		       int tex_x, int tex_y, uint32 *tex_addr)
+{
+    int rgb = get_rgb(tex_x, tex_y, tex_addr);
+		    
+    zRow[x + (rangex*y)] = zpos;
+    linebuf[x + (rangex*y)] = rgb;
+}
+
+/**
  * 長さが 1 の Span の描画 (要するに 1 pixel)
  *
  * @param span Span
  * @param startx 描画開始範囲
  * @param endx 描画終了範囲
  */
-void
-DrawSpan::drawDot(SpanPtr span, int startx, int endx)
+int
+DrawSpan::drawDot1(SpanPtr span, int startx, int endx, int wait_tag)
 {
     int rangex = endx - startx + 1;
 
@@ -303,7 +343,7 @@
     uint32 *tex_addr;
 
     if (span->x < startx || endx < span->x) {
-	return;
+	return -1;
     }
 
     tex_xpos = (int)((span->tex_width-1) * tex);
@@ -316,19 +356,26 @@
 	tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
 
 	if (!isAvailableTile(tex_addr)) {
-	    set_rgb(tex_addr);
-	    smanager->dma_wait(TEX_LOAD);
+	    set_rgb(tex_addr, wait_tag);
+	    smanager->dma_wait(wait_tag);
+	    //return startx;
 	}
 
-	int rgb = get_rgb(tex_localx, tex_localy, tex_addr);
-		    
-	zRow[localx + (rangex*localy)] = zpos;
-	linebuf[localx + (rangex*localy)] = rgb;
+	updateBuffer(zpos, rangex, localx, localy,
+		     tex_localx, tex_localy, tex_addr);
     }
+
+    return -1;
 }
 
 void
-DrawSpan::drawLine(SpanPtr span, int startx, int endx)
+DrawSpan::drawDot2(SpanPtr span, int startx, int end, int js, int wait_tag)
+{
+    //printf("%d\n", js);
+}
+
+int
+DrawSpan::drawLine1(SpanPtr span, int startx, int endx, int wait_tag)
 {
     int x = span->x;
     int rangex = endx - startx + 1;
@@ -355,6 +402,97 @@
     // Tile 内での座標
     int localx, localy = getLocalY(span->y-1);
 
+    int ret = je+1;
+
+    //for (int j = js; j <= je; j++) {
+    for (int j = je; j >= js; j--) {
+	float tex_x, tex_y, tex_z;
+
+	localx = getLocalX(x-1+j);
+
+	tex_z = zpos1*(x_len-1-j)/(x_len-1) + zpos2*j/(x_len-1);
+
+	tex_x = tex1*(x_len-1-j)/(x_len-1) + tex2*j/(x_len-1);
+	tex_y = tey1*(x_len-1-j)/(x_len-1) + tey2*j/(x_len-1);
+	if (tex_x > 1) tex_x = 1;
+	if (tex_x < 0) tex_x = 0;
+	if (tex_y > 1) tex_y = 1;
+	if (tex_y < 0) tex_y = 0;
+	tex_xpos = (int)((span->tex_width-1) * tex_x);
+	tex_ypos = (int)((span->tex_height-1) * tex_y);
+		    
+	if (tex_z < zRow[localx + (rangex*localy)]) {
+	    // (tex_xpos, tex_ypos) の、Tile 内(上の図参照)での座標と
+	    // そのブロックのアドレス(MainMemory)
+	    uint32 *tex_addr;
+	    int tex_localx;
+	    int tex_localy;
+
+	    tex_addr = getTile(tex_xpos, tex_ypos,
+			       span->tex_width, span->tex_addr);
+	    tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
+	    tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
+
+	    set_rgb(tex_addr, wait_tag);
+	    ret = j;
+	    continue;
+
+	    if (!isAvailableTile(tex_addr)) {
+#if 1
+		tex_x = tex1*(x_len-1-js)/(x_len-1) + tex2*js/(x_len-1);
+		if (tex_x > 1) tex_x = 1;
+		if (tex_x < 0) tex_x = 0;
+		tex_xpos = (int)((span->tex_width-1) * tex_x);
+
+		uint32 *max_addr = getTile(tex_xpos, tex_ypos,
+					   span->tex_width, span->tex_addr);
+
+		set_rgbs(tex_addr, max_addr, wait_tag);
+		return js;
+#else
+		set_rgb(tex_addr, wait_tag);
+		ret = j;
+		//j -= 3;
+		continue;
+#endif
+	    }
+
+	    updateBuffer(tex_z, rangex, localx, localy,
+			 tex_localx, tex_localy, tex_addr);
+	}
+    }
+
+    return ret;
+}
+
+void
+DrawSpan::drawLine2(SpanPtr span, int startx, int endx, int js, int wait_tag)
+{
+    int x = span->x;
+    int rangex = endx - startx + 1;
+    int x_len = span->length_x;
+
+    //int js = startx;
+    int je = (x + x_len > endx) ? endx - x : x_len;
+
+    /* span->x に対応する Texture の座標 (tex_xpos, tex_ypos) */
+    int tex_xpos, tex_ypos;
+
+    // span の始点に対応する座標 (tex1, tey1)
+    float tex1 = span->tex_x1;
+    float tey1 = span->tex_y1;
+
+    // span の終点に対応する座標 (tex2, tey2)
+    float tex2 = span->tex_x2;
+    float tey2 = span->tex_y2;
+
+    // span の始点、終点に対応する z 座標
+    float zpos1 = span->start_z;
+    float zpos2 = span->end_z;
+
+    // Tile 内での座標
+    int localx, localy = getLocalY(span->y-1);
+
     // (tex_xpos, tex_ypos) の、Tile 内(上の図参照)での座標と
     // そのブロックのアドレス(MainMemory)
     int tex_localx;
@@ -363,7 +501,8 @@
 
     float tex_x, tex_y, tex_z;
 
-#if 0
+    smanager->dma_wait(wait_tag);
+
     for (int j = js; j <= je; j++) {
 	localx = getLocalX(x-1+j);
 
@@ -377,134 +516,17 @@
 	if (tex_y < 0) tex_y = 0;
 	tex_xpos = (int)((span->tex_width-1) * tex_x);
 	tex_ypos = (int)((span->tex_height-1) * tex_y);
-		    
+
 	if (tex_z < zRow[localx + (rangex*localy)]) {
 	    tex_addr = getTile(tex_xpos, tex_ypos,
 			       span->tex_width, span->tex_addr);
 	    tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
 	    tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
 
-	    /**
-	     * Tile が無い場合、一旦タスクはここで中断し、
-	     * Tile をロードするタスクを走らせた後に再起動する
-	     */
-	    if (!isAvailableTile(tex_addr)) {
-		set_rgb(tex_addr);
-		smanager->dma_wait(TEX_LOAD);
-	    }
-			
-	    int rgb = get_rgb(tex_localx, tex_localy, tex_addr);
-
-	    zRow[localx + (rangex*localy)] = tex_z;
-	    linebuf[localx + (rangex*localy)] = rgb;
+	    updateBuffer(tex_z, rangex, localx, localy,
+			 tex_localx, tex_localy, tex_addr);
 	}
-    }
-#else
-    for (int j = js; j <= je; j += 4) {
-	vector signed int vec_offset_i = {j, j+1, j+2, j+3};
-	vector float vec_offset_f = {j, j+1, j+2, j+3};
-	vector float len1 = spu_splats((float)(x_len-1));
-	vector float len2 = spu_sub(len1, vec_offset_f);
-
-	vector float vec_zpos1 = spu_splats(zpos1);
-	vector float vec_zpos2 = spu_splats(zpos2);
-	vector float vec_tex1 = spu_splats(tex1);
-	vector float vec_tex2 = spu_splats(tex2);;
-	vector float vec_tey1 = spu_splats(tey1);
-	vector float vec_tey2 = spu_splats(tey2);
-
-	vector float vec_tex_x;
-	vector float vec_tex_y;
-	vector float vec_tex_z;
-
-	// localx = getLocalX(x-1+j);
-	vector signed int vec_localx
-	    = getLocalXVec(spu_add(spu_splats(x-1), vec_offset_i));
-	vector signed int vec_localy = spu_splats(localy);
-
-	// tex_z = zpos1*(x_len-1-j)/(x_len-1) + zpos2*j/(x_len-1);
-	vec_tex_z = spu_madd(spu_mul(vec_zpos1, len2), spu_re_nrm(len1),
-			     spu_mul(spu_mul(vec_zpos2, vec_offset_f),
-				     spu_re_nrm(len1)));
-
-	// tex_x = tex1*(x_len-1-j)/(x_len-1) + tex2*j/(x_len-1);
-	vec_tex_x = spu_madd(spu_mul(vec_tex1, len2), spu_re_nrm(len1),
-			     spu_mul(spu_mul(vec_tex2, vec_offset_f),
-				     spu_re_nrm(len1)));
-
-	//tex_y = tey1*(x_len-1-j)/(x_len-1) + tey2*j/(x_len-1);
-	vec_tex_y = spu_madd(spu_mul(vec_tey1, len2), spu_re_nrm(len1),
-			     spu_mul(spu_mul(vec_tey2, vec_offset_f),
-				     spu_re_nrm(len1)));
-
-#if 0
-	{
-	    vector float ov1 = spu_splats(1.0f);
-	    vector float ov0 = spu_splats(0.0f);
-
-	    // spu_cmpgt() true = 0xffffffff, false = 0x00000000
-	    vector unsigned int ovflag_1 = spu_cmpgt(vec_tex_x, ov1);
-	    vector unsigned int ovflag_0 = spu_cmpgt(vec_tex_x, ov0);
-
-	    // *_t = 0xffffffff を 1 に変換
-	    // *_f = spu_cmpgt() の 論理否定 vector
-	    //       {0, 1, 0, 1} => {1, 0, 1, 0}
-	    //       *_t 同様 0xffffffff => 1 に変換
-	    vector signed int ovflag_1_t = spu_and(ovflag_1, 0x1);
-	    vector signed int ovflag_1_f
-		= spu_and(spu_nor(ovflag_1, ovflag_1), 0x1);
-
-	    for (int h = 0; h < 4; h++) {
-		signed int fl = spu_extract(ovflag_1_f, h);
-		//float x = spu_extract((spu_mul(vec_tex_x, (vector float)ovflag_1_t)), h);
-		printf("[%d] %f %d\n", h, 3.3, fl);
-	    }
-
-	    vector unsigned int ovflag_0_t = spu_and(ovflag_0, 0x1);
-
-	    //vec_tex_x = spu_add(spu_mul(ov1, (vector float)ovflag_1_t),
-	    //spu_mul(vec_tex_x, (vector float)ovflag_1_f));
-	    //vec_tex_x = spu_mul(vec_tex_x, (vector float)ovflag_0_t);
-	}
-#endif
-	int cnt = (je - j > 4) ? 4 : je - j + 1;
-	
-	for (int i = 0; i < cnt; i++) {
-	    tex_x = spu_extract(vec_tex_x, i);
-	    tex_y = spu_extract(vec_tex_y, i);
-	    tex_z = spu_extract(vec_tex_z, i);
-	    localx = spu_extract(vec_localx, i);
-
-	    if (tex_x > 1) tex_x = 1;
-	    if (tex_x < 0) tex_x = 0;
-	    if (tex_y > 1) tex_y = 1;
-	    if (tex_y < 0) tex_y = 0;
-	    tex_xpos = (int)((span->tex_width-1) * tex_x);
-	    tex_ypos = (int)((span->tex_height-1) * tex_y);
-
-	    if (tex_z < zRow[localx + (rangex*localy)]) {
-		tex_addr = getTile(tex_xpos, tex_ypos,
-				   span->tex_width, span->tex_addr);
-		tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
-		tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
-		
-		/**
-		 * Tile が無い場合、一旦タスクはここで中断し、
-		 * Tile をロードするタスクを走らせた後に再起動する
-		 */
-		if (!isAvailableTile(tex_addr)) {
-		    set_rgb(tex_addr);
-		    smanager->dma_wait(TEX_LOAD);
-		}
-		
-		int rgb = get_rgb(tex_localx, tex_localy, tex_addr);
-		
-		zRow[localx + (rangex*localy)] = tex_z;
-		linebuf[localx + (rangex*localy)] = rgb;
-	    }
-	}
-    }
-#endif
+    }    
 }
 
 int
@@ -515,15 +537,22 @@
     SpanPackPtr free_spack = next_spack; // next_spack の free() 用
     Span *span;
 
-    void (DrawSpan::*drawFunc[2])(SpanPtr, int, int) = {
-	&DrawSpan::drawDot, &DrawSpan::drawLine
+    Span nop_span;
+    nop_span.length_x = 1;
+
+    int (DrawSpan::*drawFunc1[2])(SpanPtr, int, int, int) = {
+	&DrawSpan::drawDot1, &DrawSpan::drawLine1
+    };
+
+    void (DrawSpan::*drawFunc2[2])(SpanPtr, int, int, int, int) = {
+	&DrawSpan::drawDot2, &DrawSpan::drawLine2
     };
 
     uint32 display   = smanager->get_param(0);
     int screen_width = smanager->get_param(1);
     int rangex_start = smanager->get_param(2);
     int rangex_end   = smanager->get_param(3); 
-
+    
     // このタスクが担当する x の範囲
     int rangex = rangex_end - rangex_start + 1;
 
@@ -537,6 +566,10 @@
     linebuf = linebuf_init(rangex, rangey, 0x00ffffff);
 
     doneWrite = 0;
+
+    int tl_tag[2] = {TEX_LOAD1, TEX_LOAD2};
+    int tl_tag_flg1 = 0;
+    int tl_tag_flg2 = 1;
     
     do {
 	/**
@@ -551,13 +584,36 @@
 	    next_spack = NULL;
 	}
 
+	SpanPtr resume_span = &nop_span;
+	int resume_span_x = 0;
+
 	for (int t = 0; t < spack->info.size; t++) {	  
+	    SpanPtr next_span;
+	    int next_span_x;
+
 	    span = &spack->span[t];
 
-	    int x_len = span->length_x;
+	    next_span_x
+		= (this->*drawFunc1[(span->length_x != 1)])(
+		    span, rangex_start, rangex_end, tl_tag[tl_tag_flg1]);
+	    next_span = span;
+
+	    (this->*drawFunc2[(resume_span->length_x != 1)])(
+		resume_span, rangex_start, rangex_end, resume_span_x,
+		tl_tag[tl_tag_flg2]);
 
-	    (this->*drawFunc[(x_len != 1)])(span, rangex_start, rangex_end);
+	    resume_span = next_span;
+	    resume_span_x = next_span_x;
+	    
+	    //smanager->dma_wait(tl_tag[tl_tag_flg1]);
+
+	    tl_tag_flg1 ^= 1;
+	    tl_tag_flg2 ^= 1;
 	}
+	
+	(this->*drawFunc2[(resume_span->length_x != 1)])(
+	    resume_span, rangex_start, rangex_end, resume_span_x,
+	    tl_tag[tl_tag_flg1]);
 
 	smanager->dma_wait(SPAN_PACK_LOAD);
 
@@ -573,12 +629,12 @@
     //free(linebuf);
     free(zRow);
 
-FINISH:
+//FINISH:
     /**
      * goto FINISH; の時は reboot なので
      * linebuf, zRow は free() しない
      */
+
     free(free_spack);
-
     return 0;
 }