#include "intel_blit.h"
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
+#include "intel_mipmap_tree.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_context.h"
#include "vblank.h"
#include "utils.h"
#include "xmlpool.h" /* for symbolic values of enum-type options */
+
+#include "pipe/p_context.h"
+
+
+
#ifndef INTEL_DEBUG
int INTEL_DEBUG = (0);
#endif
// intel->pipe->glctx = ctx;
// intel_init_region_functions(intel->pipe);
+ switch (intel->intelScreen->deviceID) {
+ case PCI_CHIP_I945_G:
+ case PCI_CHIP_I945_GM:
+ case PCI_CHIP_I945_GME:
+ case PCI_CHIP_G33_G:
+ case PCI_CHIP_Q33_G:
+ case PCI_CHIP_Q35_G:
+ intel->pipe->mipmap_tree_layout = i945_miptree_layout;
+ break;
+ case PCI_CHIP_I915_G:
+ case PCI_CHIP_I915_GM:
+ case PCI_CHIP_I830_M:
+ case PCI_CHIP_I855_GM:
+ case PCI_CHIP_I865_G:
+ intel->pipe->mipmap_tree_layout = i915_miptree_layout;
+ default:
+ assert(0); /*FIX*/
+ }
+
+
/*
* memory pools
*/
}
}
-struct intel_mipmap_tree *
+struct pipe_mipmap_tree *
intel_miptree_create(struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint depth0, GLuint cpp, GLuint compress_byte)
{
GLboolean ok;
- struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
+ struct pipe_mipmap_tree *mt = calloc(sizeof(*mt), 1);
DBG("%s target %s format %s level %d..%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
mt->compressed = compress_byte ? 1 : 0;
mt->refcount = 1;
- switch (intel->intelScreen->deviceID) {
- case PCI_CHIP_I945_G:
- case PCI_CHIP_I945_GM:
- case PCI_CHIP_I945_GME:
- case PCI_CHIP_G33_G:
- case PCI_CHIP_Q33_G:
- case PCI_CHIP_Q35_G:
-// ok = i945_miptree_layout(mt);
- break;
- case PCI_CHIP_I915_G:
- case PCI_CHIP_I915_GM:
- case PCI_CHIP_I830_M:
- case PCI_CHIP_I855_GM:
- case PCI_CHIP_I865_G:
- default:
- /* All the i830 chips and the i915 use this layout:
- */
-// ok = i915_miptree_layout(mt);
- break;
- }
-
- ok = 0; /* TODO */
-
+ ok = intel->pipe->mipmap_tree_layout(intel->pipe, mt);
if (ok)
mt->region = intel->pipe->region_alloc(intel->pipe,
mt->cpp, mt->pitch, mt->total_height);
void
-intel_miptree_reference(struct intel_mipmap_tree **dst,
- struct intel_mipmap_tree *src)
+intel_miptree_reference(struct pipe_mipmap_tree **dst,
+ struct pipe_mipmap_tree *src)
{
src->refcount++;
*dst = src;
void
intel_miptree_release(struct intel_context *intel,
- struct intel_mipmap_tree **mt)
+ struct pipe_mipmap_tree **mt)
{
if (!*mt)
return;
* Not sure whether I want to pass gl_texture_image here.
*/
GLboolean
-intel_miptree_match_image(struct intel_mipmap_tree *mt,
+intel_miptree_match_image(struct pipe_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face, GLuint level)
{
void
-intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
+intel_miptree_set_level_info(struct pipe_mipmap_tree *mt,
GLuint level,
GLuint nr_images,
GLuint x, GLuint y, GLuint w, GLuint h, GLuint d)
void
-intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+intel_miptree_set_image_offset(struct pipe_mipmap_tree *mt,
GLuint level, GLuint img, GLuint x, GLuint y)
{
if (img == 0 && level == 0)
* These functions present that view to mesa:
*/
const GLuint *
-intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level)
+intel_miptree_depth_offsets(struct pipe_mipmap_tree *mt, GLuint level)
{
static const GLuint zero = 0;
GLuint
-intel_miptree_image_offset(struct intel_mipmap_tree * mt,
+intel_miptree_image_offset(struct pipe_mipmap_tree * mt,
GLuint face, GLuint level)
{
if (mt->target == GL_TEXTURE_CUBE_MAP_ARB)
*/
GLubyte *
intel_miptree_image_map(struct intel_context * intel,
- struct intel_mipmap_tree * mt,
+ struct pipe_mipmap_tree * mt,
GLuint face,
GLuint level,
GLuint * row_stride, GLuint * image_offsets)
void
intel_miptree_image_unmap(struct intel_context *intel,
- struct intel_mipmap_tree *mt)
+ struct pipe_mipmap_tree *mt)
{
DBG("%s\n", __FUNCTION__);
intel->pipe->region_unmap(intel->pipe, mt->region);
*/
void
intel_miptree_image_data(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
+ struct pipe_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
*/
void
intel_miptree_image_copy(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
+ struct pipe_mipmap_tree *dst,
GLuint face, GLuint level,
- struct intel_mipmap_tree *src)
+ struct pipe_mipmap_tree *src)
{
GLuint width = src->level[level].width;
GLuint height = src->level[level].height;
struct pipe_region;
-/* A layer on top of the pipe_regions code which adds:
- *
- * - Code to size and layout a region to hold a set of mipmaps.
- * - Query to determine if a new image fits in an existing tree.
- * - More refcounting
- * - maybe able to remove refcounting from pipe_region?
- * - ?
- *
- * The fixed mipmap layout of intel hardware where one offset
- * specifies the position of all images in a mipmap hierachy
- * complicates the implementation of GL texture image commands,
- * compared to hardware where each image is specified with an
- * independent offset.
- *
- * In an ideal world, each texture object would be associated with a
- * single bufmgr buffer or 2d pipe_region, and all the images within
- * the texture object would slot into the tree as they arrive. The
- * reality can be a little messier, as images can arrive from the user
- * with sizes that don't fit in the existing tree, or in an order
- * where the tree layout cannot be guessed immediately.
- *
- * This structure encodes an idealized mipmap tree. The GL image
- * commands build these where possible, otherwise store the images in
- * temporary system buffers.
- */
-
-
-/**
- * Describes the location of each texture image within a texture region.
- */
-struct intel_mipmap_level
-{
- GLuint level_offset;
- GLuint width;
- GLuint height;
- GLuint depth;
- GLuint nr_images;
-
- /* Explicitly store the offset of each image for each cube face or
- * depth value. Pretty much have to accept that hardware formats
- * are going to be so diverse that there is no unified way to
- * compute the offsets of depth/cube images within a mipmap level,
- * so have to store them as a lookup table:
- */
- GLuint *image_offset;
-};
-
-struct intel_mipmap_tree
-{
- /* Effectively the key:
- */
- GLenum target;
- GLenum internal_format;
-
- GLuint first_level;
- GLuint last_level;
-
- GLuint width0, height0, depth0; /**< Level zero image dimensions */
- GLuint cpp;
- GLboolean compressed;
-
- /* Derived from the above:
- */
- GLuint pitch;
- GLuint depth_pitch; /* per-image on i945? */
- GLuint total_height;
-
- /* Includes image offset tables:
- */
- struct intel_mipmap_level level[MAX_TEXTURE_LEVELS];
-
- /* The data is held here:
- */
- struct pipe_region *region;
-
- /* These are also refcounted:
- */
- GLuint refcount;
-};
-
-
-
-struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel,
+struct pipe_mipmap_tree *intel_miptree_create(struct intel_context *intel,
GLenum target,
GLenum internal_format,
GLuint first_level,
GLuint cpp,
GLuint compress_byte);
-void intel_miptree_reference(struct intel_mipmap_tree **dst,
- struct intel_mipmap_tree *src);
+void intel_miptree_reference(struct pipe_mipmap_tree **dst,
+ struct pipe_mipmap_tree *src);
void intel_miptree_release(struct intel_context *intel,
- struct intel_mipmap_tree **mt);
+ struct pipe_mipmap_tree **mt);
/* Check if an image fits an existing mipmap tree layout
*/
-GLboolean intel_miptree_match_image(struct intel_mipmap_tree *mt,
+GLboolean intel_miptree_match_image(struct pipe_mipmap_tree *mt,
struct gl_texture_image *image,
GLuint face, GLuint level);
* well.
*/
GLubyte *intel_miptree_image_map(struct intel_context *intel,
- struct intel_mipmap_tree *mt,
+ struct pipe_mipmap_tree *mt,
GLuint face,
GLuint level,
GLuint * row_stride, GLuint * image_stride);
void intel_miptree_image_unmap(struct intel_context *intel,
- struct intel_mipmap_tree *mt);
+ struct pipe_mipmap_tree *mt);
/* Return the linear offset of an image relative to the start of the
* tree:
*/
-GLuint intel_miptree_image_offset(struct intel_mipmap_tree *mt,
+GLuint intel_miptree_image_offset(struct pipe_mipmap_tree *mt,
GLuint face, GLuint level);
/* Return pointers to each 2d slice within an image. Indexed by depth
* value.
*/
-const GLuint *intel_miptree_depth_offsets(struct intel_mipmap_tree *mt,
+const GLuint *intel_miptree_depth_offsets(struct pipe_mipmap_tree *mt,
GLuint level);
-void intel_miptree_set_level_info(struct intel_mipmap_tree *mt,
+void intel_miptree_set_level_info(struct pipe_mipmap_tree *mt,
GLuint level,
GLuint nr_images,
GLuint x, GLuint y,
GLuint w, GLuint h, GLuint d);
-void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt,
+void intel_miptree_set_image_offset(struct pipe_mipmap_tree *mt,
GLuint level,
GLuint img, GLuint x, GLuint y);
/* Upload an image into a tree
*/
void intel_miptree_image_data(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
+ struct pipe_mipmap_tree *dst,
GLuint face,
GLuint level,
void *src,
/* Copy an image between two trees
*/
void intel_miptree_image_copy(struct intel_context *intel,
- struct intel_mipmap_tree *dst,
+ struct pipe_mipmap_tree *dst,
GLuint face, GLuint level,
- struct intel_mipmap_tree *src);
+ struct pipe_mipmap_tree *src);
/* i915_mipmap_tree.c:
*/
-GLboolean i915_miptree_layout(struct intel_mipmap_tree *mt);
-GLboolean i945_miptree_layout(struct intel_mipmap_tree *mt);
+GLboolean i915_miptree_layout(struct pipe_context *, struct pipe_mipmap_tree *);
+GLboolean i945_miptree_layout(struct pipe_context *, struct pipe_mipmap_tree *);
/* On validation any active images held in main memory or in other
* regions will be copied to this region and the old storage freed.
*/
- struct intel_mipmap_tree *mt;
+ struct pipe_mipmap_tree *mt;
GLboolean imageOverride;
GLint depthOverride;
* Else if intelImage->base.Data != NULL, image is stored there.
* Else there is no image data.
*/
- struct intel_mipmap_tree *mt;
+ struct pipe_mipmap_tree *mt;
};
#include "texstore.h"
#include "intel_context.h"
-#include "intel_mipmap_tree.h"
#include "intel_buffer_objects.h"
#include "intel_batchbuffer.h"
+#include "intel_mipmap_tree.h"
#include "intel_tex.h"
#include "intel_ioctl.h"
#include "intel_blit.h"
#include "intel_mipmap_tree.h"
#include "intel_tex.h"
+#include "pipe/p_state.h"
+
#define FILE_DEBUG_FLAG DEBUG_TEXTURE
/**
* Michel Dänzer <michel@tungstengraphics.com>
*/
-#include "intel_mipmap_tree.h"
-#include "intel_tex_layout.h"
#include "macros.h"
+#include "pipe/p_state.h"
+#include "intel_mipmap_tree.h"
+
+static GLuint minify( GLuint d )
+{
+ return MAX2(1, d>>1);
+}
static int align(int value, int alignment)
{
return (value + alignment - 1) & ~(alignment - 1);
}
-void i945_miptree_layout_2d( struct intel_mipmap_tree *mt )
+
+static void
+mipmaptree_set_level_info(struct pipe_mipmap_tree *mt,
+ GLuint level,
+ GLuint nr_images,
+ GLuint x, GLuint y, GLuint w, GLuint h, GLuint d)
+{
+ assert(level < MAX_TEXTURE_LEVELS);
+
+ mt->level[level].width = w;
+ mt->level[level].height = h;
+ mt->level[level].depth = d;
+ mt->level[level].level_offset = (x + y * mt->pitch) * mt->cpp;
+ mt->level[level].nr_images = nr_images;
+
+ /*
+ DBG("%s level %d size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__,
+ level, w, h, d, x, y, mt->level[level].level_offset);
+ */
+
+ /* Not sure when this would happen, but anyway:
+ */
+ if (mt->level[level].image_offset) {
+ free(mt->level[level].image_offset);
+ mt->level[level].image_offset = NULL;
+ }
+
+ assert(nr_images);
+
+ mt->level[level].image_offset = malloc(nr_images * sizeof(GLuint));
+ mt->level[level].image_offset[0] = 0;
+}
+
+
+static void
+i945_miptree_layout_2d( struct pipe_mipmap_tree *mt )
{
GLint align_h = 2, align_w = 4;
GLuint level;
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
GLuint img_height;
- intel_miptree_set_level_info(mt, level, 1, x, y, width,
- height, 1);
+ mipmaptree_set_level_info(mt, level, 1, x, y, width, height, 1);
if (mt->compressed)
img_height = MAX2(1, height/4);
height = minify(height);
}
}
+
+
+static const GLint initial_offsets[6][2] = {
+ {0, 0},
+ {0, 2},
+ {1, 0},
+ {1, 2},
+ {1, 1},
+ {1, 3}
+};
+
+static const GLint step_offsets[6][2] = {
+ {0, 2},
+ {0, 2},
+ {-1, 2},
+ {-1, 2},
+ {-1, 1},
+ {-1, 1}
+};
+
+
+GLboolean
+i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
+{
+ GLint level;
+
+ switch (mt->target) {
+ case GL_TEXTURE_CUBE_MAP:{
+ const GLuint dim = mt->width0;
+ GLuint face;
+ GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;
+
+ assert(lvlWidth == lvlHeight); /* cubemap images are square */
+
+ /* double pitch for cube layouts */
+ mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+ mt->total_height = dim * 4;
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ intel_miptree_set_level_info(mt, level, 6,
+ 0, 0,
+ /*OLD: mt->pitch, mt->total_height,*/
+ lvlWidth, lvlHeight,
+ 1);
+ lvlWidth /= 2;
+ lvlHeight /= 2;
+ }
+
+ for (face = 0; face < 6; face++) {
+ GLuint x = initial_offsets[face][0] * dim;
+ GLuint y = initial_offsets[face][1] * dim;
+ GLuint d = dim;
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ intel_miptree_set_image_offset(mt, level, face, x, y);
+
+ if (d == 0)
+ _mesa_printf("cube mipmap %d/%d (%d..%d) is 0x0\n",
+ face, level, mt->first_level, mt->last_level);
+
+ d >>= 1;
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ }
+ }
+ break;
+ }
+ case GL_TEXTURE_3D:{
+ GLuint width = mt->width0;
+ GLuint height = mt->height0;
+ GLuint depth = mt->depth0;
+ GLuint stack_height = 0;
+
+ /* Calculate the size of a single slice.
+ */
+ mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+
+ /* XXX: hardware expects/requires 9 levels at minimum.
+ */
+ for (level = mt->first_level; level <= MAX2(8, mt->last_level);
+ level++) {
+ intel_miptree_set_level_info(mt, level, depth, 0, mt->total_height,
+ width, height, depth);
+
+
+ stack_height += MAX2(2, height);
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ }
+
+ /* Fixup depth image_offsets:
+ */
+ depth = mt->depth0;
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ GLuint i;
+ for (i = 0; i < depth; i++)
+ intel_miptree_set_image_offset(mt, level, i,
+ 0, i * stack_height);
+
+ depth = minify(depth);
+ }
+
+
+ /* Multiply slice size by texture depth for total size. It's
+ * remarkable how wasteful of memory the i915 texture layouts
+ * are. They are largely fixed in the i945.
+ */
+ mt->total_height = stack_height * mt->depth0;
+ break;
+ }
+
+ default:{
+ GLuint width = mt->width0;
+ GLuint height = mt->height0;
+ GLuint img_height;
+
+ mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+ mt->total_height = 0;
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ intel_miptree_set_level_info(mt, level, 1,
+ 0, mt->total_height,
+ width, height, 1);
+
+ if (mt->compressed)
+ img_height = MAX2(1, height / 4);
+ else
+ img_height = (MAX2(2, height) + 1) & ~1;
+
+ mt->total_height += img_height;
+
+ width = minify(width);
+ height = minify(height);
+ }
+ break;
+ }
+ }
+ /*
+ DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+ mt->pitch,
+ mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp);
+ */
+
+ return GL_TRUE;
+}
+
+
+GLboolean
+i945_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
+{
+ GLint level;
+
+ switch (mt->target) {
+ case GL_TEXTURE_CUBE_MAP:{
+ const GLuint dim = mt->width0;
+ GLuint face;
+ GLuint lvlWidth = mt->width0, lvlHeight = mt->height0;
+
+ assert(lvlWidth == lvlHeight); /* cubemap images are square */
+
+ /* Depending on the size of the largest images, pitch can be
+ * determined either by the old-style packing of cubemap faces,
+ * or the final row of 4x4, 2x2 and 1x1 faces below this.
+ */
+ if (dim > 32)
+ mt->pitch = ((dim * mt->cpp * 2 + 3) & ~3) / mt->cpp;
+ else
+ mt->pitch = 14 * 8;
+
+ mt->total_height = dim * 4 + 4;
+
+ /* Set all the levels to effectively occupy the whole rectangular region.
+ */
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ intel_miptree_set_level_info(mt, level, 6,
+ 0, 0,
+ lvlWidth, lvlHeight, 1);
+ lvlWidth /= 2;
+ lvlHeight /= 2;
+ }
+
+
+ for (face = 0; face < 6; face++) {
+ GLuint x = initial_offsets[face][0] * dim;
+ GLuint y = initial_offsets[face][1] * dim;
+ GLuint d = dim;
+
+ if (dim == 4 && face >= 4) {
+ y = mt->total_height - 4;
+ x = (face - 4) * 8;
+ }
+ else if (dim < 4 && (face > 0 || mt->first_level > 0)) {
+ y = mt->total_height - 4;
+ x = face * 8;
+ }
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ intel_miptree_set_image_offset(mt, level, face, x, y);
+
+ d >>= 1;
+
+ switch (d) {
+ case 4:
+ switch (face) {
+ case FACE_POS_X:
+ case FACE_NEG_X:
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ break;
+ case FACE_POS_Y:
+ case FACE_NEG_Y:
+ y += 12;
+ x -= 8;
+ break;
+ case FACE_POS_Z:
+ case FACE_NEG_Z:
+ y = mt->total_height - 4;
+ x = (face - 4) * 8;
+ break;
+ }
+
+ case 2:
+ y = mt->total_height - 4;
+ x = 16 + face * 8;
+ break;
+
+ case 1:
+ x += 48;
+ break;
+
+ default:
+ x += step_offsets[face][0] * d;
+ y += step_offsets[face][1] * d;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case GL_TEXTURE_3D:{
+ GLuint width = mt->width0;
+ GLuint height = mt->height0;
+ GLuint depth = mt->depth0;
+ GLuint pack_x_pitch, pack_x_nr;
+ GLuint pack_y_pitch;
+ GLuint level;
+
+ mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
+ mt->total_height = 0;
+
+ pack_y_pitch = MAX2(mt->height0, 2);
+ pack_x_pitch = mt->pitch;
+ pack_x_nr = 1;
+
+ for (level = mt->first_level; level <= mt->last_level; level++) {
+ GLuint nr_images = mt->target == GL_TEXTURE_3D ? depth : 6;
+ GLint x = 0;
+ GLint y = 0;
+ GLint q, j;
+
+ intel_miptree_set_level_info(mt, level, nr_images,
+ 0, mt->total_height,
+ width, height, depth);
+
+ for (q = 0; q < nr_images;) {
+ for (j = 0; j < pack_x_nr && q < nr_images; j++, q++) {
+ intel_miptree_set_image_offset(mt, level, q, x, y);
+ x += pack_x_pitch;
+ }
+
+ x = 0;
+ y += pack_y_pitch;
+ }
+
+
+ mt->total_height += y;
+
+ if (pack_x_pitch > 4) {
+ pack_x_pitch >>= 1;
+ pack_x_nr <<= 1;
+ assert(pack_x_pitch * pack_x_nr <= mt->pitch);
+ }
+
+ if (pack_y_pitch > 2) {
+ pack_y_pitch >>= 1;
+ }
+
+ width = minify(width);
+ height = minify(height);
+ depth = minify(depth);
+ }
+ break;
+ }
+
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_RECTANGLE_ARB:
+ i945_miptree_layout_2d(mt);
+ break;
+ default:
+ _mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");
+ }
+
+ /*
+ DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,
+ mt->pitch,
+ mt->total_height, mt->cpp, mt->pitch * mt->total_height * mt->cpp);
+ */
+
+ return GL_TRUE;
+}
#include "macros.h"
-static GLuint minify( GLuint d )
-{
- return MAX2(1, d>>1);
-}
+extern void i915_miptree_layout_2d( struct pipe_context *, struct pipe_mipmap_tree *mt );
-extern void i945_miptree_layout_2d( struct intel_mipmap_tree *mt );
+extern void i945_miptree_layout_2d( struct pipe_context *, struct pipe_mipmap_tree *mt );
unsigned long offset,
unsigned long size,
void *data);
+
+ /*
+ * Texture functions
+ */
+ GLboolean (*mipmap_tree_layout)( struct pipe_context *pipe,
+ struct pipe_mipmap_tree *mt );
+
+
};
};
+/**
+ * Describes the location of each texture image within a texture region.
+ */
+struct pipe_mipmap_level
+{
+ GLuint level_offset;
+ GLuint width;
+ GLuint height;
+ GLuint depth;
+ GLuint nr_images;
+
+ /* Explicitly store the offset of each image for each cube face or
+ * depth value. Pretty much have to accept that hardware formats
+ * are going to be so diverse that there is no unified way to
+ * compute the offsets of depth/cube images within a mipmap level,
+ * so have to store them as a lookup table:
+ */
+ GLuint *image_offset;
+};
+
+struct pipe_mipmap_tree
+{
+ /* Effectively the key:
+ */
+ GLenum target;
+ GLenum internal_format;
+
+ GLuint first_level;
+ GLuint last_level;
+
+ GLuint width0, height0, depth0; /**< Level zero image dimensions */
+ GLuint cpp;
+ GLboolean compressed;
+
+ /* Derived from the above:
+ */
+ GLuint pitch;
+ GLuint depth_pitch; /* per-image on i945? */
+ GLuint total_height;
+
+ /* Includes image offset tables:
+ */
+ struct pipe_mipmap_level level[MAX_TEXTURE_LEVELS];
+
+ /* The data is held here:
+ */
+ struct pipe_region *region;
+
+ /* These are also refcounted:
+ */
+ GLuint refcount;
+};
+
+
+
struct pipe_buffer_handle;
#define PIPE_BUFFER_FLAG_READ 0x1