Commit 753db0d8 authored by Michel Dänzer's avatar Michel Dänzer

Hide texture layout details from the state tracker.

pipe->get_tex_surface() has to be used for access to texture image data.
parent 59356268
......@@ -328,8 +328,8 @@ intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
if (!stObj)
return;
if (stObj->mt)
st_miptree_release(intel->st->pipe, &stObj->mt);
if (stObj->pt)
st->pipe->texture_release(intel->st->pipe, &stObj->pt);
stObj->imageOverride = GL_TRUE;
stObj->depthOverride = depth;
......
......@@ -145,7 +145,8 @@ struct pipe_context *failover_create( struct pipe_context *hw,
failover->pipe.surface_data = hw->surface_data;
failover->pipe.surface_copy = hw->surface_copy;
failover->pipe.surface_fill = hw->surface_fill;
failover->pipe.mipmap_tree_layout = hw->mipmap_tree_layout;
failover->pipe.texture_create = hw->texture_create;
failover->pipe.texture_release = hw->texture_release;
failover->pipe.flush = hw->flush;
failover->dirty = 0;
......
......@@ -85,7 +85,7 @@ struct failover_context {
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
uint sampler_units[PIPE_MAX_SAMPLERS];
struct pipe_mipmap_tree *texture[PIPE_MAX_SAMPLERS];
struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vertex_element[PIPE_ATTRIB_MAX];
......
......@@ -402,7 +402,7 @@ failover_delete_sampler_state(struct pipe_context *pipe, void *sampler)
static void
failover_set_texture_state(struct pipe_context *pipe,
unsigned unit,
struct pipe_mipmap_tree *texture)
struct pipe_texture *texture)
{
struct failover_context *failover = failover_context(pipe);
......
......@@ -22,7 +22,7 @@ DRIVER_SOURCES = \
i915_strings.c \
i915_prim_emit.c \
i915_prim_vbuf.c \
i915_tex_layout.c \
i915_texture.c \
i915_fpc_emit.c \
i915_fpc_translate.c \
i915_surface.c
......
......@@ -29,7 +29,7 @@
#include "i915_winsys.h"
#include "i915_state.h"
#include "i915_batch.h"
#include "i915_tex_layout.h"
#include "i915_texture.h"
#include "i915_reg.h"
#include "pipe/draw/draw_context.h"
......@@ -357,11 +357,8 @@ struct pipe_context *i915_create( struct pipe_winsys *pipe_winsys,
i915->pci_id = pci_id;
i915->flags.is_i945 = is_i945;
if (i915->flags.is_i945)
i915->pipe.mipmap_tree_layout = i945_miptree_layout;
else
i915->pipe.mipmap_tree_layout = i915_miptree_layout;
i915->pipe.texture_create = i915_texture_create;
i915->pipe.texture_release = i915_texture_release;
i915->dirty = ~0;
i915->hardware_dirty = ~0;
......
......@@ -150,6 +150,34 @@ struct i915_alpha_test_state {
unsigned LIS6;
};
struct i915_texture {
struct pipe_texture base;
/* Derived from the above:
*/
unsigned pitch;
unsigned depth_pitch; /* per-image on i945? */
unsigned total_height;
unsigned nr_images[PIPE_MAX_TEXTURE_LEVELS];
/* 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:
*/
unsigned *image_offset[PIPE_MAX_TEXTURE_LEVELS]; /**< array [depth] of offsets */
/* Includes image offset tables:
*/
unsigned level_offset[PIPE_MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct pipe_region *region;
};
struct i915_context
{
struct pipe_context pipe;
......@@ -174,7 +202,7 @@ struct i915_context
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
uint sampler_units[PIPE_MAX_SAMPLERS];
struct pipe_mipmap_tree *texture[PIPE_MAX_SAMPLERS];
struct i915_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_ATTRIB_MAX];
......
......@@ -525,11 +525,11 @@ static void i915_set_constant_buffer(struct pipe_context *pipe,
static void i915_set_texture_state(struct pipe_context *pipe,
unsigned unit,
struct pipe_mipmap_tree *texture)
struct pipe_texture *texture)
{
struct i915_context *i915 = i915_context(pipe);
i915->texture[unit] = texture; /* ptr, not struct */
i915->texture[unit] = (struct i915_texture*)texture; /* ptr, not struct */
i915->dirty |= I915_NEW_TEXTURE;
}
......
......@@ -46,9 +46,11 @@
static void update_sampler(struct i915_context *i915,
uint unit,
const struct i915_sampler_state *sampler,
const struct pipe_mipmap_tree *mt,
const struct i915_texture *tex,
unsigned state[3] )
{
const struct pipe_texture *pt = &tex->base;
/* Need to do this after updating the maps, which call the
* intel_finalize_mipmap_tree and hence can update firstLevel:
*/
......@@ -56,8 +58,8 @@ static void update_sampler(struct i915_context *i915,
state[1] = sampler->state[1];
state[2] = sampler->state[2];
if (mt->format == PIPE_FORMAT_YCBCR ||
mt->format == PIPE_FORMAT_YCBCR_REV)
if (pt->format == PIPE_FORMAT_YCBCR ||
pt->format == PIPE_FORMAT_YCBCR_REV)
state[0] |= SS2_COLORSPACE_CONVERSION;
/* 3D textures don't seem to respect the border color.
......@@ -75,7 +77,7 @@ static void update_sampler(struct i915_context *i915,
const unsigned ws = sampler->templ->wrap_s;
const unsigned wt = sampler->templ->wrap_t;
const unsigned wr = sampler->templ->wrap_r;
if (mt->target == PIPE_TEXTURE_3D &&
if (pt->target == PIPE_TEXTURE_3D &&
(sampler->templ->min_img_filter != PIPE_TEX_FILTER_NEAREST ||
sampler->templ->mag_img_filter != PIPE_TEX_FILTER_NEAREST) &&
(ws == PIPE_TEX_WRAP_CLAMP ||
......@@ -105,13 +107,13 @@ void i915_update_samplers( struct i915_context *i915 )
i915->current.sampler_enable_flags = 0x0;
for (unit = 0; unit < I915_TEX_UNITS; unit++) {
/* determine unit enable/disable by looking for a bound mipmap tree */
/* determine unit enable/disable by looking for a bound texture */
/* could also examine the fragment program? */
if (i915->texture[unit]) {
update_sampler( i915,
unit,
i915->sampler[unit], /* sampler state */
i915->texture[unit], /* mipmap tree */
i915->texture[unit], /* texture */
i915->current.sampler[unit] /* the result */
);
......@@ -179,18 +181,19 @@ static void
i915_update_texture(struct i915_context *i915, uint unit,
uint state[6])
{
const struct pipe_mipmap_tree *mt = i915->texture[unit];
const struct i915_texture *tex = i915->texture[unit];
const struct pipe_texture *pt = &tex->base;
uint format, pitch;
const uint width = mt->width0, height = mt->height0, depth = mt->depth0;
const uint num_levels = mt->last_level - mt->first_level;
const uint width = pt->width[0], height = pt->height[0], depth = pt->depth[0];
const uint num_levels = pt->last_level - pt->first_level;
assert(mt);
assert(tex);
assert(width);
assert(height);
assert(depth);
format = translate_texture_format(mt->format);
pitch = mt->pitch * mt->cpp;
format = translate_texture_format(pt->format);
pitch = tex->pitch * pt->cpp;
assert(format);
assert(pitch);
......@@ -217,7 +220,7 @@ i915_update_textures(struct i915_context *i915)
uint unit;
for (unit = 0; unit < I915_TEX_UNITS; unit++) {
/* determine unit enable/disable by looking for a bound mipmap tree */
/* determine unit enable/disable by looking for a bound texture */
/* could also examine the fragment program? */
if (i915->texture[unit]) {
i915_update_texture(i915, unit, i915->current.texbuffer[unit]);
......
......@@ -187,34 +187,35 @@ i915_put_tile(struct pipe_context *pipe,
*/
static struct pipe_surface *
i915_get_tex_surface(struct pipe_context *pipe,
struct pipe_mipmap_tree *mt,
struct pipe_texture *pt,
unsigned face, unsigned level, unsigned zslice)
{
struct i915_texture *tex = (struct i915_texture *)pt;
struct pipe_surface *ps;
unsigned offset; /* in bytes */
offset = mt->level[level].level_offset;
offset = tex->level_offset[level];
if (mt->target == PIPE_TEXTURE_CUBE) {
offset += mt->level[level].image_offset[face] * mt->cpp;
if (pt->target == PIPE_TEXTURE_CUBE) {
offset += tex->image_offset[level][face] * pt->cpp;
}
else if (mt->target == PIPE_TEXTURE_3D) {
offset += mt->level[level].image_offset[zslice] * mt->cpp;
else if (pt->target == PIPE_TEXTURE_3D) {
offset += tex->image_offset[level][zslice] * pt->cpp;
}
else {
assert(face == 0);
assert(zslice == 0);
}
ps = pipe->winsys->surface_alloc(pipe->winsys, mt->format);
ps = pipe->winsys->surface_alloc(pipe->winsys, pt->format);
if (ps) {
assert(ps->format);
assert(ps->refcount);
pipe_region_reference(&ps->region, mt->region);
ps->cpp = mt->cpp;
ps->width = mt->level[level].width;
ps->height = mt->level[level].height;
ps->pitch = mt->pitch;
pipe_region_reference(&ps->region, tex->region);
ps->cpp = pt->cpp;
ps->width = pt->width[level];
ps->height = pt->height[level];
ps->pitch = tex->pitch;
ps->offset = offset;
}
return ps;
......
#ifndef I915_TEX_LAYOUT_H
#define I915_TEX_LAYOUT_H
struct pipe_context;
struct pipe_mipmap_tree;
extern boolean
i915_miptree_layout(struct pipe_context *, struct pipe_mipmap_tree *);
extern boolean
i945_miptree_layout(struct pipe_context *, struct pipe_mipmap_tree *);
#endif /* I915_TEX_LAYOUT_H */
......@@ -34,8 +34,10 @@
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
#include "i915_tex_layout.h"
#include "i915_context.h"
#include "i915_texture.h"
#include "i915_debug.h"
......@@ -51,94 +53,98 @@ static int align(int value, int alignment)
static void
i915_miptree_set_level_info(struct pipe_mipmap_tree *mt,
i915_miptree_set_level_info(struct i915_texture *tex,
unsigned level,
unsigned nr_images,
unsigned x, unsigned y, unsigned w, unsigned h, unsigned d)
{
struct pipe_texture *pt = &tex->base;
assert(level < PIPE_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;
pt->width[level] = w;
pt->height[level] = h;
pt->depth[level] = d;
tex->level_offset[level] = (x + y * tex->pitch) * pt->cpp;
tex->nr_images[level] = 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);
level, w, h, d, x, y, tex->level_offset[level]);
*/
/* 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;
if (tex->image_offset[level]) {
FREE(tex->image_offset[level]);
tex->image_offset[level] = NULL;
}
assert(nr_images);
assert(!mt->level[level].image_offset);
assert(!tex->image_offset[level]);
mt->level[level].image_offset = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
mt->level[level].image_offset[0] = 0;
tex->image_offset[level] = (unsigned *) MALLOC(nr_images * sizeof(unsigned));
tex->image_offset[level][0] = 0;
}
static void
i915_miptree_set_image_offset(struct pipe_mipmap_tree *mt,
unsigned level, unsigned img, unsigned x, unsigned y)
i915_miptree_set_image_offset(struct i915_texture *tex,
unsigned level, unsigned img, unsigned x, unsigned y)
{
if (img == 0 && level == 0)
assert(x == 0 && y == 0);
assert(img < mt->level[level].nr_images);
assert(img < tex->nr_images[level]);
mt->level[level].image_offset[img] = (x + y * mt->pitch);
tex->image_offset[level][img] = (x + y * tex->pitch);
/*
DBG("%s level %d img %d pos %d,%d image_offset %x\n",
__FUNCTION__, level, img, x, y, mt->level[level].image_offset[img]);
__FUNCTION__, level, img, x, y, tex->image_offset[level][img]);
*/
}
static void
i945_miptree_layout_2d( struct pipe_mipmap_tree *mt )
i945_miptree_layout_2d( struct i915_texture *tex )
{
struct pipe_texture *pt = &tex->base;
int align_h = 2, align_w = 4;
unsigned level;
unsigned x = 0;
unsigned y = 0;
unsigned width = mt->width0;
unsigned height = mt->height0;
unsigned width = pt->width[0];
unsigned height = pt->height[0];
mt->pitch = mt->width0;
tex->pitch = pt->width[0];
/* May need to adjust pitch to accomodate the placement of
* the 2nd mipmap. This occurs when the alignment
* constraints of mipmap placement push the right edge of the
* 2nd mipmap out past the width of its parent.
*/
if (mt->first_level != mt->last_level) {
unsigned mip1_width = align(minify(mt->width0), align_w)
+ minify(minify(mt->width0));
if (pt->first_level != pt->last_level) {
unsigned mip1_width = align(minify(pt->width[0]), align_w)
+ minify(minify(pt->width[0]));
if (mip1_width > mt->width0)
mt->pitch = mip1_width;
if (mip1_width > pt->width[0])
tex->pitch = mip1_width;
}
/* Pitch must be a whole number of dwords, even though we
* express it in texels.
*/
mt->pitch = align(mt->pitch * mt->cpp, 4) / mt->cpp;
mt->total_height = 0;
tex->pitch = align(tex->pitch * pt->cpp, 4) / pt->cpp;
tex->total_height = 0;
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {
for ( level = pt->first_level ; level <= pt->last_level ; level++ ) {
unsigned img_height;
i915_miptree_set_level_info(mt, level, 1, x, y, width, height, 1);
i915_miptree_set_level_info(tex, level, 1, x, y, width, height, 1);
if (mt->compressed)
if (pt->compressed)
img_height = MAX2(1, height/4);
else
img_height = align(height, align_h);
......@@ -147,11 +153,11 @@ i945_miptree_layout_2d( struct pipe_mipmap_tree *mt )
/* Because the images are packed better, the final offset
* might not be the maximal one:
*/
mt->total_height = MAX2(mt->total_height, y + img_height);
tex->total_height = MAX2(tex->total_height, y + img_height);
/* Layout_below: step right after second mipmap.
*/
if (level == mt->first_level + 1) {
if (level == pt->first_level + 1) {
x += align(width, align_w);
}
else {
......@@ -183,27 +189,28 @@ static const int step_offsets[6][2] = {
};
boolean
i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
static boolean
i915_miptree_layout(struct pipe_context *pipe, struct i915_texture * tex)
{
struct pipe_texture *pt = &tex->base;
unsigned level;
switch (mt->target) {
switch (pt->target) {
case PIPE_TEXTURE_CUBE: {
const unsigned dim = mt->width0;
const unsigned dim = pt->width[0];
unsigned face;
unsigned lvlWidth = mt->width0, lvlHeight = mt->height0;
unsigned lvlWidth = pt->width[0], lvlHeight = pt->height[0];
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;
tex->pitch = ((dim * pt->cpp * 2 + 3) & ~3) / pt->cpp;
tex->total_height = dim * 4;
for (level = mt->first_level; level <= mt->last_level; level++) {
i915_miptree_set_level_info(mt, level, 6,
for (level = pt->first_level; level <= pt->last_level; level++) {
i915_miptree_set_level_info(tex, level, 6,
0, 0,
/*OLD: mt->pitch, mt->total_height,*/
/*OLD: tex->pitch, tex->total_height,*/
lvlWidth, lvlHeight,
1);
lvlWidth /= 2;
......@@ -215,8 +222,8 @@ i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
unsigned y = initial_offsets[face][1] * dim;
unsigned d = dim;
for (level = mt->first_level; level <= mt->last_level; level++) {
i915_miptree_set_image_offset(mt, level, face, x, y);
for (level = pt->first_level; level <= pt->last_level; level++) {
i915_miptree_set_image_offset(tex, level, face, x, y);
d >>= 1;
x += step_offsets[face][0] * d;
y += step_offsets[face][1] * d;
......@@ -225,20 +232,20 @@ i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
break;
}
case PIPE_TEXTURE_3D:{
unsigned width = mt->width0;
unsigned height = mt->height0;
unsigned depth = mt->depth0;
unsigned width = pt->width[0];
unsigned height = pt->height[0];
unsigned depth = pt->depth[0];
unsigned stack_height = 0;
/* Calculate the size of a single slice.
*/
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
/* XXX: hardware expects/requires 9 levels at minimum.
*/
for (level = mt->first_level; level <= MAX2(8, mt->last_level);
for (level = pt->first_level; level <= MAX2(8, pt->last_level);
level++) {
i915_miptree_set_level_info(mt, level, depth, 0, mt->total_height,
i915_miptree_set_level_info(tex, level, depth, 0, tex->total_height,
width, height, depth);
......@@ -251,11 +258,11 @@ i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
/* Fixup depth image_offsets:
*/
depth = mt->depth0;
for (level = mt->first_level; level <= mt->last_level; level++) {
depth = pt->depth[0];
for (level = pt->first_level; level <= pt->last_level; level++) {
unsigned i;
for (i = 0; i < depth; i++)
i915_miptree_set_image_offset(mt, level, i,
i915_miptree_set_image_offset(tex, level, i,
0, i * stack_height);
depth = minify(depth);
......@@ -266,29 +273,29 @@ i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
* remarkable how wasteful of memory the i915 texture layouts
* are. They are largely fixed in the i945.
*/
mt->total_height = stack_height * mt->depth0;
tex->total_height = stack_height * pt->depth[0];
break;
}
default:{
unsigned width = mt->width0;
unsigned height = mt->height0;
unsigned width = pt->width[0];
unsigned height = pt->height[0];
unsigned img_height;
mt->pitch = ((mt->width0 * mt->cpp + 3) & ~3) / mt->cpp;
mt->total_height = 0;
tex->pitch = ((pt->width[0] * pt->cpp + 3) & ~3) / pt->cpp;
tex->total_height = 0;
for (level = mt->first_level; level <= mt->last_level; level++) {
i915_miptree_set_level_info(mt, level, 1,
0, mt->total_height,
for (level = pt->first_level; level <= pt->last_level; level++) {
i915_miptree_set_level_info(tex, level, 1,
0, tex->total_height,
width, height, 1);
if (mt->compressed)
if (pt->compressed)
img_height = MAX2(1, height / 4);
else
img_height = (MAX2(2, height) + 1) & ~1;
mt->total_height += img_height;
tex->total_height += img_height;
width = minify(width);
height = minify(height);
......@@ -298,24 +305,25 @@ i915_miptree_layout(struct pipe_context *pipe, struct pipe_mipmap_tree * mt)
}
/*