#include "intel_mipmap_tree.h"
#include "intel_regions.h"
#include "intel_chipset.h"
+#ifndef I915
+#include "brw_state.h"
+#endif
#include "main/enums.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
DBG("%s deleting %p\n", __FUNCTION__, *mt);
+#ifndef I915
+ /* Free up cached binding tables holding a reference on our buffer, to
+ * avoid excessive memory consumption.
+ *
+ * This isn't as aggressive as we could be, as we'd like to do
+ * it from any time we free the last ref on a region. But intel_region.c
+ * is context-agnostic. Perhaps our constant state cache should be, as
+ * well.
+ */
+ brw_state_cache_bo_delete(&brw_context(&intel->ctx)->surface_cache,
+ (*mt)->region->buffer);
+#endif
+
intel_region_release(&((*mt)->region));
for (i = 0; i < MAX_TEXTURE_LEVELS; i++)
}
-
void
-intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
- GLuint level, GLuint img,
- GLuint x, GLuint y)
+intel_miptree_set_image_offset_ex(struct intel_mipmap_tree *mt,
+ GLuint level, GLuint img,
+ GLuint x, GLuint y,
+ GLuint offset)
{
if (img == 0 && level == 0)
assert(x == 0 && y == 0);
assert(img < mt->level[level].nr_images);
- mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp;
+ mt->level[level].image_offset[img] = (x + y * mt->pitch) * mt->cpp + offset;
DBG("%s level %d img %d pos %d,%d image_offset %x\n",
__FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
}
-
-/* Although we use the image_offset[] array to store relative offsets
- * to cube faces, Mesa doesn't know anything about this and expects
- * each cube face to be treated as a separate image.
- *
- * These functions present that view to mesa:
- */
-const GLuint *
-intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level)
+void
+intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+ GLuint level, GLuint img,
+ GLuint x, GLuint y)
{
- static const GLuint zero = 0;
-
- if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1)
- return &zero;
- else
- return mt->level[level].image_offset;
+ intel_miptree_set_image_offset_ex(mt, level, img, x, y, 0);
}
+/**
+ * Return offset to the start of a 2D slice of a texture (a mipmap level,
+ * cube face, 3D Z slice).
+ * \param mt the texture object/miptree
+ * \param face cube map face in [0,5] or zero for non-cube textures
+ * \param level mipmap level
+ * \param zslice Z slice of a 3D texture, or zero for non-3D textures
+ */
GLuint
-intel_miptree_image_offset(struct intel_mipmap_tree *mt,
- GLuint face, GLuint level)
+intel_miptree_image_offset(const struct intel_mipmap_tree *mt,
+ GLuint face, GLuint level, GLuint zslice)
{
+ GLuint offset = mt->level[level].level_offset;
+
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
- return (mt->level[level].level_offset +
- mt->level[level].image_offset[face]);
- else
- return mt->level[level].level_offset;
+ offset += mt->level[level].image_offset[face];
+ else if (mt->target == GL_TEXTURE_3D)
+ offset += mt->level[level].image_offset[zslice];
+
+ return offset;
}
}
return (intel_region_map(intel, mt->region) +
- intel_miptree_image_offset(mt, face, level));
+ intel_miptree_image_offset(mt, face, level, 0));
}
void
GLuint src_image_pitch)
{
GLuint depth = dst->level[level].depth;
- GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
- const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
GLuint i;
GLuint height = 0;
DBG("%s: %d/%d\n", __FUNCTION__, face, level);
for (i = 0; i < depth; i++) {
+ GLuint dst_offset = intel_miptree_image_offset(dst, face, level, i);
height = dst->level[level].height;
if(dst->compressed)
height = (height + 3) / 4;
intel_region_data(intel,
dst->region,
- dst_offset + dst_depth_offset[i], /* dst_offset */
+ dst_offset,
0, 0, /* dstx, dsty */
src,
src_row_pitch,
0, 0, /* source x, y */
dst->level[level].width, height); /* width, height */
- src += src_image_pitch * dst->cpp;
+ src = (char *)src + src_image_pitch * dst->cpp;
}
}
-extern GLuint intel_compressed_alignment(GLenum);
+extern void intel_get_texture_alignment_unit(GLenum, GLuint *, GLuint *);
/* Copy mipmap image between trees
*/
void
GLuint width = src->level[level].width;
GLuint height = src->level[level].height;
GLuint depth = src->level[level].depth;
- GLuint dst_offset = intel_miptree_image_offset(dst, face, level);
- GLuint src_offset = intel_miptree_image_offset(src, face, level);
- const GLuint *dst_depth_offset = intel_miptree_depth_offsets(dst, level);
- const GLuint *src_depth_offset = intel_miptree_depth_offsets(src, level);
GLuint i;
GLboolean success;
if (dst->compressed) {
- GLuint alignment = intel_compressed_alignment(dst->internal_format);
+ GLuint align_w, align_h;
+
+ intel_get_texture_alignment_unit(dst->internal_format, &align_w, &align_h);
height = (height + 3) / 4;
- width = ((width + alignment - 1) & ~(alignment - 1));
+ width = ALIGN(width, align_w);
}
for (i = 0; i < depth; i++) {
+ GLuint dst_offset = intel_miptree_image_offset(dst, face, level, i);
+ GLuint src_offset = intel_miptree_image_offset(src, face, level, i);
+
success = intel_region_copy(intel,
- dst->region, dst_offset + dst_depth_offset[i],
+ dst->region, dst_offset,
0, 0,
- src->region, src_offset + src_depth_offset[i],
+ src->region, src_offset,
0, 0, width, height, GL_COPY);
if (!success) {
GLubyte *src_ptr, *dst_ptr;
src_ptr = intel_region_map(intel, src->region);
dst_ptr = intel_region_map(intel, dst->region);
- _mesa_copy_rect(dst_ptr + dst_offset + dst_depth_offset[i],
+ _mesa_copy_rect(dst_ptr + dst_offset,
dst->cpp,
dst->pitch,
0, 0, width, height,
- src_ptr + src_offset + src_depth_offset[i],
+ src_ptr + src_offset,
src->pitch,
0, 0);
intel_region_unmap(intel, src->region);