#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,
GLuint last_level,
GLuint width0,
GLuint height0,
- GLuint depth0, GLuint cpp, GLuint compress_byte)
+ GLuint depth0, GLuint cpp, GLuint compress_byte,
+ uint32_t tiling)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
#ifdef I915
if (IS_945(intel->intelScreen->deviceID))
- ok = i945_miptree_layout(intel, mt);
+ ok = i945_miptree_layout(intel, mt, tiling);
else
- ok = i915_miptree_layout(intel, mt);
+ ok = i915_miptree_layout(intel, mt, tiling);
#else
- ok = brw_miptree_layout(intel, mt);
+ ok = brw_miptree_layout(intel, mt, tiling);
#endif
if (!ok) {
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,
GLboolean expect_accelerated_upload)
{
struct intel_mipmap_tree *mt;
+ uint32_t tiling;
+
+ if (intel->use_texture_tiling && compress_byte == 0 &&
+ intel->intelScreen->kernel_exec_fencing) {
+ if (IS_965(intel->intelScreen->deviceID) &&
+ (base_format == GL_DEPTH_COMPONENT ||
+ base_format == GL_DEPTH_STENCIL_EXT))
+ tiling = I915_TILING_Y;
+ else
+ tiling = I915_TILING_X;
+ } else
+ tiling = I915_TILING_NONE;
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level, width0,
- height0, depth0, cpp, compress_byte);
+ height0, depth0, cpp, compress_byte,
+ tiling);
/*
* pitch == 0 || height == 0 indicates the null texture
*/
return NULL;
mt->region = intel_region_alloc(intel,
+ tiling,
mt->cpp,
mt->pitch,
mt->total_height,
return mt;
}
+
struct intel_mipmap_tree *
intel_miptree_create_for_region(struct intel_context *intel,
GLenum target,
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level,
region->width, region->height, 1,
- region->cpp, compress_byte);
+ region->cpp, compress_byte,
+ I915_TILING_NONE);
if (!mt)
return mt;
#if 0
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,
int pitch)
{
#ifdef I915
pitch_align = 4;
}
+ if (tiling == I915_TILING_X)
+ pitch_align = 512;
+ else if (tiling == I915_TILING_Y)
+ pitch_align = 128;
+
pitch = ALIGN(pitch * mt->cpp, pitch_align);
#ifdef I915
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);
+ 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);
+ }
}
-
}