From d9605cdf7cbbd3c81c506d01eb8e88a11ccfc09b Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 6 Aug 2007 11:22:00 -0600 Subject: [PATCH] Checkpoint lifting of intel_mipmap_tree (intel_mipmap_tree -> pipe_mipmap_tree and move some code) --- src/mesa/drivers/dri/i915pipe/intel_context.c | 26 ++ .../drivers/dri/i915pipe/intel_mipmap_tree.c | 54 +-- .../drivers/dri/i915pipe/intel_mipmap_tree.h | 114 +----- src/mesa/drivers/dri/i915pipe/intel_tex.h | 4 +- .../drivers/dri/i915pipe/intel_tex_image.c | 2 +- .../drivers/dri/i915pipe/intel_tex_validate.c | 2 + src/mesa/drivers/dri/intel/intel_tex_layout.c | 362 +++++++++++++++++- src/mesa/drivers/dri/intel/intel_tex_layout.h | 7 +- src/mesa/pipe/p_context.h | 8 + src/mesa/pipe/p_state.h | 55 +++ 10 files changed, 485 insertions(+), 149 deletions(-) diff --git a/src/mesa/drivers/dri/i915pipe/intel_context.c b/src/mesa/drivers/dri/i915pipe/intel_context.c index d43b7841120..df34c360e57 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_context.c +++ b/src/mesa/drivers/dri/i915pipe/intel_context.c @@ -53,6 +53,7 @@ #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" @@ -61,6 +62,11 @@ #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 @@ -377,6 +383,26 @@ intelCreateContext(const __GLcontextModes * mesaVis, // 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 */ diff --git a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c index 6717984f7d6..50e830281c4 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c @@ -51,7 +51,7 @@ target_to_target(GLenum target) } } -struct intel_mipmap_tree * +struct pipe_mipmap_tree * intel_miptree_create(struct intel_context *intel, GLenum target, GLenum internal_format, @@ -62,7 +62,7 @@ intel_miptree_create(struct intel_context *intel, 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), @@ -79,29 +79,7 @@ intel_miptree_create(struct intel_context *intel, 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); @@ -116,8 +94,8 @@ intel_miptree_create(struct intel_context *intel, 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; @@ -126,7 +104,7 @@ intel_miptree_reference(struct intel_mipmap_tree **dst, void intel_miptree_release(struct intel_context *intel, - struct intel_mipmap_tree **mt) + struct pipe_mipmap_tree **mt) { if (!*mt) return; @@ -157,7 +135,7 @@ intel_miptree_release(struct intel_context *intel, * 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) { @@ -184,7 +162,7 @@ intel_miptree_match_image(struct intel_mipmap_tree *mt, 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) @@ -215,7 +193,7 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt, 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) @@ -237,7 +215,7 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, * 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; @@ -249,7 +227,7 @@ intel_miptree_depth_offsets(struct intel_mipmap_tree *mt, GLuint level) 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) @@ -269,7 +247,7 @@ intel_miptree_image_offset(struct intel_mipmap_tree * mt, */ 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) @@ -291,7 +269,7 @@ intel_miptree_image_map(struct intel_context * intel, 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); @@ -303,7 +281,7 @@ intel_miptree_image_unmap(struct intel_context *intel, */ 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, @@ -336,9 +314,9 @@ intel_miptree_image_data(struct intel_context *intel, */ 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; diff --git a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h index 09b2e362fcf..94fb21372c5 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h @@ -34,89 +34,7 @@ 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, @@ -127,15 +45,15 @@ struct intel_mipmap_tree *intel_miptree_create(struct intel_context *intel, 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); @@ -143,35 +61,35 @@ GLboolean intel_miptree_match_image(struct intel_mipmap_tree *mt, * 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); @@ -179,7 +97,7 @@ void intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, /* 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, @@ -188,14 +106,14 @@ void intel_miptree_image_data(struct intel_context *intel, /* 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 *); diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex.h b/src/mesa/drivers/dri/i915pipe/intel_tex.h index 4a5081eee7a..1ee239402e1 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_tex.h +++ b/src/mesa/drivers/dri/i915pipe/intel_tex.h @@ -49,7 +49,7 @@ struct intel_texture_object /* 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; @@ -71,7 +71,7 @@ struct intel_texture_image * 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; }; diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_image.c b/src/mesa/drivers/dri/i915pipe/intel_tex_image.c index 9f8e115533c..596493f45a1 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_image.c +++ b/src/mesa/drivers/dri/i915pipe/intel_tex_image.c @@ -16,9 +16,9 @@ #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" diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c b/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c index af18c26d55c..242fe1237bb 100644 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c +++ b/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c @@ -6,6 +6,8 @@ #include "intel_mipmap_tree.h" #include "intel_tex.h" +#include "pipe/p_state.h" + #define FILE_DEBUG_FLAG DEBUG_TEXTURE /** diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index fcb5cc39068..bedd835cbb9 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -30,17 +30,57 @@ * Michel Dänzer */ -#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; @@ -73,8 +113,7 @@ void i945_miptree_layout_2d( struct intel_mipmap_tree *mt ) 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); @@ -100,3 +139,316 @@ void i945_miptree_layout_2d( struct intel_mipmap_tree *mt ) 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; +} diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h index 1e37f8f525f..cbd4b8e27ff 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.h +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -33,9 +33,6 @@ #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 ); diff --git a/src/mesa/pipe/p_context.h b/src/mesa/pipe/p_context.h index 76a25935672..db9429f8d3f 100644 --- a/src/mesa/pipe/p_context.h +++ b/src/mesa/pipe/p_context.h @@ -207,6 +207,14 @@ struct pipe_context { unsigned long offset, unsigned long size, void *data); + + /* + * Texture functions + */ + GLboolean (*mipmap_tree_layout)( struct pipe_context *pipe, + struct pipe_mipmap_tree *mt ); + + }; diff --git a/src/mesa/pipe/p_state.h b/src/mesa/pipe/p_state.h index 518110d4470..13b8813f4a4 100644 --- a/src/mesa/pipe/p_state.h +++ b/src/mesa/pipe/p_state.h @@ -292,6 +292,61 @@ struct pipe_texture_object }; +/** + * 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 -- 2.30.2