common_misc.c \
radeon_bo_legacy.c \
radeon_cs_legacy.c \
+ radeon_mipmap_tree.c \
$(EGL_SOURCES)
C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
common_lock.h \
common_misc.h \
common_misc.c \
- common_cmdbuf.h
+ common_cmdbuf.h \
+ radeon_mipmap_tree.c \
+ radeon_mipmap_tree.h
DRI_LIB_DEPS += -ldrm_radeon
r300_cmdbuf.c \
r300_state.c \
r300_render.c \
- r300_texmem.c \
r300_tex.c \
r300_texstate.c \
- r300_mipmap_tree.c \
radeon_program.c \
radeon_program_alu.c \
radeon_program_pair.c \
r300_shader.c \
r300_emit.c \
r300_swtcl.c \
+ radeon_mipmap_tree.c \
$(EGL_SOURCES)
C_SOURCES = $(COMMON_SOURCES) $(DRIVER_SOURCES)
common_lock.h \
common_misc.c \
common_misc.h \
- common_cmdbuf.h
+ common_cmdbuf.h \
+ radeon_mipmap_tree.c \
+ radeon_mipmap_tree.h
DRI_LIB_DEPS += -ldrm_radeon
#include "r300_reg.h"
#include "r300_cmdbuf.h"
#include "r300_emit.h"
-#include "r300_mipmap_tree.h"
+#include "radeon_mipmap_tree.h"
#include "r300_state.h"
#include "radeon_cs_legacy.h"
#include "radeon_cs_gem.h"
for(i = 0; i < numtmus; ++i) {
BEGIN_BATCH(2);
OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
- r300TexObj *t = r300->hw.textures[i];
+ radeonTexObj *t = r300->hw.textures[i];
if (t && !t->image_override) {
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
RADEON_GEM_DOMAIN_VRAM, 0, 0);
#include "radeon_span.h"
#include "r300_context.h"
#include "r300_cmdbuf.h"
-#include "r300_mipmap_tree.h"
#include "r300_state.h"
#include "r300_ioctl.h"
#include "r300_tex.h"
/* Texture related */
-typedef struct r300_tex_obj r300TexObj, *r300TexObjPtr;
typedef struct _r300_texture_image r300_texture_image;
* If mt == 0, the image is stored in normal memory pointed to
* by base.Data.
*/
- struct _r300_mipmap_tree *mt;
- struct radeon_bo *bo;
+ struct _radeon_mipmap_tree *mt;
+ struct radeon_bo *bo;
int mtlevel; /** if mt != 0, this is the image's level in the mipmap tree */
int mtface; /** if mt != 0, this is the image's face in the mipmap tree */
return (r300_texture_image*)image;
}
-
-/* Texture object in locally shared texture space.
- */
-struct r300_tex_obj {
- struct gl_texture_object base;
- struct _r300_mipmap_tree *mt;
-
- /**
- * This is true if we've verified that the mipmap tree above is complete
- * and so on.
- */
- GLboolean validated;
-
- GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
- GLuint override_offset;
-
- /* hardware register values */
- /* Note that R200 has 8 registers per texture and R300 only 7 */
- GLuint filter;
- GLuint filter_1;
- GLuint pitch_reg;
- GLuint size; /* npot only */
- GLuint format;
- GLuint pp_border_color;
- /* end hardware registers */
-
- GLuint tile_bits; /* hw texture tile bits used on this texture */
- struct radeon_bo *bo;
-};
-
-static INLINE r300TexObj* r300_tex_obj(struct gl_texture_object *texObj)
-{
- return (r300TexObj*)texObj;
-}
-
/* The blit width for texture uploads
*/
#define R300_BLIT_WIDTH_BYTES 1024
} tex;
struct radeon_state_atom txe; /* tex enable (4104) */
- r300TexObj *textures[R300_MAX_TEXTURE_UNITS];
+ radeonTexObj *textures[R300_MAX_TEXTURE_UNITS];
};
/**
+++ /dev/null
-/*
- * Copyright (C) 2008 Nicolai Haehnle.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#include "r300_mipmap_tree.h"
-
-#include <errno.h>
-#include <unistd.h>
-
-#include "main/simple_list.h"
-#include "main/texcompress.h"
-#include "main/texformat.h"
-
-#include "radeon_buffer.h"
-
-static GLuint r300_compressed_texture_size(GLcontext *ctx,
- GLsizei width, GLsizei height, GLsizei depth,
- GLuint mesaFormat)
-{
- GLuint size = _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
-
- if (mesaFormat == MESA_FORMAT_RGB_DXT1 ||
- mesaFormat == MESA_FORMAT_RGBA_DXT1) {
- if (width + 3 < 8) /* width one block */
- size = size * 4;
- else if (width + 3 < 16)
- size = size * 2;
- } else {
- /* DXT3/5, 16 bytes per block */
- WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
- if (width + 3 < 8)
- size = size * 2;
- }
-
- return size;
-}
-
-/**
- * Compute sizes and fill in offset and blit information for the given
- * image (determined by \p face and \p level).
- *
- * \param curOffset points to the offset at which the image is to be stored
- * and is updated by this function according to the size of the image.
- */
-static void compute_tex_image_offset(r300_mipmap_tree *mt,
- GLuint face, GLuint level, GLuint* curOffset)
-{
- r300_mipmap_level *lvl = &mt->levels[level];
-
- /* Find image size in bytes */
- if (mt->compressed) {
- /* TODO: Is this correct? Need test cases for compressed textures! */
- GLuint align;
-
- if (mt->target == GL_TEXTURE_RECTANGLE_NV)
- align = 64 / mt->bpp;
- else
- align = 32 / mt->bpp;
- lvl->rowstride = (lvl->width + align - 1) & ~(align - 1);
- lvl->size = r300_compressed_texture_size(mt->r300->radeon.glCtx,
- lvl->width, lvl->height, lvl->depth, mt->compressed);
- } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
- lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63;
- lvl->size = lvl->rowstride * lvl->height;
- } else if (mt->tilebits & R300_TXO_MICRO_TILE) {
- /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
- * though the actual offset may be different (if texture is less than
- * 32 bytes width) to the untiled case */
- lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31;
- lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
- } else {
- lvl->rowstride = (lvl->width * mt->bpp + 31) & ~31;
- lvl->size = lvl->rowstride * lvl->height * lvl->depth;
- }
- assert(lvl->size > 0);
-
- /* All images are aligned to a 32-byte offset */
- *curOffset = (*curOffset + 0x1f) & ~0x1f;
- lvl->faces[face].offset = *curOffset;
- *curOffset += lvl->size;
-}
-
-static GLuint minify(GLuint size, GLuint levels)
-{
- size = size >> levels;
- if (size < 1)
- size = 1;
- return size;
-}
-
-static void calculate_miptree_layout(r300_mipmap_tree *mt)
-{
- GLuint curOffset;
- GLuint numLevels;
- GLuint i;
-
- numLevels = mt->lastLevel - mt->firstLevel + 1;
- assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
-
- curOffset = 0;
- for(i = 0; i < numLevels; i++) {
- GLuint face;
-
- mt->levels[i].width = minify(mt->width0, i);
- mt->levels[i].height = minify(mt->height0, i);
- mt->levels[i].depth = minify(mt->depth0, i);
-
- for(face = 0; face < mt->faces; face++)
- compute_tex_image_offset(mt, face, i, &curOffset);
- }
-
- /* Note the required size in memory */
- mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
-}
-
-
-/**
- * Create a new mipmap tree, calculate its layout and allocate memory.
- */
-r300_mipmap_tree* r300_miptree_create(r300ContextPtr rmesa, r300TexObj *t,
- GLenum target, GLuint firstLevel, GLuint lastLevel,
- GLuint width0, GLuint height0, GLuint depth0,
- GLuint bpp, GLuint tilebits, GLuint compressed)
-{
- r300_mipmap_tree *mt = CALLOC_STRUCT(_r300_mipmap_tree);
-
- mt->r300 = rmesa;
- mt->refcount = 1;
- mt->t = t;
- mt->target = target;
- mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
- mt->firstLevel = firstLevel;
- mt->lastLevel = lastLevel;
- mt->width0 = width0;
- mt->height0 = height0;
- mt->depth0 = depth0;
- mt->bpp = bpp;
- mt->tilebits = tilebits;
- mt->compressed = compressed;
-
- calculate_miptree_layout(mt);
-
- mt->bo = radeon_bo_open(rmesa->radeon.radeonScreen->bom,
- 0, mt->totalsize, 1024,
- RADEON_GEM_DOMAIN_VRAM,
- 0);
-
- return mt;
-}
-
-void r300_miptree_reference(r300_mipmap_tree *mt)
-{
- mt->refcount++;
- assert(mt->refcount > 0);
-}
-
-void r300_miptree_unreference(r300_mipmap_tree *mt)
-{
- if (!mt)
- return;
-
- assert(mt->refcount > 0);
- mt->refcount--;
- if (!mt->refcount) {
- radeon_bo_unref(mt->bo);
- free(mt);
- }
-}
-
-
-static void calculate_first_last_level(struct gl_texture_object *tObj,
- GLuint *pfirstLevel, GLuint *plastLevel)
-{
- const struct gl_texture_image * const baseImage =
- tObj->Image[0][tObj->BaseLevel];
-
- /* These must be signed values. MinLod and MaxLod can be negative numbers,
- * and having firstLevel and lastLevel as signed prevents the need for
- * extra sign checks.
- */
- int firstLevel;
- int lastLevel;
-
- /* Yes, this looks overly complicated, but it's all needed.
- */
- switch (tObj->Target) {
- case GL_TEXTURE_1D:
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- case GL_TEXTURE_CUBE_MAP:
- if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
- /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
- */
- firstLevel = lastLevel = tObj->BaseLevel;
- } else {
- firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
- firstLevel = MAX2(firstLevel, tObj->BaseLevel);
- firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
- lastLevel = MAX2(lastLevel, tObj->BaseLevel);
- lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
- lastLevel = MIN2(lastLevel, tObj->MaxLevel);
- lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
- }
- break;
- case GL_TEXTURE_RECTANGLE_NV:
- case GL_TEXTURE_4D_SGIS:
- firstLevel = lastLevel = 0;
- break;
- default:
- return;
- }
-
- /* save these values */
- *pfirstLevel = firstLevel;
- *plastLevel = lastLevel;
-}
-
-
-/**
- * Checks whether the given miptree can hold the given texture image at the
- * given face and level.
- */
-GLboolean r300_miptree_matches_image(r300_mipmap_tree *mt,
- struct gl_texture_image *texImage, GLuint face, GLuint level)
-{
- r300_mipmap_level *lvl;
-
- if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
- return GL_FALSE;
-
- if (texImage->TexFormat->TexelBytes != mt->bpp)
- return GL_FALSE;
-
- lvl = &mt->levels[level - mt->firstLevel];
- if (lvl->width != texImage->Width ||
- lvl->height != texImage->Height ||
- lvl->depth != texImage->Depth)
- return GL_FALSE;
-
- return GL_TRUE;
-}
-
-
-/**
- * Checks whether the given miptree has the right format to store the given texture object.
- */
-GLboolean r300_miptree_matches_texture(r300_mipmap_tree *mt, struct gl_texture_object *texObj)
-{
- struct gl_texture_image *firstImage;
- GLuint compressed;
- GLuint numfaces = 1;
- GLuint firstLevel, lastLevel;
-
- calculate_first_last_level(texObj, &firstLevel, &lastLevel);
- if (texObj->Target == GL_TEXTURE_CUBE_MAP)
- numfaces = 6;
-
- firstImage = texObj->Image[0][firstLevel];
- compressed = firstImage->IsCompressed ? firstImage->TexFormat->MesaFormat : 0;
-
- return (mt->firstLevel == firstLevel &&
- mt->lastLevel == lastLevel &&
- mt->width0 == firstImage->Width &&
- mt->height0 == firstImage->Height &&
- mt->depth0 == firstImage->Depth &&
- mt->bpp == firstImage->TexFormat->TexelBytes &&
- mt->compressed == compressed);
-}
-
-
-/**
- * Try to allocate a mipmap tree for the given texture that will fit the
- * given image in the given position.
- */
-void r300_try_alloc_miptree(r300ContextPtr rmesa, r300TexObj *t,
- struct gl_texture_image *texImage, GLuint face, GLuint level)
-{
- GLuint compressed = texImage->IsCompressed ? texImage->TexFormat->MesaFormat : 0;
- GLuint numfaces = 1;
- GLuint firstLevel, lastLevel;
-
- assert(!t->mt);
-
- calculate_first_last_level(&t->base, &firstLevel, &lastLevel);
- if (t->base.Target == GL_TEXTURE_CUBE_MAP)
- numfaces = 6;
-
- if (level != firstLevel || face >= numfaces)
- return;
-
- t->mt = r300_miptree_create(rmesa, t, t->base.Target,
- firstLevel, lastLevel,
- texImage->Width, texImage->Height, texImage->Depth,
- texImage->TexFormat->TexelBytes, t->tile_bits, compressed);
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 Nicolai Haehnle.
- *
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial
- * portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- */
-
-#ifndef __R300_MIPMAP_TREE_H_
-#define __R300_MIPMAP_TREE_H_
-
-#include "r300_context.h"
-
-typedef struct _r300_mipmap_tree r300_mipmap_tree;
-typedef struct _r300_mipmap_level r300_mipmap_level;
-typedef struct _r300_mipmap_image r300_mipmap_image;
-
-struct _r300_mipmap_image {
- GLuint offset; /** Offset of this image from the start of mipmap tree buffer, in bytes */
-};
-
-struct _r300_mipmap_level {
- GLuint width;
- GLuint height;
- GLuint depth;
- GLuint size; /** Size of each image, in bytes */
- GLuint rowstride; /** in bytes */
- r300_mipmap_image faces[6];
-};
-
-
-/**
- * A mipmap tree contains texture images in the layout that the hardware
- * expects.
- *
- * The meta-data of mipmap trees is immutable, i.e. you cannot change the
- * layout on-the-fly; however, the texture contents (i.e. texels) can be
- * changed.
- */
-struct _r300_mipmap_tree {
- r300ContextPtr r300;
- r300TexObj *t;
- struct radeon_bo *bo;
- GLuint refcount;
-
- GLuint totalsize; /** total size of the miptree, in bytes */
-
- GLenum target; /** GL_TEXTURE_xxx */
- GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
- GLuint firstLevel; /** First mip level stored in this mipmap tree */
- GLuint lastLevel; /** Last mip level stored in this mipmap tree */
-
- GLuint width0; /** Width of firstLevel image */
- GLuint height0; /** Height of firstLevel image */
- GLuint depth0; /** Depth of firstLevel image */
-
- GLuint bpp; /** Bytes per texel */
- GLuint tilebits; /** R300_TXO_xxx_TILE */
- GLuint compressed; /** MESA_FORMAT_xxx indicating a compressed format, or 0 if uncompressed */
-
- r300_mipmap_level levels[RADEON_MAX_TEXTURE_LEVELS];
-};
-
-r300_mipmap_tree* r300_miptree_create(r300ContextPtr rmesa, r300TexObj *t,
- GLenum target, GLuint firstLevel, GLuint lastLevel,
- GLuint width0, GLuint height0, GLuint depth0,
- GLuint bpp, GLuint tilebits, GLuint compressed);
-void r300_miptree_reference(r300_mipmap_tree *mt);
-void r300_miptree_unreference(r300_mipmap_tree *mt);
-
-GLboolean r300_miptree_matches_image(r300_mipmap_tree *mt,
- struct gl_texture_image *texImage, GLuint face, GLuint level);
-GLboolean r300_miptree_matches_texture(r300_mipmap_tree *mt, struct gl_texture_object *texObj);
-void r300_try_alloc_miptree(r300ContextPtr rmesa, r300TexObj *t,
- struct gl_texture_image *texImage, GLuint face, GLuint level);
-
-
-#endif /* __R300_MIPMAP_TREE_H_ */
static void r300SetupTextures(GLcontext * ctx)
{
int i, mtu;
- struct r300_tex_obj *t;
+ struct radeon_tex_obj *t;
r300ContextPtr r300 = R300_CONTEXT(ctx);
int hw_tmu = 0;
int last_hw_tmu = -1; /* -1 translates into no setup costs for fields */
if (ctx->Texture.Unit[i]._ReallyEnabled) {
tmu_mappings[i] = hw_tmu;
- t = r300_tex_obj(ctx->Texture.Unit[i]._Current);
+ t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
if (!t)
continue;
- if ((t->format & 0xffffff00) == 0xffffff00) {
+ if ((t->pp_txformat & 0xffffff00) == 0xffffff00) {
WARN_ONCE
("unknown texture format (entry %x) encountered. Help me !\n",
- t->format & 0xff);
+ t->pp_txformat & 0xff);
}
if (RADEON_DEBUG & DEBUG_STATE)
r300->hw.tex.filter.cmd[R300_TEX_VALUE_0 +
hw_tmu] =
- gen_fixed_filter(t->filter) | (hw_tmu << 28);
+ gen_fixed_filter(t->pp_txfilter) | (hw_tmu << 28);
/* Note: There is a LOD bias per texture unit and a LOD bias
* per texture object. We add them here to get the correct behaviour.
* (The per-texture object LOD bias was introduced in OpenGL 1.4
* and is not present in the EXT_texture_object extension).
*/
r300->hw.tex.filter_1.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->filter_1 |
+ t->pp_txfilter_1 |
translate_lod_bias(ctx->Texture.Unit[i].LodBias + t->base.LodBias);
r300->hw.tex.size.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->size;
+ t->pp_txsize;
r300->hw.tex.format.cmd[R300_TEX_VALUE_0 +
- hw_tmu] = t->format;
+ hw_tmu] = t->pp_txformat;
r300->hw.tex.pitch.cmd[R300_TEX_VALUE_0 + hw_tmu] =
- t->pitch_reg;
+ t->pp_txpitch;
r300->hw.textures[hw_tmu] = t;
if (t->tile_bits & R300_TXO_MACRO_TILE) {
#include "r300_context.h"
#include "r300_state.h"
#include "r300_ioctl.h"
-#include "r300_mipmap_tree.h"
+#include "radeon_mipmap_tree.h"
#include "r300_tex.h"
#include "xmlpool.h"
*
* \param t Texture object whose wrap modes are to be set
*/
-static void r300UpdateTexWrap(r300TexObjPtr t)
+static void r300UpdateTexWrap(radeonTexObjPtr t)
{
struct gl_texture_object *tObj = &t->base;
- t->filter &=
+ t->pp_txfilter &=
~(R300_TX_WRAP_S_MASK | R300_TX_WRAP_T_MASK | R300_TX_WRAP_R_MASK);
- t->filter |= translate_wrap_mode(tObj->WrapS) << R300_TX_WRAP_S_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapS) << R300_TX_WRAP_S_SHIFT;
if (tObj->Target != GL_TEXTURE_1D) {
- t->filter |= translate_wrap_mode(tObj->WrapT) << R300_TX_WRAP_T_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapT) << R300_TX_WRAP_T_SHIFT;
if (tObj->Target == GL_TEXTURE_3D)
- t->filter |= translate_wrap_mode(tObj->WrapR) << R300_TX_WRAP_R_SHIFT;
+ t->pp_txfilter |= translate_wrap_mode(tObj->WrapR) << R300_TX_WRAP_R_SHIFT;
}
}
* \param magf Texture magnification mode
* \param anisotropy Maximum anisotropy level
*/
-static void r300SetTexFilter(r300TexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
+static void r300SetTexFilter(radeonTexObjPtr t, GLenum minf, GLenum magf, GLfloat anisotropy)
{
/* Force revalidation to account for switches from/to mipmapping. */
t->validated = GL_FALSE;
- t->filter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MIN_FILTER_MIP_MASK | R300_TX_MAG_FILTER_MASK | R300_TX_MAX_ANISO_MASK);
- t->filter_1 &= ~R300_EDGE_ANISO_EDGE_ONLY;
+ t->pp_txfilter &= ~(R300_TX_MIN_FILTER_MASK | R300_TX_MIN_FILTER_MIP_MASK | R300_TX_MAG_FILTER_MASK | R300_TX_MAX_ANISO_MASK);
+ t->pp_txfilter_1 &= ~R300_EDGE_ANISO_EDGE_ONLY;
/* Note that EXT_texture_filter_anisotropic is extremely vague about
* how anisotropic filtering interacts with the "normal" filter modes.
* filter settings completely. This includes driconf's settings.
*/
if (anisotropy >= 2.0 && (minf != GL_NEAREST) && (magf != GL_NEAREST)) {
- t->filter |= R300_TX_MAG_FILTER_ANISO
+ t->pp_txfilter |= R300_TX_MAG_FILTER_ANISO
| R300_TX_MIN_FILTER_ANISO
| R300_TX_MIN_FILTER_MIP_LINEAR
| aniso_filter(anisotropy);
switch (minf) {
case GL_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST;
break;
case GL_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_NEAREST|R300_TX_MIN_FILTER_MIP_LINEAR;
break;
case GL_LINEAR_MIPMAP_NEAREST:
- t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_NEAREST;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_NEAREST;
break;
case GL_LINEAR_MIPMAP_LINEAR:
- t->filter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_LINEAR;
+ t->pp_txfilter |= R300_TX_MIN_FILTER_LINEAR|R300_TX_MIN_FILTER_MIP_LINEAR;
break;
}
*/
switch (magf) {
case GL_NEAREST:
- t->filter |= R300_TX_MAG_FILTER_NEAREST;
+ t->pp_txfilter |= R300_TX_MAG_FILTER_NEAREST;
break;
case GL_LINEAR:
- t->filter |= R300_TX_MAG_FILTER_LINEAR;
+ t->pp_txfilter |= R300_TX_MAG_FILTER_LINEAR;
break;
}
}
-static void r300SetTexBorderColor(r300TexObjPtr t, GLubyte c[4])
+static void r300SetTexBorderColor(radeonTexObjPtr t, GLubyte c[4])
{
t->pp_border_color = PACK_COLOR_8888(c[3], c[0], c[1], c[2]);
}
r300_texture_image* image = get_r300_texture_image(timage);
if (image->mt) {
- r300_miptree_unreference(image->mt);
+ radeon_miptree_unreference(image->mt);
image->mt = 0;
assert(!image->base.Data);
} else {
/* Set Data pointer and additional data for mapped texture image */
static void teximage_set_map_data(r300_texture_image *image)
{
- r300_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
image->base.Data = image->mt->bo->ptr + lvl->faces[image->mtface].offset;
image->base.RowStride = lvl->rowstride / image->mt->bpp;
}
*/
static void r300MapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
{
- r300TexObj* t = r300_tex_obj(texObj);
+ radeonTexObj* t = radeon_tex_obj(texObj);
int face, level;
assert(texObj->_Complete);
static void r300UnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
{
- r300TexObj* t = r300_tex_obj(texObj);
+ radeonTexObj* t = radeon_tex_obj(texObj);
int face, level;
assert(texObj->_Complete);
int compressed)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300TexObj* t = r300_tex_obj(texObj);
+ radeonTexObj* t = radeon_tex_obj(texObj);
r300_texture_image* image = get_r300_texture_image(texImage);
R300_FIREVERTICES(rmesa);
r300FreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
if (!t->mt)
- r300_try_alloc_miptree(rmesa, t, texImage, face, level);
- if (t->mt && r300_miptree_matches_image(t->mt, texImage, face, level)) {
+ radeon_try_alloc_miptree(&rmesa->radeon, t, texImage, face, level);
+ if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) {
image->mt = t->mt;
image->mtlevel = level - t->mt->firstLevel;
image->mtface = face;
- r300_miptree_reference(t->mt);
+ radeon_miptree_reference(t->mt);
} else {
int size;
if (texImage->IsCompressed) {
} else {
GLuint dstRowStride;
if (image->mt) {
- r300_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
dstRowStride = lvl->rowstride;
} else {
dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
r300_teximage_map(image, GL_TRUE);
if (image->mt) {
- r300_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
+ radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
dstRowStride = lvl->rowstride;
} else {
dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
struct gl_texture_object *texObj,
GLenum pname, const GLfloat * params)
{
- r300TexObj* t = r300_tex_obj(texObj);
+ radeonTexObj* t = radeon_tex_obj(texObj);
if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
fprintf(stderr, "%s( %s )\n", __FUNCTION__,
* to simulate a clamped LOD.
*/
if (t->mt) {
- r300_miptree_unreference(t->mt);
+ radeon_miptree_unreference(t->mt);
t->mt = 0;
t->validated = GL_FALSE;
}
static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300TexObj* t = r300_tex_obj(texObj);
+ radeonTexObj* t = radeon_tex_obj(texObj);
if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
fprintf(stderr, "%s( %p (target = %s) )\n", __FUNCTION__,
}
if (t->mt) {
- r300_miptree_unreference(t->mt);
+ radeon_miptree_unreference(t->mt);
t->mt = 0;
}
_mesa_delete_texture_object(ctx, texObj);
GLenum target)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300TexObj* t = CALLOC_STRUCT(r300_tex_obj);
+ radeonTexObj* t = CALLOC_STRUCT(radeon_tex_obj);
if (RADEON_DEBUG & (DEBUG_STATE | DEBUG_TEXTURE)) {
#include "r300_state.h"
#include "r300_ioctl.h"
#include "radeon_ioctl.h"
-#include "r300_mipmap_tree.h"
+#include "radeon_mipmap_tree.h"
#include "r300_tex.h"
#include "r300_reg.h"
#include "radeon_buffer.h"
},
};
const GLuint *format;
- r300TexObjPtr t;
+ radeonTexObjPtr t;
if (!tObj)
return;
- t = r300_tex_obj(tObj);
+ t = radeon_tex_obj(tObj);
switch (tObj->Image[0][tObj->BaseLevel]->TexFormat->MesaFormat) {
case MESA_FORMAT_Z16:
switch (tObj->DepthMode) {
case GL_LUMINANCE:
- t->format = format[0];
+ t->pp_txformat = format[0];
break;
case GL_INTENSITY:
- t->format = format[1];
+ t->pp_txformat = format[1];
break;
case GL_ALPHA:
- t->format = format[2];
+ t->pp_txformat = format[2];
break;
default:
/* Error...which should have already been caught by higher
* \param rmesa Context pointer
* \param t the r300 texture object
*/
-static void setup_hardware_state(r300ContextPtr rmesa, r300TexObj *t)
+static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
{
const struct gl_texture_image *firstImage =
t->base.Image[0][t->mt->firstLevel];
if (firstImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
r300SetDepthTexMode(&t->base);
} else {
- t->format = tx_table[firstImage->TexFormat->MesaFormat].format;
+ t->pp_txformat = tx_table[firstImage->TexFormat->MesaFormat].format;
}
- t->filter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
+ t->pp_txfilter |= tx_table[firstImage->TexFormat->MesaFormat].filter;
} else if (!t->image_override) {
_mesa_problem(NULL, "unexpected texture format in %s",
__FUNCTION__);
t->tile_bits = 0;
if (t->base.Target == GL_TEXTURE_CUBE_MAP)
- t->format |= R300_TX_FORMAT_CUBIC_MAP;
+ t->pp_txformat |= R300_TX_FORMAT_CUBIC_MAP;
if (t->base.Target == GL_TEXTURE_3D)
- t->format |= R300_TX_FORMAT_3D;
+ t->pp_txformat |= R300_TX_FORMAT_3D;
- t->size = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
+ t->pp_txsize = (((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)
| ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT))
| ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT);
if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
unsigned int align = (64 / t->mt->bpp) - 1;
- t->size |= R300_TX_SIZE_TXPITCH_EN;
+ t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
if (!t->image_override)
- t->pitch_reg = ((firstImage->Width + align) & ~align) - 1;
+ t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
}
if (rmesa->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
if (firstImage->Width > 2048)
- t->pitch_reg |= R500_TXWIDTH_BIT11;
+ t->pp_txpitch |= R500_TXWIDTH_BIT11;
if (firstImage->Height > 2048)
- t->pitch_reg |= R500_TXHEIGHT_BIT11;
+ t->pp_txpitch |= R500_TXHEIGHT_BIT11;
}
}
/**
* Ensure that the given image is stored in the given miptree from now on.
*/
-static void migrate_image_to_miptree(r300_mipmap_tree *mt, r300_texture_image *image, int face, int level)
+static void migrate_image_to_miptree(radeon_mipmap_tree *mt, r300_texture_image *image, int face, int level)
{
- r300_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
+ radeon_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
unsigned char *dest;
assert(image->mt != mt);
* In fact, that memcpy() could be done by the hardware in many
* cases, provided that we have a proper memory manager.
*/
- r300_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
+ radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
assert(srclvl->size == dstlvl->size);
assert(srclvl->rowstride == dstlvl->rowstride);
dstlvl->size);
radeon_bo_unmap(image->mt->bo);
- r300_miptree_unreference(image->mt);
+ radeon_miptree_unreference(image->mt);
} else {
uint srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes;
image->mt = mt;
image->mtface = face;
image->mtlevel = level;
- r300_miptree_reference(image->mt);
+ radeon_miptree_reference(image->mt);
}
static GLboolean r300_validate_texture(GLcontext * ctx, struct gl_texture_object *texObj)
{
r300ContextPtr rmesa = R300_CONTEXT(ctx);
- r300TexObj *t = r300_tex_obj(texObj);
+ radeonTexObj *t = radeon_tex_obj(texObj);
r300_texture_image *baseimage = get_r300_texture_image(texObj->Image[0][texObj->BaseLevel]);
int face, level;
*/
if (baseimage->mt &&
baseimage->mt != t->mt &&
- r300_miptree_matches_texture(baseimage->mt, &t->base)) {
- r300_miptree_unreference(t->mt);
+ radeon_miptree_matches_texture(baseimage->mt, &t->base)) {
+ radeon_miptree_unreference(t->mt);
t->mt = baseimage->mt;
- r300_miptree_reference(t->mt);
- } else if (t->mt && !r300_miptree_matches_texture(t->mt, &t->base)) {
- r300_miptree_unreference(t->mt);
+ radeon_miptree_reference(t->mt);
+ } else if (t->mt && !radeon_miptree_matches_texture(t->mt, &t->base)) {
+ radeon_miptree_unreference(t->mt);
t->mt = 0;
}
if (!t->mt) {
if (RADEON_DEBUG & DEBUG_TEXTURE)
fprintf(stderr, " Allocate new miptree\n");
- r300_try_alloc_miptree(rmesa, t, &baseimage->base, 0, texObj->BaseLevel);
+ radeon_try_alloc_miptree(&rmesa->radeon, t, &baseimage->base, 0, texObj->BaseLevel);
if (!t->mt) {
_mesa_problem(ctx, "r300_validate_texture failed to alloc miptree");
return GL_FALSE;
r300ContextPtr rmesa = pDRICtx->driverPrivate;
struct gl_texture_object *tObj =
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
- r300TexObjPtr t = r300_tex_obj(tObj);
+ radeonTexObjPtr t = radeon_tex_obj(tObj);
uint32_t pitch_val;
if (!tObj)
return;
t->bo = NULL;
t->override_offset = offset;
- t->pitch_reg &= (1 << 13) -1;
+ t->pp_txpitch &= (1 << 13) -1;
pitch_val = pitch;
switch (depth) {
case 32:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
- t->filter |= tx_table[2].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[2].filter;
pitch_val /= 4;
break;
case 24:
default:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
- t->filter |= tx_table[4].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[4].filter;
pitch_val /= 4;
break;
case 16:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
- t->filter |= tx_table[5].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+ t->pp_txfilter |= tx_table[5].filter;
pitch_val /= 2;
break;
}
pitch_val--;
- t->pitch_reg |= pitch_val;
+ t->pp_txpitch |= pitch_val;
}
void r300SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
radeonContextPtr radeon;
r300ContextPtr rmesa;
GLframebuffer *fb;
- r300TexObjPtr t;
+ radeonTexObjPtr t;
uint32_t pitch_val;
target = GL_TEXTURE_RECTANGLE_ARB;
texImage = _mesa_get_tex_image(radeon->glCtx, texObj, target, 0);
rImage = get_r300_texture_image(texImage);
- t = r300_tex_obj(texObj);
+ t = radeon_tex_obj(texObj);
if (t == NULL) {
return;
}
t->mt = NULL;
}
if (rImage->mt) {
- r300_miptree_unreference(rImage->mt);
+ radeon_miptree_unreference(rImage->mt);
rImage->mt = NULL;
}
fprintf(stderr,"settexbuf %dx%d@%d\n", rb->width, rb->height, rb->cpp);
t->tile_bits = 0;
t->image_override = GL_TRUE;
t->override_offset = 0;
- t->pitch_reg &= (1 << 13) -1;
+ t->pp_txpitch &= (1 << 13) -1;
pitch_val = rb->pitch;
switch (rb->cpp) {
case 4:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
- t->filter |= tx_table[2].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[2].filter;
pitch_val /= 4;
break;
case 3:
default:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
- t->filter |= tx_table[4].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
+ t->pp_txfilter |= tx_table[4].filter;
pitch_val /= 4;
break;
case 2:
- t->format = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
- t->filter |= tx_table[5].filter;
+ t->pp_txformat = R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
+ t->pp_txfilter |= tx_table[5].filter;
pitch_val /= 2;
break;
}
pitch_val--;
- t->size = ((rb->width - 1) << R300_TX_WIDTHMASK_SHIFT) |
+ t->pp_txsize = ((rb->width - 1) << R300_TX_WIDTHMASK_SHIFT) |
((rb->height - 1) << R300_TX_HEIGHTMASK_SHIFT);
- t->size |= R300_TX_SIZE_TXPITCH_EN;
- t->pitch_reg |= pitch_val;
+ t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
+ t->pp_txpitch |= pitch_val;
t->validated = GL_TRUE;
_mesa_unlock_texture(radeon->glCtx, texObj);
return;
typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
+#define RADEON_TXO_MICRO_TILE (1 << 3)
+
/* Texture object in locally shared texture space.
*/
-#ifndef RADEON_COMMON_FOR_R300
struct radeon_tex_obj {
- driTextureObject base;
+ // driTextureObject base;
+ struct gl_texture_object base;
+ struct _radeon_mipmap_tree *mt;
+
+ /**
+ * This is true if we've verified that the mipmap tree above is complete
+ * and so on.
+ */
+ GLboolean validated;
+
+ GLuint override_offset;
+ GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
+ GLuint tile_bits; /* hw texture tile bits used on this texture */
+ struct radeon_bo *bo;
GLuint bufAddr; /* Offset to start of locally
shared texture block */
drm_radeon_tex_image_t image[6][RADEON_MAX_TEXTURE_LEVELS];
/* Six, for the cube faces */
- GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
+
GLuint pp_txfilter; /* hardware register values */
GLuint pp_txformat;
GLuint pp_border_color;
GLuint pp_cubic_faces; /* cube face 1,2,3,4 log2 sizes */
+ GLuint pp_txfilter_1; /* r300 */
+
GLboolean border_fallback;
- GLuint tile_bits; /* hw texture tile bits used on this texture */
+
};
-#endif
+
+static INLINE radeonTexObj* radeon_tex_obj(struct gl_texture_object *texObj)
+{
+ return (radeonTexObj*)texObj;
+}
/* Need refcounting on dma buffers:
*/
--- /dev/null
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "radeon_mipmap_tree.h"
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "main/simple_list.h"
+#include "main/texcompress.h"
+#include "main/texformat.h"
+
+#include "radeon_buffer.h"
+
+static GLuint radeon_compressed_texture_size(GLcontext *ctx,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLuint mesaFormat)
+{
+ GLuint size = _mesa_compressed_texture_size(ctx, width, height, depth, mesaFormat);
+
+ if (mesaFormat == MESA_FORMAT_RGB_DXT1 ||
+ mesaFormat == MESA_FORMAT_RGBA_DXT1) {
+ if (width + 3 < 8) /* width one block */
+ size = size * 4;
+ else if (width + 3 < 16)
+ size = size * 2;
+ } else {
+ /* DXT3/5, 16 bytes per block */
+ // WARN_ONCE("DXT 3/5 suffers from multitexturing problems!\n");
+ if (width + 3 < 8)
+ size = size * 2;
+ }
+
+ return size;
+}
+
+/**
+ * Compute sizes and fill in offset and blit information for the given
+ * image (determined by \p face and \p level).
+ *
+ * \param curOffset points to the offset at which the image is to be stored
+ * and is updated by this function according to the size of the image.
+ */
+static void compute_tex_image_offset(radeon_mipmap_tree *mt,
+ GLuint face, GLuint level, GLuint* curOffset)
+{
+ radeon_mipmap_level *lvl = &mt->levels[level];
+
+ /* Find image size in bytes */
+ if (mt->compressed) {
+ /* TODO: Is this correct? Need test cases for compressed textures! */
+ GLuint align;
+
+ if (mt->target == GL_TEXTURE_RECTANGLE_NV)
+ align = 64 / mt->bpp;
+ else
+ align = 32 / mt->bpp;
+ lvl->rowstride = (lvl->width + align - 1) & ~(align - 1);
+ lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx,
+ lvl->width, lvl->height, lvl->depth, mt->compressed);
+ } else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
+ lvl->rowstride = (lvl->width * mt->bpp + 63) & ~63;
+ lvl->size = lvl->rowstride * lvl->height;
+ } else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
+ /* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
+ * though the actual offset may be different (if texture is less than
+ * 32 bytes width) to the untiled case */
+ lvl->rowstride = (lvl->width * mt->bpp * 2 + 31) & ~31;
+ lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
+ } else {
+ lvl->rowstride = (lvl->width * mt->bpp + 31) & ~31;
+ lvl->size = lvl->rowstride * lvl->height * lvl->depth;
+ }
+ assert(lvl->size > 0);
+
+ /* All images are aligned to a 32-byte offset */
+ *curOffset = (*curOffset + 0x1f) & ~0x1f;
+ lvl->faces[face].offset = *curOffset;
+ *curOffset += lvl->size;
+}
+
+static GLuint minify(GLuint size, GLuint levels)
+{
+ size = size >> levels;
+ if (size < 1)
+ size = 1;
+ return size;
+}
+
+static void calculate_miptree_layout(radeon_mipmap_tree *mt)
+{
+ GLuint curOffset;
+ GLuint numLevels;
+ GLuint i;
+
+ numLevels = mt->lastLevel - mt->firstLevel + 1;
+ assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+
+ curOffset = 0;
+ for(i = 0; i < numLevels; i++) {
+ GLuint face;
+
+ mt->levels[i].width = minify(mt->width0, i);
+ mt->levels[i].height = minify(mt->height0, i);
+ mt->levels[i].depth = minify(mt->depth0, i);
+
+ for(face = 0; face < mt->faces; face++)
+ compute_tex_image_offset(mt, face, i, &curOffset);
+ }
+
+ /* Note the required size in memory */
+ mt->totalsize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+}
+
+
+/**
+ * Create a new mipmap tree, calculate its layout and allocate memory.
+ */
+radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
+ GLenum target, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed)
+{
+ radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
+
+ mt->radeon = rmesa;
+ mt->refcount = 1;
+ mt->t = t;
+ mt->target = target;
+ mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+ mt->firstLevel = firstLevel;
+ mt->lastLevel = lastLevel;
+ mt->width0 = width0;
+ mt->height0 = height0;
+ mt->depth0 = depth0;
+ mt->bpp = bpp;
+ mt->tilebits = tilebits;
+ mt->compressed = compressed;
+
+ calculate_miptree_layout(mt);
+
+ mt->bo = radeon_bo_open(rmesa->radeonScreen->bom,
+ 0, mt->totalsize, 1024,
+ RADEON_GEM_DOMAIN_VRAM,
+ 0);
+
+ return mt;
+}
+
+void radeon_miptree_reference(radeon_mipmap_tree *mt)
+{
+ mt->refcount++;
+ assert(mt->refcount > 0);
+}
+
+void radeon_miptree_unreference(radeon_mipmap_tree *mt)
+{
+ if (!mt)
+ return;
+
+ assert(mt->refcount > 0);
+ mt->refcount--;
+ if (!mt->refcount) {
+ radeon_bo_unref(mt->bo);
+ free(mt);
+ }
+}
+
+
+static void calculate_first_last_level(struct gl_texture_object *tObj,
+ GLuint *pfirstLevel, GLuint *plastLevel)
+{
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[0][tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+ firstLevel = lastLevel = tObj->BaseLevel;
+ } else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ *pfirstLevel = firstLevel;
+ *plastLevel = lastLevel;
+}
+
+
+/**
+ * Checks whether the given miptree can hold the given texture image at the
+ * given face and level.
+ */
+GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
+ struct gl_texture_image *texImage, GLuint face, GLuint level)
+{
+ radeon_mipmap_level *lvl;
+
+ if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
+ return GL_FALSE;
+
+ if (texImage->TexFormat->TexelBytes != mt->bpp)
+ return GL_FALSE;
+
+ lvl = &mt->levels[level - mt->firstLevel];
+ if (lvl->width != texImage->Width ||
+ lvl->height != texImage->Height ||
+ lvl->depth != texImage->Depth)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Checks whether the given miptree has the right format to store the given texture object.
+ */
+GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj)
+{
+ struct gl_texture_image *firstImage;
+ GLuint compressed;
+ GLuint numfaces = 1;
+ GLuint firstLevel, lastLevel;
+
+ calculate_first_last_level(texObj, &firstLevel, &lastLevel);
+ if (texObj->Target == GL_TEXTURE_CUBE_MAP)
+ numfaces = 6;
+
+ firstImage = texObj->Image[0][firstLevel];
+ compressed = firstImage->IsCompressed ? firstImage->TexFormat->MesaFormat : 0;
+
+ return (mt->firstLevel == firstLevel &&
+ mt->lastLevel == lastLevel &&
+ mt->width0 == firstImage->Width &&
+ mt->height0 == firstImage->Height &&
+ mt->depth0 == firstImage->Depth &&
+ mt->bpp == firstImage->TexFormat->TexelBytes &&
+ mt->compressed == compressed);
+}
+
+
+/**
+ * Try to allocate a mipmap tree for the given texture that will fit the
+ * given image in the given position.
+ */
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
+ struct gl_texture_image *texImage, GLuint face, GLuint level)
+{
+ GLuint compressed = texImage->IsCompressed ? texImage->TexFormat->MesaFormat : 0;
+ GLuint numfaces = 1;
+ GLuint firstLevel, lastLevel;
+
+ assert(!t->mt);
+
+ calculate_first_last_level(&t->base, &firstLevel, &lastLevel);
+ if (t->base.Target == GL_TEXTURE_CUBE_MAP)
+ numfaces = 6;
+
+ if (level != firstLevel || face >= numfaces)
+ return;
+
+ t->mt = radeon_miptree_create(rmesa, t, t->base.Target,
+ firstLevel, lastLevel,
+ texImage->Width, texImage->Height, texImage->Depth,
+ texImage->TexFormat->TexelBytes, t->tile_bits, compressed);
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 Nicolai Haehnle.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __RADEON_MIPMAP_TREE_H_
+#define __RADEON_MIPMAP_TREE_H_
+
+#include "common_context.h"
+
+typedef struct _radeon_mipmap_tree radeon_mipmap_tree;
+typedef struct _radeon_mipmap_level radeon_mipmap_level;
+typedef struct _radeon_mipmap_image radeon_mipmap_image;
+
+struct _radeon_mipmap_image {
+ GLuint offset; /** Offset of this image from the start of mipmap tree buffer, in bytes */
+};
+
+struct _radeon_mipmap_level {
+ GLuint width;
+ GLuint height;
+ GLuint depth;
+ GLuint size; /** Size of each image, in bytes */
+ GLuint rowstride; /** in bytes */
+ radeon_mipmap_image faces[6];
+};
+
+
+/**
+ * A mipmap tree contains texture images in the layout that the hardware
+ * expects.
+ *
+ * The meta-data of mipmap trees is immutable, i.e. you cannot change the
+ * layout on-the-fly; however, the texture contents (i.e. texels) can be
+ * changed.
+ */
+struct _radeon_mipmap_tree {
+ radeonContextPtr radeon;
+ radeonTexObj *t;
+ struct radeon_bo *bo;
+ GLuint refcount;
+
+ GLuint totalsize; /** total size of the miptree, in bytes */
+
+ GLenum target; /** GL_TEXTURE_xxx */
+ GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
+ GLuint firstLevel; /** First mip level stored in this mipmap tree */
+ GLuint lastLevel; /** Last mip level stored in this mipmap tree */
+
+ GLuint width0; /** Width of firstLevel image */
+ GLuint height0; /** Height of firstLevel image */
+ GLuint depth0; /** Depth of firstLevel image */
+
+ GLuint bpp; /** Bytes per texel */
+ GLuint tilebits; /** RADEON_TXO_xxx_TILE */
+ GLuint compressed; /** MESA_FORMAT_xxx indicating a compressed format, or 0 if uncompressed */
+
+ radeon_mipmap_level levels[RADEON_MAX_TEXTURE_LEVELS];
+};
+
+radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
+ GLenum target, GLuint firstLevel, GLuint lastLevel,
+ GLuint width0, GLuint height0, GLuint depth0,
+ GLuint bpp, GLuint tilebits, GLuint compressed);
+void radeon_miptree_reference(radeon_mipmap_tree *mt);
+void radeon_miptree_unreference(radeon_mipmap_tree *mt);
+
+GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
+ struct gl_texture_image *texImage, GLuint face, GLuint level);
+GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj);
+void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
+ struct gl_texture_image *texImage, GLuint face, GLuint level);
+
+
+#endif /* __RADEON_MIPMAP_TREE_H_ */