swrast: s/Data/Map/ in swrast_texture_image
[profile/ivi/mesa.git] / src / mesa / drivers / dri / radeon / radeon_mipmap_tree.c
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, GLuint target)
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) || target == GL_TEXTURE_RECTANGLE) {
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, mt->target);
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(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 /**
186  * Create a new mipmap tree, calculate its layout and allocate memory.
187  */
188 radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
189                                           GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
190                                           GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
191 {
192         radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
193
194         radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
195                 "%s(%p) new tree is %p.\n",
196                 __func__, rmesa, mt);
197
198         mt->mesaFormat = mesaFormat;
199         mt->refcount = 1;
200         mt->target = target;
201         mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
202         mt->baseLevel = baseLevel;
203         mt->numLevels = numLevels;
204         mt->width0 = width0;
205         mt->height0 = height0;
206         mt->depth0 = depth0;
207         mt->tilebits = tilebits;
208
209         calculate_miptree_layout(rmesa, mt);
210
211         mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
212                             0, mt->totalsize, 1024,
213                             RADEON_GEM_DOMAIN_VRAM,
214                             0);
215
216         return mt;
217 }
218
219 void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr)
220 {
221         assert(!*ptr);
222
223         mt->refcount++;
224         assert(mt->refcount > 0);
225
226         *ptr = mt;
227 }
228
229 void radeon_miptree_unreference(radeon_mipmap_tree **ptr)
230 {
231         radeon_mipmap_tree *mt = *ptr;
232         if (!mt)
233                 return;
234
235         assert(mt->refcount > 0);
236
237         mt->refcount--;
238         if (!mt->refcount) {
239                 radeon_bo_unref(mt->bo);
240                 free(mt);
241         }
242
243         *ptr = 0;
244 }
245
246 /**
247  * Calculate min and max LOD for the given texture object.
248  * @param[in] tObj texture object whose LOD values to calculate
249  * @param[out] pminLod minimal LOD
250  * @param[out] pmaxLod maximal LOD
251  */
252 static void calculate_min_max_lod(struct gl_texture_object *tObj,
253                                        unsigned *pminLod, unsigned *pmaxLod)
254 {
255         int minLod, maxLod;
256         /* Yes, this looks overly complicated, but it's all needed.
257         */
258         switch (tObj->Target) {
259         case GL_TEXTURE_1D:
260         case GL_TEXTURE_2D:
261         case GL_TEXTURE_3D:
262         case GL_TEXTURE_CUBE_MAP:
263                 if (tObj->Sampler.MinFilter == GL_NEAREST || tObj->Sampler.MinFilter == GL_LINEAR) {
264                         /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
265                         */
266                         minLod = maxLod = tObj->BaseLevel;
267                 } else {
268                         minLod = tObj->BaseLevel + (GLint)(tObj->Sampler.MinLod);
269                         minLod = MAX2(minLod, tObj->BaseLevel);
270                         minLod = MIN2(minLod, tObj->MaxLevel);
271                         maxLod = tObj->BaseLevel + (GLint)(tObj->Sampler.MaxLod + 0.5);
272                         maxLod = MIN2(maxLod, tObj->MaxLevel);
273                         maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxLog2 + minLod);
274                         maxLod = MAX2(maxLod, minLod); /* need at least one level */
275                 }
276                 break;
277         case GL_TEXTURE_RECTANGLE_NV:
278         case GL_TEXTURE_4D_SGIS:
279                 minLod = maxLod = 0;
280                 break;
281         default:
282                 return;
283         }
284
285         radeon_print(RADEON_TEXTURE, RADEON_TRACE,
286                         "%s(%p) target %s, min %d, max %d.\n",
287                         __func__, tObj,
288                         _mesa_lookup_enum_by_nr(tObj->Target),
289                         minLod, maxLod);
290
291         /* save these values */
292         *pminLod = minLod;
293         *pmaxLod = maxLod;
294 }
295
296 /**
297  * Checks whether the given miptree can hold the given texture image at the
298  * given face and level.
299  */
300 GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
301                                        struct gl_texture_image *texImage)
302 {
303         radeon_mipmap_level *lvl;
304         GLuint level = texImage->Level;
305         if (texImage->TexFormat != mt->mesaFormat)
306                 return GL_FALSE;
307
308         lvl = &mt->levels[level];
309         if (!lvl->valid ||
310             lvl->width != texImage->Width ||
311             lvl->height != texImage->Height ||
312             lvl->depth != texImage->Depth)
313                 return GL_FALSE;
314
315         return GL_TRUE;
316 }
317
318 /**
319  * Checks whether the given miptree has the right format to store the given texture object.
320  */
321 static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
322 {
323         struct gl_texture_image *firstImage;
324         unsigned numLevels;
325         radeon_mipmap_level *mtBaseLevel;
326
327         if (texObj->BaseLevel < mt->baseLevel)
328                 return GL_FALSE;
329
330         mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
331         firstImage = texObj->Image[0][texObj->BaseLevel];
332         numLevels = MIN2(texObj->_MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
333
334         if (radeon_is_debug_enabled(RADEON_TEXTURE,RADEON_TRACE)) {
335                 fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
336                 fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
337                 fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
338                 fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
339                 fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
340                 fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height);
341                 fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth);
342                 if (mt->target == texObj->Target &&
343                 mt->mesaFormat == firstImage->TexFormat &&
344                 mt->numLevels >= numLevels &&
345                 mtBaseLevel->width == firstImage->Width &&
346                 mtBaseLevel->height == firstImage->Height &&
347                 mtBaseLevel->depth == firstImage->Depth) {
348                         fprintf(stderr, "MATCHED\n");
349                 } else {
350                         fprintf(stderr, "NOT MATCHED\n");
351                 }
352         }
353
354         return (mt->target == texObj->Target &&
355                 mt->mesaFormat == firstImage->TexFormat &&
356                 mt->numLevels >= numLevels &&
357                 mtBaseLevel->width == firstImage->Width &&
358                 mtBaseLevel->height == firstImage->Height &&
359                 mtBaseLevel->depth == firstImage->Depth);
360 }
361
362 /**
363  * Try to allocate a mipmap tree for the given texture object.
364  * @param[in] rmesa radeon context
365  * @param[in] t radeon texture object
366  */
367 void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
368 {
369         struct gl_texture_object *texObj = &t->base;
370         struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
371         GLuint numLevels;
372         assert(!t->mt);
373
374         if (!texImg) {
375                 radeon_warning("%s(%p) No image in given texture object(%p).\n",
376                                 __func__, rmesa, t);
377                 return;
378         }
379
380
381         numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxLog2 + 1);
382
383         t->mt = radeon_miptree_create(rmesa, t->base.Target,
384                 texImg->TexFormat, texObj->BaseLevel,
385                 numLevels, texImg->Width, texImg->Height,
386                 texImg->Depth, t->tile_bits);
387 }
388
389 GLuint
390 radeon_miptree_image_offset(radeon_mipmap_tree *mt,
391                             GLuint face, GLuint level)
392 {
393         if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
394                 return (mt->levels[level].faces[face].offset);
395         else
396                 return mt->levels[level].faces[0].offset;
397 }
398
399 /**
400  * Ensure that the given image is stored in the given miptree from now on.
401  */
402 static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
403                                                                          radeon_texture_image *image,
404                                                                          int face, int level)
405 {
406         radeon_mipmap_level *dstlvl = &mt->levels[level];
407         unsigned char *dest;
408
409         assert(image->mt != mt);
410         assert(dstlvl->valid);
411         assert(dstlvl->width == image->base.Base.Width);
412         assert(dstlvl->height == image->base.Base.Height);
413         assert(dstlvl->depth == image->base.Base.Depth);
414
415         radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
416                         "%s miptree %p, image %p, face %d, level %d.\n",
417                         __func__, mt, image, face, level);
418
419         radeon_bo_map(mt->bo, GL_TRUE);
420         dest = mt->bo->ptr + dstlvl->faces[face].offset;
421
422         if (image->mt) {
423                 /* Format etc. should match, so we really just need a memcpy().
424                  * In fact, that memcpy() could be done by the hardware in many
425                  * cases, provided that we have a proper memory manager.
426                  */
427                 assert(mt->mesaFormat == image->base.Base.TexFormat);
428
429                 radeon_mipmap_level *srclvl = &image->mt->levels[image->base.Base.Level];
430
431                 assert(image->base.Base.Level == level);
432                 assert(srclvl->size == dstlvl->size);
433                 assert(srclvl->rowstride == dstlvl->rowstride);
434
435                 radeon_bo_map(image->mt->bo, GL_FALSE);
436
437                 memcpy(dest,
438                         image->mt->bo->ptr + srclvl->faces[face].offset,
439                         dstlvl->size);
440                 radeon_bo_unmap(image->mt->bo);
441
442                 radeon_miptree_unreference(&image->mt);
443         } else if (image->base.Map) {
444                 /* This condition should be removed, it's here to workaround
445                  * a segfault when mapping textures during software fallbacks.
446                  */
447                 radeon_print(RADEON_FALLBACKS, RADEON_IMPORTANT,
448                                 "%s Trying to map texture in sowftware fallback.\n",
449                                 __func__);
450                 const uint32_t srcrowstride = _mesa_format_row_stride(image->base.Base.TexFormat, image->base.Base.Width);
451                 uint32_t rows = image->base.Base.Height * image->base.Base.Depth;
452
453                 if (_mesa_is_format_compressed(image->base.Base.TexFormat)) {
454                         uint32_t blockWidth, blockHeight;
455                         _mesa_get_format_block_size(image->base.Base.TexFormat, &blockWidth, &blockHeight);
456                         rows = (rows + blockHeight - 1) / blockHeight;
457                 }
458
459                 copy_rows(dest, dstlvl->rowstride, image->base.Map, srcrowstride,
460                                   rows, srcrowstride);
461
462                 _mesa_align_free(image->base.Map);
463                 image->base.Map = 0;
464         }
465
466         radeon_bo_unmap(mt->bo);
467
468         radeon_miptree_reference(mt, &image->mt);
469 }
470
471 /**
472  * Filter matching miptrees, and select one with the most of data.
473  * @param[in] texObj radeon texture object
474  * @param[in] firstLevel first texture level to check
475  * @param[in] lastLevel last texture level to check
476  */
477 static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
478                                                                                                                  unsigned firstLevel,
479                                                                                                                  unsigned lastLevel)
480 {
481         const unsigned numLevels = lastLevel - firstLevel + 1;
482         unsigned *mtSizes = calloc(numLevels, sizeof(unsigned));
483         radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *));
484         unsigned mtCount = 0;
485         unsigned maxMtIndex = 0;
486         radeon_mipmap_tree *tmp;
487         unsigned int level;
488         int i;
489
490         for (level = firstLevel; level <= lastLevel; ++level) {
491                 radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]);
492                 unsigned found = 0;
493                 // TODO: why this hack??
494                 if (!img)
495                         break;
496
497                 if (!img->mt)
498                         continue;
499
500                 for (i = 0; i < mtCount; ++i) {
501                         if (mts[i] == img->mt) {
502                                 found = 1;
503                                 mtSizes[i] += img->mt->levels[img->base.Base.Level].size;
504                                 break;
505                         }
506                 }
507
508                 if (!found && radeon_miptree_matches_texture(img->mt, &texObj->base)) {
509                         mtSizes[mtCount] = img->mt->levels[img->base.Base.Level].size;
510                         mts[mtCount] = img->mt;
511                         mtCount++;
512                 }
513         }
514
515         if (mtCount == 0) {
516                 free(mtSizes);
517                 free(mts);
518                 return NULL;
519         }
520
521         for (i = 1; i < mtCount; ++i) {
522                 if (mtSizes[i] > mtSizes[maxMtIndex]) {
523                         maxMtIndex = i;
524                 }
525         }
526
527         tmp = mts[maxMtIndex];
528         free(mtSizes);
529         free(mts);
530
531         return tmp;
532 }
533
534 /**
535  * Validate texture mipmap tree.
536  * If individual images are stored in different mipmap trees
537  * use the mipmap tree that has the most of the correct data.
538  */
539 int radeon_validate_texture_miptree(struct gl_context * ctx, struct gl_texture_object *texObj)
540 {
541         radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
542         radeonTexObj *t = radeon_tex_obj(texObj);
543         radeon_mipmap_tree *dst_miptree;
544
545         if (t->validated || t->image_override) {
546                 return GL_TRUE;
547         }
548
549         calculate_min_max_lod(&t->base, &t->minLod, &t->maxLod);
550
551         radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
552                         "%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
553                         __FUNCTION__, texObj ,t->minLod, t->maxLod);
554
555         dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base._MaxLevel);
556
557         radeon_miptree_unreference(&t->mt);
558         if (!dst_miptree) {
559                 radeon_try_alloc_miptree(rmesa, t);
560                 radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
561                         "%s: No matching miptree found, allocated new one %p\n",
562                         __FUNCTION__, t->mt);
563
564         } else {
565                 radeon_miptree_reference(dst_miptree, &t->mt);
566                 radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
567                         "%s: Using miptree %p\n", __FUNCTION__, t->mt);
568         }
569
570         const unsigned faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
571         unsigned face, level;
572         radeon_texture_image *img;
573         /* Validate only the levels that will actually be used during rendering */
574         for (face = 0; face < faces; ++face) {
575                 for (level = t->minLod; level <= t->maxLod; ++level) {
576                         img = get_radeon_texture_image(texObj->Image[face][level]);
577
578                         radeon_print(RADEON_TEXTURE, RADEON_TRACE,
579                                 "Checking image level %d, face %d, mt %p ... ",
580                                 level, face, img->mt);
581                         
582                         if (img->mt != t->mt && !img->used_as_render_target) {
583                                 radeon_print(RADEON_TEXTURE, RADEON_TRACE,
584                                         "MIGRATING\n");
585
586                                 struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo;
587                                 if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) {
588                                         radeon_firevertices(rmesa);
589                                 }
590                                 migrate_image_to_miptree(t->mt, img, face, level);
591                         } else
592                                 radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n");
593                 }
594         }
595
596         t->validated = GL_TRUE;
597
598         return GL_TRUE;
599 }
600
601 uint32_t get_base_teximage_offset(radeonTexObj *texObj)
602 {
603         if (!texObj->mt) {
604                 return 0;
605         } else {
606                 return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod);
607         }
608 }