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/teximage.h"
35#include "main/texobj.h"
36#include "main/enums.h"
37#include "radeon_texture.h"
38#include "radeon_tile.h"
39
40static unsigned get_aligned_compressed_row_stride(
41		mesa_format format,
42		unsigned width,
43		unsigned minStride)
44{
45	const unsigned blockBytes = _mesa_get_format_bytes(format);
46	unsigned blockWidth, blockHeight;
47	unsigned stride;
48
49	_mesa_get_format_block_size(format, &blockWidth, &blockHeight);
50
51	/* Count number of blocks required to store the given width.
52	 * And then multiple it with bytes required to store a block.
53	 */
54	stride = (width + blockWidth - 1) / blockWidth * blockBytes;
55
56	/* Round the given minimum stride to the next full blocksize.
57	 * (minStride + blockBytes - 1) / blockBytes * blockBytes
58	 */
59	if ( stride < minStride )
60		stride = (minStride + blockBytes - 1) / blockBytes * blockBytes;
61
62	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
63			"%s width %u, minStride %u, block(bytes %u, width %u):"
64			"stride %u\n",
65			__func__, width, minStride,
66			blockBytes, blockWidth,
67			stride);
68
69	return stride;
70}
71
72unsigned get_texture_image_size(
73		mesa_format format,
74		unsigned rowStride,
75		unsigned height,
76		unsigned depth,
77		unsigned tiling)
78{
79	if (_mesa_is_format_compressed(format)) {
80		unsigned blockWidth, blockHeight;
81
82		_mesa_get_format_block_size(format, &blockWidth, &blockHeight);
83
84		return rowStride * ((height + blockHeight - 1) / blockHeight) * depth;
85	} else if (tiling) {
86		/* Need to align height to tile height */
87		unsigned tileWidth, tileHeight;
88
89		get_tile_size(format, &tileWidth, &tileHeight);
90		tileHeight--;
91
92		height = (height + tileHeight) & ~tileHeight;
93	}
94
95	return rowStride * height * depth;
96}
97
98unsigned get_texture_image_row_stride(radeonContextPtr rmesa, mesa_format format, unsigned width, unsigned tiling, GLuint target)
99{
100	if (_mesa_is_format_compressed(format)) {
101		return get_aligned_compressed_row_stride(format, width, rmesa->texture_compressed_row_align);
102	} else {
103		unsigned row_align;
104
105		if (!_mesa_is_pow_two(width) || target == GL_TEXTURE_RECTANGLE) {
106			row_align = rmesa->texture_rect_row_align - 1;
107		} else if (tiling) {
108			unsigned tileWidth, tileHeight;
109			get_tile_size(format, &tileWidth, &tileHeight);
110			row_align = tileWidth * _mesa_get_format_bytes(format) - 1;
111		} else {
112			row_align = rmesa->texture_row_align - 1;
113		}
114
115		return (_mesa_format_row_stride(format, width) + row_align) & ~row_align;
116	}
117}
118
119/**
120 * Compute sizes and fill in offset and blit information for the given
121 * image (determined by \p face and \p level).
122 *
123 * \param curOffset points to the offset at which the image is to be stored
124 * and is updated by this function according to the size of the image.
125 */
126static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree *mt,
127	GLuint face, GLuint level, GLuint* curOffset)
128{
129	radeon_mipmap_level *lvl = &mt->levels[level];
130	GLuint height;
131
132	height = _mesa_next_pow_two_32(lvl->height);
133
134	lvl->rowstride = get_texture_image_row_stride(rmesa, mt->mesaFormat, lvl->width, mt->tilebits, mt->target);
135	lvl->size = get_texture_image_size(mt->mesaFormat, lvl->rowstride, height, lvl->depth, mt->tilebits);
136
137	assert(lvl->size > 0);
138
139	lvl->faces[face].offset = *curOffset;
140	*curOffset += lvl->size;
141
142	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
143			"%s(%p) level %d, face %d: rs:%d %dx%d at %d\n",
144			__func__, rmesa,
145			level, face,
146			lvl->rowstride, lvl->width, height, lvl->faces[face].offset);
147}
148
149static void calculate_miptree_layout(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
150{
151	GLuint curOffset, i, face, level;
152
153	assert(mt->numLevels <= rmesa->glCtx.Const.MaxTextureLevels);
154
155	curOffset = 0;
156	for(face = 0; face < mt->faces; face++) {
157
158		for(i = 0, level = mt->baseLevel; i < mt->numLevels; i++, level++) {
159			mt->levels[level].valid = 1;
160			mt->levels[level].width = minify(mt->width0, i);
161			mt->levels[level].height = minify(mt->height0, i);
162			mt->levels[level].depth = minify(mt->depth0, i);
163			compute_tex_image_offset(rmesa, mt, face, level, &curOffset);
164		}
165	}
166
167	/* Note the required size in memory */
168	mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
169
170	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
171			"%s(%p, %p) total size %d\n",
172			__func__, rmesa, mt, mt->totalsize);
173}
174
175/**
176 * Create a new mipmap tree, calculate its layout and allocate memory.
177 */
178radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
179					  GLenum target, mesa_format mesaFormat, GLuint baseLevel, GLuint numLevels,
180					  GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
181{
182	radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
183
184	radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
185		"%s(%p) new tree is %p.\n",
186		__func__, rmesa, mt);
187
188	mt->mesaFormat = mesaFormat;
189	mt->refcount = 1;
190	mt->target = target;
191	mt->faces = _mesa_num_tex_faces(target);
192	mt->baseLevel = baseLevel;
193	mt->numLevels = numLevels;
194	mt->width0 = width0;
195	mt->height0 = height0;
196	mt->depth0 = depth0;
197	mt->tilebits = tilebits;
198
199	calculate_miptree_layout(rmesa, mt);
200
201	mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
202                            0, mt->totalsize, 1024,
203                            RADEON_GEM_DOMAIN_VRAM,
204                            0);
205
206	return mt;
207}
208
209void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr)
210{
211	assert(!*ptr);
212
213	mt->refcount++;
214	assert(mt->refcount > 0);
215
216	*ptr = mt;
217}
218
219void radeon_miptree_unreference(radeon_mipmap_tree **ptr)
220{
221	radeon_mipmap_tree *mt = *ptr;
222	if (!mt)
223		return;
224
225	assert(mt->refcount > 0);
226
227	mt->refcount--;
228	if (!mt->refcount) {
229		radeon_bo_unref(mt->bo);
230		free(mt);
231	}
232
233	*ptr = 0;
234}
235
236/**
237 * Calculate min and max LOD for the given texture object.
238 * @param[in] tObj texture object whose LOD values to calculate
239 * @param[out] pminLod minimal LOD
240 * @param[out] pmaxLod maximal LOD
241 */
242static void calculate_min_max_lod(struct gl_sampler_object *samp, struct gl_texture_object *tObj,
243				       unsigned *pminLod, unsigned *pmaxLod)
244{
245	int minLod, maxLod;
246	/* Yes, this looks overly complicated, but it's all needed.
247	*/
248	switch (tObj->Target) {
249	case GL_TEXTURE_1D:
250	case GL_TEXTURE_2D:
251	case GL_TEXTURE_3D:
252	case GL_TEXTURE_CUBE_MAP:
253		if (samp->MinFilter == GL_NEAREST || samp->MinFilter == GL_LINEAR) {
254			/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
255			*/
256			minLod = maxLod = tObj->BaseLevel;
257		} else {
258			minLod = tObj->BaseLevel + (GLint)(samp->MinLod);
259			minLod = MAX2(minLod, tObj->BaseLevel);
260			minLod = MIN2(minLod, tObj->MaxLevel);
261			maxLod = tObj->BaseLevel + (GLint)(samp->MaxLod + 0.5);
262			maxLod = MIN2(maxLod, tObj->MaxLevel);
263			maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxNumLevels - 1 + minLod);
264			maxLod = MAX2(maxLod, minLod); /* need at least one level */
265		}
266		break;
267	case GL_TEXTURE_RECTANGLE_NV:
268	case GL_TEXTURE_4D_SGIS:
269		minLod = maxLod = 0;
270		break;
271	default:
272		return;
273	}
274
275	radeon_print(RADEON_TEXTURE, RADEON_TRACE,
276			"%s(%p) target %s, min %d, max %d.\n",
277			__func__, tObj,
278			_mesa_enum_to_string(tObj->Target),
279			minLod, maxLod);
280
281	/* save these values */
282	*pminLod = minLod;
283	*pmaxLod = maxLod;
284}
285
286/**
287 * Checks whether the given miptree can hold the given texture image at the
288 * given face and level.
289 */
290GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
291				       struct gl_texture_image *texImage)
292{
293	radeon_mipmap_level *lvl;
294	GLuint level = texImage->Level;
295	if (texImage->TexFormat != mt->mesaFormat)
296		return GL_FALSE;
297
298	lvl = &mt->levels[level];
299	if (!lvl->valid ||
300	    lvl->width != texImage->Width ||
301	    lvl->height != texImage->Height ||
302	    lvl->depth != texImage->Depth)
303		return GL_FALSE;
304
305	return GL_TRUE;
306}
307
308/**
309 * Checks whether the given miptree has the right format to store the given texture object.
310 */
311static GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
312{
313	struct gl_texture_image *firstImage;
314	unsigned numLevels;
315	radeon_mipmap_level *mtBaseLevel;
316
317	if (texObj->BaseLevel < mt->baseLevel)
318		return GL_FALSE;
319
320	mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
321	firstImage = texObj->Image[0][texObj->BaseLevel];
322	numLevels = MIN2(texObj->_MaxLevel - texObj->BaseLevel + 1, firstImage->MaxNumLevels);
323
324	if (radeon_is_debug_enabled(RADEON_TEXTURE,RADEON_TRACE)) {
325		fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
326		fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
327		fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
328		fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
329		fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
330		fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height);
331		fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth);
332		if (mt->target == texObj->Target &&
333	        mt->mesaFormat == firstImage->TexFormat &&
334	        mt->numLevels >= numLevels &&
335	        mtBaseLevel->width == firstImage->Width &&
336	        mtBaseLevel->height == firstImage->Height &&
337	        mtBaseLevel->depth == firstImage->Depth) {
338			fprintf(stderr, "MATCHED\n");
339		} else {
340			fprintf(stderr, "NOT MATCHED\n");
341		}
342	}
343
344	return (mt->target == texObj->Target &&
345	        mt->mesaFormat == firstImage->TexFormat &&
346	        mt->numLevels >= numLevels &&
347	        mtBaseLevel->width == firstImage->Width &&
348	        mtBaseLevel->height == firstImage->Height &&
349	        mtBaseLevel->depth == firstImage->Depth);
350}
351
352/**
353 * Try to allocate a mipmap tree for the given texture object.
354 * @param[in] rmesa radeon context
355 * @param[in] t radeon texture object
356 */
357void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
358{
359	struct gl_texture_object *texObj = &t->base;
360	struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
361	GLuint numLevels;
362	assert(!t->mt);
363
364	if (!texImg) {
365		radeon_warning("%s(%p) No image in given texture object(%p).\n",
366				__func__, rmesa, t);
367		return;
368	}
369
370
371	numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxNumLevels);
372
373	t->mt = radeon_miptree_create(rmesa, t->base.Target,
374		texImg->TexFormat, texObj->BaseLevel,
375		numLevels, texImg->Width, texImg->Height,
376		texImg->Depth, t->tile_bits);
377}
378
379GLuint
380radeon_miptree_image_offset(radeon_mipmap_tree *mt,
381			    GLuint face, GLuint level)
382{
383	if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
384		return (mt->levels[level].faces[face].offset);
385	else
386		return mt->levels[level].faces[0].offset;
387}
388
389/**
390 * Ensure that the given image is stored in the given miptree from now on.
391 */
392static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
393									 radeon_texture_image *image,
394									 int face, int level)
395{
396	radeon_mipmap_level *dstlvl = &mt->levels[level];
397	unsigned char *dest;
398
399	assert(image->mt != mt);
400	assert(dstlvl->valid);
401	assert(dstlvl->width == image->base.Base.Width);
402	assert(dstlvl->height == image->base.Base.Height);
403	assert(dstlvl->depth == image->base.Base.Depth);
404
405	radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
406			"%s miptree %p, image %p, face %d, level %d.\n",
407			__func__, mt, image, face, level);
408
409	radeon_bo_map(mt->bo, GL_TRUE);
410	dest = mt->bo->ptr + dstlvl->faces[face].offset;
411
412	if (image->mt) {
413		/* Format etc. should match, so we really just need a memcpy().
414		 * In fact, that memcpy() could be done by the hardware in many
415		 * cases, provided that we have a proper memory manager.
416		 */
417		assert(mt->mesaFormat == image->base.Base.TexFormat);
418
419		radeon_mipmap_level *srclvl = &image->mt->levels[image->base.Base.Level];
420
421		assert(image->base.Base.Level == level);
422		assert(srclvl->size == dstlvl->size);
423		assert(srclvl->rowstride == dstlvl->rowstride);
424
425		radeon_bo_map(image->mt->bo, GL_FALSE);
426
427		memcpy(dest,
428			image->mt->bo->ptr + srclvl->faces[face].offset,
429			dstlvl->size);
430		radeon_bo_unmap(image->mt->bo);
431
432		radeon_miptree_unreference(&image->mt);
433	}
434
435	radeon_bo_unmap(mt->bo);
436
437	radeon_miptree_reference(mt, &image->mt);
438}
439
440/**
441 * Filter matching miptrees, and select one with the most of data.
442 * @param[in] texObj radeon texture object
443 * @param[in] firstLevel first texture level to check
444 * @param[in] lastLevel last texture level to check
445 */
446static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
447														 unsigned firstLevel,
448														 unsigned lastLevel)
449{
450	const unsigned numLevels = lastLevel - firstLevel + 1;
451	unsigned *mtSizes = calloc(numLevels, sizeof(unsigned));
452	radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *));
453	unsigned mtCount = 0;
454	unsigned maxMtIndex = 0;
455	radeon_mipmap_tree *tmp;
456	unsigned int level;
457	int i;
458
459	for (level = firstLevel; level <= lastLevel; ++level) {
460		radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]);
461		unsigned found = 0;
462		// TODO: why this hack??
463		if (!img)
464			break;
465
466		if (!img->mt)
467			continue;
468
469		for (i = 0; i < mtCount; ++i) {
470			if (mts[i] == img->mt) {
471				found = 1;
472				mtSizes[i] += img->mt->levels[img->base.Base.Level].size;
473				break;
474			}
475		}
476
477		if (!found && radeon_miptree_matches_texture(img->mt, &texObj->base)) {
478			mtSizes[mtCount] = img->mt->levels[img->base.Base.Level].size;
479			mts[mtCount] = img->mt;
480			mtCount++;
481		}
482	}
483
484	if (mtCount == 0) {
485		free(mtSizes);
486		free(mts);
487		return NULL;
488	}
489
490	for (i = 1; i < mtCount; ++i) {
491		if (mtSizes[i] > mtSizes[maxMtIndex]) {
492			maxMtIndex = i;
493		}
494	}
495
496	tmp = mts[maxMtIndex];
497	free(mtSizes);
498	free(mts);
499
500	return tmp;
501}
502
503/**
504 * Validate texture mipmap tree.
505 * If individual images are stored in different mipmap trees
506 * use the mipmap tree that has the most of the correct data.
507 */
508int radeon_validate_texture_miptree(struct gl_context * ctx,
509				    struct gl_sampler_object *samp,
510				    struct gl_texture_object *texObj)
511{
512	radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
513	radeonTexObj *t = radeon_tex_obj(texObj);
514	radeon_mipmap_tree *dst_miptree;
515
516	if (samp == &texObj->Sampler && (t->validated || t->image_override)) {
517		return GL_TRUE;
518	}
519
520	calculate_min_max_lod(samp, &t->base, &t->minLod, &t->maxLod);
521
522	radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
523			"%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
524			__func__, texObj ,t->minLod, t->maxLod);
525
526	dst_miptree = get_biggest_matching_miptree(t, t->base.BaseLevel, t->base._MaxLevel);
527
528	radeon_miptree_unreference(&t->mt);
529	if (!dst_miptree) {
530		radeon_try_alloc_miptree(rmesa, t);
531		radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
532			"%s: No matching miptree found, allocated new one %p\n",
533			__func__, t->mt);
534
535	} else {
536		radeon_miptree_reference(dst_miptree, &t->mt);
537		radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
538			"%s: Using miptree %p\n", __func__, t->mt);
539	}
540
541	const unsigned faces = _mesa_num_tex_faces(texObj->Target);
542	unsigned face, level;
543	radeon_texture_image *img;
544	/* Validate only the levels that will actually be used during rendering */
545	for (face = 0; face < faces; ++face) {
546		for (level = t->minLod; level <= t->maxLod; ++level) {
547			img = get_radeon_texture_image(texObj->Image[face][level]);
548
549			radeon_print(RADEON_TEXTURE, RADEON_TRACE,
550				"Checking image level %d, face %d, mt %p ... ",
551				level, face, img->mt);
552
553			if (img->mt != t->mt && !img->used_as_render_target) {
554				radeon_print(RADEON_TEXTURE, RADEON_TRACE,
555					"MIGRATING\n");
556
557				struct radeon_bo *src_bo = (img->mt) ? img->mt->bo : img->bo;
558				if (src_bo && radeon_bo_is_referenced_by_cs(src_bo, rmesa->cmdbuf.cs)) {
559					radeon_firevertices(rmesa);
560				}
561				migrate_image_to_miptree(t->mt, img, face, level);
562			} else
563				radeon_print(RADEON_TEXTURE, RADEON_TRACE, "OK\n");
564		}
565	}
566
567	t->validated = GL_TRUE;
568
569	return GL_TRUE;
570}
571
572uint32_t get_base_teximage_offset(radeonTexObj *texObj)
573{
574	if (!texObj->mt) {
575		return 0;
576	} else {
577		return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod);
578	}
579}
580