@@ -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 | |||
*/ |
@@ -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; |
@@ -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 *); | |||
@@ -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; | |||
}; | |||
@@ -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" |
@@ -6,6 +6,8 @@ | |||
#include "intel_mipmap_tree.h" | |||
#include "intel_tex.h" | |||
#include "pipe/p_state.h" | |||
#define FILE_DEBUG_FLAG DEBUG_TEXTURE | |||
/** |
@@ -30,17 +30,57 @@ | |||
* 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; | |||
@@ -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; | |||
} |
@@ -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 ); |
@@ -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 ); | |||
}; | |||
@@ -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 |