radeon_mipmap_tree.c revision dc8a707c672918b88dd4135930bef60ed148d8ce
18bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/*
28bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Copyright (C) 2008 Nicolai Haehnle.
38bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
48bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * All Rights Reserved.
58bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
68bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Permission is hereby granted, free of charge, to any person obtaining
78bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * a copy of this software and associated documentation files (the
88bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * "Software"), to deal in the Software without restriction, including
98bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * without limitation the rights to use, copy, modify, merge, publish,
108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * distribute, sublicense, and/or sell copies of the Software, and to
118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * permit persons to whom the Software is furnished to do so, subject to
128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * the following conditions:
138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * The above copyright notice and this permission notice (including the
158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * next paragraph) shall be included in all copies or substantial
168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * portions of the Software.
178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "radeon_mipmap_tree.h"
298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include <errno.h>
318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include <unistd.h>
328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "main/simple_list.h"
348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "main/texcompress.h"
358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling#include "main/texformat.h"
368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingstatic GLuint radeon_compressed_texture_size(GLcontext *ctx,
388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLsizei width, GLsizei height, GLsizei depth,
398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLuint mesaFormat)
408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint size = _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (mesaFormat == MESA_FORMAT_RGB_DXT1 ||
448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	    mesaFormat == MESA_FORMAT_RGBA_DXT1) {
458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		if (width + 3 < 8)	/* width one block */
468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			size = size * 4;
478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		else if (width + 3 < 16)
488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			size = size * 2;
498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	} else {
508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		/* DXT3/5, 16 bytes per block */
518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	  //		WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		if (width + 3 < 8)
538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			size = size * 2;
548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	}
558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	return size;
578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/**
608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Compute sizes and fill in offset and blit information for the given
618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * image (determined by \p face and \p level).
628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling *
638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * \param curOffset points to the offset at which the image is to be stored
648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * and is updated by this function according to the size of the image.
658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
668bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingstatic void compute_tex_image_offset(radeon_mipmap_tree *mt,
678bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint face, GLuint level, GLuint* curOffset)
688bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
698bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	radeon_mipmap_level *lvl = &mt->levels[level];
708bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
718bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* Find image size in bytes */
728bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (mt->compressed) {
738bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		/* TODO: Is this correct? Need test cases for compressed textures! */
748bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLuint align;
758bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
768bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		if (mt->target == GL_TEXTURE_RECTANGLE_NV)
778bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			align = 64 / mt->bpp;
788bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		else
798bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			align = 32 / mt->bpp;
808bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->rowstride = (lvl->width + align - 1) & ~(align - 1);
818bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx,
828bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lvl->width, lvl->height, lvl->depth, mt->compressed);
838bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	} else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
848bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63;
858bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->size = lvl->rowstride * lvl->height;
868bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	} else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
878bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	  /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
888bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		 * though the actual offset may be different (if texture is less than
898bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		 * 32 bytes width) to the untiled case */
908bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31;
918bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
928bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	} else {
938bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->rowstride = (lvl->width * mt->bpp + 31) & ~31;
948bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		lvl->size = lvl->rowstride * lvl->height * lvl->depth;
958bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	}
968bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	assert(lvl->size > 0);
978bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
988bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* All images are aligned to a 32-byte offset */
998bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*curOffset = (*curOffset + 0x1f) & ~0x1f;
1008bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	lvl->faces[face].offset = *curOffset;
1018bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*curOffset += lvl->size;
1028bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1038bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (RADEON_DEBUG & DEBUG_TEXTURE)
1048bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	  fprintf(stderr,
1058bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		  "level %d, face %d: rs:%d %dx%d at %d\n",
1068bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		  level, face, lvl->rowstride, lvl->width, lvl->height, lvl->faces[face].offset);
1078bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1088bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1098bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingstatic GLuint minify(GLuint size, GLuint levels)
1108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	size = size >> levels;
1128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (size < 1)
1138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		size = 1;
1148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	return size;
1158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingstatic void calculate_miptree_layout(radeon_mipmap_tree *mt)
1188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint curOffset;
1208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint numLevels;
1218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint i;
1228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	numLevels = mt->lastLevel - mt->firstLevel + 1;
1248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
1258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	curOffset = 0;
1278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	for(i = 0; i < numLevels; i++) {
1288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLuint face;
1298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		mt->levels[i].width = minify(mt->width0, i);
1318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		mt->levels[i].height = minify(mt->height0, i);
1328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		mt->levels[i].depth = minify(mt->depth0, i);
1338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		for(face = 0; face < mt->faces; face++)
1358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			compute_tex_image_offset(mt, face, i, &curOffset);
1368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	}
1378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* Note the required size in memory */
1398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
1408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/**
1448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Create a new mipmap tree, calculate its layout and allocate memory.
1458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
1468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingradeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
1478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLenum target, GLuint firstLevel, GLuint lastLevel,
1488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLuint width0, GLuint height0, GLuint depth0,
1498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		GLuint bpp, GLuint tilebits, GLuint compressed)
1508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
1528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->radeon = rmesa;
1548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->refcount = 1;
1558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->t = t;
1568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->target = target;
1578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
1588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->firstLevel = firstLevel;
1598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->lastLevel = lastLevel;
1608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->width0 = width0;
1618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->height0 = height0;
1628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->depth0 = depth0;
1638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->bpp = bpp;
1648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->tilebits = tilebits;
1658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->compressed = compressed;
1668bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1678bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	calculate_miptree_layout(mt);
1688bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1698bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
1708bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                            0, mt->totalsize, 1024,
1718bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                            RADEON_GEM_DOMAIN_VRAM,
1728bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling                            0);
1738bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1748bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	return mt;
1758bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1768bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1778bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingvoid radeon_miptree_reference(radeon_mipmap_tree *mt)
1788bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1798bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->refcount++;
1808bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	assert(mt->refcount > 0);
1818bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1828bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1838bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingvoid radeon_miptree_unreference(radeon_mipmap_tree *mt)
1848bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
1858bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (!mt)
1868bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return;
1878bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1888bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	assert(mt->refcount > 0);
1898bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	mt->refcount--;
1908bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (!mt->refcount) {
1918bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		radeon_bo_unref(mt->bo);
1928bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		free(mt);
1938bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	}
1948bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
1958bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1968bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
1978bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingstatic void calculate_first_last_level(struct gl_texture_object *tObj,
1988bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling				       GLuint *pfirstLevel, GLuint *plastLevel)
1998bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
2008bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	const struct gl_texture_image * const baseImage =
2018bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		tObj->Image[0][tObj->BaseLevel];
2028bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2038bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* These must be signed values.  MinLod and MaxLod can be negative numbers,
2048bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	* and having firstLevel and lastLevel as signed prevents the need for
2058bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	* extra sign checks.
2068bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*/
2078bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	int   firstLevel;
2088bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	int   lastLevel;
2098bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* Yes, this looks overly complicated, but it's all needed.
2118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*/
2128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	switch (tObj->Target) {
2138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_1D:
2148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_2D:
2158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_3D:
2168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_CUBE_MAP:
2178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
2188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
2198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			*/
2208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			firstLevel = lastLevel = tObj->BaseLevel;
2218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		} else {
2228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
2238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			firstLevel = MAX2(firstLevel, tObj->BaseLevel);
2248bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
2258bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
2268bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lastLevel = MAX2(lastLevel, tObj->BaseLevel);
2278bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
2288bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lastLevel = MIN2(lastLevel, tObj->MaxLevel);
2298bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling			lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
2308bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		}
2318bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		break;
2328bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_RECTANGLE_NV:
2338bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	case GL_TEXTURE_4D_SGIS:
2348bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		firstLevel = lastLevel = 0;
2358bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		break;
2368bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	default:
2378bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return;
2388bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	}
2398bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2408bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	/* save these values */
2418bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*pfirstLevel = firstLevel;
2428bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	*plastLevel = lastLevel;
2438bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
2448bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2458bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2468bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/**
2478bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Checks whether the given miptree can hold the given texture image at the
2488bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * given face and level.
2498bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
2508bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha HaeberlingGLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
2518bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		struct gl_texture_image *texImage, GLuint face, GLuint level)
2528bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
2538bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	radeon_mipmap_level *lvl;
2548bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2558bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
2568bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return GL_FALSE;
2578bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2588bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (texImage->TexFormat->TexelBytes != mt->bpp)
2598bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return GL_FALSE;
2608bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2618bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	lvl = &mt->levels[level - mt->firstLevel];
2628bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (lvl->width != texImage->Width ||
2638bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	    lvl->height != texImage->Height ||
2648bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	    lvl->depth != texImage->Depth)
2658bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return GL_FALSE;
2668bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2678bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	return GL_TRUE;
2688bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
2698bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2708bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2718bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/**
2728bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Checks whether the given miptree has the right format to store the given texture object.
2738bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
2748bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha HaeberlingGLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
2758bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
2768bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	struct gl_texture_image *firstImage;
2778bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint compressed;
2788bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint numfaces = 1;
2798bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint firstLevel, lastLevel;
2808bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2818bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	calculate_first_last_level(texObj, &firstLevel, &lastLevel);
2828bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (texObj->Target == GL_TEXTURE_CUBE_MAP)
2838bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		numfaces = 6;
2848bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2858bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	firstImage = texObj->Image[0][firstLevel];
2868bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	compressed = firstImage->IsCompressed ? firstImage->TexFormat->MesaFormat : 0;
2878bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2888bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	return (mt->firstLevel == firstLevel &&
2898bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->lastLevel == lastLevel &&
2908bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->width0 == firstImage->Width &&
2918bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->height0 == firstImage->Height &&
2928bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->depth0 == firstImage->Depth &&
2938bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->bpp == firstImage->TexFormat->TexelBytes &&
2948bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	        mt->compressed == compressed);
2958bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
2968bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2978bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
2988bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling/**
2998bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * Try to allocate a mipmap tree for the given texture that will fit the
3008bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling * given image in the given position.
3018bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling */
3028bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberlingvoid radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
3038bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		struct gl_texture_image *texImage, GLuint face, GLuint level)
3048bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling{
3058bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint compressed = texImage->IsCompressed ? texImage->TexFormat->MesaFormat : 0;
3068bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint numfaces = 1;
3078bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	GLuint firstLevel, lastLevel;
3088bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
3098bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	assert(!t->mt);
3108bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
3118bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	calculate_first_last_level(&t->base, &firstLevel, &lastLevel);
3128bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (t->base.Target == GL_TEXTURE_CUBE_MAP)
3138bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		numfaces = 6;
3148bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
3158bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	if (level != firstLevel || face >= numfaces)
3168bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		return;
3178bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling
3188bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling	t->mt = radeon_miptree_create(rmesa, t, t->base.Target,
3198bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		firstLevel, lastLevel,
3208bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		texImage->Width, texImage->Height, texImage->Depth,
3218bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling		texImage->TexFormat->TexelBytes, t->tile_bits, compressed);
3228bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling}
3238bddf8ce4f3dcbb56edb12cee7e93f3a9daa3f96Sascha Haeberling