#include "intel_context.h"
#include "intel_mipmap_tree.h"
#include "intel_regions.h"
+#include "intel_tex_layout.h"
#include "intel_chipset.h"
+#ifndef I915
+#include "brw_state.h"
+#endif
#include "main/enums.h"
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
+
static GLenum
target_to_target(GLenum target)
{
}
}
+
static struct intel_mipmap_tree *
intel_miptree_create_internal(struct intel_context *intel,
GLenum target,
return mt;
}
+
struct intel_mipmap_tree *
intel_miptree_create(struct intel_context *intel,
GLenum target,
+ GLenum base_format,
GLenum internal_format,
GLuint first_level,
GLuint last_level,
if (intel->use_texture_tiling && compress_byte == 0 &&
intel->intelScreen->kernel_exec_fencing) {
if (IS_965(intel->intelScreen->deviceID) &&
- internal_format == GL_DEPTH_COMPONENT)
+ (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL_EXT))
tiling = I915_TILING_Y;
else
tiling = I915_TILING_X;
return mt;
}
+
struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
GLenum target,
intel_region_reference(&mt->region, region);
return mt;
- }
+}
+
/**
* intel_miptree_pitch_align:
* Given @pitch, compute a larger value which accounts for
* any necessary alignment required by the device
*/
-
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling,
return pitch;
}
+
void
intel_miptree_reference(struct intel_mipmap_tree **dst,
struct intel_mipmap_tree *src)
DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount);
}
+
void
intel_miptree_release(struct intel_context *intel,
struct intel_mipmap_tree **mt)
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++)
}
-
-
-/* Can the image be pulled into a unified mipmap tree. This mirrors
+/**
+ * Can the image be pulled into a unified mipmap tree? This mirrors
* the completeness test in a lot of ways.
*
* Not sure whether I want to pass gl_texture_image here.
}
-
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
intel_miptree_image_unmap(struct intel_context *intel,
struct intel_mipmap_tree *mt)
}
-
-/* Upload data for a particular image.
+/**
+ * Upload data for a particular image.
*/
void
intel_miptree_image_data(struct intel_context *intel,
GLuint src_row_pitch,
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);
+ const GLuint depth = dst->level[level].depth;
GLuint i;
- GLuint height = 0;
DBG("%s: %d/%d\n", __FUNCTION__, face, level);
for (i = 0; i < depth; i++) {
- height = dst->level[level].height;
- if(dst->compressed)
+ GLuint dst_offset = intel_miptree_image_offset(dst, face, level, i);
+ GLuint 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);
-/* Copy mipmap image between trees
+
+/**
+ * Copy mipmap image between trees
*/
void
intel_miptree_image_copy(struct intel_context *intel,
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++) {
- intel_region_copy(intel,
- dst->region, dst_offset + dst_depth_offset[i],
- 0,
- 0,
- src->region, src_offset + src_depth_offset[i],
- 0, 0, width, height, GL_COPY);
+ 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,
+ 0, 0,
+ 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->cpp,
+ dst->pitch,
+ 0, 0, width, height,
+ src_ptr + src_offset,
+ src->pitch,
+ 0, 0);
+ intel_region_unmap(intel, src->region);
+ intel_region_unmap(intel, dst->region);
+ }
}
-
}