~ubuntu-branches/ubuntu/precise/mesa/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/r300/radeon_mipmap_tree.c

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2012-02-02 12:05:48 UTC
  • mfrom: (1.7.1) (3.3.27 sid)
  • Revision ID: package-import@ubuntu.com-20120202120548-nvkma85jq0h4coix
Tags: 8.0~rc2-0ubuntu4
Drop drisearchdir handling, it is no longer needed with multiarch
and dri-alternates being removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2009 Maciej Cencora.
3
 
 * Copyright (C) 2008 Nicolai Haehnle.
4
 
 *
5
 
 * All Rights Reserved.
6
 
 *
7
 
 * Permission is hereby granted, free of charge, to any person obtaining
8
 
 * a copy of this software and associated documentation files (the
9
 
 * "Software"), to deal in the Software without restriction, including
10
 
 * without limitation the rights to use, copy, modify, merge, publish,
11
 
 * distribute, sublicense, and/or sell copies of the Software, and to
12
 
 * permit persons to whom the Software is furnished to do so, subject to
13
 
 * the following conditions:
14
 
 *
15
 
 * The above copyright notice and this permission notice (including the
16
 
 * next paragraph) shall be included in all copies or substantial
17
 
 * portions of the Software.
18
 
 *
19
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
 
 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
23
 
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
 
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
 
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
 
 *
27
 
 */
28
 
 
29
 
#include "radeon_mipmap_tree.h"
30
 
 
31
 
#include <errno.h>
32
 
#include <unistd.h>
33
 
 
34
 
#include "main/simple_list.h"
35
 
#include "main/teximage.h"
36
 
#include "main/texobj.h"
37
 
#include "main/enums.h"
38
 
#include "radeon_texture.h"
39
 
#include "radeon_tile.h"
40
 
 
41
 
static unsigned get_aligned_compressed_row_stride(
42
 
                gl_format format,
43
 
                unsigned width,
44
 
                unsigned minStride)
45
 
{
46
 
        const unsigned blockBytes = _mesa_get_format_bytes(format);
47
 
        unsigned blockWidth, blockHeight;
48
 
        unsigned stride;
49
 
 
50
 
        _mesa_get_format_block_size(format, &blockWidth, &blockHeight);
51
 
 
52
 
        /* Count number of blocks required to store the given width.
53
 
         * And then multiple it with bytes required to store a block.
54
 
         */
55
 
        stride = (width + blockWidth - 1) / blockWidth * blockBytes;
56
 
 
57
 
        /* Round the given minimum stride to the next full blocksize.
58
 
         * (minStride + blockBytes - 1) / blockBytes * blockBytes
59
 
         */
60
 
        if ( stride < minStride )
61
 
                stride = (minStride + blockBytes - 1) / blockBytes * blockBytes;
62
 
 
63
 
        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
64
 
                        "%s width %u, minStride %u, block(bytes %u, width %u):"
65
 
                        "stride %u\n",
66
 
                        __func__, width, minStride,
67
 
                        blockBytes, blockWidth,
68
 
                        stride);
69
 
 
70
 
        return stride;
71
 
}
72
 
 
73
 
unsigned get_texture_image_size(
74
 
                gl_format format,
75
 
                unsigned rowStride,
76
 
                unsigned height,
77
 
                unsigned depth,
78
 
                unsigned tiling)
79
 
{
80
 
        if (_mesa_is_format_compressed(format)) {
81
 
                unsigned blockWidth, blockHeight;
82
 
 
83
 
                _mesa_get_format_block_size(format, &blockWidth, &blockHeight);
84
 
 
85
 
                return rowStride * ((height + blockHeight - 1) / blockHeight) * depth;
86
 
        } else if (tiling) {
87
 
                /* Need to align height to tile height */
88
 
                unsigned tileWidth, tileHeight;
89
 
 
90
 
                get_tile_size(format, &tileWidth, &tileHeight);
91
 
                tileHeight--;
92
 
 
93
 
                height = (height + tileHeight) & ~tileHeight;
94
 
        }
95
 
 
96
 
        return rowStride * height * depth;
97
 
}
98
 
 
99
 
unsigned get_texture_image_row_stride(radeonContextPtr rmesa, gl_format format, unsigned width, unsigned tiling)
100
 
{
101
 
        if (_mesa_is_format_compressed(format)) {
102
 
                return get_aligned_compressed_row_stride(format, width, rmesa->texture_compressed_row_align);
103
 
        } else {
104
 
                unsigned row_align;
105
 
 
106
 
                if (!_mesa_is_pow_two(width)) {
107
 
                        row_align = rmesa->texture_rect_row_align - 1;
108
 
                } else if (tiling) {
109
 
                        unsigned tileWidth, tileHeight;
110
 
                        get_tile_size(format, &tileWidth, &tileHeight);
111
 
                        row_align = tileWidth * _mesa_get_format_bytes(format) - 1;
112
 
                } else {
113
 
                        row_align = rmesa->texture_row_align - 1;
114
 
                }
115
 
 
116
 
                return (_mesa_format_row_stride(format, width) + row_align) & ~row_align;
117
 
        }
118
 
}
119
 
 
120
 
/**
121
 
 * Compute sizes and fill in offset and blit information for the given
122
 
 * image (determined by \p face and \p level).
123
 
 *
124
 
 * \param curOffset points to the offset at which the image is to be stored
125
 
 * and is updated by this function according to the size of the image.
126
 
 */
127
 
static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree *mt,
128
 
        GLuint face, GLuint level, GLuint* curOffset)
129
 
{
130
 
        radeon_mipmap_level *lvl = &mt->levels[level];
131
 
        GLuint height;
132
 
 
133
 
        height = _mesa_next_pow_two_32(lvl->height);
134
 
 
135
 
        lvl->rowstride = get_texture_image_row_stride(rmesa, mt->mesaFormat, lvl->width, mt->tilebits);
136
 
        lvl->size = get_texture_image_size(mt->mesaFormat, lvl->rowstride, height, lvl->depth, mt->tilebits);
137
 
 
138
 
        assert(lvl->size > 0);
139
 
 
140
 
        lvl->faces[face].offset = *curOffset;
141
 
        *curOffset += lvl->size;
142
 
 
143
 
        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
144
 
                        "%s(%p) level %d, face %d: rs:%d %dx%d at %d\n",
145
 
                        __func__, rmesa,
146
 
                        level, face,
147
 
                        lvl->rowstride, lvl->width, height, lvl->faces[face].offset);
148
 
}
149
 
 
150
 
static GLuint minify(GLuint size, GLuint levels)
151
 
{
152
 
        size = size >> levels;
153
 
        if (size < 1)
154
 
                size = 1;
155
 
        return size;
156
 
}
157
 
 
158
 
 
159
 
static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
160
 
{
161
 
        GLuint curOffset, i, face, level;
162
 
 
163
 
        assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
164
 
 
165
 
        curOffset = 0;
166
 
        for(face = 0; face < mt->faces; face++) {
167
 
 
168
 
                for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
169
 
                        mt->levels[level].valid = 1;
170
 
                        mt->levels[level].width = minify(mt->width0, i);
171
 
                        mt->levels[level].height = minify(mt->height0, i);
172
 
                        mt->levels[level].depth = minify(mt->depth0, i);
173
 
                        compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
174
 
                }
175
 
        }
176
 
 
177
 
        /* Note the required size in memory */
178
 
        mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
179
 
 
180
 
        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
181
 
                        "%s(%p, %p) total size %d\n",
182
 
                        __func__, rmesa, mt, mt->totalsize);
183
 
}
184
 
 
185
 
static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
186
 
{
187
 
        GLuint curOffset, i, level;
188
 
 
189
 
        assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
190
 
 
191
 
        curOffset = 0;
192
 
        for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
193
 
                GLuint face;
194
 
 
195
 
                mt->levels[level].valid = 1;
196
 
                mt->levels[level].width = minify(mt->width0, i);
197
 
                mt->levels[level].height = minify(mt->height0, i);
198
 
                mt->levels[level].depth = minify(mt->depth0, i);
199
 
 
200
 
                for(face = 0; face < mt->faces; face++)
201
 
                        compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
202
 
                /* from r700? cube levels seems to be aligned to 8 faces,
203
 
                 * as we have separate register for 1'st level offset add
204
 
                 * 2 image alignment after 1'st mip level */
205
 
                if(rmesa->radeonScreen->chip_family >= CHIP_FAMILY_RV770 &&
206
 
                   mt->target == GL_TEXTURE_CUBE_MAP && level >= 1)
207
 
                        curOffset += 2 * mt->levels[level].size;
208
 
        }
209
 
 
210
 
        /* Note the required size in memory */
211
 
        mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
212
 
 
213
 
        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
214
 
                        "%s(%p, %p) total size %d\n",
215
 
                        __func__, rmesa, mt, mt->totalsize);
216
 
}
217
 
 
218
 
/**
219
 
 * Create a new mipmap tree, calculate its layout and allocate memory.
220
 
 */
221
 
static radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
222
 
                GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
223
 
                GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
224
 
{
225
 
        radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
226
 
 
227
 
        radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
228
 
                "%s(%p) new tree is %p.\n",
229
 
                __func__, rmesa, mt);
230
 
 
231
 
        mt->mesaFormat = mesaFormat;
232
 
        mt->refcount = 1;
233
 
        mt->target = target;
234
 
        mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
235
 
        mt->baseLevel = baseLevel;
236
 
        mt->numLevels = numLevels;
237
 
        mt->width0 = width0;
238
 
        mt->height0 = height0;
239
 
        mt->depth0 = depth0;
240
 
        mt->tilebits = tilebits;
241
 
 
242
 
        if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
243
 
                calculate_miptree_layout_r300(rmesa, mt);
244
 
        else
245
 
                calculate_miptree_layout_r100(rmesa, mt);
246
 
 
247
 
        mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
248
 
                            0, mt->totalsize, 1024,
249
 
                            RADEON_GEM_DOMAIN_VRAM,
250
 
                            0);
251
 
 
252
 
        return mt;
253
 
}
254
 
 
255
 
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr)
256
 
{
257
 
        assert(!*ptr);
258
 
 
259
 
        mt->refcount++;
260
 
        assert(mt->refcount > 0);
261
 
 
262
 
        *ptr = mt;
263
 
}
264
 
 
265
 
void radeon_miptree_unreference(radeon_mipmap_tree **ptr)
266
 
{
267
 
        radeon_mipmap_tree *mt = *ptr;
268
 
        if (!mt)
269
 
                return;
270
 
 
271
 
        assert(mt->refcount > 0);
272
 
 
273
 
        mt->refcount--;
274
 
        if (!mt->refcount) {
275
 
                radeon_bo_unref(mt->bo);
276
 
                free(mt);
277
 
        }
278
 
 
279
 
        *ptr = 0;
280
 
}
281
 
 
282
 
/**
283
 
 * Calculate min and max LOD for the given texture object.
284
 
 * @param[in] tObj texture object whose LOD values to calculate
285
 
 * @param[out] pminLod minimal LOD
286
 
 * @param[out] pmaxLod maximal LOD
287
 
 */
288
 
static void calculate_min_max_lod(struct gl_texture_object *tObj,
289
 
                                       unsigned *pminLod, unsigned *pmaxLod)
290
 
{
291
 
        int minLod, maxLod;
292
 
        /* Yes, this looks overly complicated, but it's all needed.
293
 
        */
294
 
        switch (tObj->Target) {
295
 
        case GL_TEXTURE_1D:
296
 
        case GL_TEXTURE_2D:
297
 
        case GL_TEXTURE_3D:
298
 
        case GL_TEXTURE_CUBE_MAP:
299
 
                if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) {
300
 
                        /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
301
 
                        */
302
 
                        minLod = maxLod = tObj->BaseLevel;
303
 
                } else {
304
 
                        minLod = tObj->BaseLevel + (GLint)(tObj->Sampler.MinLod);
305
 
                        minLod = MAX2(minLod, tObj->BaseLevel);
306
 
                        minLod = MIN2(minLod, tObj->MaxLevel);
307
 
                        maxLod = tObj->BaseLevel + (GLint)(tObj->Sampler.MaxLod + 0.5);
308
 
                        maxLod = MIN2(maxLod, tObj->MaxLevel);
309
 
                        maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxLog2 + minLod);
310
 
                        maxLod = MAX2(maxLod, minLod); /* need at least one level */
311
 
                }
312
 
                break;
313
 
        case GL_TEXTURE_RECTANGLE_NV:
314
 
        case GL_TEXTURE_4D_SGIS:
315
 
                minLod = maxLod = 0;
316
 
                break;
317
 
        default:
318
 
                return;
319
 
        }
320
 
 
321
 
        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
322
 
                        "%s(%p) target %s, min %d, max %d.\n",
323
 
                        __func__, tObj,
324
 
                        _mesa_lookup_enum_by_nr(tObj->Target),
325
 
                        minLod, maxLod);
326
 
 
327
 
        /* save these values */
328
 
        *pminLod = minLod;
329
 
        *pmaxLod = maxLod;
330
 
}
331
 
 
332
 
/**
333
 
 * Checks whether the given miptree can hold the given texture image at the
334
 
 * given face and level.
335
 
 */
336
 
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
337
 
                struct gl_texture_image *texImage, GLuint face, GLuint level)
338
 
{
339
 
        radeon_mipmap_level *lvl;
340
 
 
341
 
        if (face >= mt->faces)
342
 
                return GL_FALSE;
343
 
 
344
 
        if (texImage->TexFormat != mt->mesaFormat)
345
 
                return GL_FALSE;
346
 
 
347
 
        lvl = &mt->levels[level];
348
 
        if (!lvl->valid ||
349
 
            lvl->width != texImage->Width ||
350
 
            lvl->height != texImage->Height ||
351
 
            lvl->depth != texImage->Depth)
352
 
                return GL_FALSE;
353
 
 
354
 
        return GL_TRUE;
355
 
}
356
 
 
357
 
/**
358
 
 * Checks whether the given miptree has the right format to store the given texture object.
359
 
 */
360
 
static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
361
 
{
362
 
        struct gl_texture_image *firstImage;
363
 
        unsigned numLevels;
364
 
        radeon_mipmap_level *mtBaseLevel;
365
 
 
366
 
        if (texObj->BaseLevel < mt->baseLevel)
367
 
                return GL_FALSE;
368
 
 
369
 
        mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
370
 
        firstImage = texObj->Image[0][texObj->BaseLevel];
371
 
        numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
372
 
 
373
 
        if (radeon_is_debug_enabled(RADEON_TEXTURE,RADEON_TRACE)) {
374
 
                fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
375
 
                fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
376
 
                fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
377
 
                fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
378
 
                fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
379
 
                fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height);
380
 
                fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth);
381
 
                if (mt->target == texObj->Target &&
382
 
                mt->mesaFormat == firstImage->TexFormat &&
383
 
                mt->numLevels >= numLevels &&
384
 
                mtBaseLevel->width == firstImage->Width &&
385
 
                mtBaseLevel->height == firstImage->Height &&
386
 
                mtBaseLevel->depth == firstImage->Depth) {
387
 
                        fprintf(stderr, "MATCHED\n");
388
 
                } else {
389
 
                        fprintf(stderr, "NOT MATCHED\n");
390
 
                }
391
 
        }
392
 
 
393
 
        return (mt->target == texObj->Target &&
394
 
                mt->mesaFormat == firstImage->TexFormat &&
395
 
                mt->numLevels >= numLevels &&
396
 
                mtBaseLevel->width == firstImage->Width &&
397
 
                mtBaseLevel->height == firstImage->Height &&
398
 
                mtBaseLevel->depth == firstImage->Depth);
399
 
}
400
 
 
401
 
/**
402
 
 * Try to allocate a mipmap tree for the given texture object.
403
 
 * @param[in] rmesa radeon context
404
 
 * @param[in] t radeon texture object
405
 
 */
406
 
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
407
 
{
408
 
        struct gl_texture_object *texObj = &t->base;
409
 
        struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
410
 
        GLuint numLevels;
411
 
 
412
 
        assert(!t->mt);
413
 
 
414
 
        if (!texImg) {
415
 
                radeon_warning("%s(%p) No image in given texture object(%p).\n",
416
 
                                __func__, rmesa, t);
417
 
                return;
418
 
        }
419
 
 
420
 
 
421
 
        numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxLog2 + 1);
422
 
 
423
 
        t->mt = radeon_miptree_create(rmesa, t->base.Target,
424
 
                texImg->TexFormat, texObj->BaseLevel,
425
 
                numLevels, texImg->Width, texImg->Height,
426
 
                texImg->Depth, t->tile_bits);
427
 
}
428
 
 
429
 
GLuint
430
 
radeon_miptree_image_offset(radeon_mipmap_tree *mt,
431
 
                            GLuint face, GLuint level)
432
 
{
433
 
        if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
434
 
                return (mt->levels[level].faces[face].offset);
435
 
        else
436
 
                return mt->levels[level].faces[0].offset;
437
 
}
438
 
 
439
 
/**
440
 
 * Ensure that the given image is stored in the given miptree from now on.
441
 
 */
442
 
static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
443
 
                                                                         radeon_texture_image *image,
444
 
                                                                         int face, int level)
445
 
{
446
 
        radeon_mipmap_level *dstlvl = &mt->levels[level];
447
 
        unsigned char *dest;
448
 
 
449
 
        assert(image->mt != mt);
450
 
        assert(dstlvl->valid);
451
 
        assert(dstlvl->width == image->base.Width);
452
 
        assert(dstlvl->height == image->base.Height);
453
 
        assert(dstlvl->depth == image->base.Depth);
454
 
 
455
 
        radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
456
 
                        "%s miptree %p, image %p, face %d, level %d.\n",
457
 
                        __func__, mt, image, face, level);
458
 
 
459
 
        radeon_bo_map(mt->bo, GL_TRUE);
460
 
        dest = mt->bo->ptr + dstlvl->faces[face].offset;
461
 
 
462
 
        if (image->mt) {
463
 
                /* Format etc. should match, so we really just need a memcpy().
464
 
                 * In fact, that memcpy() could be done by the hardware in many
465
 
                 * cases, provided that we have a proper memory manager.
466
 
                 */
467
 
                assert(mt->mesaFormat == image->base.TexFormat);
468
 
 
469
 
                radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
470
 
 
471
 
                assert(image->mtlevel == level);
472
 
                assert(srclvl->size == dstlvl->size);
473
 
                assert(srclvl->rowstride == dstlvl->rowstride);
474
 
 
475
 
                radeon_bo_map(image->mt->bo, GL_FALSE);
476
 
 
477
 
                memcpy(dest,
478
 
                        image->mt->bo->ptr + srclvl->faces[face].offset,
479
 
                        dstlvl->size);
480
 
                radeon_bo_unmap(image->mt->bo);
481
 
 
482
 
                radeon_miptree_unreference(&image->mt);
483
 
        } else if (image->base.Data) {
484
 
                /* This condition should be removed, it's here to workaround
485
 
                 * a segfault when mapping textures during software fallbacks.
486
 
                 */
487
 
                radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT,
488
 
                                "%s Trying to map texture in sowftware fallback.\n",
489
 
                                __func__);
490
 
                const uint32_t srcrowstride = _mesa_format_row_stride(image->base.TexFormat, image->base.Width);
491
 
                uint32_t rows = image->base.Height * image->base.Depth;
492
 
 
493
 
                if (_mesa_is_format_compressed(image->base.TexFormat)) {
494
 
                        uint32_t blockWidth, blockHeight;
495
 
                        _mesa_get_format_block_size(image->base.TexFormat, &blockWidth, &blockHeight);
496
 
                        rows = (rows + blockHeight - 1) / blockHeight;
497
 
                }
498
 
 
499
 
                copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
500
 
                                  rows, srcrowstride);
501
 
 
502
 
                _mesa_free_texmemory(image->base.Data);
503
 
                image->base.Data = 0;
504
 
        }
505
 
 
506
 
        radeon_bo_unmap(mt->bo);
507
 
 
508
 
        radeon_miptree_reference(mt, &image->mt);
509
 
        image->mtface = face;
510
 
        image->mtlevel = level;
511
 
}
512
 
 
513
 
/**
514
 
 * Filter matching miptrees, and select one with the most of data.
515
 
 * @param[in] texObj radeon texture object
516
 
 * @param[in] firstLevel first texture level to check
517
 
 * @param[in] lastLevel last texture level to check
518
 
 */
519
 
static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
520
 
                                                                                                                 unsigned firstLevel,
521
 
                                                                                                                 unsigned lastLevel)
522
 
{
523
 
        const unsigned numLevels = lastLevel - firstLevel + 1;
524
 
        unsigned *mtSizes = calloc(numLevels, sizeof(unsigned));
525
 
        radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *));
526
 
        unsigned mtCount = 0;
527
 
        unsigned maxMtIndex = 0;
528
 
        radeon_mipmap_tree *tmp;
529
 
        unsigned int level;
530
 
        int i;
531
 
 
532
 
        for (level = firstLevel; level <= lastLevel; ++level) {
533
 
                radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]);
534
 
                unsigned found = 0;
535
 
                // TODO: why this hack??
536
 
                if (!img)
537
 
                        break;
538
 
 
539
 
                if (!img->mt)
540
 
                        continue;
541
 
 
542
 
                for (i = 0; i < mtCount; ++i) {
543
 
                        if (mts[i] == img->mt) {
544
 
                                found = 1;
545
 
                                mtSizes[i] += img->mt->levels[img->mtlevel].size;
546
 
                                break;
547
 
                        }
548
 
                }
549
 
 
550
 
                if (!found && radeon_miptree_matches_texture(img->mt, &texObj->base)) {
551
 
                        mtSizes[mtCount] = img->mt->levels[img->mtlevel].size;
552
 
                        mts[mtCount] = img->mt;
553
 
                        mtCount++;
554
 
                }
555
 
        }
556
 
 
557
 
        if (mtCount == 0) {
558
 
                free(mtSizes);
559
 
                free(mts);
560
 
                return NULL;
561
 
        }
562
 
 
563
 
        for (i = 1; i < mtCount; ++i) {
564
 
                if (mtSizes[i] > mtSizes[maxMtIndex]) {
565
 
                        maxMtIndex = i;
566
 
                }
567
 
        }
568
 
 
569
 
        tmp = mts[maxMtIndex];
570
 
        free(mtSizes);
571
 
        free(mts);
572
 
 
573
 
        return tmp;
574
 
}
575
 
 
576
 
/**
577
 
 * Validate texture mipmap tree.
578
 
 * If individual images are stored in different mipmap trees
579
 
 * use the mipmap tree that has the most of the correct data.
580
 
 */
581
 
int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_texture_object *texObj)
582
 
{
583
 
        radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
584
 
        radeonTexObj *t = radeon_tex_obj(texObj);
585
 
 
586
 
        if (t->validated || t->image_override) {
587
 
                return GL_TRUE;
588
 
        }
589
 
 
590
 
        if (texObj->Image[0][texObj->BaseLevel]->Border > 0)
591
 
                return GL_FALSE;
592
 
 
593
 
        _mesa_test_texobj_completeness(rmesa->glCtx, texObj);
594
 
        if (!texObj->_Complete) {
595
 
                return GL_FALSE;
596
 
        }
597
 
 
598
 
        calculate_min_max_lod(&t->base, &t->minLod, &t->maxLod);
599
 
 
600
 
        radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
601
 
                        "%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
602
 
                        __FUNCTION__, texObj ,t->minLod, t->maxLod);
603
 
 
604
 
        radeon_mipmap_tree *dst_miptree;
605
 
        dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base.MaxLevel);
606
 
 
607
 
        radeon_miptree_unreference(&t->mt);
608
 
        if (!dst_miptree) {
609
 
                radeon_try_alloc_miptree(rmesa, t);
610
 
                radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
611
 
                        "%s: No matching miptree found, allocated new one %p\n",
612
 
                        __FUNCTION__, t->mt);
613
 
 
614
 
        } else {
615
 
                radeon_miptree_reference(dst_miptree, &t->mt);
616
 
                radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
617
 
                        "%s: Using miptree %p\n", __FUNCTION__, t->mt);
618
 
        }
619
 
 
620
 
        const unsigned faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
621
 
        unsigned face, level;
622
 
        radeon_texture_image *img;
623
 
        /* Validate only the levels that will actually be used during rendering */
624
 
        for (face = 0; face < faces; ++face) {
625
 
                for (level = t->minLod; level <= t->maxLod; ++level) {
626
 
                        img = get_radeon_texture_image(texObj->Image[face][level]);
627
 
 
628
 
                        radeon_print(RADEON_TEXTURE, RADEON_TRACE,
629
 
                                "Checking image level %d, face %d, mt %p ... ",
630
 
                                level, face, img->mt);
631
 
                        
632
 
                        if (img->mt != t->mt) {
633
 
                                radeon_print(RADEON_TEXTURE, RADEON_TRACE,
634
 
                                        "MIGRATING\n");
635
 
 
636
 
                                struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo;
637
 
                                if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) {
638
 
                                        radeon_firevertices(rmesa);
639
 
                                }
640
 
                                migrate_image_to_miptree(t->mt, img, face, level);
641
 
                        } else
642
 
                                radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n");
643
 
                }
644
 
        }
645
 
 
646
 
        t->validated = GL_TRUE;
647
 
 
648
 
        return GL_TRUE;
649
 
}
650
 
 
651
 
uint32_t get_base_teximage_offset(radeonTexObj *texObj)
652
 
{
653
 
        if (!texObj->mt) {
654
 
                return 0;
655
 
        } else {
656
 
                return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod);
657
 
        }
658
 
}