~ubuntu-branches/ubuntu/trusty/blender/trusty

« back to all changes in this revision

Viewing changes to source/blender/imbuf/intern/cache.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-03-06 12:08:47 UTC
  • mfrom: (1.5.1) (14.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20130306120847-frjfaryb2zrotwcg
Tags: 2.66a-1ubuntu1
* Resynchronize with Debian (LP: #1076930, #1089256, #1052743, #999024,
  #1122888, #1147084)
* debian/control:
  - Lower build-depends on libavcodec-dev since we're not
    doing the libav9 transition in Ubuntu yet

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
 * back to the global cache every pixel, but not to big to keep too many tiles
49
49
 * locked and using memory. */
50
50
 
51
 
#define IB_THREAD_CACHE_SIZE    100
 
51
#define IB_THREAD_CACHE_SIZE    100
52
52
 
53
53
typedef struct ImGlobalTile {
54
54
        struct ImGlobalTile *next, *prev;
82
82
        MemArena *memarena;
83
83
        uintptr_t totmem, maxmem;
84
84
 
85
 
        ImThreadTileCache thread_cache[BLENDER_MAX_THREADS+1];
 
85
        ImThreadTileCache thread_cache[BLENDER_MAX_THREADS + 1];
86
86
        int totthread;
87
87
 
88
88
        ThreadMutex mutex;
96
96
 
97
97
static unsigned int imb_global_tile_hash(const void *gtile_p)
98
98
{
99
 
        const ImGlobalTile *gtile= gtile_p;
 
99
        const ImGlobalTile *gtile = gtile_p;
100
100
 
101
 
        return ((unsigned int)(intptr_t)gtile->ibuf)*769 + gtile->tx*53 + gtile->ty*97;
 
101
        return ((unsigned int)(intptr_t)gtile->ibuf) * 769 + gtile->tx * 53 + gtile->ty * 97;
102
102
}
103
103
 
104
104
static int imb_global_tile_cmp(const void *a_p, const void *b_p)
105
105
{
106
 
        const ImGlobalTile *a= a_p;
107
 
        const ImGlobalTile *b= b_p;
 
106
        const ImGlobalTile *a = a_p;
 
107
        const ImGlobalTile *b = b_p;
108
108
 
109
109
        if (a->ibuf == b->ibuf && a->tx == b->tx && a->ty == b->ty) return 0;
110
110
        else if (a->ibuf < b->ibuf || a->tx < b->tx || a->ty < b->ty) return -1;
113
113
 
114
114
static unsigned int imb_thread_tile_hash(const void *ttile_p)
115
115
{
116
 
        const ImThreadTile *ttile= ttile_p;
 
116
        const ImThreadTile *ttile = ttile_p;
117
117
 
118
 
        return ((unsigned int)(intptr_t)ttile->ibuf)*769 + ttile->tx*53 + ttile->ty*97;
 
118
        return ((unsigned int)(intptr_t)ttile->ibuf) * 769 + ttile->tx * 53 + ttile->ty * 97;
119
119
}
120
120
 
121
121
static int imb_thread_tile_cmp(const void *a_p, const void *b_p)
122
122
{
123
 
        const ImThreadTile *a= a_p;
124
 
        const ImThreadTile *b= b_p;
 
123
        const ImThreadTile *a = a_p;
 
124
        const ImThreadTile *b = b_p;
125
125
 
126
126
        if (a->ibuf == b->ibuf && a->tx == b->tx && a->ty == b->ty) return 0;
127
127
        else if (a->ibuf < b->ibuf || a->tx < b->tx || a->ty < b->ty) return -1;
132
132
 
133
133
static void imb_global_cache_tile_load(ImGlobalTile *gtile)
134
134
{
135
 
        ImBuf *ibuf= gtile->ibuf;
136
 
        int toffs= ibuf->xtiles*gtile->ty + gtile->tx;
 
135
        ImBuf *ibuf = gtile->ibuf;
 
136
        int toffs = ibuf->xtiles * gtile->ty + gtile->tx;
137
137
        unsigned int *rect;
138
138
 
139
 
        rect = MEM_callocN(sizeof(unsigned int)*ibuf->tilex*ibuf->tiley, "imb_tile");
 
139
        rect = MEM_callocN(sizeof(unsigned int) * ibuf->tilex * ibuf->tiley, "imb_tile");
140
140
        imb_loadtile(ibuf, gtile->tx, gtile->ty, rect);
141
 
        ibuf->tiles[toffs]= rect;
 
141
        ibuf->tiles[toffs] = rect;
142
142
}
143
143
 
144
144
static void imb_global_cache_tile_unload(ImGlobalTile *gtile)
145
145
{
146
 
        ImBuf *ibuf= gtile->ibuf;
147
 
        int toffs= ibuf->xtiles*gtile->ty + gtile->tx;
 
146
        ImBuf *ibuf = gtile->ibuf;
 
147
        int toffs = ibuf->xtiles * gtile->ty + gtile->tx;
148
148
 
149
149
        MEM_freeN(ibuf->tiles[toffs]);
150
 
        ibuf->tiles[toffs]= NULL;
 
150
        ibuf->tiles[toffs] = NULL;
151
151
 
152
 
        GLOBAL_CACHE.totmem -= sizeof(unsigned int)*ibuf->tilex*ibuf->tiley;
 
152
        GLOBAL_CACHE.totmem -= sizeof(unsigned int) * ibuf->tilex * ibuf->tiley;
153
153
}
154
154
 
155
155
/* external free */
162
162
        lookuptile.ibuf = ibuf;
163
163
        lookuptile.tx = tx;
164
164
        lookuptile.ty = ty;
165
 
        gtile= BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile);
 
165
        gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile);
166
166
 
167
167
        if (gtile) {
168
168
                /* in case another thread is loading this */
186
186
 
187
187
        memset(cache, 0, sizeof(ImThreadTileCache));
188
188
 
189
 
        cache->tilehash= BLI_ghash_new(imb_thread_tile_hash, imb_thread_tile_cmp, "imb_thread_cache_init gh");
 
189
        cache->tilehash = BLI_ghash_new(imb_thread_tile_hash, imb_thread_tile_cmp, "imb_thread_cache_init gh");
190
190
 
191
191
        /* pre-allocate all thread local tiles in unused list */
192
 
        for (a=0; a<IB_THREAD_CACHE_SIZE; a++) {
193
 
                ttile= BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImThreadTile));
 
192
        for (a = 0; a < IB_THREAD_CACHE_SIZE; a++) {
 
193
                ttile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImThreadTile));
194
194
                BLI_addtail(&cache->unused, ttile);
195
195
        }
196
196
}
219
219
        int a;
220
220
 
221
221
        if (GLOBAL_CACHE.initialized) {
222
 
                for (gtile=GLOBAL_CACHE.tiles.first; gtile; gtile=gtile->next)
 
222
                for (gtile = GLOBAL_CACHE.tiles.first; gtile; gtile = gtile->next)
223
223
                        imb_global_cache_tile_unload(gtile);
224
224
 
225
 
                for (a=0; a<GLOBAL_CACHE.totthread; a++)
 
225
                for (a = 0; a < GLOBAL_CACHE.totthread; a++)
226
226
                        imb_thread_cache_exit(&GLOBAL_CACHE.thread_cache[a]);
227
227
 
228
228
                if (GLOBAL_CACHE.memarena)
253
253
 
254
254
        memset(&GLOBAL_CACHE, 0, sizeof(ImGlobalTileCache));
255
255
 
256
 
        GLOBAL_CACHE.tilehash= BLI_ghash_new(imb_global_tile_hash, imb_global_tile_cmp, "tile_cache_params gh");
 
256
        GLOBAL_CACHE.tilehash = BLI_ghash_new(imb_global_tile_hash, imb_global_tile_cmp, "tile_cache_params gh");
257
257
 
258
 
        GLOBAL_CACHE.memarena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "ImTileCache arena");
 
258
        GLOBAL_CACHE.memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "ImTileCache arena");
259
259
        BLI_memarena_use_calloc(GLOBAL_CACHE.memarena);
260
260
 
261
 
        GLOBAL_CACHE.maxmem= maxmem*1024*1024;
 
261
        GLOBAL_CACHE.maxmem = maxmem * 1024 * 1024;
262
262
 
263
 
        GLOBAL_CACHE.totthread= totthread;
264
 
        for (a=0; a<totthread; a++)
 
263
        GLOBAL_CACHE.totthread = totthread;
 
264
        for (a = 0; a < totthread; a++)
265
265
                imb_thread_cache_init(&GLOBAL_CACHE.thread_cache[a]);
266
266
 
267
267
        BLI_mutex_init(&GLOBAL_CACHE.mutex);
282
282
        lookuptile.ibuf = ibuf;
283
283
        lookuptile.tx = tx;
284
284
        lookuptile.ty = ty;
285
 
        gtile= BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile);
 
285
        gtile = BLI_ghash_lookup(GLOBAL_CACHE.tilehash, &lookuptile);
286
286
        
287
287
        if (gtile) {
288
288
                /* found tile. however it may be in the process of being loaded
301
301
                /* first check if we hit the memory limit */
302
302
                if (GLOBAL_CACHE.maxmem && GLOBAL_CACHE.totmem > GLOBAL_CACHE.maxmem) {
303
303
                        /* find an existing tile to unload */
304
 
                        for (gtile=GLOBAL_CACHE.tiles.last; gtile; gtile=gtile->prev)
 
304
                        for (gtile = GLOBAL_CACHE.tiles.last; gtile; gtile = gtile->prev)
305
305
                                if (gtile->refcount == 0 && gtile->loading == 0)
306
306
                                        break;
307
307
                }
315
315
                else {
316
316
                        /* allocate a new tile or reuse unused */
317
317
                        if (GLOBAL_CACHE.unused.first) {
318
 
                                gtile= GLOBAL_CACHE.unused.first;
 
318
                                gtile = GLOBAL_CACHE.unused.first;
319
319
                                BLI_remlink(&GLOBAL_CACHE.unused, gtile);
320
320
                        }
321
321
                        else
322
 
                                gtile= BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile));
 
322
                                gtile = BLI_memarena_alloc(GLOBAL_CACHE.memarena, sizeof(ImGlobalTile));
323
323
                }
324
324
 
325
325
                /* setup new tile */
326
 
                gtile->ibuf= ibuf;
327
 
                gtile->tx= tx;
328
 
                gtile->ty= ty;
329
 
                gtile->refcount= 1;
330
 
                gtile->loading= 1;
 
326
                gtile->ibuf = ibuf;
 
327
                gtile->tx = tx;
 
328
                gtile->ty = ty;
 
329
                gtile->refcount = 1;
 
330
                gtile->loading = 1;
331
331
 
332
332
                BLI_ghash_insert(GLOBAL_CACHE.tilehash, gtile, gtile);
333
333
                BLI_addhead(&GLOBAL_CACHE.tiles, gtile);
334
334
 
335
335
                /* mark as being loaded and unlock to allow other threads to load too */
336
 
                GLOBAL_CACHE.totmem += sizeof(unsigned int)*ibuf->tilex*ibuf->tiley;
 
336
                GLOBAL_CACHE.totmem += sizeof(unsigned int) * ibuf->tilex * ibuf->tiley;
337
337
 
338
338
                BLI_mutex_unlock(&GLOBAL_CACHE.mutex);
339
339
 
341
341
                imb_global_cache_tile_load(gtile);
342
342
 
343
343
                /* mark as done loading */
344
 
                gtile->loading= 0;
 
344
                gtile->loading = 0;
345
345
        }
346
346
 
347
347
        return gtile;
353
353
{
354
354
        ImThreadTile *ttile, lookuptile;
355
355
        ImGlobalTile *gtile, *replacetile;
356
 
        int toffs= ibuf->xtiles*ty + tx;
 
356
        int toffs = ibuf->xtiles * ty + tx;
357
357
 
358
358
        /* test if it is already in our thread local cache */
359
 
        if ((ttile=cache->tiles.first)) {
 
359
        if ((ttile = cache->tiles.first)) {
360
360
                /* check last used tile before going to hash */
361
361
                if (ttile->ibuf == ibuf && ttile->tx == tx && ttile->ty == ty)
362
362
                        return ibuf->tiles[toffs];
366
366
                lookuptile.tx = tx;
367
367
                lookuptile.ty = ty;
368
368
 
369
 
                if ((ttile=BLI_ghash_lookup(cache->tilehash, &lookuptile))) {
 
369
                if ((ttile = BLI_ghash_lookup(cache->tilehash, &lookuptile))) {
370
370
                        BLI_remlink(&cache->tiles, ttile);
371
371
                        BLI_addhead(&cache->tiles, ttile);
372
372
 
376
376
 
377
377
        /* not found, have to do slow lookup in global cache */
378
378
        if (cache->unused.first == NULL) {
379
 
                ttile= cache->tiles.last;
380
 
                replacetile= ttile->global;
 
379
                ttile = cache->tiles.last;
 
380
                replacetile = ttile->global;
381
381
                BLI_remlink(&cache->tiles, ttile);
382
382
                BLI_ghash_remove(cache->tilehash, ttile, NULL, NULL);
383
383
        }
384
384
        else {
385
 
                ttile= cache->unused.first;
386
 
                replacetile= NULL;
 
385
                ttile = cache->unused.first;
 
386
                replacetile = NULL;
387
387
                BLI_remlink(&cache->unused, ttile);
388
388
        }
389
389
 
390
390
        BLI_addhead(&cache->tiles, ttile);
391
391
        BLI_ghash_insert(cache->tilehash, ttile, ttile);
392
392
 
393
 
        gtile= imb_global_cache_get_tile(ibuf, tx, ty, replacetile);
 
393
        gtile = imb_global_cache_get_tile(ibuf, tx, ty, replacetile);
394
394
 
395
 
        ttile->ibuf= gtile->ibuf;
396
 
        ttile->tx= gtile->tx;
397
 
        ttile->ty= gtile->ty;
398
 
        ttile->global= gtile;
 
395
        ttile->ibuf = gtile->ibuf;
 
396
        ttile->tx = gtile->tx;
 
397
        ttile->ty = gtile->ty;
 
398
        ttile->global = gtile;
399
399
 
400
400
        return ibuf->tiles[toffs];
401
401
}
402
402
 
403
403
unsigned int *IMB_gettile(ImBuf *ibuf, int tx, int ty, int thread)
404
404
{
405
 
        return imb_thread_cache_get_tile(&GLOBAL_CACHE.thread_cache[thread+1], ibuf, tx, ty);
 
405
        return imb_thread_cache_get_tile(&GLOBAL_CACHE.thread_cache[thread + 1], ibuf, tx, ty);
406
406
}
407
407
 
408
408
void IMB_tiles_to_rect(ImBuf *ibuf)
412
412
        unsigned int *to, *from;
413
413
        int a, tx, ty, y, w, h;
414
414
 
415
 
        for (a=0; a<ibuf->miptot; a++) {
416
 
                mipbuf= IMB_getmipmap(ibuf, a);
 
415
        for (a = 0; a < ibuf->miptot; a++) {
 
416
                mipbuf = IMB_getmipmap(ibuf, a);
417
417
 
418
418
                /* don't call imb_addrectImBuf, it frees all mipmaps */
419
419
                if (!mipbuf->rect) {
420
 
                        if ((mipbuf->rect = MEM_mapallocN(ibuf->x*ibuf->y*sizeof(unsigned int), "imb_addrectImBuf"))) {
 
420
                        if ((mipbuf->rect = MEM_mapallocN(ibuf->x * ibuf->y * sizeof(unsigned int), "imb_addrectImBuf"))) {
421
421
                                mipbuf->mall |= IB_rect;
422
422
                                mipbuf->flags |= IB_rect;
423
423
                        }
425
425
                                break;
426
426
                }
427
427
 
428
 
                for (ty=0; ty<mipbuf->ytiles; ty++) {
429
 
                        for (tx=0; tx<mipbuf->xtiles; tx++) {
 
428
                for (ty = 0; ty < mipbuf->ytiles; ty++) {
 
429
                        for (tx = 0; tx < mipbuf->xtiles; tx++) {
430
430
                                /* acquire tile through cache, this assumes cache is initialized,
431
431
                                 * which it is always now but it's a weak assumption ... */
432
 
                                gtile= imb_global_cache_get_tile(mipbuf, tx, ty, NULL);
 
432
                                gtile = imb_global_cache_get_tile(mipbuf, tx, ty, NULL);
433
433
 
434
434
                                /* setup pointers */
435
 
                                from= mipbuf->tiles[mipbuf->xtiles*ty + tx];
436
 
                                to= mipbuf->rect + mipbuf->x*ty*mipbuf->tiley + tx*mipbuf->tilex;
 
435
                                from = mipbuf->tiles[mipbuf->xtiles * ty + tx];
 
436
                                to = mipbuf->rect + mipbuf->x * ty * mipbuf->tiley + tx * mipbuf->tilex;
437
437
 
438
438
                                /* exception in tile width/height for tiles at end of image */
439
 
                                w= (tx == mipbuf->xtiles-1)? mipbuf->x - tx*mipbuf->tilex: mipbuf->tilex;
440
 
                                h= (ty == mipbuf->ytiles-1)? mipbuf->y - ty*mipbuf->tiley: mipbuf->tiley;
 
439
                                w = (tx == mipbuf->xtiles - 1) ? mipbuf->x - tx * mipbuf->tilex : mipbuf->tilex;
 
440
                                h = (ty == mipbuf->ytiles - 1) ? mipbuf->y - ty * mipbuf->tiley : mipbuf->tiley;
441
441
 
442
 
                                for (y=0; y<h; y++) {
443
 
                                        memcpy(to, from, sizeof(unsigned int)*w);
 
442
                                for (y = 0; y < h; y++) {
 
443
                                        memcpy(to, from, sizeof(unsigned int) * w);
444
444
                                        from += mipbuf->tilex;
445
445
                                        to += mipbuf->x;
446
446
                                }