~ubuntu-branches/ubuntu/maverick/blender/maverick

« back to all changes in this revision

Viewing changes to extern/qdune/svm/TexCache.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Khashayar Naderehvandi, Khashayar Naderehvandi, Alessio Treglia
  • Date: 2009-01-22 16:53:59 UTC
  • mfrom: (14.1.1 experimental)
  • Revision ID: james.westby@ubuntu.com-20090122165359-v0996tn7fbit64ni
Tags: 2.48a+dfsg-1ubuntu1
[ Khashayar Naderehvandi ]
* Merge from debian experimental (LP: #320045), Ubuntu remaining changes:
  - Add patch correcting header file locations.
  - Add libvorbis-dev and libgsm1-dev to Build-Depends.
  - Use avcodec_decode_audio2() in source/blender/src/hddaudio.c

[ Alessio Treglia ]
* Add missing previous changelog entries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//---------------------------------------------------------------------------------------
2
 
// Simple LRU based texture cache
3
 
//---------------------------------------------------------------------------------------
4
 
 
5
 
// TODO:
6
 
// While it works as it should, it is rather simplistic and not particularly efficient.
7
 
// Probably a much better approach is to actually allocate a single block of memory,
8
 
// directly load tiles into it which can be directly accessed.
9
 
// Usage counts then should be maintained so that no data needs to be moved around.
10
 
// Problem then is how to organize everything by texture file, tile levels, etc.
11
 
// TODO
12
 
 
13
 
#include "TexCache.h"
14
 
#include "exr_io.h"
15
 
#include "Mathutil.h"
16
 
 
17
 
#include <iostream>
18
 
 
19
 
__BEGIN_QDRENDER
20
 
 
21
 
//---------------------------------------------------------------------------------------
22
 
 
23
 
using namespace std;
24
 
 
25
 
// cache stats
26
 
static unsigned int cache_total = 0;
27
 
static unsigned int cache_hit = 0;
28
 
static unsigned int cache_miss = 0;
29
 
static size_t texmem_total = 0;
30
 
 
31
 
TextureCache::TextureCache(size_t memory_maximum) : maxmem(memory_maximum)
32
 
{
33
 
        // set textile_db size to hold as many tiles as the specified memory allows
34
 
        // this is currently based on float RGB tiles of 64x64 only = 4*3*64*64 = 49152 bytes,
35
 
        // so maxtiles is not necessarily the correct number, it depends on the actual data loaded
36
 
        // Should remove the maxitem limit from lrulist and let the code here
37
 
        // signal the list when the cache is full based on 'texmem_total' TODO
38
 
        const size_t maxtiles = (maxmem < 49152) ? 1 : (maxmem / 49152);        // at least one tile
39
 
        //cout << "current memory of " << maxmem << " allows " << maxtiles << " color tiles in memory." << endl;
40
 
        textile_db = new lrulist_t<tileID_t, textile_t*>(maxtiles);
41
 
        cache_total = cache_hit = cache_miss = 0;
42
 
}
43
 
 
44
 
TextureCache::~TextureCache()
45
 
{
46
 
        cout << "cache memory total: " << texmem_total << endl;
47
 
        cout << "cache total : " << cache_total << endl;
48
 
        const float cdv = cache_total ? 100.f/float(cache_total) : 1.f;
49
 
        cout << "cache hit   : " << cache_hit << " ( " << cache_hit*cdv << "\% )\n";
50
 
        cout << "cache miss  : " << cache_miss << " ( " << cache_miss*cdv << "\% )\n";
51
 
 
52
 
        //cout << "texture_db size = " << texture_db.size() << endl;
53
 
        EXRbuf_t** ei = texture_db.first();
54
 
        int n = 0;
55
 
        while (ei) {
56
 
                delete *ei;
57
 
                ei = texture_db.next();
58
 
                n++;
59
 
        }
60
 
        //cout << "deleted " << n << " textures\n";
61
 
 
62
 
        cout <<  "Total tiles in memory: " << textile_db->size() << endl;
63
 
        textile_t* tt = textile_db->first();
64
 
        while (tt) {
65
 
                delete[] tt->color_data;
66
 
                delete tt;
67
 
                tt = textile_db->next();
68
 
        }
69
 
        delete textile_db;
70
 
}
71
 
 
72
 
// loads new texture if not available yet.
73
 
// if that failed or some other error occured, will store NULL ptr to prevent the file from trying to be opened continuously
74
 
const EXRbuf_t* TextureCache::getTextureInfo(const char texname[]) const
75
 
{
76
 
        EXRbuf_t** ei = texture_db.find(texname);
77
 
        if (ei) return *ei;
78
 
        // not found, open new .tqd file
79
 
        //char fullpath[512] = {0};
80
 
        //snprintf(fullpath, 512, "%s%s", State::Instance()->topOptions().basepath, texname);
81
 
        EXRbuf_t* ebc = new EXRbuf_t(texname); //fullpath);
82
 
        if (!ebc->valid()) {
83
 
                texture_db.insert(texname, NULL);
84
 
                delete ebc;
85
 
                return NULL;
86
 
        }
87
 
        texture_db.insert(texname, ebc);
88
 
        return ebc;
89
 
}
90
 
 
91
 
textile_t* TextureCache::getTile(const tileID_t& tileID) const
92
 
{
93
 
        cache_total++;
94
 
        textile_t** cached_tile = textile_db->find(tileID);
95
 
        if (cached_tile) {
96
 
                cache_hit++;
97
 
                return *cached_tile;
98
 
        }
99
 
        cache_miss++;
100
 
 
101
 
        // not found, load new tile
102
 
        // possibly the main bottleneck in the code, some sort of prefetching technique might make a difference... TODO
103
 
        textile_t* tt = new textile_t;
104
 
        if (tileID.tex->numChannels() == 1)
105
 
                tt->float_data = tileID.tex->getFloatTile(tileID);
106
 
        else
107
 
                tt->color_data = tileID.tex->getColorTile(tileID);
108
 
        if (tt->color_data == NULL) {   // is union, so also valid if float_data==NULL
109
 
                delete tt;
110
 
                return NULL;
111
 
        }
112
 
 
113
 
        texmem_total += tileID.tex->getTileDataSize();
114
 
 
115
 
        // add new tile to texture tile database,
116
 
        // also free data of possibly discarded tile if addition of new tile caused an older one to be thrown out
117
 
        textile_t* discarded_tile = NULL;
118
 
        textile_db->insert(tileID, tt, discarded_tile);
119
 
        if (discarded_tile) {
120
 
                texmem_total -= tileID.tex->getTileDataSize();
121
 
                delete[] discarded_tile->color_data;
122
 
                delete discarded_tile;
123
 
        }
124
 
 
125
 
        return tt;
126
 
}
127
 
 
128
 
 
129
 
// returns color at integer coords x,y at level L in 'col', handles all necessary tile updates
130
 
void TextureCache::getColor(const EXRbuf_t* texinfo, int x, int y, int L, RtColor col) const
131
 
{
132
 
        if (texinfo == NULL) return;
133
 
 
134
 
        const int maxXtile = texinfo->getXTiles(L) - 1, maxYtile = texinfo->getYTiles(L) - 1;
135
 
        const int tilesize = texinfo->getTileXSize();   // mipmap, so always square
136
 
        // tile numbers
137
 
        const int tx = MIN2(int(x / tilesize), maxXtile), ty = MIN2(int(y / tilesize), maxYtile);
138
 
        // tile coords, modulomax w/h not quite correct here yet, depends on wrap modes TODO (same for above tile numbers)
139
 
        x %= tilesize, y %= tilesize;
140
 
        // correction for tiles that overlap the border, only partially valid
141
 
        if (tx == maxXtile) x = MIN2(x, (texinfo->getWidth(L) - 1) % tilesize);
142
 
        if (ty == maxYtile) y = MIN2(y, (texinfo->getHeight(L) - 1) % tilesize);
143
 
 
144
 
        const tileID_t tileID = {texinfo, tx, ty, L, L};        // mipmap for now, so levelX==levelY
145
 
        const textile_t* const tt = getTile(tileID);
146
 
        assert(tt != NULL);
147
 
 
148
 
        const unsigned int p = y*tilesize + x;
149
 
        col[0] = tt->color_data[p][0], col[1] = tt->color_data[p][1], col[2] = tt->color_data[p][2];
150
 
}
151
 
 
152
 
 
153
 
// returns float at integer coords x,y at level L, handles all necessary tile updates
154
 
float TextureCache::getFloat(const EXRbuf_t* texinfo, int x, int y, int L) const
155
 
{
156
 
        if (texinfo == NULL) return 0.f;
157
 
 
158
 
        const int maxXtile = texinfo->getXTiles(L) - 1, maxYtile = texinfo->getYTiles(L) - 1;
159
 
        const int tilesize = texinfo->getTileXSize();   // mipmap, so always square
160
 
        // tile numbers
161
 
        const int tx = MIN2(int(x / tilesize), maxXtile), ty = MIN2(int(y / tilesize), maxYtile);
162
 
        // tile coords, modulomax w/h not quite correct here yet, depends on wrap modes TODO (same for above tile numbers)
163
 
        x %= tilesize, y %= tilesize;
164
 
        // correction for tiles that overlap the border, only partially valid
165
 
        if (tx == maxXtile) x = MIN2(x, (texinfo->getWidth(L) - 1) % tilesize);
166
 
        if (ty == maxYtile) y = MIN2(y, (texinfo->getHeight(L) - 1) % tilesize);
167
 
 
168
 
        const tileID_t tileID = {texinfo, tx, ty, L, L};        // mipmap for now, so levelX==levelY
169
 
        const textile_t* const tt = getTile(tileID);
170
 
        assert(tt != NULL);
171
 
 
172
 
        return tt->float_data[y*tilesize + x];
173
 
}
174
 
 
175
 
 
176
 
// For use with shadowmaps, returns value at integer coords x,y (always level 0), handles all necessary tile updates
177
 
// If out of range, returns -1, valid depthvalues are always positive
178
 
float TextureCache::getDepth(const EXRbuf_t* texinfo, int x, int y) const
179
 
{
180
 
        if ((texinfo == NULL) ||
181
 
            (x < 0) || (y < 0) || (x >= texinfo->getWidth()) || (y >= texinfo->getHeight())) return -1.f;       // out of range
182
 
        const int tilesize = texinfo->getTileXSize();   // single level mipmap, always square
183
 
        const tileID_t tileID = {texinfo, MIN2(int(x / tilesize), texinfo->getXTiles() - 1),
184
 
                                 MIN2(int(y / tilesize), texinfo->getYTiles() - 1), 0, 0};
185
 
        const textile_t* const tt = getTile(tileID);
186
 
        assert(tt != NULL);
187
 
        return tt->float_data[(y % tilesize)*tilesize + (x % tilesize)];
188
 
}
189
 
 
190
 
__END_QDRENDER