diff TaskManager/Test/test_render/spe/DrawSpan.cpp @ 128:776eca0daa02

texture load use hash table
author gongo@charles.cr.ie.u-ryukyu.ac.jp
date Tue, 25 Nov 2008 15:52:28 +0900
parents 7635f223fc7d
children 805d27efafd8
line wrap: on
line diff
--- a/TaskManager/Test/test_render/spe/DrawSpan.cpp	Tue Nov 25 12:22:03 2008 +0900
+++ b/TaskManager/Test/test_render/spe/DrawSpan.cpp	Tue Nov 25 15:52:28 2008 +0900
@@ -11,7 +11,64 @@
 
 SchedDefineTask(DrawSpan);
 
-unsigned char *tex;
+static const int hashsize = 263;
+
+static TilePtr hash_table[hashsize] = {NULL};
+
+unsigned short PRIME[8] = {
+    0x002, 0x065, 0x0c7, 0x133, 0x191, 0x1f3, 0x259, 0x2bd,
+};
+
+static TileListPtr tileList;
+
+static int
+hash(uint32 data)
+{
+    int value = 0;
+    int n = 0;
+    int key;
+
+    for (int i = 0; i < 8; i ++) {
+	key = data & 0xf;
+	value += key * PRIME[n++];
+	data >>= 4;
+    }
+
+    return value % hashsize;
+}
+
+static int
+put(void *key, TilePtr data)
+{
+    int hashval = hash((uint32)key);
+
+    for (int i = 0; i < hashsize/2; i++) {
+	int index = (hashval + i*i)%hashsize;
+
+	if (hash_table[index] == 0) {
+	    hash_table[index] = data;
+	    return index;
+	}
+    }
+
+    return -1;
+}
+
+static TilePtr
+get(void *key)
+{
+    int hashval = hash((uint32)key);
+
+    for (int i = 0; i < hashsize/2; i++) {
+	int index = (hashval + i*i)%hashsize;
+	
+	if (hash_table[index]->texture_addr == key) {
+	    return hash_table[index];
+	}
+    }
+
+    return NULL;
+}
 
 void
 DrawSpan::linebuf_init(int *buf, int x, int rgb)
@@ -54,25 +111,44 @@
     Uint8 red, green, blue, alpha;
 
     if (tx<0) tx = 0;
-    if (128-1< tx) tx = 128-1 ;
+    if (tex_width-1< tx) tx = tex_width-1 ;
     if (ty<0) ty = 0;
-    if (128-1< ty) ty = 128-1 ;
+    if (tex_height-1< ty) ty = tex_height-1 ;
 
-#if 0
-    char *p = get_pixel(tx,ty,texture);
-#else
     void *texture_addr;
 
     int blockX = tx / 8;
     int blockY = ty / 8;
     void** addrList = (void**)global_get(TEXTURE2_ID);
-    
-    texture_addr = addrList[blockX + 16*blockY];
-    smanager->dma_load(tex, (uint32)texture_addr, sizeof(uint32)*64, TEX_LOAD);
-    smanager->dma_wait(TEX_LOAD);
+    TilePtr tile;
+
+    texture_addr = addrList[blockX + (tex_width/8)*blockY];
+
+    tile = get(texture_addr);
+    if (tile == NULL) {
+	if (tileList->size >= MAX_TILE) {
+	    tileList->init();
+	    bzero(hash_table, sizeof(TilePtr)*hashsize);
+	}
+
+	tile = &tileList->tile[tileList->size];
+	tile->texture_addr = texture_addr;
 
-    char *p = get_pixel(tx%8, ty%8, tex);
-#endif
+	smanager->dma_load(tile->pixel, (uint32)texture_addr,
+			   sizeof(uint32)*64, TEX_LOAD);
+
+	int index = put(tile->texture_addr, tile);
+	if (index < 0) {
+	    printf("[%p] Can't entry\n", tile);
+	    return 0xff0000;
+	}
+
+	tileList->size++;
+
+	smanager->dma_wait(TEX_LOAD);
+    }
+
+    char *p = get_pixel(tx%8, ty%8, tile);
     
     alpha = 255;
     red   = (Uint8) p[0];
@@ -93,6 +169,9 @@
     SpanPack *tmp_sp = NULL;
     Span *span;
 
+    tileList = (TileListPtr)smanager->allocate(sizeof(TileList));
+    tileList->init();
+
     int render_y = sp->info.y_top;
     void *texture_image = global_get(TEXTURE_ID);
 
@@ -105,14 +184,13 @@
 
     int **linebuf = (int**)smanager->allocate(sizeof(int*)*rangey);
 
-    tex = (unsigned char*)smanager->allocate(sizeof(unsigned char)*64*4);
-
     for (int i = 0; i < rangey; i++) {
 	linebuf[i] = (int*)smanager->get_output(i);
-	//linebuf_init(linebuf[i], rangex, 0x00ff00ff);
 	linebuf_init(linebuf[i], rangex, 0);
     }
 
+    bzero(hash_table, sizeof(TilePtr)*hashsize);
+
     do {
 	/**
 	 * SpanPack->next が存在する場合、
@@ -196,7 +274,7 @@
     free(free_sp);
     free(linebuf);
     free(zRow);
-    free(tex);
+    free(tileList);
 
     return 0;
 }