mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 06:48:06 +02:00
Merge branch 'radeon-texrewrite-clean' into mesa_7_7_branch
This commit is contained in:
commit
cefee4e327
26 changed files with 624 additions and 621 deletions
|
|
@ -640,7 +640,7 @@ static void tex_emit(GLcontext *ctx, struct radeon_state_atom *atom)
|
||||||
OUT_BATCH_TABLE(atom->cmd, 10);
|
OUT_BATCH_TABLE(atom->cmd, 10);
|
||||||
|
|
||||||
if (t && t->mt && !t->image_override) {
|
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);
|
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
||||||
} else if (!t) {
|
} else if (!t) {
|
||||||
/* workaround for old CS mechanism */
|
/* workaround for old CS mechanism */
|
||||||
|
|
|
||||||
|
|
@ -385,16 +385,7 @@ static void r200TexParameter( GLcontext *ctx, GLenum target,
|
||||||
case GL_TEXTURE_MAX_LEVEL:
|
case GL_TEXTURE_MAX_LEVEL:
|
||||||
case GL_TEXTURE_MIN_LOD:
|
case GL_TEXTURE_MIN_LOD:
|
||||||
case GL_TEXTURE_MAX_LOD:
|
case GL_TEXTURE_MAX_LOD:
|
||||||
/* This isn't the most efficient solution but there doesn't appear to
|
t->validated = GL_FALSE;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -413,7 +404,7 @@ static void r200DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
|
||||||
(void *)texObj,
|
(void *)texObj,
|
||||||
_mesa_lookup_enum_by_nr(texObj->Target));
|
_mesa_lookup_enum_by_nr(texObj->Target));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rmesa) {
|
if (rmesa) {
|
||||||
int i;
|
int i;
|
||||||
radeon_firevertices(&rmesa->radeon);
|
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);
|
||||||
radeon_miptree_unreference(t->mt);
|
|
||||||
t->mt = 0;
|
|
||||||
}
|
|
||||||
_mesa_delete_texture_object(ctx, texObj);
|
_mesa_delete_texture_object(ctx, texObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -824,14 +824,10 @@ void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
|
||||||
radeon_bo_unref(rImage->bo);
|
radeon_bo_unref(rImage->bo);
|
||||||
rImage->bo = NULL;
|
rImage->bo = NULL;
|
||||||
}
|
}
|
||||||
if (t->mt) {
|
|
||||||
radeon_miptree_unreference(t->mt);
|
radeon_miptree_unreference(&t->mt);
|
||||||
t->mt = NULL;
|
radeon_miptree_unreference(&rImage->mt);
|
||||||
}
|
|
||||||
if (rImage->mt) {
|
|
||||||
radeon_miptree_unreference(rImage->mt);
|
|
||||||
rImage->mt = NULL;
|
|
||||||
}
|
|
||||||
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
||||||
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
||||||
texImage->RowStride = rb->pitch / 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)
|
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][t->minLod];
|
||||||
const struct gl_texture_image *firstImage = t->base.Image[0][firstlevel];
|
|
||||||
GLint log2Width, log2Height, log2Depth, texelBytes;
|
GLint log2Width, log2Height, log2Depth, texelBytes;
|
||||||
|
|
||||||
if ( t->bo ) {
|
if ( t->bo ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1454,9 +1449,9 @@ static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
|
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 |
|
t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
|
||||||
R200_TXFORMAT_HEIGHT_MASK |
|
R200_TXFORMAT_HEIGHT_MASK |
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
#include "r300_context.h"
|
#include "r300_context.h"
|
||||||
#include "r300_ioctl.h"
|
#include "r300_ioctl.h"
|
||||||
#include "radeon_reg.h"
|
|
||||||
#include "r300_reg.h"
|
#include "r300_reg.h"
|
||||||
#include "r300_cmdbuf.h"
|
#include "r300_cmdbuf.h"
|
||||||
#include "r300_emit.h"
|
#include "r300_emit.h"
|
||||||
#include "radeon_bocs_wrapper.h"
|
#include "radeon_bocs_wrapper.h"
|
||||||
#include "radeon_mipmap_tree.h"
|
#include "radeon_mipmap_tree.h"
|
||||||
#include "r300_state.h"
|
#include "r300_state.h"
|
||||||
#include "radeon_reg.h"
|
|
||||||
#include "radeon_queryobj.h"
|
#include "radeon_queryobj.h"
|
||||||
|
|
||||||
/** # of dwords reserved for additional instructions that may need to be written
|
/** # 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) {
|
if (t && !t->image_override) {
|
||||||
BEGIN_BATCH_NO_AUTOSTATE(4);
|
BEGIN_BATCH_NO_AUTOSTATE(4);
|
||||||
OUT_BATCH_REGSEQ(R300_TX_OFFSET_0 + (i * 4), 1);
|
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);
|
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
||||||
END_BATCH();
|
END_BATCH();
|
||||||
} else if (!t) {
|
} else if (!t) {
|
||||||
|
|
|
||||||
|
|
@ -439,7 +439,7 @@ static void r300InitGLExtensions(GLcontext *ctx)
|
||||||
if (r300->options.stencil_two_side_disabled)
|
if (r300->options.stencil_two_side_disabled)
|
||||||
_mesa_disable_extension(ctx, "GL_EXT_stencil_two_side");
|
_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_EXT_texture_compression_s3tc");
|
||||||
_mesa_enable_extension(ctx, "GL_S3_s3tc");
|
_mesa_enable_extension(ctx, "GL_S3_s3tc");
|
||||||
} else if (r300->options.s3tc_force_disabled) {
|
} else if (r300->options.s3tc_force_disabled) {
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,6 @@
|
||||||
#include "main/glheader.h"
|
#include "main/glheader.h"
|
||||||
#include "r300_context.h"
|
#include "r300_context.h"
|
||||||
#include "r300_cmdbuf.h"
|
#include "r300_cmdbuf.h"
|
||||||
#include "radeon_reg.h"
|
|
||||||
|
|
||||||
static INLINE uint32_t cmdpacket0(struct radeon_screen *rscrn,
|
static INLINE uint32_t cmdpacket0(struct radeon_screen *rscrn,
|
||||||
int reg, int count)
|
int reg, int count)
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include "vbo/vbo_split.h"
|
#include "vbo/vbo_split.h"
|
||||||
#include "tnl/tnl.h"
|
#include "tnl/tnl.h"
|
||||||
#include "tnl/t_vp_build.h"
|
#include "tnl/t_vp_build.h"
|
||||||
#include "radeon_reg.h"
|
|
||||||
#include "radeon_macros.h"
|
|
||||||
#include "r300_context.h"
|
#include "r300_context.h"
|
||||||
#include "r300_ioctl.h"
|
#include "r300_ioctl.h"
|
||||||
#include "r300_state.h"
|
#include "r300_state.h"
|
||||||
|
|
|
||||||
|
|
@ -1741,7 +1741,8 @@ static void r300Enable(GLcontext * ctx, GLenum cap, GLboolean state)
|
||||||
r300SetPolygonOffsetState(ctx, state);
|
r300SetPolygonOffsetState(ctx, state);
|
||||||
break;
|
break;
|
||||||
case GL_SCISSOR_TEST:
|
case GL_SCISSOR_TEST:
|
||||||
radeon_firevertices(&rmesa->radeon);
|
if (!rmesa->radeon.radeonScreen->kernel_mm)
|
||||||
|
radeon_firevertices(&rmesa->radeon);
|
||||||
rmesa->radeon.state.scissor.enabled = state;
|
rmesa->radeon.state.scissor.enabled = state;
|
||||||
radeonUpdateScissor( ctx );
|
radeonUpdateScissor( ctx );
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -223,16 +223,7 @@ static void r300TexParameter(GLcontext * ctx, GLenum target,
|
||||||
case GL_TEXTURE_MAX_LEVEL:
|
case GL_TEXTURE_MAX_LEVEL:
|
||||||
case GL_TEXTURE_MIN_LOD:
|
case GL_TEXTURE_MIN_LOD:
|
||||||
case GL_TEXTURE_MAX_LOD:
|
case GL_TEXTURE_MAX_LOD:
|
||||||
/* This isn't the most efficient solution but there doesn't appear to
|
t->validated = GL_FALSE;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_DEPTH_TEXTURE_MODE:
|
case GL_DEPTH_TEXTURE_MODE:
|
||||||
|
|
@ -270,7 +261,11 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
|
||||||
|
|
||||||
if (rmesa) {
|
if (rmesa) {
|
||||||
int i;
|
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)
|
for(i = 0; i < R300_MAX_TEXTURE_UNITS; ++i)
|
||||||
if (rmesa->hw.textures[i] == t)
|
if (rmesa->hw.textures[i] == t)
|
||||||
|
|
@ -282,10 +277,8 @@ static void r300DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
|
||||||
t->bo = NULL;
|
t->bo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->mt) {
|
radeon_miptree_unreference(&t->mt);
|
||||||
radeon_miptree_unreference(t->mt);
|
|
||||||
t->mt = 0;
|
|
||||||
}
|
|
||||||
_mesa_delete_texture_object(ctx, texObj);
|
_mesa_delete_texture_object(ctx, texObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,7 @@ static const struct tx_table {
|
||||||
_ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
|
_ASSIGN(ARGB8888, R300_EASY_TX_FORMAT(W, Z, Y, X, W8Z8Y8X8)),
|
||||||
_ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
|
_ASSIGN(ARGB8888_REV, R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8)),
|
||||||
#endif
|
#endif
|
||||||
|
_ASSIGN(XRGB8888, R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8)),
|
||||||
_ASSIGN(RGB888, 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, R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5)),
|
||||||
_ASSIGN(RGB565_REV, 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)
|
static void setup_hardware_state(r300ContextPtr rmesa, radeonTexObj *t)
|
||||||
{
|
{
|
||||||
const struct gl_texture_image *firstImage;
|
const struct gl_texture_image *firstImage;
|
||||||
int firstlevel = t->mt ? t->mt->firstLevel : 0;
|
firstImage = t->base.Image[0][t->minLod];
|
||||||
|
|
||||||
firstImage = t->base.Image[0][firstlevel];
|
|
||||||
|
|
||||||
if (!t->image_override
|
if (!t->image_override
|
||||||
&& VALID_FORMAT(firstImage->TexFormat)) {
|
&& 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)))
|
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_HEIGHTMASK_MASK & ((firstImage->Height - 1) << R300_TX_HEIGHTMASK_SHIFT)))
|
||||||
| ((R300_TX_DEPTHMASK_MASK & ((firstImage->DepthLog2) << R300_TX_DEPTHMASK_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;
|
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) {
|
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;
|
t->pp_txsize |= R300_TX_SIZE_TXPITCH_EN;
|
||||||
if (!t->image_override)
|
if (!t->image_override)
|
||||||
t->pp_txpitch = ((firstImage->Width + align) & ~align) - 1;
|
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);
|
radeon_bo_unref(rImage->bo);
|
||||||
rImage->bo = NULL;
|
rImage->bo = NULL;
|
||||||
}
|
}
|
||||||
if (t->mt) {
|
|
||||||
radeon_miptree_unreference(t->mt);
|
radeon_miptree_unreference(&t->mt);
|
||||||
t->mt = NULL;
|
radeon_miptree_unreference(&rImage->mt);
|
||||||
}
|
|
||||||
if (rImage->mt) {
|
|
||||||
radeon_miptree_unreference(rImage->mt);
|
|
||||||
rImage->mt = NULL;
|
|
||||||
}
|
|
||||||
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
||||||
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
||||||
texImage->RowStride = rb->pitch / rb->cpp;
|
texImage->RowStride = rb->pitch / rb->cpp;
|
||||||
|
|
|
||||||
|
|
@ -312,16 +312,7 @@ static void r600TexParameter(GLcontext * ctx, GLenum target,
|
||||||
case GL_TEXTURE_MAX_LEVEL:
|
case GL_TEXTURE_MAX_LEVEL:
|
||||||
case GL_TEXTURE_MIN_LOD:
|
case GL_TEXTURE_MIN_LOD:
|
||||||
case GL_TEXTURE_MAX_LOD:
|
case GL_TEXTURE_MAX_LOD:
|
||||||
/* This isn't the most efficient solution but there doesn't appear to
|
t->validated = GL_FALSE;
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GL_DEPTH_TEXTURE_MODE:
|
case GL_DEPTH_TEXTURE_MODE:
|
||||||
|
|
@ -369,10 +360,8 @@ static void r600DeleteTexture(GLcontext * ctx, struct gl_texture_object *texObj)
|
||||||
t->bo = NULL;
|
t->bo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->mt) {
|
radeon_miptree_unreference(&t->mt);
|
||||||
radeon_miptree_unreference(t->mt);
|
|
||||||
t->mt = 0;
|
|
||||||
}
|
|
||||||
_mesa_delete_texture_object(ctx, texObj);
|
_mesa_delete_texture_object(ctx, texObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -649,7 +649,6 @@ static void setup_hardware_state(context_t *rmesa, struct gl_texture_object *tex
|
||||||
{
|
{
|
||||||
radeonTexObj *t = radeon_tex_obj(texObj);
|
radeonTexObj *t = radeon_tex_obj(texObj);
|
||||||
const struct gl_texture_image *firstImage;
|
const struct gl_texture_image *firstImage;
|
||||||
int firstlevel = t->mt ? t->mt->firstLevel : 0;
|
|
||||||
GLuint uTexelPitch, row_align;
|
GLuint uTexelPitch, row_align;
|
||||||
|
|
||||||
if (rmesa->radeon.radeonScreen->driScreen->dri2.enabled &&
|
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)
|
t->bo)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
firstImage = t->base.Image[0][firstlevel];
|
firstImage = t->base.Image[0][t->minLod];
|
||||||
|
|
||||||
if (!t->image_override) {
|
if (!t->image_override) {
|
||||||
if (!r600GetTexFormat(texObj, firstImage->TexFormat)) {
|
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;
|
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)
|
uTexelPitch = (uTexelPitch + R700_TEXEL_PITCH_ALIGNMENT_MASK)
|
||||||
& ~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,
|
SETfield(t->SQ_TEX_RESOURCE1, firstImage->Height - 1,
|
||||||
TEX_HEIGHT_shift, TEX_HEIGHT_mask);
|
TEX_HEIGHT_shift, TEX_HEIGHT_mask);
|
||||||
|
|
||||||
if ((t->mt->lastLevel - t->mt->firstLevel) > 0) {
|
if ((t->maxLod - t->minLod) > 0) {
|
||||||
t->SQ_TEX_RESOURCE3 = t->mt->levels[0].size / 256;
|
t->SQ_TEX_RESOURCE3 = t->mt->levels[t->minLod].size / 256;
|
||||||
SETfield(t->SQ_TEX_RESOURCE4, t->mt->firstLevel, BASE_LEVEL_shift, BASE_LEVEL_mask);
|
SETfield(t->SQ_TEX_RESOURCE4, 0, BASE_LEVEL_shift, BASE_LEVEL_mask);
|
||||||
SETfield(t->SQ_TEX_RESOURCE5, t->mt->lastLevel, LAST_LEVEL_shift, LAST_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 =
|
struct gl_texture_object *tObj =
|
||||||
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
|
_mesa_lookup_texture(rmesa->radeon.glCtx, texname);
|
||||||
radeonTexObjPtr t = radeon_tex_obj(tObj);
|
radeonTexObjPtr t = radeon_tex_obj(tObj);
|
||||||
int firstlevel = t->mt ? t->mt->firstLevel : 0;
|
|
||||||
const struct gl_texture_image *firstImage;
|
const struct gl_texture_image *firstImage;
|
||||||
uint32_t pitch_val, size, row_align, bpp;
|
uint32_t pitch_val, size, row_align;
|
||||||
|
|
||||||
if (!tObj)
|
if (!tObj)
|
||||||
return;
|
return;
|
||||||
|
|
@ -820,13 +819,9 @@ void r600SetTexOffset(__DRIcontext * pDRICtx, GLint texname,
|
||||||
if (!offset)
|
if (!offset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bpp = depth / 8;
|
firstImage = t->base.Image[0][t->minLod];
|
||||||
if (bpp == 3)
|
|
||||||
bpp = 4;
|
|
||||||
|
|
||||||
firstImage = t->base.Image[0][firstlevel];
|
|
||||||
row_align = rmesa->radeon.texture_row_align - 1;
|
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) {
|
if (t->bo) {
|
||||||
radeon_bo_unref(t->bo);
|
radeon_bo_unref(t->bo);
|
||||||
t->bo = NULL;
|
t->bo = NULL;
|
||||||
|
|
@ -949,14 +944,10 @@ void r600SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_fo
|
||||||
radeon_bo_unref(rImage->bo);
|
radeon_bo_unref(rImage->bo);
|
||||||
rImage->bo = NULL;
|
rImage->bo = NULL;
|
||||||
}
|
}
|
||||||
if (t->mt) {
|
|
||||||
radeon_miptree_unreference(t->mt);
|
radeon_miptree_unreference(&t->mt);
|
||||||
t->mt = NULL;
|
radeon_miptree_unreference(&rImage->mt);
|
||||||
}
|
|
||||||
if (rImage->mt) {
|
|
||||||
radeon_miptree_unreference(rImage->mt);
|
|
||||||
rImage->mt = NULL;
|
|
||||||
}
|
|
||||||
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
||||||
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
||||||
texImage->RowStride = rb->pitch / rb->cpp;
|
texImage->RowStride = rb->pitch / rb->cpp;
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,15 @@ static void r700SendTexState(GLcontext *ctx, struct radeon_state_atom *atom)
|
||||||
for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
|
for (i = 0; i < R700_TEXTURE_NUMBERUNITS; i++) {
|
||||||
if (ctx->Texture.Unit[i]._ReallyEnabled) {
|
if (ctx->Texture.Unit[i]._ReallyEnabled) {
|
||||||
radeonTexObj *t = r700->textures[i];
|
radeonTexObj *t = r700->textures[i];
|
||||||
|
uint32_t offset;
|
||||||
if (t) {
|
if (t) {
|
||||||
if (!t->image_override)
|
if (!t->image_override) {
|
||||||
bo = t->mt->bo;
|
bo = t->mt->bo;
|
||||||
else
|
offset = get_base_teximage_offset(t);
|
||||||
|
} else {
|
||||||
bo = t->bo;
|
bo = t->bo;
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
if (bo) {
|
if (bo) {
|
||||||
|
|
||||||
r700SyncSurf(context, 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(r700->textures[i]->SQ_TEX_RESOURCE6);
|
||||||
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2,
|
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE2,
|
||||||
bo,
|
bo,
|
||||||
0,
|
offset,
|
||||||
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
||||||
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3,
|
R600_OUT_BATCH_RELOC(r700->textures[i]->SQ_TEX_RESOURCE3,
|
||||||
bo,
|
bo,
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#define RADEON_BO_FLAGS_MICRO_TILE 2
|
#define RADEON_BO_FLAGS_MICRO_TILE 2
|
||||||
|
|
||||||
struct radeon_bo_manager;
|
struct radeon_bo_manager;
|
||||||
|
struct radeon_cs;
|
||||||
|
|
||||||
struct radeon_bo {
|
struct radeon_bo {
|
||||||
uint32_t alignment;
|
uint32_t alignment;
|
||||||
|
|
@ -74,6 +75,7 @@ struct radeon_bo_funcs {
|
||||||
int (*bo_get_tiling)(struct radeon_bo *bo, uint32_t *tiling_flags,
|
int (*bo_get_tiling)(struct radeon_bo *bo, uint32_t *tiling_flags,
|
||||||
uint32_t *pitch);
|
uint32_t *pitch);
|
||||||
int (*bo_is_busy)(struct radeon_bo *bo, uint32_t *domain);
|
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 {
|
struct radeon_bo_manager {
|
||||||
|
|
@ -199,6 +201,15 @@ static inline int radeon_bo_is_static(struct radeon_bo *bo)
|
||||||
return 0;
|
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)\
|
#define radeon_bo_open(bom, h, s, a, d, f)\
|
||||||
_radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
|
_radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
|
||||||
#define radeon_bo_ref(bo)\
|
#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__)
|
_radeon_bo_wait(bo, __FILE__, __func__, __LINE__)
|
||||||
#define radeon_bo_is_busy(bo, domain) \
|
#define radeon_bo_is_busy(bo, domain) \
|
||||||
_radeon_bo_is_busy(bo, domain, __FILE__, __func__, __LINE__)
|
_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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -136,8 +136,13 @@ radeonBufferSubData(GLcontext * ctx,
|
||||||
const GLvoid * data,
|
const GLvoid * data,
|
||||||
struct gl_buffer_object *obj)
|
struct gl_buffer_object *obj)
|
||||||
{
|
{
|
||||||
|
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
|
||||||
struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj);
|
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);
|
radeon_bo_map(radeon_obj->bo, GL_TRUE);
|
||||||
|
|
||||||
_mesa_memcpy(radeon_obj->bo->ptr + offset, data, size);
|
_mesa_memcpy(radeon_obj->bo->ptr + offset, data, size);
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,9 @@ void radeonScissor(GLcontext* ctx, GLint x, GLint y, GLsizei w, GLsizei h)
|
||||||
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
|
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
|
||||||
if (ctx->Scissor.Enabled) {
|
if (ctx->Scissor.Enabled) {
|
||||||
/* We don't pipeline cliprect changes */
|
/* We don't pipeline cliprect changes */
|
||||||
radeon_firevertices(radeon);
|
if (!radeon->radeonScreen->kernel_mm) {
|
||||||
|
radeon_firevertices(radeon);
|
||||||
|
}
|
||||||
radeonUpdateScissor(ctx);
|
radeonUpdateScissor(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1123,8 +1125,6 @@ void radeonFlush(GLcontext *ctx)
|
||||||
if (radeon->dma.flush)
|
if (radeon->dma.flush)
|
||||||
radeon->dma.flush( ctx );
|
radeon->dma.flush( ctx );
|
||||||
|
|
||||||
radeonEmitState(radeon);
|
|
||||||
|
|
||||||
if (radeon->cmdbuf.cs->cdw)
|
if (radeon->cmdbuf.cs->cdw)
|
||||||
rcommonFlushCmdBuf(radeon, __FUNCTION__);
|
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
|
/* Make sure all commands have been sent to the hardware and have
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,6 @@ GLboolean radeonInitContext(radeonContextPtr radeon,
|
||||||
radeon->texture_compressed_row_align = 64;
|
radeon->texture_compressed_row_align = 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
make_empty_list(&radeon->query.not_flushed_head);
|
|
||||||
radeon_init_dma(radeon);
|
radeon_init_dma(radeon);
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
|
|
|
||||||
|
|
@ -208,6 +208,10 @@ struct radeon_tex_obj {
|
||||||
* and so on.
|
* and so on.
|
||||||
*/
|
*/
|
||||||
GLboolean validated;
|
GLboolean validated;
|
||||||
|
/* Minimum LOD to be used during rendering */
|
||||||
|
unsigned minLod;
|
||||||
|
/* Miximum LOD to be used during rendering */
|
||||||
|
unsigned maxLod;
|
||||||
|
|
||||||
GLuint override_offset;
|
GLuint override_offset;
|
||||||
GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
|
GLboolean image_override; /* Image overridden by GLX_EXT_tfp */
|
||||||
|
|
@ -502,7 +506,6 @@ struct radeon_context {
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct radeon_query_object *current;
|
struct radeon_query_object *current;
|
||||||
struct radeon_query_object not_flushed_head;
|
|
||||||
struct radeon_state_atom queryobj;
|
struct radeon_state_atom queryobj;
|
||||||
} query;
|
} query;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2009 Maciej Cencora.
|
||||||
* Copyright (C) 2008 Nicolai Haehnle.
|
* Copyright (C) 2008 Nicolai Haehnle.
|
||||||
*
|
*
|
||||||
* All Rights Reserved.
|
* All Rights Reserved.
|
||||||
|
|
@ -32,10 +33,13 @@
|
||||||
|
|
||||||
#include "main/simple_list.h"
|
#include "main/simple_list.h"
|
||||||
#include "main/texcompress.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,
|
static GLuint radeon_compressed_texture_size(GLcontext *ctx,
|
||||||
GLsizei width, GLsizei height, GLsizei depth,
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
GLuint mesaFormat)
|
gl_format mesaFormat)
|
||||||
{
|
{
|
||||||
GLuint size = _mesa_format_image_size(mesaFormat, width, height, depth);
|
GLuint size = _mesa_format_image_size(mesaFormat, width, height, depth);
|
||||||
|
|
||||||
|
|
@ -55,29 +59,6 @@ static GLuint radeon_compressed_texture_size(GLcontext *ctx,
|
||||||
return size;
|
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
|
* Compute sizes and fill in offset and blit information for the given
|
||||||
* image (determined by \p face and \p level).
|
* 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;
|
uint32_t row_align;
|
||||||
|
|
||||||
/* Find image size in bytes */
|
/* 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! */
|
/* TODO: Is this correct? Need test cases for compressed textures! */
|
||||||
row_align = rmesa->texture_compressed_row_align - 1;
|
row_align = rmesa->texture_compressed_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 = radeon_compressed_texture_size(mt->radeon->glCtx,
|
lvl->size = radeon_compressed_texture_size(rmesa->glCtx, lvl->width, lvl->height, lvl->depth, mt->mesaFormat);
|
||||||
lvl->width, lvl->height, lvl->depth, mt->compressed);
|
|
||||||
} else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
|
} else if (mt->target == GL_TEXTURE_RECTANGLE_NV) {
|
||||||
row_align = rmesa->texture_rect_row_align - 1;
|
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;
|
lvl->size = lvl->rowstride * lvl->height;
|
||||||
} else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
|
} else if (mt->tilebits & RADEON_TXO_MICRO_TILE) {
|
||||||
/* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
|
/* tile pattern is 16 bytes x2. mipmaps stay 32 byte aligned,
|
||||||
* though the actual offset may be different (if texture is less than
|
* though the actual offset may be different (if texture is less than
|
||||||
* 32 bytes width) to the untiled case */
|
* 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;
|
lvl->size = lvl->rowstride * ((lvl->height + 1) / 2) * lvl->depth;
|
||||||
} else {
|
} else {
|
||||||
row_align = rmesa->texture_row_align - 1;
|
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;
|
lvl->size = lvl->rowstride * lvl->height * lvl->depth;
|
||||||
}
|
}
|
||||||
assert(lvl->size > 0);
|
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)
|
static void calculate_miptree_layout_r100(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
|
||||||
{
|
{
|
||||||
GLuint curOffset;
|
GLuint curOffset;
|
||||||
GLuint numLevels;
|
|
||||||
GLuint i;
|
GLuint i;
|
||||||
GLuint face;
|
GLuint face;
|
||||||
|
|
||||||
numLevels = mt->lastLevel - mt->firstLevel + 1;
|
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
|
||||||
assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
|
|
||||||
|
|
||||||
curOffset = 0;
|
curOffset = 0;
|
||||||
for(face = 0; face < mt->faces; face++) {
|
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].width = minify(mt->width0, i);
|
||||||
mt->levels[i].height = minify(mt->height0, i);
|
mt->levels[i].height = minify(mt->height0, i);
|
||||||
mt->levels[i].depth = minify(mt->depth0, 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)
|
static void calculate_miptree_layout_r300(radeonContextPtr rmesa, radeon_mipmap_tree *mt)
|
||||||
{
|
{
|
||||||
GLuint curOffset;
|
GLuint curOffset;
|
||||||
GLuint numLevels;
|
|
||||||
GLuint i;
|
GLuint i;
|
||||||
|
|
||||||
numLevels = mt->lastLevel - mt->firstLevel + 1;
|
assert(mt->numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
|
||||||
assert(numLevels <= rmesa->glCtx->Const.MaxTextureLevels);
|
|
||||||
|
|
||||||
curOffset = 0;
|
curOffset = 0;
|
||||||
for(i = 0; i < numLevels; i++) {
|
for(i = 0; i < mt->numLevels; i++) {
|
||||||
GLuint face;
|
GLuint face;
|
||||||
|
|
||||||
mt->levels[i].width = minify(mt->width0, i);
|
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.
|
* Create a new mipmap tree, calculate its layout and allocate memory.
|
||||||
*/
|
*/
|
||||||
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
|
static radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa,
|
||||||
GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
|
GLenum target, gl_format mesaFormat, GLuint baseLevel, GLuint numLevels,
|
||||||
GLuint width0, GLuint height0, GLuint depth0,
|
GLuint width0, GLuint height0, GLuint depth0, GLuint tilebits)
|
||||||
GLuint bpp, GLuint tilebits, GLuint compressed)
|
|
||||||
{
|
{
|
||||||
radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
|
radeon_mipmap_tree *mt = CALLOC_STRUCT(_radeon_mipmap_tree);
|
||||||
|
|
||||||
mt->radeon = rmesa;
|
mt->mesaFormat = mesaFormat;
|
||||||
mt->internal_format = internal_format;
|
|
||||||
mt->refcount = 1;
|
mt->refcount = 1;
|
||||||
mt->t = t;
|
|
||||||
mt->target = target;
|
mt->target = target;
|
||||||
mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
mt->faces = (target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
|
||||||
mt->firstLevel = firstLevel;
|
mt->baseLevel = baseLevel;
|
||||||
mt->lastLevel = lastLevel;
|
mt->numLevels = numLevels;
|
||||||
mt->width0 = width0;
|
mt->width0 = width0;
|
||||||
mt->height0 = height0;
|
mt->height0 = height0;
|
||||||
mt->depth0 = depth0;
|
mt->depth0 = depth0;
|
||||||
mt->bpp = compressed ? radeon_compressed_num_bytes(compressed) : bpp;
|
|
||||||
mt->tilebits = tilebits;
|
mt->tilebits = tilebits;
|
||||||
mt->compressed = compressed;
|
|
||||||
|
|
||||||
if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
|
if (rmesa->radeonScreen->chip_family >= CHIP_FAMILY_R300)
|
||||||
calculate_miptree_layout_r300(rmesa, mt);
|
calculate_miptree_layout_r300(rmesa, mt);
|
||||||
|
|
@ -223,53 +194,43 @@ radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *
|
||||||
return mt;
|
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++;
|
mt->refcount++;
|
||||||
assert(mt->refcount > 0);
|
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)
|
if (!mt)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(mt->refcount > 0);
|
assert(mt->refcount > 0);
|
||||||
|
|
||||||
mt->refcount--;
|
mt->refcount--;
|
||||||
if (!mt->refcount) {
|
if (!mt->refcount) {
|
||||||
radeon_bo_unref(mt->bo);
|
radeon_bo_unref(mt->bo);
|
||||||
free(mt);
|
free(mt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate first and last mip levels for the given texture object,
|
* Calculate min and max LOD for the given texture object.
|
||||||
* where the dimensions are taken from the given texture image at
|
* @param[in] tObj texture object whose LOD values to calculate
|
||||||
* the given level.
|
* @param[out] pminLod minimal LOD
|
||||||
*
|
* @param[out] pmaxLod maximal LOD
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
static void calculate_first_last_level(struct gl_texture_object *tObj,
|
static void calculate_min_max_lod(struct gl_texture_object *tObj,
|
||||||
GLuint *pfirstLevel, GLuint *plastLevel,
|
unsigned *pminLod, unsigned *pmaxLod)
|
||||||
GLuint face, GLuint level)
|
|
||||||
{
|
{
|
||||||
const struct gl_texture_image * const baseImage =
|
int minLod, maxLod;
|
||||||
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;
|
|
||||||
|
|
||||||
/* Yes, this looks overly complicated, but it's all needed.
|
/* Yes, this looks overly complicated, but it's all needed.
|
||||||
*/
|
*/
|
||||||
switch (tObj->Target) {
|
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) {
|
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
|
||||||
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
|
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
|
||||||
*/
|
*/
|
||||||
firstLevel = lastLevel = tObj->BaseLevel;
|
minLod = maxLod = tObj->BaseLevel;
|
||||||
} else {
|
} else {
|
||||||
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
|
minLod = tObj->BaseLevel + (GLint)(tObj->MinLod);
|
||||||
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
|
minLod = MAX2(minLod, tObj->BaseLevel);
|
||||||
firstLevel = MIN2(firstLevel, level + baseImage->MaxLog2);
|
minLod = MIN2(minLod, tObj->MaxLevel);
|
||||||
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
|
maxLod = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
|
||||||
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
|
maxLod = MIN2(maxLod, tObj->MaxLevel);
|
||||||
lastLevel = MIN2(lastLevel, level + baseImage->MaxLog2);
|
maxLod = MIN2(maxLod, tObj->Image[0][minLod]->MaxLog2 + minLod);
|
||||||
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
|
maxLod = MAX2(maxLod, minLod); /* need at least one level */
|
||||||
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GL_TEXTURE_RECTANGLE_NV:
|
case GL_TEXTURE_RECTANGLE_NV:
|
||||||
case GL_TEXTURE_4D_SGIS:
|
case GL_TEXTURE_4D_SGIS:
|
||||||
firstLevel = lastLevel = 0;
|
minLod = maxLod = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save these values */
|
/* save these values */
|
||||||
*pfirstLevel = firstLevel;
|
*pminLod = minLod;
|
||||||
*plastLevel = lastLevel;
|
*pmaxLod = maxLod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given miptree can hold the given texture image at the
|
* Checks whether the given miptree can hold the given texture image at the
|
||||||
* given face and level.
|
* given face and level.
|
||||||
*/
|
*/
|
||||||
GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
|
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;
|
radeon_mipmap_level *lvl;
|
||||||
|
|
||||||
if (face >= mt->faces || level < mt->firstLevel || level > mt->lastLevel)
|
if (face >= mt->faces || mtLevel > mt->numLevels)
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
if (texImage->InternalFormat != mt->internal_format ||
|
if (texImage->TexFormat != mt->mesaFormat)
|
||||||
isCompressed != mt->compressed)
|
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
if (!isCompressed &&
|
lvl = &mt->levels[mtLevel];
|
||||||
!mt->compressed &&
|
|
||||||
_mesa_get_format_bytes(texImage->TexFormat) != mt->bpp)
|
|
||||||
return GL_FALSE;
|
|
||||||
|
|
||||||
lvl = &mt->levels[level - mt->firstLevel];
|
|
||||||
if (lvl->width != texImage->Width ||
|
if (lvl->width != texImage->Width ||
|
||||||
lvl->height != texImage->Height ||
|
lvl->height != texImage->Height ||
|
||||||
lvl->depth != texImage->Depth)
|
lvl->depth != texImage->Depth)
|
||||||
|
|
@ -337,64 +289,72 @@ GLboolean radeon_miptree_matches_image(radeon_mipmap_tree *mt,
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given miptree has the right format to store the given texture object.
|
* 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;
|
struct gl_texture_image *firstImage;
|
||||||
GLuint compressed;
|
unsigned numLevels;
|
||||||
GLuint numfaces = 1;
|
radeon_mipmap_level *mtBaseLevel;
|
||||||
GLuint firstLevel, lastLevel;
|
|
||||||
GLuint texelBytes;
|
|
||||||
|
|
||||||
calculate_first_last_level(texObj, &firstLevel, &lastLevel, 0, texObj->BaseLevel);
|
if (texObj->BaseLevel < mt->baseLevel)
|
||||||
if (texObj->Target == GL_TEXTURE_CUBE_MAP)
|
return GL_FALSE;
|
||||||
numfaces = 6;
|
|
||||||
|
|
||||||
firstImage = texObj->Image[0][firstLevel];
|
mtBaseLevel = &mt->levels[texObj->BaseLevel - mt->baseLevel];
|
||||||
compressed = _mesa_is_format_compressed(firstImage->TexFormat) ? firstImage->TexFormat : 0;
|
firstImage = texObj->Image[0][texObj->BaseLevel];
|
||||||
texelBytes = _mesa_get_format_bytes(firstImage->TexFormat);
|
numLevels = MIN2(texObj->MaxLevel - texObj->BaseLevel + 1, firstImage->MaxLog2 + 1);
|
||||||
|
|
||||||
return (mt->firstLevel == firstLevel &&
|
if (RADEON_DEBUG & RADEON_TEXTURE) {
|
||||||
mt->lastLevel == lastLevel &&
|
fprintf(stderr, "Checking if miptree %p matches texObj %p\n", mt, texObj);
|
||||||
mt->width0 == firstImage->Width &&
|
fprintf(stderr, "target %d vs %d\n", mt->target, texObj->Target);
|
||||||
mt->height0 == firstImage->Height &&
|
fprintf(stderr, "format %d vs %d\n", mt->mesaFormat, firstImage->TexFormat);
|
||||||
mt->depth0 == firstImage->Depth &&
|
fprintf(stderr, "numLevels %d vs %d\n", mt->numLevels, numLevels);
|
||||||
mt->compressed == compressed &&
|
fprintf(stderr, "width0 %d vs %d\n", mtBaseLevel->width, firstImage->Width);
|
||||||
(!mt->compressed ? (mt->bpp == texelBytes) : 1));
|
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
|
* Try to allocate a mipmap tree for the given texture object.
|
||||||
* given image in the given position.
|
* @param[in] rmesa radeon context
|
||||||
|
* @param[in] t radeon texture object
|
||||||
*/
|
*/
|
||||||
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
|
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t)
|
||||||
radeon_texture_image *image, GLuint face, GLuint level)
|
|
||||||
{
|
{
|
||||||
GLuint compressed = _mesa_is_format_compressed(image->base.TexFormat) ? image->base.TexFormat : 0;
|
struct gl_texture_object *texObj = &t->base;
|
||||||
GLuint numfaces = 1;
|
struct gl_texture_image *texImg = texObj->Image[0][texObj->BaseLevel];
|
||||||
GLuint firstLevel, lastLevel;
|
GLuint numLevels;
|
||||||
GLuint texelBytes;
|
|
||||||
|
|
||||||
assert(!t->mt);
|
assert(!t->mt);
|
||||||
|
|
||||||
calculate_first_last_level(&t->base, &firstLevel, &lastLevel, face, level);
|
if (!texImg)
|
||||||
if (t->base.Target == GL_TEXTURE_CUBE_MAP)
|
|
||||||
numfaces = 6;
|
|
||||||
|
|
||||||
if (level != firstLevel || face >= numfaces)
|
|
||||||
return;
|
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,
|
t->mt = radeon_miptree_create(rmesa, t->base.Target,
|
||||||
image->base.InternalFormat,
|
texImg->TexFormat, texObj->BaseLevel,
|
||||||
firstLevel, lastLevel,
|
numLevels, texImg->Width, texImg->Height,
|
||||||
image->base.Width, image->base.Height, image->base.Depth,
|
texImg->Depth, t->tile_bits);
|
||||||
texelBytes, t->tile_bits, compressed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Although we use the image_offset[] array to store relative offsets
|
/* 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
|
void
|
||||||
radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets)
|
radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets)
|
||||||
{
|
{
|
||||||
if (mt->target != GL_TEXTURE_3D || mt->faces == 1)
|
if (mt->target != GL_TEXTURE_3D || mt->faces == 1) {
|
||||||
offsets[0] = 0;
|
offsets[0] = 0;
|
||||||
else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++) {
|
||||||
offsets[i] = mt->levels[level].faces[i].offset;
|
offsets[i] = mt->levels[level].faces[i].offset;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint
|
GLuint
|
||||||
radeon_miptree_image_offset(radeon_mipmap_tree *mt,
|
radeon_miptree_image_offset(radeon_mipmap_tree *mt,
|
||||||
GLuint face, GLuint level)
|
GLuint face, GLuint level)
|
||||||
{
|
{
|
||||||
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
|
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
|
||||||
return (mt->levels[level].faces[face].offset);
|
return (mt->levels[level].faces[face].offset);
|
||||||
else
|
else
|
||||||
return mt->levels[level].faces[0].offset;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,43 +59,38 @@ struct _radeon_mipmap_level {
|
||||||
* changed.
|
* changed.
|
||||||
*/
|
*/
|
||||||
struct _radeon_mipmap_tree {
|
struct _radeon_mipmap_tree {
|
||||||
radeonContextPtr radeon;
|
|
||||||
radeonTexObj *t;
|
|
||||||
struct radeon_bo *bo;
|
struct radeon_bo *bo;
|
||||||
GLuint refcount;
|
GLuint refcount;
|
||||||
|
|
||||||
GLuint totalsize; /** total size of the miptree, in bytes */
|
GLuint totalsize; /** total size of the miptree, in bytes */
|
||||||
|
|
||||||
GLenum target; /** GL_TEXTURE_xxx */
|
GLenum target; /** GL_TEXTURE_xxx */
|
||||||
GLenum internal_format;
|
GLenum mesaFormat; /** MESA_FORMAT_xxx */
|
||||||
GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
|
GLuint faces; /** # of faces: 6 for cubemaps, 1 otherwise */
|
||||||
GLuint firstLevel; /** First mip level stored in this mipmap tree */
|
GLuint baseLevel; /** gl_texture_object->baseLevel it was created for */
|
||||||
GLuint lastLevel; /** Last mip level stored in this mipmap tree */
|
GLuint numLevels; /** Number of mip levels stored in this mipmap tree */
|
||||||
|
|
||||||
GLuint width0; /** Width of firstLevel image */
|
GLuint width0; /** Width of firstLevel image */
|
||||||
GLuint height0; /** Height of firstLevel image */
|
GLuint height0; /** Height of firstLevel image */
|
||||||
GLuint depth0; /** Depth of firstLevel image */
|
GLuint depth0; /** Depth of firstLevel image */
|
||||||
|
|
||||||
GLuint bpp; /** Bytes per texel */
|
|
||||||
GLuint tilebits; /** RADEON_TXO_xxx_TILE */
|
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_level levels[RADEON_MIPTREE_MAX_TEXTURE_LEVELS];
|
||||||
};
|
};
|
||||||
|
|
||||||
radeon_mipmap_tree* radeon_miptree_create(radeonContextPtr rmesa, radeonTexObj *t,
|
void radeon_miptree_reference(radeon_mipmap_tree *mt, radeon_mipmap_tree **ptr);
|
||||||
GLenum target, GLenum internal_format, GLuint firstLevel, GLuint lastLevel,
|
void radeon_miptree_unreference(radeon_mipmap_tree **ptr);
|
||||||
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,
|
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 level);
|
||||||
GLboolean radeon_miptree_matches_texture(radeon_mipmap_tree *mt, struct gl_texture_object *texObj);
|
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t);
|
||||||
void radeon_try_alloc_miptree(radeonContextPtr rmesa, radeonTexObj *t,
|
|
||||||
radeon_texture_image *texImage, GLuint face, GLuint level);
|
|
||||||
GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
|
GLuint radeon_miptree_image_offset(radeon_mipmap_tree *mt,
|
||||||
GLuint face, GLuint level);
|
GLuint face, GLuint level);
|
||||||
void radeon_miptree_depth_offsets(radeon_mipmap_tree *mt, GLuint level, GLuint *offsets);
|
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_ */
|
#endif /* __RADEON_MIPMAP_TREE_H_ */
|
||||||
|
|
|
||||||
|
|
@ -31,20 +31,6 @@
|
||||||
#include "main/imports.h"
|
#include "main/imports.h"
|
||||||
#include "main/simple_list.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)
|
static void radeonQueryGetResult(GLcontext *ctx, struct gl_query_object *q)
|
||||||
{
|
{
|
||||||
radeonContextPtr radeon = RADEON_CONTEXT(ctx);
|
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)
|
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;
|
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 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);
|
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);
|
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->query.queryobj.dirty = GL_TRUE;
|
||||||
radeon->hw.is_dirty = GL_TRUE;
|
radeon->hw.is_dirty = GL_TRUE;
|
||||||
insert_at_tail(&radeon->query.not_flushed_head, query);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeonEmitQueryEnd(GLcontext *ctx)
|
void radeonEmitQueryEnd(GLcontext *ctx)
|
||||||
|
|
@ -206,7 +191,7 @@ static void radeonCheckQuery(GLcontext *ctx, struct gl_query_object *q)
|
||||||
uint32_t domain;
|
uint32_t domain;
|
||||||
|
|
||||||
/* Need to perform a flush, as per ARB_occlusion_query spec */
|
/* 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);
|
ctx->Driver.Flush(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
OUT_BATCH(CP_PACKET0(RADEON_PP_TXOFFSET_0 + (24 * i), 0));
|
||||||
if (t->mt && !t->image_override) {
|
if (t->mt && !t->image_override) {
|
||||||
if ((ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_CUBE_BIT)) {
|
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,
|
OUT_BATCH_RELOC(lvl->faces[5].offset, t->mt->bo, lvl->faces[5].offset,
|
||||||
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
||||||
} else {
|
} 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);
|
RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -348,17 +348,7 @@ static void radeonTexParameter( GLcontext *ctx, GLenum target,
|
||||||
case GL_TEXTURE_MAX_LEVEL:
|
case GL_TEXTURE_MAX_LEVEL:
|
||||||
case GL_TEXTURE_MIN_LOD:
|
case GL_TEXTURE_MIN_LOD:
|
||||||
case GL_TEXTURE_MAX_LOD:
|
case GL_TEXTURE_MAX_LOD:
|
||||||
|
t->validated = GL_FALSE;
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -388,10 +378,8 @@ static void radeonDeleteTexture( GLcontext *ctx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->mt) {
|
radeon_miptree_unreference(&t->mt);
|
||||||
radeon_miptree_unreference(t->mt);
|
|
||||||
t->mt = 0;
|
|
||||||
}
|
|
||||||
/* Free mipmap images and the texture object itself */
|
/* Free mipmap images and the texture object itself */
|
||||||
_mesa_delete_texture_object(ctx, texObj);
|
_mesa_delete_texture_object(ctx, texObj);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -699,14 +699,10 @@ void radeonSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint glx_texture_
|
||||||
radeon_bo_unref(rImage->bo);
|
radeon_bo_unref(rImage->bo);
|
||||||
rImage->bo = NULL;
|
rImage->bo = NULL;
|
||||||
}
|
}
|
||||||
if (t->mt) {
|
|
||||||
radeon_miptree_unreference(t->mt);
|
radeon_miptree_unreference(&t->mt);
|
||||||
t->mt = NULL;
|
radeon_miptree_unreference(&rImage->mt);
|
||||||
}
|
|
||||||
if (rImage->mt) {
|
|
||||||
radeon_miptree_unreference(rImage->mt);
|
|
||||||
rImage->mt = NULL;
|
|
||||||
}
|
|
||||||
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
_mesa_init_teximage_fields(radeon->glCtx, target, texImage,
|
||||||
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
rb->base.Width, rb->base.Height, 1, 0, rb->cpp);
|
||||||
texImage->RowStride = rb->pitch / 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;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
firstImage = t->base.Image[0][t->mt->firstLevel];
|
firstImage = t->base.Image[0][t->minLod];
|
||||||
|
|
||||||
if (firstImage->Border > 0) {
|
if (firstImage->Border > 0) {
|
||||||
fprintf(stderr, "%s: border\n", __FUNCTION__);
|
fprintf(stderr, "%s: border\n", __FUNCTION__);
|
||||||
|
|
@ -1049,9 +1045,9 @@ static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
|
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 |
|
t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
|
||||||
RADEON_TXFORMAT_HEIGHT_MASK |
|
RADEON_TXFORMAT_HEIGHT_MASK |
|
||||||
|
|
@ -1060,9 +1056,9 @@ static GLboolean setup_hardware_state(r100ContextPtr rmesa, radeonTexObj *t, int
|
||||||
RADEON_TXFORMAT_F5_HEIGHT_MASK);
|
RADEON_TXFORMAT_F5_HEIGHT_MASK);
|
||||||
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
|
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
|
||||||
(log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
|
(log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
|
||||||
|
|
||||||
t->tile_bits = 0;
|
t->tile_bits = 0;
|
||||||
|
|
||||||
if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
|
if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
|
||||||
ASSERT(log2Width == log2Height);
|
ASSERT(log2Width == log2Height);
|
||||||
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
|
t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_F5_WIDTH_SHIFT) |
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2009 Maciej Cencora.
|
||||||
* Copyright (C) 2008 Nicolai Haehnle.
|
* Copyright (C) 2008 Nicolai Haehnle.
|
||||||
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
|
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
|
||||||
*
|
*
|
||||||
|
|
@ -46,7 +47,7 @@
|
||||||
#include "radeon_mipmap_tree.h"
|
#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)
|
GLuint numrows, GLuint rowsize)
|
||||||
{
|
{
|
||||||
assert(rowsize <= dststride);
|
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);
|
radeon_texture_image* image = get_radeon_texture_image(timage);
|
||||||
|
|
||||||
if (image->mt) {
|
if (image->mt) {
|
||||||
radeon_miptree_unreference(image->mt);
|
radeon_miptree_unreference(&image->mt);
|
||||||
image->mt = 0;
|
|
||||||
assert(!image->base.Data);
|
assert(!image->base.Data);
|
||||||
} else {
|
} else {
|
||||||
_mesa_free_texture_image_data(ctx, timage);
|
_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];
|
lvl = &image->mt->levels[image->mtlevel];
|
||||||
|
|
||||||
image->base.Data = image->mt->bo->ptr + lvl->faces[image->mtface].offset;
|
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);
|
radeon_bo_map(t->mt->bo, GL_FALSE);
|
||||||
for(face = 0; face < t->mt->faces; ++face) {
|
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]));
|
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;
|
return;
|
||||||
|
|
||||||
for(face = 0; face < t->mt->faces; ++face) {
|
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;
|
texObj->Image[face][level]->Data = 0;
|
||||||
}
|
}
|
||||||
radeon_bo_unmap(t->mt->bo);
|
radeon_bo_unmap(t->mt->bo);
|
||||||
|
|
@ -240,8 +240,7 @@ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
|
||||||
image->mtlevel = i;
|
image->mtlevel = i;
|
||||||
image->mtface = face;
|
image->mtface = face;
|
||||||
|
|
||||||
radeon_miptree_unreference(image->mt);
|
radeon_miptree_unreference(&image->mt);
|
||||||
image->mt = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -510,6 +509,135 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
|
||||||
return MESA_FORMAT_NONE; /* never get here */
|
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.
|
* All glTexImage calls go through this function.
|
||||||
*/
|
*/
|
||||||
|
|
@ -528,13 +656,17 @@ static void radeon_teximage(
|
||||||
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
|
radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
|
||||||
radeonTexObj* t = radeon_tex_obj(texObj);
|
radeonTexObj* t = radeon_tex_obj(texObj);
|
||||||
radeon_texture_image* image = get_radeon_texture_image(texImage);
|
radeon_texture_image* image = get_radeon_texture_image(texImage);
|
||||||
GLuint dstRowStride;
|
|
||||||
GLint postConvWidth = width;
|
GLint postConvWidth = width;
|
||||||
GLint postConvHeight = height;
|
GLint postConvHeight = height;
|
||||||
GLuint texelBytes;
|
|
||||||
GLuint face = radeon_face_for_target(target);
|
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;
|
t->validated = GL_FALSE;
|
||||||
|
|
||||||
|
|
@ -543,53 +675,30 @@ static void radeon_teximage(
|
||||||
&postConvHeight);
|
&postConvHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mesa_is_format_compressed(texImage->TexFormat)) {
|
if (!_mesa_is_format_compressed(texImage->TexFormat)) {
|
||||||
texelBytes = 0;
|
GLuint texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
|
||||||
} else {
|
|
||||||
texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
|
|
||||||
/* Minimum pitch of 32 bytes */
|
/* Minimum pitch of 32 bytes */
|
||||||
if (postConvWidth * texelBytes < 32) {
|
if (postConvWidth * texelBytes < 32) {
|
||||||
postConvWidth = 32 / texelBytes;
|
postConvWidth = 32 / texelBytes;
|
||||||
texImage->RowStride = postConvWidth;
|
texImage->RowStride = postConvWidth;
|
||||||
}
|
}
|
||||||
if (!image->mt) {
|
if (!image->mt) {
|
||||||
assert(texImage->RowStride == postConvWidth);
|
assert(texImage->RowStride == postConvWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for image */
|
/* Mesa core only clears texImage->Data but not image->mt */
|
||||||
radeonFreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
|
radeonFreeTexImageData(ctx, texImage);
|
||||||
|
|
||||||
if (t->mt &&
|
if (!t->bo) {
|
||||||
t->mt->firstLevel == level &&
|
teximage_assign_miptree(rmesa, texObj, texImage, face, level);
|
||||||
t->mt->lastLevel == level &&
|
if (!t->mt) {
|
||||||
t->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
|
int size = _mesa_format_image_size(texImage->TexFormat,
|
||||||
!radeon_miptree_matches_image(t->mt, texImage, face, level)) {
|
texImage->Width,
|
||||||
radeon_miptree_unreference(t->mt);
|
texImage->Height,
|
||||||
t->mt = NULL;
|
texImage->Depth);
|
||||||
}
|
texImage->Data = _mesa_alloc_texmemory(size);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
texImage->Data = _mesa_alloc_texmemory(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Upload texture image; note that the spec allows pixels to be NULL */
|
/* Upload texture image; note that the spec allows pixels to be NULL */
|
||||||
|
|
@ -603,65 +712,16 @@ static void radeon_teximage(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixels) {
|
if (pixels) {
|
||||||
radeon_teximage_map(image, GL_TRUE);
|
radeon_store_teximage(ctx, dims,
|
||||||
if (compressed) {
|
0, 0, 0,
|
||||||
if (image->mt) {
|
width, height, depth,
|
||||||
uint32_t srcRowStride, bytesPerRow, rows;
|
imageSize, format, type,
|
||||||
srcRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
|
pixels, packing,
|
||||||
bytesPerRow = srcRowStride;
|
texObj, texImage,
|
||||||
rows = (height + 3) / 4;
|
compressed);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||||
|
|
||||||
if (pixels)
|
|
||||||
radeon_teximage_unmap(image);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
|
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,
|
static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level,
|
||||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
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);
|
radeonTexObj* t = radeon_tex_obj(texObj);
|
||||||
radeon_texture_image* image = get_radeon_texture_image(texImage);
|
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;
|
t->validated = GL_FALSE;
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
pixels = _mesa_validate_pbo_compressed_teximage(
|
pixels = _mesa_validate_pbo_compressed_teximage(
|
||||||
ctx, imageSize, pixels, packing, "glCompressedTexImage");
|
ctx, imageSize, pixels, packing, "glCompressedTexSubImage");
|
||||||
} else {
|
} else {
|
||||||
pixels = _mesa_validate_pbo_teximage(ctx, dims,
|
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) {
|
if (pixels) {
|
||||||
GLint dstRowStride;
|
radeon_store_teximage(ctx, dims,
|
||||||
radeon_teximage_map(image, GL_TRUE);
|
xoffset, yoffset, zoffset,
|
||||||
|
width, height, depth,
|
||||||
if (image->mt) {
|
imageSize, format, type,
|
||||||
radeon_mipmap_level *lvl = &image->mt->levels[image->mtlevel];
|
pixels, packing,
|
||||||
dstRowStride = lvl->rowstride;
|
texObj, texImage,
|
||||||
} else {
|
compressed);
|
||||||
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_teximage_unmap(image);
|
|
||||||
|
|
||||||
_mesa_unmap_teximage_pbo(ctx, packing);
|
_mesa_unmap_teximage_pbo(ctx, packing);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
|
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);
|
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,
|
* Need to map texture image into memory before copying image data,
|
||||||
* then unmap it.
|
* then unmap it.
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@
|
||||||
|
|
||||||
#include "main/formats.h"
|
#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);
|
struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx);
|
||||||
void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage);
|
void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue