diff TaskManager/Test/test_render/spe/DrawSpan.cpp @ 184:a19d3ed4ce5b draft

fix
author gongo@gendarme.cr.ie.u-ryukyu.ac.jp
date Tue, 06 Jan 2009 15:39:48 +0900
parents 8e9ada0c1ed0
children 06cdf8baa989
line wrap: on
line diff
--- a/TaskManager/Test/test_render/spe/DrawSpan.cpp	Tue Dec 23 16:27:07 2008 +0900
+++ b/TaskManager/Test/test_render/spe/DrawSpan.cpp	Tue Jan 06 15:39:48 2009 +0900
@@ -2,19 +2,15 @@
 #include <string.h>
 #include "DrawSpan.h"
 #include "polygon_pack.h"
-#include "SpanPack.h"
 #include "texture.h"
 #include "viewer_types.h"
-#include "TileHash.h"
+#include "Func.h"
 
 #define SPAN_PACK_LOAD 0
 #define TEX_LOAD 1
 
 SchedDefineTask(DrawSpan);
 
-static TileHashPtr hash;
-static TileListPtr tileList;
-
 /**
  * テクスチャは、TEXTURE_SPLIT_PIXEL^2 のブロックに分割する
  *
@@ -45,8 +41,8 @@
  * @param[in] twidth  Width of texture
  * @return block ID
  */
-static inline int
-get_tex_block(int tx, int ty, int twidth)
+int
+DrawSpan::getTexBlock(int tx, int ty, int twidth)
 {
      int blockX, blockY;
 
@@ -66,10 +62,10 @@
  * @param[in] tex_addr_top (tx,ty) で使うテクスチャの先頭address
  * @return block ID
  */
-static inline uint32*
-getTile(int tx, int ty, int tw, uint32 *tex_addr_top)
+uint32*
+DrawSpan::getTile(int tx, int ty, int tw, uint32 *tex_addr_top)
 {
-    int block = get_tex_block(tx, ty, tw);
+    int block = getTexBlock(tx, ty, tw);
     return tex_addr_top + block*TEXTURE_BLOCK_SIZE;
 }
 
@@ -81,54 +77,115 @@
     }
 }
 
+/**
+ * Span が使う Texture Tile があるか
+ *
+ * @retval != NULL 存在する
+ * @retval NULL    存在しない
+ */
+TilePtr
+DrawSpan::isAvailableTile(uint32 *addr)
+{
+    return hash->get(addr);
+}
+
+void
+DrawSpan::set_rgb(uint32 *addr)
+{
+    TilePtr tile;
+
+    if (!isAvailableTile(addr)) {
+	tile = tileList->nextTile();
+	/**
+	 * FIFO なので、もし前のが残っていれば削除
+	 */
+	hash->remove(tile->texture_addr);
+	
+	tile->texture_addr = addr;
+	
+	hash->put(tile->texture_addr, tile);
+	
+	smanager->dma_load(tile->pixel, (uint32)addr,
+			   sizeof(uint32)*TEXTURE_BLOCK_SIZE, TEX_LOAD);
+	
+	smanager->dma_wait(TEX_LOAD);
+    }
+}
+
+void
+DrawSpan::set_rgbs(uint32 *addr, uint32 *max_addr)
+{
+    uint32 start = (uint32)addr;
+    uint32 end = (uint32)max_addr;
+    uint32 length = end-start;
+    uint32 diff = sizeof(uint32)*TEXTURE_BLOCK_SIZE;
+    uint32 max_tile = 8;
+    
+    for (uint32 i = 0, j = 0; i <= length && j < max_tile; i += diff, j++) {
+	set_rgb((uint32*)(start + i));
+    }
+}
+
 Uint32
 DrawSpan::get_rgb(int tx, int ty, uint32 *addr)
 {
     TilePtr tile;
 
     tile = hash->get(addr);
-    if (tile == NULL) {
-	tile = tileList->nextTile();
-
-	/**
-	 * FIFO なので、もし前のが残っていれば削除
-	 */
-	hash->remove(tile->texture_addr);
-
-	tile->texture_addr = addr;
-
-	smanager->dma_load(tile->pixel, (uint32)addr,
-			   sizeof(uint32)*TEXTURE_BLOCK_SIZE, TEX_LOAD);
-
-	int index = hash->put(tile->texture_addr, tile);
-
-	/**
-	 * TODO:
-	 *   入らなかったやつは
-	 *   今までのやつを描画してから続きをするとか
-	 */
-	if (index < 0) {
-	    printf("[%p] Can't entry\n", tile);
-	    return 0xff0000;
-	}
-
-	smanager->dma_wait(TEX_LOAD);
-    }
-
     return tile->pixel[(TEXTURE_SPLIT_PIXEL)*ty+tx];
 }
 
+/**
+ * DrawSpan の再起動 (DrawSpanRenew 生成)
+ *
+ * @param[in] spack 現在処理している SpanPack
+ * @param[in] cur_span_x span->length_x != 1 の時の Span の処理で
+ *                       どこまで進んでいるか
+ */
+void
+DrawSpan::reboot(SpanPackPtr spack, int cur_span_x)
+{
+    TaskPtr renew_task = smanager->create_task(TASK_DRAW_SPAN2);
+    int rangey = smanager->get_param(2);
 
+    /**
+     * 共通の outData, param はそのまま渡す
+     */
+    for (int i = 0; i < rangey; i++) {
+	renew_task->add_outData(smanager->get_outputAddr(i),
+			   smanager->get_outputSize(i));
+    }
+
+    // rangex_start, rangex_end, rangey
+    renew_task->add_param(smanager->get_param(0));
+    renew_task->add_param(smanager->get_param(1)); 
+    renew_task->add_param(smanager->get_param(2));
+
+    /**
+     * SpanPack は続きから開始するので、
+     * 現在の状態をコピーしておく。
+     * spack は rbuf から取得してる可能性があり
+     * rbuf はシステムが自動的に free() するため
+     * アドレスだけ渡すのはNG
+     */ 
+    SpanPackPtr curr = (SpanPackPtr)smanager->allocate(sizeof(SpanPack));
+    memcpy(curr, spack, sizeof(SpanPack));
+    renew_task->add_param((int)curr);
+
+    renew_task->add_param(cur_span_x);
+
+    /**
+     * 再起動したタスクを待つ
+     */ 
+    smanager->wait_task(renew_task);
+
+    // next_spack は free() するので wait する
+    smanager->dma_wait(SPAN_PACK_LOAD);
+}
 
 int
 DrawSpan::run(void *rbuf, void *wbuf)
 {
-    SpanPack *spack = (SpanPack*)smanager->get_input(0);
-    SpanPack *next_spack =
-	(SpanPack*)smanager->allocate(sizeof(SpanPack));
-    SpanPack *free_spack = next_spack; // next_spack の free() 用
-    Span *span;
-
     hash = (TileHashPtr)smanager->global_get(GLOBAL_TEXTURE_HASH);
     tileList = (TileListPtr)smanager->global_get(GLOBAL_TILE_LIST);
 
@@ -141,7 +198,12 @@
     // y の範囲 (render_y + rangey - 1)
     int rangey        = smanager->get_param(2);
     
-    float *zRow = (float*)smanager->get_input(1);
+    float *zRow = (float*)smanager->allocate(sizeof(float)*rangex*rangey);
+
+    for (int i = 0; i < rangex*rangey; i++) {
+	zRow[i] = 65535.0f;
+    }
+
     int **linebuf = (int**)smanager->allocate(sizeof(int*)*rangey);
 
     for (int i = 0; i < rangey; i++) {
@@ -149,6 +211,11 @@
 	linebuf_init(linebuf[i], rangex, 0xffffffff);
     }
 
+    SpanPackPtr spack = (SpanPackPtr)smanager->get_input(0);
+    SpanPackPtr next_spack = (SpanPackPtr)smanager->allocate(sizeof(SpanPack));
+    SpanPackPtr free_spack = next_spack; // next_spack の free() 用
+    Span *span;
+
     do {
 	/**
 	 * SpanPack->next が存在する場合、
@@ -210,6 +277,20 @@
 		    tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
 		    tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
 		    
+		    /**
+		     * Tile が無い場合、一旦タスクはここで中断し、
+		     * Tile をロードするタスクを走らせた後に再起動する
+		     */
+		    if (!isAvailableTile(tex_addr)) {
+			spack->info.start = t;
+			//set_rgb(tex_addr);
+			set_rgbs(tex_addr,
+				 getTile(span->tex_width-1, tex_ypos,
+					 span->tex_width, span->tex_addr));
+			reboot(spack, 0);
+			goto FINISH;
+		    }
+
 		    rgb = get_rgb(tex_localx, tex_localy, tex_addr);
 
 		    zRow[localx + (rangex * localy)] = zpos;
@@ -239,6 +320,16 @@
 					   span->tex_width, span->tex_addr);
 			tex_localx = tex_xpos % TEXTURE_SPLIT_PIXEL;
 			tex_localy = tex_ypos % TEXTURE_SPLIT_PIXEL;
+
+			if (!isAvailableTile(tex_addr)) {
+			    spack->info.start = t;
+			    //set_rgb(tex_addr);
+			    set_rgbs(tex_addr,
+				     getTile(span->tex_width-1, tex_ypos,
+					     span->tex_width, span->tex_addr));
+			    reboot(spack, j);
+			    goto FINISH;
+			}
 			
 			rgb = get_rgb(tex_localx, tex_localy, tex_addr);
 		    
@@ -251,11 +342,13 @@
 
 	smanager->dma_wait(SPAN_PACK_LOAD);
 
-	SpanPack *tmp_spack = spack;
+	SpanPackPtr tmp_spack = spack;
 	spack = next_spack;
 	next_spack = tmp_spack;
     } while (spack);
 
+
+FINISH:
     free(free_spack);
     free(linebuf);