Merge branch 'radeon-texrewrite-clean' into mesa_7_7_branch

This commit is contained in:
Maciej Cencora 2009-11-18 22:09:33 +01:00
commit cefee4e327
26 changed files with 624 additions and 621 deletions

View file

@ -640,7 +640,7 @@ static void tex_emit(GLcontext *ctx, struct radeon_state_atom *atom)
OUT_BATCH_TABLE(atom->cmd, 10);
if (t && t->mt && !t->image_override) {
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t),
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
} else if (!t) {
/* workaround for old CS mechanism */

View file

@ -385,16 +385,7 @@ static void r200TexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
t->validated = GL_FALSE;
}
t->validated = GL_FALSE;
break;
default:
@ -413,7 +404,7 @@ static void r200DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
(void *)texObj,
_mesa_lookup_enum_by_nr(texObj->Target));
}
if (rmesa) {
int i;
radeon_firevertices(&rmesa->radeon);
@ -425,11 +416,9 @@ static void r200DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
}
}
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
}
radeon_miptree_unreference(&t->mt);
_mesa_delete_texture_object(ctx, texObj);
}

View file

@ -824,14 +824,10 @@ void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
radeon_bo_unref(rImage->bo);
rImage->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = NULL;
}
if (rImage->mt) {
radeon_miptree_unreference(rImage->mt);
rImage->mt = NULL;
}
radeon_miptree_unreference(&t->mt);
radeon_miptree_unreference(&rImage->mt);
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
texImage->RowStride = rb->pitch / rb->cpp;
@ -1423,10 +1419,9 @@ void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
*/
static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
{
int firstlevel = t->mt ? t->mt->firstLevel : 0;
const struct gl_texture_image *firstImage = t->base.Image[0][firstlevel];
const struct gl_texture_image *firstImage = t->base.Image[0][t->minLod];
GLint log2Width, log2Height, log2Depth, texelBytes;
if ( t->bo ) {
return;
}
@ -1454,9 +1449,9 @@ static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
return;
}
}
t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
t->pp_txfilter |= (t->mt->lastLevel - t->mt->firstLevel) << R200_MAX_MIP_LEVEL_SHIFT;
t->pp_txfilter |= (t->maxLod - t->minLod) << R200_MAX_MIP_LEVEL_SHIFT;
t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
R200_TXFORMAT_HEIGHT_MASK |

View file

@ -46,14 +46,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "r300_context.h"
#include "r300_ioctl.h"
#include "radeon_reg.h"
#include "r300_reg.h"
#include "r300_cmdbuf.h"
#include "r300_emit.h"
#include "radeon_bocs_wrapper.h"
#include "radeon_mipmap_tree.h"
#include "r300_state.h"
#include "radeon_reg.h"
#include "radeon_queryobj.h"
/** # of dwords reserved for additional instructions that may need to be written
@ -171,7 +169,7 @@ static void emit_tex_offsets(GLcontext *ctx, struct radeon_state_atom * atom)
if (t && !t->image_override) {
BEGIN_BATCH_NO_AUTOSTATE(4);
OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t),
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
END_BATCH();
} else if (!t) {

View file

@ -439,7 +439,7 @@ static void r300InitGLExtensions(GLcontext *ctx)
if (r300->options.stencil_two_side_disabled)
_mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
if (r300->options.s3tc_force_enabled) {
if (ctx->Mesa_DXTn || r300->options.s3tc_force_enabled) {
_mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
_mesa_enable_extension(ctx, "GL_S3_s3tc");
} else if (r300->options.s3tc_force_disabled) {

View file

@ -42,7 +42,6 @@
#include "main/glheader.h"
#include "r300_context.h"
#include "r300_cmdbuf.h"
#include "radeon_reg.h"
static INLINE uint32_t cmdpacket0(struct radeon_screen *rscrn,
int reg, int count)

View file

@ -67,8 +67,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "vbo/vbo_split.h"
#include "tnl/tnl.h"
#include "tnl/t_vp_build.h"
#include "radeon_reg.h"
#include "radeon_macros.h"
#include "r300_context.h"
#include "r300_ioctl.h"
#include "r300_state.h"

View file

@ -1741,7 +1741,8 @@ static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state)
r300SetPolygonOffsetState(ctx, state);
break;
case GL_SCISSOR_TEST:
radeon_firevertices(&rmesa->radeon);
if (!rmesa->radeon.radeonScreen->kernel_mm)
radeon_firevertices(&rmesa->radeon);
rmesa->radeon.state.scissor.enabled = state;
radeonUpdateScissor( ctx );
break;

View file

@ -223,16 +223,7 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
t->validated = GL_FALSE;
}
t->validated = GL_FALSE;
break;
case GL_DEPTH_TEXTURE_MODE:
@ -270,7 +261,11 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
if (rmesa) {
int i;
radeon_firevertices(&rmesa->radeon);
struct radeon_bo *bo;
bo = !t->mt ? t->bo : t->mt->bo;
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->radeon.cmdbuf.cs)) {
radeon_firevertices(&rmesa->radeon);
}
for(i = 0; i < R300_MAX_TEXTURE_UNITS; ++i)
if (rmesa->hw.textures[i] == t)
@ -282,10 +277,8 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
t->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
}
radeon_miptree_unreference(&t->mt);
_mesa_delete_texture_object(ctx, texObj);
}

View file

@ -83,6 +83,7 @@ static const struct tx_table {
_ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
_ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
#endif
_ASSIGN(XRGB8888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)),
_ASSIGN(RGB888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)),
_ASSIGN(RGB565, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
_ASSIGN(RGB565_REV, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
@ -202,9 +203,7 @@ void r300SetDepthTexMode(struct gl_texture_object *tObj)
static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
{
const struct gl_texture_image *firstImage;
int firstlevel = t->mt ? t->mt->firstLevel : 0;
firstImage = t->base.Image[0][firstlevel];
firstImage = t->base.Image[0][t->minLod];
if (!t->image_override
&& VALID_FORMAT(firstImage->TexFormat)) {
@ -227,7 +226,7 @@ static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
t->pp_txsize = (((R300_TX_WIDTHMASK_MASK & ((firstImage->Width - 1) << R300_TX_WIDTHMASK_SHIFT)))
| ((R300_TX_HEIGHTMASK_MASK & ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)))
| ((R300_TX_DEPTHMASK_MASK & ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_SHIFT)))
| ((R300_TX_MAX_MIP_LEVEL_MASK & ((t->mt->lastLevel - t->mt->firstLevel) << R300_TX_MAX_MIP_LEVEL_SHIFT))));
| ((R300_TX_MAX_MIP_LEVEL_MASK & ((t->maxLod - t->minLod) << R300_TX_MAX_MIP_LEVEL_SHIFT))));
t->tile_bits = 0;
@ -238,7 +237,7 @@ static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
unsigned int align = (64 / t->mt->bpp) - 1;
unsigned int align = (64 / _mesa_get_format_bytes(firstImage->TexFormat)) - 1;
t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
if (!t->image_override)
t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
@ -437,14 +436,10 @@ void r300SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
radeon_bo_unref(rImage->bo);
rImage->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = NULL;
}
if (rImage->mt) {
radeon_miptree_unreference(rImage->mt);
rImage->mt = NULL;
}
radeon_miptree_unreference(&t->mt);
radeon_miptree_unreference(&rImage->mt);
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
texImage->RowStride = rb->pitch / rb->cpp;

View file

@ -312,16 +312,7 @@ static void r600TexParameter(GLcontext * ctx, GLenum target,
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
t->validated = GL_FALSE;
}
t->validated = GL_FALSE;
break;
case GL_DEPTH_TEXTURE_MODE:
@ -369,10 +360,8 @@ static void r600DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
t->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
}
radeon_miptree_unreference(&t->mt);
_mesa_delete_texture_object(ctx, texObj);
}

View file

@ -649,7 +649,6 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex
{
radeonTexObj *t = radeon_tex_obj(texObj);
const struct gl_texture_image *firstImage;
int firstlevel = t->mt ? t->mt->firstLevel : 0;
GLuint uTexelPitch, row_align;
if (rmesa->radeon.radeonScreen->driScreen->dri2.enabled &&
@ -657,7 +656,7 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex
t->bo)
return;
firstImage = t->base.Image[0][firstlevel];
firstImage = t->base.Image[0][t->minLod];
if (!t->image_override) {
if (!r600GetTexFormat(texObj, firstImage->TexFormat)) {
@ -692,7 +691,8 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex
}
row_align = rmesa->radeon.texture_row_align - 1;
uTexelPitch = ((firstImage->Width * t->mt->bpp + row_align) & ~row_align) / t->mt->bpp;
uTexelPitch = (_mesa_format_row_stride(firstImage->TexFormat, firstImage->Width) + row_align) & ~row_align;
uTexelPitch = uTexelPitch / _mesa_get_format_bytes(firstImage->TexFormat);
uTexelPitch = (uTexelPitch + R700_TEXEL_PITCH_ALIGNMENT_MASK)
& ~R700_TEXEL_PITCH_ALIGNMENT_MASK;
@ -706,10 +706,10 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex
SETfield(t->SQ_TEX_RESOURCE1, firstImage->Height - 1,
TEX_HEIGHT_shift, TEX_HEIGHT_mask);
if ((t->mt->lastLevel - t->mt->firstLevel) > 0) {
t->SQ_TEX_RESOURCE3 = t->mt->levels[0].size / 256;
SETfield(t->SQ_TEX_RESOURCE4, t->mt->firstLevel, BASE_LEVEL_shift, BASE_LEVEL_mask);
SETfield(t->SQ_TEX_RESOURCE5, t->mt->lastLevel, LAST_LEVEL_shift, LAST_LEVEL_mask);
if ((t->maxLod - t->minLod) > 0) {
t->SQ_TEX_RESOURCE3 = t->mt->levels[t->minLod].size / 256;
SETfield(t->SQ_TEX_RESOURCE4, 0, BASE_LEVEL_shift, BASE_LEVEL_mask);
SETfield(t->SQ_TEX_RESOURCE5, t->maxLod - t->minLod, LAST_LEVEL_shift, LAST_LEVEL_mask);
}
}
@ -808,9 +808,8 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
struct gl_texture_object *tObj =
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
radeonTexObjPtr t = radeon_tex_obj(tObj);
int firstlevel = t->mt ? t->mt->firstLevel : 0;
const struct gl_texture_image *firstImage;
uint32_t pitch_val, size, row_align, bpp;
uint32_t pitch_val, size, row_align;
if (!tObj)
return;
@ -820,13 +819,9 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
if (!offset)
return;
bpp = depth / 8;
if (bpp == 3)
bpp = 4;
firstImage = t->base.Image[0][firstlevel];
firstImage = t->base.Image[0][t->minLod];
row_align = rmesa->radeon.texture_row_align - 1;
size = ((firstImage->Width * bpp + row_align) & ~row_align) * firstImage->Height;
size = ((_mesa_format_row_stride(firstImage->TexFormat, firstImage->Width) + row_align) & ~row_align) * firstImage->Height;
if (t->bo) {
radeon_bo_unref(t->bo);
t->bo = NULL;
@ -949,14 +944,10 @@ void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
radeon_bo_unref(rImage->bo);
rImage->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = NULL;
}
if (rImage->mt) {
radeon_miptree_unreference(rImage->mt);
rImage->mt = NULL;
}
radeon_miptree_unreference(&t->mt);
radeon_miptree_unreference(&rImage->mt);
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
texImage->RowStride = rb->pitch / rb->cpp;

View file

@ -54,11 +54,15 @@ static void r700SendTexState(GLcontext *ctx, struct radeon_state_atom *atom)
for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled) {
radeonTexObj *t = r700->textures[i];
uint32_t offset;
if (t) {
if (!t->image_override)
if (!t->image_override) {
bo = t->mt->bo;
else
offset = get_base_teximage_offset(t);
} else {
bo = t->bo;
offset = 0;
}
if (bo) {
r700SyncSurf(context, bo,
@ -77,7 +81,7 @@ static void r700SendTexState(GLcontext *ctx, struct radeon_state_atom *atom)
R600_OUT_BATCH(r700->textures[i]->SQ_TEX_RESOURCE6);
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2,
bo,
0,
offset,
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3,
bo,

View file

@ -39,6 +39,7 @@
#define RADEON_BO_FLAGS_MICRO_TILE 2
struct radeon_bo_manager;
struct radeon_cs;
struct radeon_bo {
uint32_t alignment;
@ -74,6 +75,7 @@ struct radeon_bo_funcs {
int (*bo_get_tiling)(struct radeon_bo *bo, uint32_t *tiling_flags,
uint32_t *pitch);
int (*bo_is_busy)(struct radeon_bo *bo, uint32_t *domain);
int (*bo_is_referenced_by_cs)(struct radeon_bo *bo, struct radeon_cs *cs);
};
struct radeon_bo_manager {
@ -199,6 +201,15 @@ static inline int radeon_bo_is_static(struct radeon_bo *bo)
return 0;
}
static inline int _radeon_bo_is_referenced_by_cs(struct radeon_bo *bo,
struct radeon_cs *cs,
const char *file,
const char *func,
unsigned line)
{
return bo->cref > 1;
}
#define radeon_bo_open(bom, h, s, a, d, f)\
_radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
#define radeon_bo_ref(bo)\
@ -215,5 +226,7 @@ static inline int radeon_bo_is_static(struct radeon_bo *bo)
_radeon_bo_wait(bo, __FILE__, __func__, __LINE__)
#define radeon_bo_is_busy(bo, domain) \
_radeon_bo_is_busy(bo, domain, __FILE__, __func__, __LINE__)
#define radeon_bo_is_referenced_by_cs(bo, cs) \
_radeon_bo_is_referenced_by_cs(bo, cs, __FILE__, __FUNCTION__, __LINE__)
#endif

View file

@ -136,8 +136,13 @@ radeonBufferSubData(GLcontext * ctx,
const GLvoid * data,
struct gl_buffer_object *obj)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
if (radeon_bo_is_referenced_by_cs(radeon_obj->bo, radeon->cmdbuf.cs)) {
radeon_firevertices(radeon);
}
radeon_bo_map(radeon_obj->bo, GL_TRUE);
_mesa_memcpy(radeon_obj->bo->ptr + offset, data, size);

View file

@ -257,7 +257,9 @@ void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
if (ctx->Scissor.Enabled) {
/* We don't pipeline cliprect changes */
radeon_firevertices(radeon);
if (!radeon->radeonScreen->kernel_mm) {
radeon_firevertices(radeon);
}
radeonUpdateScissor(ctx);
}
}
@ -1123,8 +1125,6 @@ void radeonFlush(GLcontext *ctx)
if (radeon->dma.flush)
radeon->dma.flush( ctx );
radeonEmitState(radeon);
if (radeon->cmdbuf.cs->cdw)
rcommonFlushCmdBuf(radeon, __FUNCTION__);
@ -1147,9 +1147,6 @@ void radeonFlush(GLcontext *ctx)
}
}
}
make_empty_list(&radeon->query.not_flushed_head);
}
/* Make sure all commands have been sent to the hardware and have

View file

@ -265,7 +265,6 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
radeon->texture_compressed_row_align = 64;
}
make_empty_list(&radeon->query.not_flushed_head);
radeon_init_dma(radeon);
return GL_TRUE;

View file

@ -208,6 +208,10 @@ struct radeon_tex_obj {
* and so on.
*/
GLboolean validated;
/* Minimum LOD to be used during rendering */
unsigned minLod;
/* Miximum LOD to be used during rendering */
unsigned maxLod;
GLuint override_offset;
GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
@ -502,7 +506,6 @@ struct radeon_context {
struct {
struct radeon_query_object *current;
struct radeon_query_object not_flushed_head;
struct radeon_state_atom queryobj;
} query;

View file

@ -1,4 +1,5 @@
/*
* Copyright (C) 2009 Maciej Cencora.
* Copyright (C) 2008 Nicolai Haehnle.
*
* All Rights Reserved.
@ -32,10 +33,13 @@
#include "main/simple_list.h"
#include "main/texcompress.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "radeon_texture.h"
static GLuint radeon_compressed_texture_size(GLcontext *ctx,
GLsizei width, GLsizei height, GLsizei depth,
GLuint mesaFormat)
gl_format mesaFormat)
{
GLuint size = _mesa_format_image_size(mesaFormat, width, height, depth);
@ -55,29 +59,6 @@ static GLuint radeon_compressed_texture_size(GLcontext *ctx,
return size;
}
static int radeon_compressed_num_bytes(GLuint mesaFormat)
{
int bytes = 0;
switch(mesaFormat) {
case MESA_FORMAT_RGB_FXT1:
case MESA_FORMAT_RGBA_FXT1:
case MESA_FORMAT_RGB_DXT1:
case MESA_FORMAT_RGBA_DXT1:
bytes = 2;
break;
case MESA_FORMAT_RGBA_DXT3:
case MESA_FORMAT_RGBA_DXT5:
bytes = 4;
default:
break;
}
return bytes;
}
/**
* Compute sizes and fill in offset and blit information for the given
* image (determined by \p face and \p level).
@ -92,25 +73,24 @@ static void compute_tex_image_offset(radeonContextPtr rmesa, radeon_mipmap_tree
uint32_t row_align;
/* Find image size in bytes */
if (mt->compressed) {
if (_mesa_is_format_compressed(mt->mesaFormat)) {
/* TODO: Is this correct? Need test cases for compressed textures! */
row_align = rmesa->texture_compressed_row_align - 1;
lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
lvl->size = radeon_compressed_texture_size(mt->radeon->glCtx,
lvl->width, lvl->height, lvl->depth, mt->compressed);
lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
lvl->size = radeon_compressed_texture_size(rmesa->glCtx, lvl->width, lvl->height, lvl->depth, mt->mesaFormat);
} else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
row_align = rmesa->texture_rect_row_align - 1;
lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
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->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) * 2 + 31) & ~31;
lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
} else {
row_align = rmesa->texture_row_align - 1;
lvl->rowstride = (lvl->width * mt->bpp + row_align) & ~row_align;
lvl->rowstride = (_mesa_format_row_stride(mt->mesaFormat, lvl->width) + row_align) & ~row_align;
lvl->size = lvl->rowstride * lvl->height * lvl->depth;
}
assert(lvl->size > 0);
@ -138,17 +118,15 @@ static GLuint minify(GLuint size, GLuint levels)
static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
{
GLuint curOffset;
GLuint numLevels;
GLuint i;
GLuint face;
numLevels = mt->lastLevel - mt->firstLevel + 1;
assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
curOffset = 0;
for(face = 0; face < mt->faces; face++) {
for(i = 0; i < numLevels; i++) {
for(i = 0; i < mt->numLevels; i++) {
mt->levels[i].width = minify(mt->width0, i);
mt->levels[i].height = minify(mt->height0, i);
mt->levels[i].depth = minify(mt->depth0, i);
@ -163,14 +141,12 @@ static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_
static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
{
GLuint curOffset;
GLuint numLevels;
GLuint i;
numLevels = mt->lastLevel - mt->firstLevel + 1;
assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
curOffset = 0;
for(i = 0; i < numLevels; i++) {
for(i = 0; i < mt->numLevels; i++) {
GLuint face;
mt->levels[i].width = minify(mt->width0, i);
@ -188,27 +164,22 @@ static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_
/**
* Create a new mipmap tree, calculate its layout and allocate memory.
*/
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
GLuint width0, GLuint height0, GLuint depth0,
GLuint bpp, GLuint tilebits, GLuint compressed)
static radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
{
radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
mt->radeon = rmesa;
mt->internal_format = internal_format;
mt->mesaFormat = mesaFormat;
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->baseLevel = baseLevel;
mt->numLevels = numLevels;
mt->width0 = width0;
mt->height0 = height0;
mt->depth0 = depth0;
mt->bpp = compressed ? radeon_compressed_num_bytes(compressed) : bpp;
mt->tilebits = tilebits;
mt->compressed = compressed;
if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
calculate_miptree_layout_r300(rmesa, mt);
@ -223,53 +194,43 @@ radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *
return mt;
}
void radeon_miptree_reference(radeon_mipmap_tree *mt)
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr)
{
assert(!*ptr);
mt->refcount++;
assert(mt->refcount > 0);
*ptr = mt;
}
void radeon_miptree_unreference(radeon_mipmap_tree *mt)
void radeon_miptree_unreference(radeon_mipmap_tree **ptr)
{
radeon_mipmap_tree *mt = *ptr;
if (!mt)
return;
assert(mt->refcount > 0);
mt->refcount--;
if (!mt->refcount) {
radeon_bo_unref(mt->bo);
free(mt);
}
*ptr = 0;
}
/**
* Calculate first and last mip levels for the given texture object,
* where the dimensions are taken from the given texture image at
* the given level.
*
* Note: level is the OpenGL level number, which is not necessarily the same
* as the first level that is actually present.
*
* The base level image of the given texture face must be non-null,
* or this will fail.
* Calculate min and max LOD for the given texture object.
* @param[in] tObj texture object whose LOD values to calculate
* @param[out] pminLod minimal LOD
* @param[out] pmaxLod maximal LOD
*/
static void calculate_first_last_level(struct gl_texture_object *tObj,
GLuint *pfirstLevel, GLuint *plastLevel,
GLuint face, GLuint level)
static void calculate_min_max_lod(struct gl_texture_object *tObj,
unsigned *pminLod, unsigned *pmaxLod)
{
const struct gl_texture_image * const baseImage =
tObj->Image[face][level];
assert(baseImage);
/* 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;
int minLod, maxLod;
/* Yes, this looks overly complicated, but it's all needed.
*/
switch (tObj->Target) {
@ -280,55 +241,46 @@ static void calculate_first_last_level(struct gl_texture_object *tObj,
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;
minLod = maxLod = tObj->BaseLevel;
} else {
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
firstLevel = MIN2(firstLevel, level + baseImage->MaxLog2);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, level + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
minLod = tObj->BaseLevel + (GLint)(tObj->MinLod);
minLod = MAX2(minLod, tObj->BaseLevel);
minLod = MIN2(minLod, tObj->MaxLevel);
maxLod = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
maxLod = MIN2(maxLod, tObj->MaxLevel);
maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxLog2 + minLod);
maxLod = MAX2(maxLod, minLod); /* need at least one level */
}
break;
case GL_TEXTURE_RECTANGLE_NV:
case GL_TEXTURE_4D_SGIS:
firstLevel = lastLevel = 0;
minLod = maxLod = 0;
break;
default:
return;
}
/* save these values */
*pfirstLevel = firstLevel;
*plastLevel = lastLevel;
*pminLod = minLod;
*pmaxLod = maxLod;
}
/**
* 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)
struct gl_texture_image *texImage, GLuint face, GLuint mtLevel)
{
GLboolean isCompressed = _mesa_is_format_compressed(texImage->TexFormat);
radeon_mipmap_level *lvl;
if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
if (face >= mt->faces || mtLevel > mt->numLevels)
return GL_FALSE;
if (texImage->InternalFormat != mt->internal_format ||
isCompressed != mt->compressed)
if (texImage->TexFormat != mt->mesaFormat)
return GL_FALSE;
if (!isCompressed &&
!mt->compressed &&
_mesa_get_format_bytes(texImage->TexFormat) != mt->bpp)
return GL_FALSE;
lvl = &mt->levels[level - mt->firstLevel];
lvl = &mt->levels[mtLevel];
if (lvl->width != texImage->Width ||
lvl->height != texImage->Height ||
lvl->depth != texImage->Depth)
@ -337,64 +289,72 @@ GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
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)
static 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;
GLuint texelBytes;
unsigned numLevels;
radeon_mipmap_level *mtBaseLevel;
calculate_first_last_level(texObj, &firstLevel, &lastLevel, 0, texObj->BaseLevel);
if (texObj->Target == GL_TEXTURE_CUBE_MAP)
numfaces = 6;
if (texObj->BaseLevel < mt->baseLevel)
return GL_FALSE;
firstImage = texObj->Image[0][firstLevel];
compressed = _mesa_is_format_compressed(firstImage->TexFormat) ? firstImage->TexFormat : 0;
texelBytes = _mesa_get_format_bytes(firstImage->TexFormat);
mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
firstImage = texObj->Image[0][texObj->BaseLevel];
numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
return (mt->firstLevel == firstLevel &&
mt->lastLevel == lastLevel &&
mt->width0 == firstImage->Width &&
mt->height0 == firstImage->Height &&
mt->depth0 == firstImage->Depth &&
mt->compressed == compressed &&
(!mt->compressed ? (mt->bpp == texelBytes) : 1));
if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
fprintf(stderr, "height0 %d vs %d\n", mtBaseLevel->height, firstImage->Height);
fprintf(stderr, "depth0 %d vs %d\n", mtBaseLevel->depth, firstImage->Depth);
if (mt->target == texObj->Target &&
mt->mesaFormat == firstImage->TexFormat &&
mt->numLevels >= numLevels &&
mtBaseLevel->width == firstImage->Width &&
mtBaseLevel->height == firstImage->Height &&
mtBaseLevel->depth == firstImage->Depth) {
fprintf(stderr, "MATCHED\n");
} else {
fprintf(stderr, "NOT MATCHED\n");
}
}
return (mt->target == texObj->Target &&
mt->mesaFormat == firstImage->TexFormat &&
mt->numLevels >= numLevels &&
mtBaseLevel->width == firstImage->Width &&
mtBaseLevel->height == firstImage->Height &&
mtBaseLevel->depth == firstImage->Depth);
}
/**
* Try to allocate a mipmap tree for the given texture that will fit the
* given image in the given position.
* Try to allocate a mipmap tree for the given texture object.
* @param[in] rmesa radeon context
* @param[in] t radeon texture object
*/
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
radeon_texture_image *image, GLuint face, GLuint level)
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
{
GLuint compressed = _mesa_is_format_compressed(image->base.TexFormat) ? image->base.TexFormat : 0;
GLuint numfaces = 1;
GLuint firstLevel, lastLevel;
GLuint texelBytes;
struct gl_texture_object *texObj = &t->base;
struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
GLuint numLevels;
assert(!t->mt);
calculate_first_last_level(&t->base, &firstLevel, &lastLevel, face, level);
if (t->base.Target == GL_TEXTURE_CUBE_MAP)
numfaces = 6;
if (level != firstLevel || face >= numfaces)
if (!texImg)
return;
texelBytes = _mesa_get_format_bytes(image->base.TexFormat);
numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, texImg->MaxLog2 + 1);
t->mt = radeon_miptree_create(rmesa, t, t->base.Target,
image->base.InternalFormat,
firstLevel, lastLevel,
image->base.Width, image->base.Height, image->base.Depth,
texelBytes, t->tile_bits, compressed);
t->mt = radeon_miptree_create(rmesa, t->base.Target,
texImg->TexFormat, texObj->BaseLevel,
numLevels, texImg->Width, texImg->Height,
texImg->Depth, t->tile_bits);
}
/* Although we use the image_offset[] array to store relative offsets
@ -406,21 +366,239 @@ void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
void
radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets)
{
if (mt->target != GL_TEXTURE_3D || mt->faces == 1)
offsets[0] = 0;
else {
int i;
for (i = 0; i < 6; i++)
offsets[i] = mt->levels[level].faces[i].offset;
}
if (mt->target != GL_TEXTURE_3D || mt->faces == 1) {
offsets[0] = 0;
} else {
int i;
for (i = 0; i < 6; i++) {
offsets[i] = mt->levels[level].faces[i].offset;
}
}
}
GLuint
radeon_miptree_image_offset(radeon_mipmap_tree *mt,
GLuint face, GLuint level)
{
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
return (mt->levels[level].faces[face].offset);
else
return mt->levels[level].faces[0].offset;
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
return (mt->levels[level].faces[face].offset);
else
return mt->levels[level].faces[0].offset;
}
/**
* Convert radeon miptree texture level to GL texture level
* @param[in] tObj texture object whom level is to be converted
* @param[in] level radeon miptree texture level
* @return GL texture level
*/
unsigned radeon_miptree_level_to_gl_level(struct gl_texture_object *tObj, unsigned level)
{
return level + tObj->BaseLevel;
}
/**
* Convert GL texture level to radeon miptree texture level
* @param[in] tObj texture object whom level is to be converted
* @param[in] level GL texture level
* @return radeon miptree texture level
*/
unsigned radeon_gl_level_to_miptree_level(struct gl_texture_object *tObj, unsigned level)
{
return level - tObj->BaseLevel;
}
/**
* Ensure that the given image is stored in the given miptree from now on.
*/
static void migrate_image_to_miptree(radeon_mipmap_tree *mt,
radeon_texture_image *image,
int face, int mtLevel)
{
radeon_mipmap_level *dstlvl = &mt->levels[mtLevel];
unsigned char *dest;
assert(image->mt != mt);
assert(dstlvl->width == image->base.Width);
assert(dstlvl->height == image->base.Height);
assert(dstlvl->depth == image->base.Depth);
radeon_bo_map(mt->bo, GL_TRUE);
dest = mt->bo->ptr + dstlvl->faces[face].offset;
if (image->mt) {
/* Format etc. should match, so we really just need a memcpy().
* In fact, that memcpy() could be done by the hardware in many
* cases, provided that we have a proper memory manager.
*/
assert(mt->mesaFormat == image->base.TexFormat);
radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel];
assert(srclvl->size == dstlvl->size);
assert(srclvl->rowstride == dstlvl->rowstride);
radeon_bo_map(image->mt->bo, GL_FALSE);
memcpy(dest,
image->mt->bo->ptr + srclvl->faces[face].offset,
dstlvl->size);
radeon_bo_unmap(image->mt->bo);
radeon_miptree_unreference(&image->mt);
} else {
/* need to confirm this value is correct */
if (_mesa_is_format_compressed(image->base.TexFormat)) {
unsigned size = _mesa_format_image_size(image->base.TexFormat,
image->base.Width,
image->base.Height,
image->base.Depth);
memcpy(dest, image->base.Data, size);
} else {
uint32_t srcrowstride;
uint32_t height;
height = image->base.Height * image->base.Depth;
srcrowstride = image->base.Width * _mesa_get_format_bytes(image->base.TexFormat);
copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
height, srcrowstride);
}
_mesa_free_texmemory(image->base.Data);
image->base.Data = 0;
}
radeon_bo_unmap(mt->bo);
radeon_miptree_reference(mt, &image->mt);
image->mtface = face;
image->mtlevel = mtLevel;
}
/**
* Filter matching miptrees, and select one with the most of data.
* @param[in] texObj radeon texture object
* @param[in] firstLevel first texture level to check
* @param[in] lastLevel last texture level to check
*/
static radeon_mipmap_tree * get_biggest_matching_miptree(radeonTexObj *texObj,
unsigned firstLevel,
unsigned lastLevel)
{
const unsigned numLevels = lastLevel - firstLevel;
unsigned *mtSizes = calloc(numLevels, sizeof(unsigned));
radeon_mipmap_tree **mts = calloc(numLevels, sizeof(radeon_mipmap_tree *));
unsigned mtCount = 0;
unsigned maxMtIndex = 0;
for (unsigned level = firstLevel; level <= lastLevel; ++level) {
radeon_texture_image *img = get_radeon_texture_image(texObj->base.Image[0][level]);
unsigned found = 0;
// TODO: why this hack??
if (!img)
break;
if (!img->mt || !radeon_miptree_matches_texture(img->mt, &texObj->base))
continue;
for (int i = 0; i < mtCount; ++i) {
if (mts[i] == img->mt) {
found = 1;
mtSizes[i] += img->mt->levels[img->mtlevel].size;
break;
}
}
if (!found) {
mtSizes[mtCount] += img->mt->levels[img->mtlevel].size;
mts[mtCount++] = img->mt;
mtCount++;
}
}
if (mtCount == 0) {
return NULL;
}
for (int i = 1; i < mtCount; ++i) {
if (mtSizes[i] > mtSizes[maxMtIndex]) {
maxMtIndex = i;
}
}
return mts[maxMtIndex];
}
/**
* Validate texture mipmap tree.
* If individual images are stored in different mipmap trees
* use the mipmap tree that has the most of the correct data.
*/
int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObj *t = radeon_tex_obj(texObj);
if (t->validated || t->image_override) {
return GL_TRUE;
}
if (texObj->Image[0][texObj->BaseLevel]->Border > 0)
return GL_FALSE;
_mesa_test_texobj_completeness(rmesa->glCtx, texObj);
if (!texObj->_Complete) {
return GL_FALSE;
}
calculate_min_max_lod(&t->base, &t->minLod, &t->maxLod);
if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, "%s: Validating texture %p now, minLod = %d, maxLod = %d\n",
__FUNCTION__, texObj ,t->minLod, t->maxLod);
radeon_mipmap_tree *dst_miptree;
dst_miptree = get_biggest_matching_miptree(t, t->minLod, t->maxLod);
if (!dst_miptree) {
radeon_miptree_unreference(&t->mt);
radeon_try_alloc_miptree(rmesa, t);
dst_miptree = t->mt;
}
const unsigned faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
unsigned face, level;
radeon_texture_image *img;
/* Validate only the levels that will actually be used during rendering */
for (face = 0; face < faces; ++face) {
for (level = t->minLod; level <= t->maxLod; ++level) {
img = get_radeon_texture_image(texObj->Image[face][level]);
if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "Checking image level %d, face %d, mt %p ... ", level, face, img->mt);
}
if (img->mt != dst_miptree) {
if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "MIGRATING\n");
}
migrate_image_to_miptree(dst_miptree, img, face, radeon_gl_level_to_miptree_level(texObj, level));
} else if (RADEON_DEBUG & RADEON_TEXTURE) {
fprintf(stderr, "OK\n");
}
}
}
t->validated = GL_TRUE;
return GL_TRUE;
}
uint32_t get_base_teximage_offset(radeonTexObj *texObj)
{
if (!texObj->mt) {
return 0;
} else {
return radeon_miptree_image_offset(texObj->mt, 0, texObj->minLod);
}
}

View file

@ -59,43 +59,38 @@ struct _radeon_mipmap_level {
* 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 */
GLenum internal_format;
GLenum mesaFormat; /** MESA_FORMAT_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 baseLevel; /** gl_texture_object->baseLevel it was created for */
GLuint numLevels; /** Number of mip levels 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_MIPTREE_MAX_TEXTURE_LEVELS];
};
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
GLenum target, GLenum internal_format, 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);
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr);
void radeon_miptree_unreference(radeon_mipmap_tree **ptr);
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,
radeon_texture_image *texImage, GLuint face, GLuint level);
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t);
GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
GLuint face, GLuint level);
void radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets);
unsigned radeon_miptree_level_to_gl_level(struct gl_texture_object *tObj, unsigned level);
unsigned radeon_gl_level_to_miptree_level(struct gl_texture_object *tObj, unsigned level);
uint32_t get_base_teximage_offset(radeonTexObj *texObj);
#endif /* __RADEON_MIPMAP_TREE_H_ */

View file

@ -31,20 +31,6 @@
#include "main/imports.h"
#include "main/simple_list.h"
static int radeonQueryIsFlushed(GLcontext *ctx, struct gl_query_object *q)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
struct radeon_query_object *tmp, *query = (struct radeon_query_object *)q;
foreach(tmp, &radeon->query.not_flushed_head) {
if (tmp == query) {
return 0;
}
}
return 1;
}
static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
@ -122,10 +108,11 @@ static void radeonDeleteQuery(GLcontext *ctx, struct gl_query_object *q)
static void radeonWaitQuery(GLcontext *ctx, struct gl_query_object *q)
{
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
struct radeon_query_object *query = (struct radeon_query_object *)q;
/* If the cmdbuf with packets for this query hasn't been flushed yet, do it now */
if (!radeonQueryIsFlushed(ctx, q))
if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs))
ctx->Driver.Flush(ctx);
radeon_print(RADEON_STATE, RADEON_VERBOSE, "%s: query id %d, bo %p, offset %d\n", __FUNCTION__, q->Id, query->bo, query->curr_offset);
@ -157,8 +144,6 @@ static void radeonBeginQuery(GLcontext *ctx, struct gl_query_object *q)
radeon->query.queryobj.dirty = GL_TRUE;
radeon->hw.is_dirty = GL_TRUE;
insert_at_tail(&radeon->query.not_flushed_head, query);
}
void radeonEmitQueryEnd(GLcontext *ctx)
@ -206,7 +191,7 @@ static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q)
uint32_t domain;
/* Need to perform a flush, as per ARB_occlusion_query spec */
if (!radeonQueryIsFlushed(ctx, q)) {
if (radeon_bo_is_referenced_by_cs(query->bo, radeon->cmdbuf.cs)) {
ctx->Driver.Flush(ctx);
}

View file

@ -645,11 +645,11 @@ static void tex_emit_cs(GLcontext *ctx, struct radeon_state_atom *atom)
OUT_BATCH(CP_PACKET0(RADEON_PP_TXOFFSET_0 + (24 * i), 0));
if (t->mt && !t->image_override) {
if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) {
lvl = &t->mt->levels[0];
lvl = &t->mt->levels[t->minLod];
OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset,
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
} else {
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, 0,
OUT_BATCH_RELOC(t->tile_bits, t->mt->bo, get_base_teximage_offset(t),
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
}
} else {

View file

@ -348,17 +348,7 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target,
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
t->validated = GL_FALSE;
}
t->validated = GL_FALSE;
break;
default:
@ -388,10 +378,8 @@ static void radeonDeleteTexture( GLcontext *ctx,
}
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = 0;
}
radeon_miptree_unreference(&t->mt);
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, texObj);
}

View file

@ -699,14 +699,10 @@ void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_
radeon_bo_unref(rImage->bo);
rImage->bo = NULL;
}
if (t->mt) {
radeon_miptree_unreference(t->mt);
t->mt = NULL;
}
if (rImage->mt) {
radeon_miptree_unreference(rImage->mt);
rImage->mt = NULL;
}
radeon_miptree_unreference(&t->mt);
radeon_miptree_unreference(&rImage->mt);
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
texImage->RowStride = rb->pitch / rb->cpp;
@ -1021,7 +1017,7 @@ static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int
return GL_TRUE;
}
firstImage = t->base.Image[0][t->mt->firstLevel];
firstImage = t->base.Image[0][t->minLod];
if (firstImage->Border > 0) {
fprintf(stderr, "%s: border\n", __FUNCTION__);
@ -1049,9 +1045,9 @@ static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int
return GL_FALSE;
}
}
t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
t->pp_txfilter |= (t->mt->lastLevel - t->mt->firstLevel) << RADEON_MAX_MIP_LEVEL_SHIFT;
t->pp_txfilter |= (t->maxLod - t->minLod) << RADEON_MAX_MIP_LEVEL_SHIFT;
t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
RADEON_TXFORMAT_HEIGHT_MASK |
@ -1060,9 +1056,9 @@ static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int
RADEON_TXFORMAT_F5_HEIGHT_MASK);
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
(log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
t->tile_bits = 0;
if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
ASSERT(log2Width == log2Height);
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |

View file

@ -1,4 +1,5 @@
/*
* Copyright (C) 2009 Maciej Cencora.
* Copyright (C) 2008 Nicolai Haehnle.
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
*
@ -46,7 +47,7 @@
#include "radeon_mipmap_tree.h"
static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
GLuint numrows, GLuint rowsize)
{
assert(rowsize <= dststride);
@ -81,8 +82,7 @@ void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage)
radeon_texture_image* image = get_radeon_texture_image(timage);
if (image->mt) {
radeon_miptree_unreference(image->mt);
image->mt = 0;
radeon_miptree_unreference(&image->mt);
assert(!image->base.Data);
} else {
_mesa_free_texture_image_data(ctx, timage);
@ -108,7 +108,7 @@ static void teximage_set_map_data(radeon_texture_image *image)
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;
image->base.RowStride = lvl->rowstride / _mesa_get_format_bytes(image->base.TexFormat);
}
@ -174,7 +174,7 @@ void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
radeon_bo_map(t->mt->bo, GL_FALSE);
for(face = 0; face < t->mt->faces; ++face) {
for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
for(level = t->minLod; level <= t->maxLod; ++level)
teximage_set_map_data(get_radeon_texture_image(texObj->Image[face][level]));
}
}
@ -191,7 +191,7 @@ void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
return;
for(face = 0; face < t->mt->faces; ++face) {
for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level)
for(level = t->minLod; level <= t->maxLod; ++level)
texObj->Image[face][level]->Data = 0;
}
radeon_bo_unmap(t->mt->bo);
@ -240,8 +240,7 @@ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
image->mtlevel = i;
image->mtface = face;
radeon_miptree_unreference(image->mt);
image->mt = NULL;
radeon_miptree_unreference(&image->mt);
}
}
@ -510,6 +509,135 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
return MESA_FORMAT_NONE; /* never get here */
}
static void teximage_assign_miptree(radeonContextPtr rmesa,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
unsigned face,
unsigned level)
{
radeonTexObj *t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
/* Try using current miptree, or create new if there isn't any */
if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face,
radeon_gl_level_to_miptree_level(texObj, level))) {
radeon_miptree_unreference(&t->mt);
radeon_try_alloc_miptree(rmesa, t);
}
/* Miptree alocation may have failed,
* when there was no image for baselevel specified */
if (t->mt) {
image->mtface = face;
image->mtlevel = radeon_gl_level_to_miptree_level(texObj, level);
radeon_miptree_reference(t->mt, &image->mt);
}
}
static GLuint * allocate_image_offsets(GLcontext *ctx,
unsigned alignedWidth,
unsigned height,
unsigned depth)
{
int i;
GLuint *offsets;
offsets = _mesa_malloc(depth * sizeof(GLuint)) ;
if (!offsets) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex[Sub]Image");
return NULL;
}
for (i = 0; i < depth; ++i) {
offsets[i] = alignedWidth * height * i;
}
return offsets;
}
/**
* Update a subregion of the given texture image.
*/
static void radeon_store_teximage(GLcontext* ctx, int dims,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLsizei imageSize,
GLenum format, GLenum type,
const GLvoid * pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
int compressed)
{
radeonTexObj *t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
GLuint dstRowStride;
GLuint *dstImageOffsets;
if (image->mt) {
dstRowStride = image->mt->levels[image->mtlevel].rowstride;
} else if (t->bo) {
/* TFP case */
/* TODO */
assert(0);
} else {
dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
}
if (dims == 3) {
unsigned alignedWidth = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat);
dstImageOffsets = allocate_image_offsets(ctx, alignedWidth, height, depth);
if (!dstImageOffsets) {
return;
}
} else {
dstImageOffsets = texImage->ImageOffsets;
}
radeon_teximage_map(image, GL_TRUE);
if (compressed) {
uint32_t srcRowStride, bytesPerRow, rows;
GLubyte *img_start;
if (!image->mt) {
dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
texImage->TexFormat,
texImage->Width, texImage->Data);
}
else {
uint32_t blocks_x, block_width, block_height;
_mesa_get_format_block_size(image->mt->mesaFormat, &block_width, &block_height);
blocks_x = dstRowStride / block_width;
img_start = texImage->Data + _mesa_get_format_bytes(image->mt->mesaFormat) * 4 * (blocks_x * (yoffset / 4) + xoffset / 4);
}
srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
bytesPerRow = srcRowStride;
rows = (height + 3) / 4;
copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
}
else {
if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat, texImage->Data,
xoffset, yoffset, zoffset,
dstRowStride,
dstImageOffsets,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
}
}
if (dims == 3) {
_mesa_free(dstImageOffsets);
}
radeon_teximage_unmap(image);
}
/**
* All glTexImage calls go through this function.
*/
@ -528,13 +656,17 @@ static void radeon_teximage(
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObj* t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
GLuint dstRowStride;
GLint postConvWidth = width;
GLint postConvHeight = height;
GLuint texelBytes;
GLuint face = radeon_face_for_target(target);
radeon_firevertices(rmesa);
{
struct radeon_bo *bo;
bo = !image->mt ? image->bo : image->mt->bo;
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
radeon_firevertices(rmesa);
}
}
t->validated = GL_FALSE;
@ -543,53 +675,30 @@ static void radeon_teximage(
&postConvHeight);
}
if (_mesa_is_format_compressed(texImage->TexFormat)) {
texelBytes = 0;
} else {
texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
if (!_mesa_is_format_compressed(texImage->TexFormat)) {
GLuint texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
/* Minimum pitch of 32 bytes */
if (postConvWidth * texelBytes < 32) {
postConvWidth = 32 / texelBytes;
texImage->RowStride = postConvWidth;
postConvWidth = 32 / texelBytes;
texImage->RowStride = postConvWidth;
}
if (!image->mt) {
if (!image->mt) {
assert(texImage->RowStride == postConvWidth);
}
}
/* Allocate memory for image */
radeonFreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
/* Mesa core only clears texImage->Data but not image->mt */
radeonFreeTexImageData(ctx, texImage);
if (t->mt &&
t->mt->firstLevel == level &&
t->mt->lastLevel == level &&
t->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
!radeon_miptree_matches_image(t->mt, texImage, face, level)) {
radeon_miptree_unreference(t->mt);
t->mt = NULL;
}
if (!t->mt)
radeon_try_alloc_miptree(rmesa, t, image, face, level);
if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) {
radeon_mipmap_level *lvl;
image->mt = t->mt;
image->mtlevel = level - t->mt->firstLevel;
image->mtface = face;
radeon_miptree_reference(t->mt);
lvl = &image->mt->levels[image->mtlevel];
dstRowStride = lvl->rowstride;
} else {
int size;
if (_mesa_is_format_compressed(texImage->TexFormat)) {
size = _mesa_format_image_size(texImage->TexFormat,
texImage->Width,
texImage->Height,
texImage->Depth);
} else {
size = texImage->Width * texImage->Height * texImage->Depth * _mesa_get_format_bytes(texImage->TexFormat);
if (!t->bo) {
teximage_assign_miptree(rmesa, texObj, texImage, face, level);
if (!t->mt) {
int size = _mesa_format_image_size(texImage->TexFormat,
texImage->Width,
texImage->Height,
texImage->Depth);
texImage->Data = _mesa_alloc_texmemory(size);
}
texImage->Data = _mesa_alloc_texmemory(size);
}
/* Upload texture image; note that the spec allows pixels to be NULL */
@ -603,65 +712,16 @@ static void radeon_teximage(
}
if (pixels) {
radeon_teximage_map(image, GL_TRUE);
if (compressed) {
if (image->mt) {
uint32_t srcRowStride, bytesPerRow, rows;
srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
bytesPerRow = srcRowStride;
rows = (height + 3) / 4;
copy_rows(texImage->Data, image->mt->levels[level].rowstride,
pixels, srcRowStride, rows, bytesPerRow);
} else {
memcpy(texImage->Data, pixels, imageSize);
}
} else {
GLuint dstRowStride;
GLuint *dstImageOffsets;
if (image->mt) {
radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
dstRowStride = lvl->rowstride;
} else {
dstRowStride = texImage->Width * _mesa_get_format_bytes(texImage->TexFormat);
}
if (dims == 3) {
int i;
dstImageOffsets = _mesa_malloc(depth * sizeof(GLuint)) ;
if (!dstImageOffsets)
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
for (i = 0; i < depth; ++i) {
dstImageOffsets[i] = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat) * height * i;
}
} else {
dstImageOffsets = texImage->ImageOffsets;
}
if (!_mesa_texstore(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */
dstRowStride,
dstImageOffsets,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
}
if (dims == 3)
_mesa_free(dstImageOffsets);
}
radeon_store_teximage(ctx, dims,
0, 0, 0,
width, height, depth,
imageSize, format, type,
pixels, packing,
texObj, texImage,
compressed);
}
_mesa_unmap_teximage_pbo(ctx, packing);
if (pixels)
radeon_teximage_unmap(image);
}
void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
@ -714,7 +774,7 @@ void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
}
/**
* Update a subregion of the given texture image.
* All glTexSubImage calls go through this function.
*/
static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level,
GLint xoffset, GLint yoffset, GLint zoffset,
@ -731,66 +791,34 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve
radeonTexObj* t = radeon_tex_obj(texObj);
radeon_texture_image* image = get_radeon_texture_image(texImage);
radeon_firevertices(rmesa);
{
struct radeon_bo *bo;
bo = !image->mt ? image->bo : image->mt->bo;
if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
radeon_firevertices(rmesa);
}
}
t->validated = GL_FALSE;
if (compressed) {
pixels = _mesa_validate_pbo_compressed_teximage(
ctx, imageSize, pixels, packing, "glCompressedTexImage");
ctx, imageSize, pixels, packing, "glCompressedTexSubImage");
} else {
pixels = _mesa_validate_pbo_teximage(ctx, dims,
width, height, depth, format, type, pixels, packing, "glTexSubImage1D");
width, height, depth, format, type, pixels, packing, "glTexSubImage");
}
if (pixels) {
GLint dstRowStride;
radeon_teximage_map(image, GL_TRUE);
if (image->mt) {
radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
dstRowStride = lvl->rowstride;
} else {
dstRowStride = texImage->RowStride * _mesa_get_format_bytes(texImage->TexFormat);
}
if (compressed) {
uint32_t srcRowStride, bytesPerRow, rows;
GLubyte *img_start;
if (!image->mt) {
dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
img_start = _mesa_compressed_image_address(xoffset, yoffset, 0,
texImage->TexFormat,
texImage->Width, texImage->Data);
}
else {
uint32_t blocks_x = dstRowStride / (image->mt->bpp * 4);
img_start = texImage->Data + image->mt->bpp * 4 * (blocks_x * (yoffset / 4) + xoffset / 4);
}
srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
bytesPerRow = srcRowStride;
rows = (height + 3) / 4;
copy_rows(img_start, dstRowStride, pixels, srcRowStride, rows, bytesPerRow);
}
else {
if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat, texImage->Data,
xoffset, yoffset, zoffset,
dstRowStride,
texImage->ImageOffsets,
width, height, depth,
format, type, pixels, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
}
}
radeon_store_teximage(ctx, dims,
xoffset, yoffset, zoffset,
width, height, depth,
imageSize, format, type,
pixels, packing,
texObj, texImage,
compressed);
}
radeon_teximage_unmap(image);
_mesa_unmap_teximage_pbo(ctx, packing);
}
void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
@ -846,143 +874,6 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
format, type, pixels, packing, texObj, texImage, 0);
}
/**
* Ensure that the given image is stored in the given miptree from now on.
*/
static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_image *image, int face, int level)
{
radeon_mipmap_level *dstlvl = &mt->levels[level - mt->firstLevel];
unsigned char *dest;
assert(image->mt != mt);
assert(dstlvl->width == image->base.Width);
assert(dstlvl->height == image->base.Height);
assert(dstlvl->depth == image->base.Depth);
radeon_bo_map(mt->bo, GL_TRUE);
dest = mt->bo->ptr + dstlvl->faces[face].offset;
if (image->mt) {
/* Format etc. should match, so we really just need a memcpy().
* In fact, that memcpy() could be done by the hardware in many
* cases, provided that we have a proper memory manager.
*/
radeon_mipmap_level *srclvl = &image->mt->levels[image->mtlevel-image->mt->firstLevel];
assert(srclvl->size == dstlvl->size);
assert(srclvl->rowstride == dstlvl->rowstride);
radeon_bo_map(image->mt->bo, GL_FALSE);
memcpy(dest,
image->mt->bo->ptr + srclvl->faces[face].offset,
dstlvl->size);
radeon_bo_unmap(image->mt->bo);
radeon_miptree_unreference(image->mt);
} else {
uint32_t srcrowstride;
uint32_t height;
/* need to confirm this value is correct */
if (mt->compressed) {
height = (image->base.Height + 3) / 4;
srcrowstride = _mesa_format_row_stride(image->base.TexFormat, image->base.Width);
} else {
height = image->base.Height * image->base.Depth;
srcrowstride = image->base.Width * _mesa_get_format_bytes(image->base.TexFormat);
}
// if (mt->tilebits)
// WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
height, srcrowstride);
_mesa_free_texmemory(image->base.Data);
image->base.Data = 0;
}
radeon_bo_unmap(mt->bo);
image->mt = mt;
image->mtface = face;
image->mtlevel = level;
radeon_miptree_reference(image->mt);
}
int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *texObj)
{
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
radeonTexObj *t = radeon_tex_obj(texObj);
radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[0][texObj->BaseLevel]);
int face, level;
if (t->validated || t->image_override)
return GL_TRUE;
if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, "%s: Validating texture %p now\n", __FUNCTION__, texObj);
if (baseimage->base.Border > 0)
return GL_FALSE;
/* Ensure a matching miptree exists.
*
* Differing mipmap trees can result when the app uses TexImage to
* change texture dimensions.
*
* Prefer to use base image's miptree if it
* exists, since that most likely contains more valid data (remember
* that the base level is usually significantly larger than the rest
* of the miptree, so cubemaps are the only possible exception).
*/
if (baseimage->mt &&
baseimage->mt != t->mt &&
radeon_miptree_matches_texture(baseimage->mt, &t->base)) {
radeon_miptree_unreference(t->mt);
t->mt = baseimage->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 & RADEON_TEXTURE)
fprintf(stderr, " Allocate new miptree\n");
radeon_try_alloc_miptree(rmesa, t, baseimage, 0, texObj->BaseLevel);
if (!t->mt) {
_mesa_problem(ctx, "radeon_validate_texture failed to alloc miptree");
return GL_FALSE;
}
}
/* Ensure all images are stored in the single main miptree */
for(face = 0; face < t->mt->faces; ++face) {
for(level = t->mt->firstLevel; level <= t->mt->lastLevel; ++level) {
radeon_texture_image *image = get_radeon_texture_image(texObj->Image[face][level]);
if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, " face %i, level %i... %p vs %p ", face, level, t->mt, image->mt);
if (t->mt == image->mt || (!image->mt && !image->base.Data)) {
if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, "OK\n");
continue;
}
if (RADEON_DEBUG & RADEON_TEXTURE)
fprintf(stderr, "migrating\n");
migrate_image_to_miptree(t->mt, image, face, level);
}
}
return GL_TRUE;
}
/**
* Need to map texture image into memory before copying image data,
* then unmap it.

View file

@ -33,7 +33,8 @@
#include "main/formats.h"
void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
GLuint numrows, GLuint rowsize);
struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx);
void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage);