diff options
21 files changed, 1516 insertions, 1824 deletions
diff --git a/src/mesa/drivers/dri/i915/Makefile b/src/mesa/drivers/dri/i915/Makefile index 846acd32f7..fecb41e3d8 100644 --- a/src/mesa/drivers/dri/i915/Makefile +++ b/src/mesa/drivers/dri/i915/Makefile @@ -6,23 +6,24 @@ LIBNAME = i915_dri.so DRIVER_SOURCES = \ bufmgr_fake.c \ + intel_regions.c \ + intel_mipmap_tree.c \ + i915_tex_layout.c \ + intel_tex_image.c \ + intel_tex_subimage.c \ + intel_tex_validate.c \ + intel_tex_format.c \ + intel_tex.c \ + i915_tex.c \ + i915_texstate.c \ i915_context.c \ i915_debug.c \ i915_fragprog.c \ i915_metaops.c \ i915_program.c \ i915_state.c \ - i915_tex.c \ i915_texprog.c \ - i915_texstate.c \ i915_vtbl.c \ - i830_context.c \ - i830_metaops.c \ - i830_state.c \ - i830_texblend.c \ - i830_tex.c \ - i830_texstate.c \ - i830_vtbl.c \ intel_batchbuffer.c \ intel_context.c \ intel_ioctl.c \ @@ -31,9 +32,18 @@ DRIVER_SOURCES = \ intel_screen.c \ intel_span.c \ intel_state.c \ - intel_tex.c \ intel_tris.c + +DISABLED = \ + i830_context.c \ + i830_metaops.c \ + i830_state.c \ + i830_texblend.c \ + i830_tex.c \ + i830_texstate.c \ + i830_vtbl.c + C_SOURCES = \ $(COMMON_SOURCES) \ $(MINIGLX_SOURCES) \ diff --git a/src/mesa/drivers/dri/i915/i830_tex.c b/src/mesa/drivers/dri/i915/i830_tex.c index d56a4df8bb..56b2b92bde 100644 --- a/src/mesa/drivers/dri/i915/i830_tex.c +++ b/src/mesa/drivers/dri/i915/i830_tex.c @@ -200,7 +200,7 @@ intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj ) texObj->DriverData = t; t->intel.base.tObj = texObj; - t->intel.dirty = I830_UPLOAD_TEX_ALL; + t->intel.dirty = ~0; make_empty_list( &t->intel.base ); t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */ @@ -268,7 +268,7 @@ static void i830TexParameter( GLcontext *ctx, GLenum target, return; } - t->intel.dirty = I830_UPLOAD_TEX_ALL; + t->intel.dirty = ~0; } diff --git a/src/mesa/drivers/dri/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c index ba972dac8f..85da0ee281 100644 --- a/src/mesa/drivers/dri/i915/i830_texstate.c +++ b/src/mesa/drivers/dri/i915/i830_texstate.c @@ -246,7 +246,7 @@ static GLboolean i830SetTexImages( i830ContextPtr i830, t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK; t->Setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK; t->Setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT; - t->intel.dirty = I830_UPLOAD_TEX_ALL; + t->intel.dirty = ~0; return intelUploadTexImages( &i830->intel, &t->intel, 0 ); } @@ -259,11 +259,7 @@ static void i830_import_tex_unit( i830ContextPtr i830, if(INTEL_DEBUG&DEBUG_TEXTURE) fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); - if (i830->intel.CurrentTexObj[unit]) - i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); - i830->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; - t->intel.base.bound |= (1 << unit); I830_STATECHANGE( i830, I830_UPLOAD_TEX(unit) ); @@ -285,7 +281,7 @@ static void i830_import_tex_unit( i830ContextPtr i830, i830->state.Tex[unit][I830_TEXREG_CUBE] = t->Setup[I830_TEXREG_CUBE]; i830->state.Tex[unit][I830_TEXREG_MCS] |= MAP_UNIT(unit); - t->intel.dirty &= ~I830_UPLOAD_TEX(unit); + t->intel.dirty &= ~(1<<unit); /* This is broken! */ } @@ -317,7 +313,7 @@ static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) * time. */ if (i830->intel.CurrentTexObj[unit] != &t->intel || - (t->intel.dirty & I830_UPLOAD_TEX(unit))) { + (t->intel.dirty & (1<<unit))) { i830_import_tex_unit( i830, t, unit); } @@ -419,14 +415,10 @@ static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) * one if nothing is enabled. */ - if ( i830->intel.CurrentTexObj[unit] != NULL ) { - /* The old texture is no longer bound to this texture unit. - * Mark it as such. - */ - - i830->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); - i830->intel.CurrentTexObj[unit] = NULL; - } + /* The old texture is no longer bound to this texture unit. + * Mark it as such. + */ + i830->intel.CurrentTexObj[unit] = NULL; return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i915/i915_context.c b/src/mesa/drivers/dri/i915/i915_context.c index cd0eaf2470..817a7bb5f1 100644 --- a/src/mesa/drivers/dri/i915/i915_context.c +++ b/src/mesa/drivers/dri/i915/i915_context.c @@ -41,6 +41,8 @@ #include "utils.h" #include "i915_reg.h" +#include "bufmgr.h" + /*************************************** * Mesa's Driver Functions ***************************************/ @@ -119,33 +121,22 @@ GLboolean i915CreateContext( const __GLcontextModes *mesaVis, ctx->Const.MaxTextureImageUnits = I915_TEX_UNITS; ctx->Const.MaxTextureCoordUnits = I915_TEX_UNITS; - intel->nr_heaps = 1; - intel->texture_heaps[0] = - driCreateTextureHeap( 0, intel, - intel->intelScreen->tex.size, - 12, - I830_NR_TEX_REGIONS, - intel->sarea->texList, - & intel->sarea->texAge, - & intel->swapped, - sizeof( struct i915_texture_object ), - (destroy_texture_object_t *)intelDestroyTexObj ); - - /* FIXME: driCalculateMaxTextureLevels assumes that mipmaps are - * tightly packed, but they're not in Intel graphics - * hardware. + intel->bm = bm_fake_intel_Attach( intel ); + + bmInitPool(intel->bm, + 0, + 0, /* low offset */ + intel->intelScreen->tex.size, /* high offset */ + intel->intelScreen->tex.map); /* virtual base */ + + /* AGP allocation won't work: */ - ctx->Const.MaxTextureUnits = 1; - driCalculateMaxTextureLevels( intel->texture_heaps, - intel->nr_heaps, - &intel->ctx.Const, - 4, - 11, /* max 2D texture size is 2048x2048 */ - 8, /* 3D texture */ - 11, /* cube texture. */ - 11, /* rect texture */ - 12, - GL_FALSE ); + intel->intelScreen->allow_batchbuffer = GL_FALSE; + + ctx->Const.MaxTextureLevels = 11; + ctx->Const.Max3DTextureLevels = 8; + ctx->Const.MaxCubeTextureLevels = 11; + ctx->Const.MaxTextureRectSize = (1<<11); ctx->Const.MaxTextureUnits = I915_TEX_UNITS; /* GL_ARB_fragment_program limits - don't think Mesa actually diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h index 8046277643..fa63d794f9 100644 --- a/src/mesa/drivers/dri/i915/i915_context.h +++ b/src/mesa/drivers/dri/i915/i915_context.h @@ -163,8 +163,6 @@ struct i915_fragment_program { GLuint nr_params; - - /* Helpers for i915_texprog.c: */ GLuint src_texture; /* Reg containing sampled texture color, @@ -185,13 +183,6 @@ struct i915_fragment_program { -struct i915_texture_object -{ - struct intel_texture_object intel; - GLenum lastTarget; - GLboolean refs_border_color; - GLuint Setup[I915_TEX_SETUP_SIZE]; -}; #define I915_TEX_UNITS 8 @@ -220,6 +211,8 @@ struct i915_context GLuint last_ReallyEnabled; GLuint vertex_fog; + GLuint lodbias_ss2[MAX_TEXTURE_UNITS]; + struct i915_fragment_program tex_program; struct i915_fragment_program *current_program; @@ -229,10 +222,6 @@ struct i915_context typedef struct i915_context *i915ContextPtr; -typedef struct i915_texture_object *i915TextureObjectPtr; - -#define I915_CONTEXT(ctx) ((i915ContextPtr)(ctx)) - #define I915_STATECHANGE(i915, flag) \ @@ -346,6 +335,22 @@ i915ClearWithTris( intelContextPtr intel, GLbitfield mask, */ extern void i915ValidateFragmentProgram( i915ContextPtr i915 ); extern void i915InitFragProgFuncs( struct dd_function_table *functions ); + +/*====================================================================== + * Inline conversion functions. These are better-typed than the + * macros used previously: + */ +static inline struct i915_context * +i915_context( GLcontext *ctx ) +{ + return (struct i915_context *)ctx; +} + + + +#define I915_CONTEXT(ctx) i915_context(ctx) + + #endif diff --git a/src/mesa/drivers/dri/i915/i915_metaops.c b/src/mesa/drivers/dri/i915/i915_metaops.c index a3d22b7bd0..066c6b5ecd 100644 --- a/src/mesa/drivers/dri/i915/i915_metaops.c +++ b/src/mesa/drivers/dri/i915/i915_metaops.c @@ -447,7 +447,7 @@ i915ClearWithTris(intelContextPtr intel, GLbitfield mask, GLboolean all, GLint cx, GLint cy, GLint cw, GLint ch) { - i915ContextPtr i915 = I915_CONTEXT( intel ); + i915ContextPtr i915 = i915_context( &intel->ctx ); __DRIdrawablePrivate *dPriv = intel->driDrawable; intelScreenPrivate *screen = intel->intelScreen; int x0, y0, x1, y1; diff --git a/src/mesa/drivers/dri/i915/i915_tex.c b/src/mesa/drivers/dri/i915/i915_tex.c index 4f77833e19..92bc94b8ee 100644 --- a/src/mesa/drivers/dri/i915/i915_tex.c +++ b/src/mesa/drivers/dri/i915/i915_tex.c @@ -45,76 +45,10 @@ - - - -/** - * Allocate space for and load the mesa images into the texture memory block. - * This will happen before drawing with a new texture, or drawing with a - * texture after it was swapped out or teximaged again. - */ - -intelTextureObjectPtr i915AllocTexObj( struct gl_texture_object *texObj ) -{ - i915TextureObjectPtr t = CALLOC_STRUCT( i915_texture_object ); - if ( !t ) - return NULL; - - texObj->DriverData = t; - t->intel.base.tObj = texObj; - t->intel.dirty = I915_UPLOAD_TEX_ALL; - make_empty_list( &t->intel.base ); - return &t->intel; -} - - -static void i915TexParameter( GLcontext *ctx, GLenum target, - struct gl_texture_object *tObj, - GLenum pname, const GLfloat *params ) -{ - i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; - - switch (pname) { - case GL_TEXTURE_MIN_FILTER: - case GL_TEXTURE_MAG_FILTER: - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - case GL_TEXTURE_WRAP_S: - case GL_TEXTURE_WRAP_T: - case GL_TEXTURE_WRAP_R: - case GL_TEXTURE_BORDER_COLOR: - t->intel.dirty = I915_UPLOAD_TEX_ALL; - break; - - case GL_TEXTURE_COMPARE_MODE: - t->intel.dirty = I915_UPLOAD_TEX_ALL; - break; - case GL_TEXTURE_COMPARE_FUNC: - t->intel.dirty = I915_UPLOAD_TEX_ALL; - break; - - case GL_TEXTURE_BASE_LEVEL: - case GL_TEXTURE_MAX_LEVEL: - case GL_TEXTURE_MIN_LOD: - case GL_TEXTURE_MAX_LOD: - /* The i915 and its successors can do a lot of this without - * reloading the textures. A project for someone? - */ - intelFlush( ctx ); - driSwapOutTextureObject( (driTextureObject *) t ); - t->intel.dirty = I915_UPLOAD_TEX_ALL; - break; - - default: - return; - } -} - - static void i915TexEnv( GLcontext *ctx, GLenum target, GLenum pname, const GLfloat *param ) { i915ContextPtr i915 = I915_CONTEXT( ctx ); - GLuint unit = ctx->Texture.CurrentUnit; switch (pname) { case GL_TEXTURE_ENV_COLOR: /* Should be a tracked param */ @@ -139,13 +73,12 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, break; case GL_TEXTURE_LOD_BIAS: { - int b = (int) ((*param) * 16.0); + GLuint unit = ctx->Texture.CurrentUnit; + GLint b = (int) ((*param) * 16.0); if (b > 255) b = 255; if (b < -256) b = -256; I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - i915->state.Tex[unit][I915_TEXREG_SS2] &= ~SS2_LOD_BIAS_MASK; - i915->state.Tex[unit][I915_TEXREG_SS2] |= - ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); + i915->lodbias_ss2[unit] = ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); break; } @@ -156,15 +89,8 @@ static void i915TexEnv( GLcontext *ctx, GLenum target, static void i915BindTexture( GLcontext *ctx, GLenum target, - struct gl_texture_object *texObj ) + struct gl_texture_object *texobj ) { - i915TextureObjectPtr tex = (i915TextureObjectPtr)texObj->DriverData; - - if (tex->lastTarget != texObj->Target) { - tex->intel.dirty = I915_UPLOAD_TEX_ALL; - tex->lastTarget = texObj->Target; - } - /* Need this if image format changes between bound textures. * Could try and shortcircuit by checking for differences in * state between incoming and outgoing textures: @@ -178,5 +104,4 @@ void i915InitTextureFuncs( struct dd_function_table *functions ) { functions->BindTexture = i915BindTexture; functions->TexEnv = i915TexEnv; - functions->TexParameter = i915TexParameter; } diff --git a/src/mesa/drivers/dri/i915/i915_tex_layout.c b/src/mesa/drivers/dri/i915/i915_tex_layout.c new file mode 100644 index 0000000000..d79a64ea67 --- /dev/null +++ b/src/mesa/drivers/dri/i915/i915_tex_layout.c @@ -0,0 +1,330 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* Code to layout images in a mipmap tree for i915 and i945 + * respectively. + */ + +#include "intel_mipmap_tree.h" +#include "macros.h" + +static GLint initial_offsets[6][2] = { {0,0}, + {0,2}, + {1,0}, + {1,2}, + {1,1}, + {1,3} }; + + +static GLint step_offsets[6][2] = { {0,2}, + {0,2}, + {-1,2}, + {-1,2}, + {-1,1}, + {-1,1} }; + +static GLuint minify( GLuint d ) +{ + return MAX2(1, d>>1); +} + +GLboolean i915_miptree_layout( struct intel_mipmap_tree *mt ) +{ + GLint i; + GLint numLevels = mt->last_level - mt->first_level + 1; + + switch (mt->target) { + case GL_TEXTURE_CUBE_MAP: { + const GLuint dim = mt->width0; + GLuint face; + + /* double pitch for cube layouts */ + mt->pitch = (dim * mt->cpp * 2 + 3) & ~3; + mt->total_height = dim * 4; + + for ( face = 0 ; face < 6 ; face++) { + GLuint x = initial_offsets[face][0] * dim; + GLuint y = initial_offsets[face][1] * dim; + GLuint d = dim; + + for (i = 0; i < numLevels; i++) { + mt->offset[face][i].x = x; + mt->offset[face][i].y = y; + mt->offset[face][i].width = d; + mt->offset[face][i].height = d; + mt->offset[face][i].depth = 0; + + d >>= 1; + assert(d > 0); + + 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 tmp_numLevels = MAX2(numLevels, 9); + + /* Calculate the size of a single slice. Hardware demands a + * minimum of 8 mipmaps, some of which might ultimately not be + * used: + */ + mt->pitch = (mt->width0 * mt->cpp + 3) & ~3; + mt->total_height = 0; + + for ( i = 0 ; i < tmp_numLevels ; i++ ) { + mt->offset[0][i].x = 0; + mt->offset[0][i].y = mt->total_height; + mt->offset[0][i].width = width; + mt->offset[0][i].height = height; + mt->offset[0][i].depth = depth; + + mt->total_height += MAX2(2, height); + + width = minify(width); + height = minify(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->depth_pitch = mt->total_height * mt->pitch; + mt->total_height *= mt->depth0; + break; + } + + default: { + GLuint width = mt->width0; + GLuint height = mt->height0; + + mt->pitch = (mt->width0 * mt->cpp + 3) & ~3; + mt->total_height = 0; + + for ( i = 0 ; i < numLevels ; i++ ) { + mt->offset[0][i].x = 0; + mt->offset[0][i].y = mt->total_height; + mt->offset[0][i].height = height; + mt->offset[0][i].width = width; + mt->offset[0][i].depth = 0; + + + if (mt->compressed) + mt->total_height += MAX2(1, height/4); + else + mt->total_height += MAX2(2, height); + + width = minify(width); + height = minify(height); + } + break; + } + } + + return GL_TRUE; +} + + +GLboolean i945_miptree_layout( struct intel_mipmap_tree *mt ) +{ + GLint numLevels = mt->last_level - mt->first_level + 1; + GLint i; + + switch (mt->target) { + case GL_TEXTURE_CUBE_MAP: { + const GLuint dim = mt->width0; + GLuint face; + + /* 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; + else + mt->pitch = 14 * 8 * mt->cpp; + + mt->total_height = dim * 4 + 4; + + + 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) { + y = mt->total_height - 4; + x = face * 8; + } + + for (i = 0; i < numLevels; i++) { + mt->offset[face][i].x = x; + mt->offset[face][i].y = y; + mt->offset[face][i].width = d; + mt->offset[face][i].height = d; + mt->offset[face][i].depth = 0; + + d >>= 1; + assert(d > 0); + + 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 depth_pack_pitch; + GLuint depth_packing = 0; + + mt->pitch = (mt->width0 * mt->cpp + 3) & ~3; + mt->total_height = 0; + + depth_pack_pitch = mt->pitch; + + for ( i = 0 ; i < numLevels ; i++ ) { + + mt->offset[0][i].x = 0; + mt->offset[0][i].y = mt->total_height; + mt->offset[0][i].width = width; + mt->offset[0][i].height = height; + mt->offset[0][i].depth = depth; + + mt->total_height += MAX2(2, height) * MAX2((depth >> depth_packing), 1); + + /* When alignment dominates, can't increase depth packing? + * Or does pitch grow??? What are the alignment constraints, + * anyway? + */ + if (depth_pack_pitch > 4) { + depth_packing++; + depth_pack_pitch <<= 2; /* KW: is this right?? */ + } + + width = minify(width); + height = minify(height); + depth = minify(depth); + + /* XXX: Not sure how 3d textures work on i945 - where did + * t->depth_pitch get set in the old code. Did it ever work? + * Fix up later. + */ + } + break; + } + + default: { + GLuint x = 0; + GLuint y = 0; + GLuint width = mt->width0; + GLuint height = mt->height0; + + mt->pitch = (mt->width0 * mt->cpp + 3) & ~3; + mt->total_height = 0; + + for ( i = 0 ; i < numLevels ; i++ ) { + mt->offset[0][i].x = x; + mt->offset[0][i].y = y; + mt->offset[0][i].height = height; + mt->offset[0][i].width = width; + mt->offset[0][i].depth = 0; + + + /* LPT change: step right after second mipmap. + */ + if (i == 1) + x += mt->pitch / (2 * mt->cpp); + else { + GLuint img_height; + + if (mt->compressed) + img_height = MAX2(1, height/4); + else + img_height = MAX2(2, height); + + y += img_height; + } + + /* Because the images are packed better, the final offset + * might not be the maximal one: + */ + mt->total_height = MAX2(mt->total_height, y); + + width = minify(width); + height = minify(height); + } + break; + } + } + return GL_TRUE; +} + diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index efd6fc9450..410890f6da 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -25,500 +25,61 @@ * **************************************************************************/ -#include "glheader.h" -#include "macros.h" #include "mtypes.h" -#include "simple_list.h" #include "enums.h" #include "texformat.h" -#include "texstore.h" -#include "mm.h" - -#include "intel_screen.h" -#include "intel_ioctl.h" +#include "intel_mipmap_tree.h" #include "intel_tex.h" #include "i915_context.h" #include "i915_reg.h" -static GLint initial_offsets[6][2] = { {0,0}, - {0,2}, - {1,0}, - {1,2}, - {1,1}, - {1,3} }; - - -static GLint step_offsets[6][2] = { {0,2}, - {0,2}, - {-1,2}, - {-1,2}, - {-1,1}, - {-1,1} }; - - -#define I915_TEX_UNIT_ENABLED(unit) (1<<unit) - -static void i915LayoutTextureImages( i915ContextPtr i915, - struct gl_texture_object *tObj ) -{ - const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; - i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; - GLint firstLevel, lastLevel, numLevels; - GLint i, total_height, pitch; - - /* Compute which mipmap levels we really want to send to the hardware. - */ - driCalculateTextureFirstLastLevel( (driTextureObject *) t ); - - /* Figure out the amount of memory required to hold all the mipmap - * levels. Choose the smallest pitch to accomodate the largest - * mipmap: - */ - firstLevel = t->intel.base.firstLevel; - lastLevel = t->intel.base.lastLevel; - numLevels = lastLevel - firstLevel + 1; - - - - /* All images must be loaded at this pitch. Count the number of - * lines required: - */ - switch (tObj->Target) { - case GL_TEXTURE_CUBE_MAP: { - const GLuint dim = tObj->Image[0][firstLevel]->Width; - GLuint face; - - pitch = dim * t->intel.texelBytes; - pitch *= 2; /* double pitch for cube layouts */ - pitch = (pitch + 3) & ~3; - - total_height = dim * 4; - - for ( face = 0 ; face < 6 ; face++) { - GLuint x = initial_offsets[face][0] * dim; - GLuint y = initial_offsets[face][1] * dim; - GLuint d = dim; - - t->intel.base.dirty_images[face] = ~0; - - assert(tObj->Image[face][firstLevel]->Width == dim); - assert(tObj->Image[face][firstLevel]->Height == dim); - - for (i = 0; i < numLevels; i++) { - t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; - if (!t->intel.image[face][i].image) { - fprintf(stderr, "no image %d %d\n", face, i); - break; /* can't happen */ - } - - t->intel.image[face][i].offset = - y * pitch + x * t->intel.texelBytes; - t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; - - d >>= 1; - x += step_offsets[face][0] * d; - y += step_offsets[face][1] * d; - } - } - break; - } - case GL_TEXTURE_3D: { - GLuint virtual_height; - GLuint tmp_numLevels = numLevels; - pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; - pitch = (pitch + 3) & ~3; - t->intel.base.dirty_images[0] = ~0; - - /* Calculate the size of a single slice. Hardware demands a - * minimum of 8 mipmaps, some of which might ultimately not be - * used: - */ - if (tmp_numLevels < 9) - tmp_numLevels = 9; - - virtual_height = tObj->Image[0][firstLevel]->Height; - - for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { - t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; - if (t->intel.image[0][i].image) { - t->intel.image[0][i].offset = total_height * pitch; - t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; - } - - total_height += MAX2(2, virtual_height); - virtual_height >>= 1; - } - - t->intel.depth_pitch = total_height * pitch; - - /* Multiply slice size by texture depth for total size. It's - * remarkable how wasteful of memory all the i8x0 texture - * layouts are. - */ - total_height *= t->intel.image[0][0].image->Depth; - break; - } - default: - pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; - pitch = (pitch + 3) & ~3; - t->intel.base.dirty_images[0] = ~0; - - for ( total_height = i = 0 ; i < numLevels ; i++ ) { - t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; - if (!t->intel.image[0][i].image) - break; - - t->intel.image[0][i].offset = total_height * pitch; - t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; - if (t->intel.image[0][i].image->IsCompressed) - { - if (t->intel.image[0][i].image->Height > 4) - total_height += t->intel.image[0][i].image->Height/4; - else - total_height += 1; - } - else - total_height += MAX2(2, t->intel.image[0][i].image->Height); - } - break; - } - - t->intel.Pitch = pitch; - t->intel.base.totalSize = total_height*pitch; - t->intel.max_level = numLevels-1; -} - -static void i945LayoutTextureImages( i915ContextPtr i915, - struct gl_texture_object *tObj ) +static GLuint translate_texture_format( GLuint mesa_format ) { - const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; - i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; - GLint firstLevel, lastLevel, numLevels; - GLint i, total_height, pitch, sz, max_offset = 0, offset; - - - /* Compute which mipmap levels we really want to send to the hardware. - */ - driCalculateTextureFirstLastLevel( (driTextureObject *) t ); - - /* Figure out the amount of memory required to hold all the mipmap - * levels. Choose the smallest pitch to accomodate the largest - * mipmap: - */ - firstLevel = t->intel.base.firstLevel; - lastLevel = t->intel.base.lastLevel; - numLevels = lastLevel - firstLevel + 1; - - - - /* All images must be loaded at this pitch. Count the number of - * lines required: - */ - switch (tObj->Target) { - case GL_TEXTURE_CUBE_MAP: { - const GLuint dim = tObj->Image[0][firstLevel]->Width; - GLuint face; - - /* 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) { - pitch = dim * t->intel.texelBytes; - pitch *= 2; /* double pitch for cube layouts */ - pitch = (pitch + 3) & ~3; - } - else { - pitch = 14 * 8 * t->intel.texelBytes; /* determined by row of - * little maps at - * bottom */ - } - - total_height = dim * 4 + 4; - - 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 = total_height - 4; - x = (face - 4) * 8; - } - else if (dim < 4) { - y = total_height - 4; - x = face * 8; - } - - t->intel.base.dirty_images[face] = ~0; - - assert(tObj->Image[face][firstLevel]->Width == dim); - assert(tObj->Image[face][firstLevel]->Height == dim); - - for (i = 0; i < numLevels; i++) { - - - t->intel.image[face][i].image = tObj->Image[face][firstLevel + i]; - assert(t->intel.image[face][i].image); - - t->intel.image[face][i].offset = - y * pitch + x * t->intel.texelBytes; - t->intel.image[face][i].internalFormat = baseImage->_BaseFormat; - - 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 = total_height - 4; - x = (face - 4) * 8; - break; - } - - case 2: - y = 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; - } - } - } - max_offset = total_height * pitch; - break; - } - case GL_TEXTURE_3D: { - GLuint depth_packing = 0, depth_pack_pitch; - GLuint tmp_numLevels = numLevels; - pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; - pitch = (pitch + 3) & ~3; - depth_pack_pitch = pitch; - - t->intel.base.dirty_images[0] = ~0; - - - for ( total_height = i = 0 ; i < tmp_numLevels ; i++ ) { - t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; - if (!t->intel.image[0][i].image) - break; - - - t->intel.image[0][i].offset = total_height * pitch; - t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; - - - - total_height += MAX2(2, t->intel.image[0][i].image->Height) * - MAX2((t->intel.image[0][i].image->Depth >> depth_packing), 1); - - /* When alignment dominates, can't increase depth packing? - * Or does pitch grow??? What are the alignment constraints, - * anyway? - */ - if (depth_pack_pitch > 4) { - depth_packing++; - depth_pack_pitch <<= 2; - } - } - - max_offset = total_height * pitch; - break; - } - default: - pitch = tObj->Image[0][firstLevel]->Width * t->intel.texelBytes; - pitch = (pitch + 3) & ~3; - t->intel.base.dirty_images[0] = ~0; - max_offset = 0; - - for ( offset = i = 0 ; i < numLevels ; i++ ) { - t->intel.image[0][i].image = tObj->Image[0][firstLevel + i]; - if (!t->intel.image[0][i].image) - break; - - t->intel.image[0][i].offset = offset; - t->intel.image[0][i].internalFormat = baseImage->_BaseFormat; - - if (t->intel.image[0][i].image->IsCompressed) - sz = MAX2(1, t->intel.image[0][i].image->Height/4) * pitch; - else - sz = MAX2(2, t->intel.image[0][i].image->Height) * pitch; - - /* Because the images are packed better, the final offset - * might not be the maximal one: - */ - max_offset = MAX2(max_offset, offset + sz); - - /* LPT change: step right after second mipmap. - */ - if (i == 1) - offset += pitch / 2; - else - offset += sz; - - } - break; - } - - t->intel.Pitch = pitch; - t->intel.base.totalSize = max_offset; - t->intel.max_level = numLevels-1; -} - - - - -static void i915SetTexImages( i915ContextPtr i915, - struct gl_texture_object *tObj ) -{ - GLuint textureFormat; - i915TextureObjectPtr t = (i915TextureObjectPtr) tObj->DriverData; - const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; - GLint ss2 = 0; - - switch( baseImage->TexFormat->MesaFormat ) { + switch (mesa_format) { case MESA_FORMAT_L8: - t->intel.texelBytes = 1; - textureFormat = MAPSURF_8BIT | MT_8BIT_L8; - break; - + return MAPSURF_8BIT | MT_8BIT_L8; case MESA_FORMAT_I8: - t->intel.texelBytes = 1; - textureFormat = MAPSURF_8BIT | MT_8BIT_I8; - break; - + return MAPSURF_8BIT | MT_8BIT_I8; case MESA_FORMAT_A8: - t->intel.texelBytes = 1; - textureFormat = MAPSURF_8BIT | MT_8BIT_A8; - break; - + return MAPSURF_8BIT | MT_8BIT_A8; case MESA_FORMAT_AL88: - t->intel.texelBytes = 2; - textureFormat = MAPSURF_16BIT | MT_16BIT_AY88; - break; - + return MAPSURF_16BIT | MT_16BIT_AY88; case MESA_FORMAT_RGB565: - t->intel.texelBytes = 2; - textureFormat = MAPSURF_16BIT | MT_16BIT_RGB565; - break; - + return MAPSURF_16BIT | MT_16BIT_RGB565; case MESA_FORMAT_ARGB1555: - t->intel.texelBytes = 2; - textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB1555; - break; - + return MAPSURF_16BIT | MT_16BIT_ARGB1555; case MESA_FORMAT_ARGB4444: - t->intel.texelBytes = 2; - textureFormat = MAPSURF_16BIT | MT_16BIT_ARGB4444; - break; - + return MAPSURF_16BIT | MT_16BIT_ARGB4444; case MESA_FORMAT_ARGB8888: - t->intel.texelBytes = 4; - textureFormat = MAPSURF_32BIT | MT_32BIT_ARGB8888; - break; - + return MAPSURF_32BIT | MT_32BIT_ARGB8888; case MESA_FORMAT_YCBCR_REV: - t->intel.texelBytes = 2; - textureFormat = (MAPSURF_422 | MT_422_YCRCB_NORMAL); - ss2 |= SS2_COLORSPACE_CONVERSION; - break; - + return (MAPSURF_422 | MT_422_YCRCB_NORMAL); case MESA_FORMAT_YCBCR: - t->intel.texelBytes = 2; - textureFormat = (MAPSURF_422 | MT_422_YCRCB_SWAPY); - ss2 |= SS2_COLORSPACE_CONVERSION; - break; - + return (MAPSURF_422 | MT_422_YCRCB_SWAPY); case MESA_FORMAT_RGB_FXT1: case MESA_FORMAT_RGBA_FXT1: - t->intel.texelBytes = 2; - textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); - break; - + return (MAPSURF_COMPRESSED | MT_COMPRESS_FXT1); case MESA_FORMAT_DEPTH_COMPONENT16: - t->intel.texelBytes = 2; - textureFormat = (MAPSURF_16BIT | MT_16BIT_L16); - break; - + return (MAPSURF_16BIT | MT_16BIT_L16); case MESA_FORMAT_RGBA_DXT1: case MESA_FORMAT_RGB_DXT1: - /* - * DXTn pitches are Width/4 * blocksize in bytes - * for DXT1: blocksize=8 so Width/4*8 = Width * 2 - * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4 - */ - t->intel.texelBytes = 2; - textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); - break; - + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT1); case MESA_FORMAT_RGBA_DXT3: - t->intel.texelBytes = 4; - textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); - break; - + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT2_3); case MESA_FORMAT_RGBA_DXT5: - t->intel.texelBytes = 4; - textureFormat = (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); - break; - -#if 0 - case MESA_FORMAT_DEPTH_COMPONENT_X8Z24: - t->intel.texelBytes = 4; - textureFormat = (MAPSURF_32BIT | MT_32BIT_xL824); - break; -#endif - + return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); default: fprintf(stderr, "%s: bad image format %x\n", __FUNCTION__, - baseImage->TexFormat->MesaFormat); + mesa_format); abort(); + return 0; } +} - if (i915->intel.intelScreen->deviceID == PCI_CHIP_I945_G) - i945LayoutTextureImages( i915, tObj ); - else - i915LayoutTextureImages( i915, tObj ); - - t->Setup[I915_TEXREG_MS3] = - (((tObj->Image[0][t->intel.base.firstLevel]->Height - 1) << MS3_HEIGHT_SHIFT) | - ((tObj->Image[0][t->intel.base.firstLevel]->Width - 1) << MS3_WIDTH_SHIFT) | - textureFormat | - MS3_USE_FENCE_REGS); - - t->Setup[I915_TEXREG_MS4] = - ((((t->intel.Pitch / 4) - 1) << MS4_PITCH_SHIFT) | - MS4_CUBE_FACE_ENA_MASK | - (((t->intel.max_level * 4)) << MS4_MAX_LOD_SHIFT) | - ((tObj->Image[0][t->intel.base.firstLevel]->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); - - t->Setup[I915_TEXREG_SS2] &= ~(SS2_COLORSPACE_CONVERSION); - t->Setup[I915_TEXREG_SS2] |= ss2; - - t->intel.dirty = I915_UPLOAD_TEX_ALL; - -} /* The i915 (and related graphics cores) do not support GL_CLAMP. The @@ -528,383 +89,192 @@ static void i915SetTexImages( i915ContextPtr i915, static GLuint translate_wrap_mode( GLenum wrap ) { switch( wrap ) { - case GL_REPEAT: return TEXCOORDMODE_WRAP; - case GL_CLAMP: return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ - case GL_CLAMP_TO_EDGE: return TEXCOORDMODE_CLAMP_EDGE; - case GL_CLAMP_TO_BORDER: return TEXCOORDMODE_CLAMP_BORDER; - case GL_MIRRORED_REPEAT: return TEXCOORDMODE_MIRROR; - default: return TEXCOORDMODE_WRAP; - } -} - - -/** - */ -static void i915ImportTexObjState( struct gl_texture_object *texObj ) -{ - i915TextureObjectPtr t = (i915TextureObjectPtr)texObj->DriverData; - int minFilt = 0, mipFilt = 0, magFilt = 0, shadow = 0; - - if(INTEL_DEBUG&DEBUG_DRI) - fprintf(stderr, "%s\n", __FUNCTION__); - - switch (texObj->MinFilter) { - case GL_NEAREST: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_NONE; - break; - case GL_LINEAR: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_NEAREST; - break; - case GL_LINEAR_MIPMAP_NEAREST: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_NEAREST; - break; - case GL_NEAREST_MIPMAP_LINEAR: - minFilt = FILTER_NEAREST; - mipFilt = MIPFILTER_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - minFilt = FILTER_LINEAR; - mipFilt = MIPFILTER_LINEAR; - break; - default: - break; - } - - if ( texObj->MaxAnisotropy > 1.0 ) { - minFilt = FILTER_ANISOTROPIC; - magFilt = FILTER_ANISOTROPIC; - } - else { - switch (texObj->MagFilter) { - case GL_NEAREST: - magFilt = FILTER_NEAREST; - break; - case GL_LINEAR: - magFilt = FILTER_LINEAR; - break; - default: - break; - } - } - - if (texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && - texObj->Target != GL_TEXTURE_3D) { - - shadow = SS2_SHADOW_ENABLE; - shadow |= intel_translate_compare_func( texObj->CompareFunc ); - - minFilt = FILTER_4X4_FLAT; - magFilt = FILTER_4X4_FLAT; - } - - - t->Setup[I915_TEXREG_SS2] &= ~(SS2_MIN_FILTER_MASK | - SS2_MIP_FILTER_MASK | - SS2_MAG_FILTER_MASK | - SS2_SHADOW_ENABLE | - SS2_SHADOW_FUNC_MASK); - t->Setup[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | - (mipFilt << SS2_MIP_FILTER_SHIFT) | - (magFilt << SS2_MAG_FILTER_SHIFT) | - shadow); - - { - GLuint ss3 = t->Setup[I915_TEXREG_SS3] & ~(SS3_TCX_ADDR_MODE_MASK | - SS3_TCY_ADDR_MODE_MASK | - SS3_TCZ_ADDR_MODE_MASK); - GLenum ws = texObj->WrapS; - GLenum wt = texObj->WrapT; - GLenum wr = texObj->WrapR; - - t->refs_border_color = 0; - - if (texObj->Target == GL_TEXTURE_3D && - (texObj->MinFilter != GL_NEAREST || - texObj->MagFilter != GL_NEAREST)) { - - /* Try to mimic GL_CLAMP functionality a little better - - * switch to CLAMP_TO_BORDER whenever a non-NEAREST filter is - * in use. Only do this for 3D textures at the moment -- - * doing it universally would fix the conform texbc.c - * failure, though. - */ - if (ws == GL_CLAMP) ws = GL_CLAMP_TO_BORDER; - if (wt == GL_CLAMP) wt = GL_CLAMP_TO_BORDER; - if (wr == GL_CLAMP) wr = GL_CLAMP_TO_BORDER; - - /* 3D textures don't seem to respect the border color. - * Fallback if there's ever a danger that they might refer to - * it. - */ - if (ws == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; - if (wt == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; - if (wr == GL_CLAMP_TO_BORDER) t->refs_border_color = 1; - } - - ss3 |= translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT; - ss3 |= translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT; - ss3 |= translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT; - - if (ss3 != t->Setup[I915_TEXREG_SS3]) { - t->intel.dirty = I915_UPLOAD_TEX_ALL; - t->Setup[I915_TEXREG_SS3] = ss3; - } - } - - { - const GLubyte *color = texObj->_BorderChan; - - t->Setup[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(color[0],color[1], - color[2],color[3]); + case GL_REPEAT: + return TEXCOORDMODE_WRAP; + case GL_CLAMP: + return TEXCOORDMODE_CLAMP_EDGE; /* not quite correct */ + case GL_CLAMP_TO_EDGE: + return TEXCOORDMODE_CLAMP_EDGE; + case GL_CLAMP_TO_BORDER: + return TEXCOORDMODE_CLAMP_BORDER; + case GL_MIRRORED_REPEAT: + return TEXCOORDMODE_MIRROR; + default: + return TEXCOORDMODE_WRAP; } } -static void i915_import_tex_unit( i915ContextPtr i915, - i915TextureObjectPtr t, - GLuint unit ) +/* Recalculate all state from scratch. Perhaps not the most + * efficient, but this has gotten complex enough that we need + * something which is understandable and reliable. + */ +static GLboolean i915_update_tex_unit( GLcontext *ctx, + GLuint unit, + GLuint ss3 ) { + struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; + struct intel_texture_object *intelObj = intel_texture_object(tObj); + struct i915_context *i915 = i915_context(ctx); GLuint state[I915_TEX_SETUP_SIZE]; + struct gl_texture_image *firstImage; + GLuint firstImageOffset; - if(INTEL_DEBUG&DEBUG_TEXTURE) - fprintf(stderr, "%s unit(%d)\n", __FUNCTION__, unit); - - if (i915->intel.CurrentTexObj[unit]) - i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << unit); - - i915->intel.CurrentTexObj[unit] = (intelTextureObjectPtr)t; - t->intel.base.bound |= (1 << unit); - - if (t->intel.dirty & I915_UPLOAD_TEX(unit)) { - i915ImportTexObjState( t->intel.base.tObj ); - t->intel.dirty &= ~I915_UPLOAD_TEX(unit); - } - - state[I915_TEXREG_MS2] = t->intel.TextureOffset; - state[I915_TEXREG_MS3] = t->Setup[I915_TEXREG_MS3]; - state[I915_TEXREG_MS4] = t->Setup[I915_TEXREG_MS4]; - - state[I915_TEXREG_SS2] = (i915->state.Tex[unit][I915_TEXREG_SS2] & - SS2_LOD_BIAS_MASK); - state[I915_TEXREG_SS2] |= (t->Setup[I915_TEXREG_SS2] & ~SS2_LOD_BIAS_MASK); - - state[I915_TEXREG_SS3] = (i915->state.Tex[unit][I915_TEXREG_SS3] & - SS3_NORMALIZED_COORDS); - state[I915_TEXREG_SS3] |= (t->Setup[I915_TEXREG_SS3] & - ~(SS3_NORMALIZED_COORDS| - SS3_TEXTUREMAP_INDEX_MASK)); - - state[I915_TEXREG_SS3] |= (unit<<SS3_TEXTUREMAP_INDEX_SHIFT); - - state[I915_TEXREG_SS4] = t->Setup[I915_TEXREG_SS4]; - - - if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) { - I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) ); - memcpy(i915->state.Tex[unit], state, sizeof(state)); - } -} - - - -static GLboolean enable_tex_common( GLcontext *ctx, GLuint unit ) -{ - i915ContextPtr i915 = I915_CONTEXT(ctx); - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - struct gl_texture_object *tObj = texUnit->_Current; - i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; - - if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, unit); + memset(state, 0, sizeof(state)); - if (!(i915->state.active & I915_UPLOAD_TEX(unit))) { - I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_TRUE); - } + /* Will return the offset for the image at intelObj->firstLevel + * (firstLevel and lastLevel are calculated in + * validate_mipmap_tree). We will program the hardware as if this + * is level 0. + */ + firstImageOffset = intel_validate_mipmap_tree( intel_context(ctx), intelObj ); + firstImage = tObj->Image[0][intelObj->firstLevel]; - /* Fallback if there's a texture border */ - if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 ) { + if (!firstImageOffset) return GL_FALSE; - } - - - /* Update state if this is a different texture object to last - * time. - */ - if (i915->intel.CurrentTexObj[unit] != &t->intel || - (t->intel.dirty & I915_UPLOAD_TEX(unit))) { - i915_import_tex_unit( i915, t, unit); - i915->tex_program.translated = 0; - } - return GL_TRUE; -} + state[I915_TEXREG_MS2] = firstImageOffset; + state[I915_TEXREG_MS3] = + (((firstImage->Height - 1) << MS3_HEIGHT_SHIFT) | + ((firstImage->Width - 1) << MS3_WIDTH_SHIFT) | + translate_texture_format( firstImage->TexFormat->MesaFormat ) | + MS3_USE_FENCE_REGS); -static GLboolean enable_tex_rect( GLcontext *ctx, GLuint unit ) -{ - i915ContextPtr i915 = I915_CONTEXT(ctx); - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - struct gl_texture_object *tObj = texUnit->_Current; - i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; - GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; + state[I915_TEXREG_MS4] = + ((((intelObj->mt->pitch / 4) - 1) << MS4_PITCH_SHIFT) | + MS4_CUBE_FACE_ENA_MASK | + ((((intelObj->lastLevel - intelObj->firstLevel) * 4)) << MS4_MAX_LOD_SHIFT) | + ((firstImage->Depth - 1) << MS4_VOLUME_DEPTH_SHIFT)); - ss3 &= ~SS3_NORMALIZED_COORDS; - if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { - I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; - } + { + GLuint minFilt, mipFilt, magFilt; - /* Upload teximages (not pipelined) - */ - if (t->intel.base.dirty_images[0]) { - i915SetTexImages( i915, tObj ); - if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) { + switch (tObj->MinFilter) { + case GL_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NONE; + break; + case GL_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_LINEAR_MIPMAP_NEAREST: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_NEAREST; + break; + case GL_NEAREST_MIPMAP_LINEAR: + minFilt = FILTER_NEAREST; + mipFilt = MIPFILTER_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + minFilt = FILTER_LINEAR; + mipFilt = MIPFILTER_LINEAR; + break; + default: return GL_FALSE; } - } - return GL_TRUE; -} - - -static GLboolean enable_tex_2d( GLcontext *ctx, GLuint unit ) -{ - i915ContextPtr i915 = I915_CONTEXT(ctx); - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - struct gl_texture_object *tObj = texUnit->_Current; - i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; - GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; - - ss3 |= SS3_NORMALIZED_COORDS; - - if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { - I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; - } - - /* Upload teximages (not pipelined) - */ - if (t->intel.base.dirty_images[0]) { - i915SetTexImages( i915, tObj ); - if (!intelUploadTexImages( &i915->intel, &t->intel, 0 )) { - return GL_FALSE; + if ( tObj->MaxAnisotropy > 1.0 ) { + minFilt = FILTER_ANISOTROPIC; + magFilt = FILTER_ANISOTROPIC; } - } - - return GL_TRUE; -} - -static GLboolean enable_tex_cube( GLcontext *ctx, GLuint unit ) -{ - i915ContextPtr i915 = I915_CONTEXT(ctx); - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - struct gl_texture_object *tObj = texUnit->_Current; - i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; - GLuint ss3 = i915->state.Tex[unit][I915_TEXREG_SS3]; - GLuint face; - - ss3 |= SS3_NORMALIZED_COORDS; - - if (ss3 != i915->state.Tex[unit][I915_TEXREG_SS3]) { - I915_STATECHANGE(i915, I915_UPLOAD_TEX(unit)); - i915->state.Tex[unit][I915_TEXREG_SS3] = ss3; - } - - /* Upload teximages (not pipelined) - */ - if ( t->intel.base.dirty_images[0] || t->intel.base.dirty_images[1] || - t->intel.base.dirty_images[2] || t->intel.base.dirty_images[3] || - t->intel.base.dirty_images[4] || t->intel.base.dirty_images[5] ) { - i915SetTexImages( i915, tObj ); - } - - /* upload (per face) */ - for (face = 0; face < 6; face++) { - if (t->intel.base.dirty_images[face]) { - if (!intelUploadTexImages( &i915->intel, &t->intel, face )) { + else { + switch (tObj->MagFilter) { + case GL_NEAREST: + magFilt = FILTER_NEAREST; + break; + case GL_LINEAR: + magFilt = FILTER_LINEAR; + break; + default: return GL_FALSE; - } + } } - } + state[I915_TEXREG_SS2] = i915->lodbias_ss2[unit]; - return GL_TRUE; -} + /* YUV conversion: + */ + if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR || + firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV) + state[I915_TEXREG_SS2] |= SS2_COLORSPACE_CONVERSION; -static GLboolean enable_tex_3d( GLcontext *ctx, GLuint unit ) -{ - struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; - i915TextureObjectPtr t = (i915TextureObjectPtr)tObj->DriverData; + /* Shadow: + */ + if (tObj->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && + tObj->Target != GL_TEXTURE_3D) { - /* 3D textures on I915 seem to get bogus border colors, hence this - * fallback: - */ - if (t->refs_border_color) - return GL_FALSE; + state[I915_TEXREG_SS2] |= + (SS2_SHADOW_ENABLE | + intel_translate_compare_func( tObj->CompareFunc )); + + minFilt = FILTER_4X4_FLAT; + magFilt = FILTER_4X4_FLAT; + } - return GL_TRUE; -} + state[I915_TEXREG_SS2] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | + (mipFilt << SS2_MIP_FILTER_SHIFT) | + (magFilt << SS2_MAG_FILTER_SHIFT)); + } + { + GLenum ws = tObj->WrapS; + GLenum wt = tObj->WrapT; + GLenum wr = tObj->WrapR; + + /* 3D textures don't seem to respect the border color. + * Fallback if there's ever a danger that they might refer to + * it. + * + * Effectively this means fallback on 3D clamp or + * clamp_to_border. + */ + if (tObj->Target == GL_TEXTURE_3D && + (tObj->MinFilter != GL_NEAREST || + tObj->MagFilter != GL_NEAREST) && + (ws == GL_CLAMP || + wt == GL_CLAMP || + wr == GL_CLAMP || + ws == GL_CLAMP_TO_BORDER || + wt == GL_CLAMP_TO_BORDER || + wr == GL_CLAMP_TO_BORDER)) + return GL_FALSE; + - -static GLboolean disable_tex( GLcontext *ctx, GLuint unit ) -{ - i915ContextPtr i915 = I915_CONTEXT(ctx); + state[I915_TEXREG_SS3] = ss3; /* SS3_NORMALIZED_COORDS */ - if (i915->state.active & I915_UPLOAD_TEX(unit)) { - I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(unit), GL_FALSE); - } + state[I915_TEXREG_SS3] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | + (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | + (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); - /* The old texture is no longer bound to this texture unit. - * Mark it as such. - */ - if ( i915->intel.CurrentTexObj[unit] != NULL ) { - i915->intel.CurrentTexObj[unit]->base.bound &= ~(1U << 0); - i915->intel.CurrentTexObj[unit] = NULL; + state[I915_TEXREG_SS3] |= (unit << SS3_TEXTUREMAP_INDEX_SHIFT); } - return GL_TRUE; -} -static GLboolean i915UpdateTexUnit( GLcontext *ctx, GLuint unit ) -{ - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; + state[I915_TEXREG_SS4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0], + tObj->_BorderChan[1], + tObj->_BorderChan[2], + tObj->_BorderChan[3]); + - if (texUnit->_ReallyEnabled && - INTEL_CONTEXT(ctx)->intelScreen->tex.size < 2048 * 1024) - return GL_FALSE; - switch (texUnit->_ReallyEnabled) { - case TEXTURE_1D_BIT: - case TEXTURE_2D_BIT: - return (enable_tex_2d( ctx, unit ) && - enable_tex_common( ctx, unit )); - case TEXTURE_RECT_BIT: - return (enable_tex_rect( ctx, unit ) && - enable_tex_common( ctx, unit )); - case TEXTURE_CUBE_BIT: - return (enable_tex_cube( ctx, unit ) && - enable_tex_common( ctx, unit )); - case TEXTURE_3D_BIT: - return (enable_tex_2d( ctx, unit ) && - enable_tex_common( ctx, unit ) && - enable_tex_3d( ctx, unit)); - case 0: - return disable_tex( ctx, unit ); - default: - return GL_FALSE; + if (memcmp(state, i915->state.Tex[unit], sizeof(state)) != 0) { + I915_STATECHANGE( i915, I915_UPLOAD_TEX(unit) ); + memcpy(i915->state.Tex[unit], state, sizeof(state)); } + + return GL_TRUE; } + void i915UpdateTextureState( intelContextPtr intel ) { GLcontext *ctx = &intel->ctx; @@ -912,7 +282,26 @@ void i915UpdateTextureState( intelContextPtr intel ) GLuint i; for (i = 0 ; i < I915_TEX_UNITS && ok ; i++) { - ok = i915UpdateTexUnit( ctx, i ); + switch (ctx->Texture.Unit[i]._ReallyEnabled) { + case TEXTURE_1D_BIT: + case TEXTURE_2D_BIT: + case TEXTURE_CUBE_BIT: + ok = i915_update_tex_unit( ctx, i, SS3_NORMALIZED_COORDS ); + break; + case TEXTURE_RECT_BIT: + case TEXTURE_3D_BIT: + ok = i915_update_tex_unit( ctx, i, 0 ); + break; + case 0: { + struct i915_context *i915 = i915_context(ctx); + if (i915->state.active & I915_UPLOAD_TEX(i)) + I915_ACTIVESTATE(i915, I915_UPLOAD_TEX(i), GL_FALSE); + break; + } + default: + ok = GL_FALSE; + break; + } } FALLBACK( intel, I915_FALLBACK_TEXTURE, !ok ); diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 7952866010..cd7b0c0ee7 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -44,7 +44,7 @@ static void i915_render_start( intelContextPtr intel ) { GLcontext *ctx = &intel->ctx; - i915ContextPtr i915 = I915_CONTEXT(intel); + i915ContextPtr i915 = i915_context(&intel->ctx); if (ctx->FragmentProgram._Active) i915ValidateFragmentProgram( i915 ); @@ -56,7 +56,7 @@ static void i915_render_start( intelContextPtr intel ) static void i915_reduced_primitive_state( intelContextPtr intel, GLenum rprim ) { - i915ContextPtr i915 = I915_CONTEXT(intel); + i915ContextPtr i915 = i915_context(&intel->ctx); GLuint st1 = i915->state.Stipple[I915_STPREG_ST1]; st1 &= ~ST1_ENABLE; @@ -88,7 +88,7 @@ static void i915_reduced_primitive_state( intelContextPtr intel, static GLboolean i915_check_vertex_size( intelContextPtr intel, GLuint expected ) { - i915ContextPtr i915 = I915_CONTEXT(intel); + i915ContextPtr i915 = i915_context(&intel->ctx); int lis2 = i915->current->Ctx[I915_CTXREG_LIS2]; int lis4 = i915->current->Ctx[I915_CTXREG_LIS4]; int i, sz = 0; @@ -218,7 +218,7 @@ do { \ */ static void i915_emit_state( intelContextPtr intel ) { - i915ContextPtr i915 = I915_CONTEXT(intel); + i915ContextPtr i915 = i915_context(&intel->ctx); struct i915_hw_state *state = i915->current; int i; GLuint dirty; @@ -314,14 +314,15 @@ static void i915_destroy_context( intelContextPtr intel ) static void i915_set_draw_offset( intelContextPtr intel, int offset ) { - i915ContextPtr i915 = I915_CONTEXT(intel); + i915ContextPtr i915 = i915_context(&intel->ctx); I915_STATECHANGE( i915, I915_UPLOAD_BUFFERS ); i915->state.Buffer[I915_DESTREG_CBUFADDR2] = offset; } static void i915_lost_hardware( intelContextPtr intel ) { - I915_CONTEXT(intel)->state.emitted = 0; + i915ContextPtr i915 = i915_context(&intel->ctx); + i915->state.emitted = 0; } static void i915_emit_flush( intelContextPtr intel ) diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c index 170d1df25d..dad68a19ec 100644 --- a/src/mesa/drivers/dri/i915/intel_context.c +++ b/src/mesa/drivers/dri/i915/intel_context.c @@ -300,9 +300,6 @@ GLboolean intelInitContext( intelContextPtr intel, intel->sarea = saPriv; - (void) memset( intel->texture_heaps, 0, sizeof( intel->texture_heaps ) ); - make_empty_list( & intel->swapped ); - ctx->Const.MaxTextureMaxAnisotropy = 2.0; ctx->Const.MinLineWidth = 1.0; @@ -438,14 +435,7 @@ void intelDestroyContext(__DRIcontextPrivate *driContextPriv) /* This share group is about to go away, free our private * texture object data. */ - int i; - - for ( i = 0 ; i < intel->nr_heaps ; i++ ) { - driDestroyTextureHeap( intel->texture_heaps[ i ] ); - intel->texture_heaps[ i ] = NULL; - } - - assert( is_empty_list( & intel->swapped ) ); + fprintf(stderr, "do somethign to free texture heaps\n"); } /* free the Mesa context */ @@ -586,7 +576,6 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) __DRIscreenPrivate *sPriv = intel->driScreen; drmI830Sarea * sarea = intel->sarea; int me = intel->hHWContext; - unsigned i; drmGetLock(intel->driFd, intel->hHWContext, flags); @@ -609,15 +598,6 @@ void intelGetLock( intelContextPtr intel, GLuint flags ) sarea->ctxOwner = me; } - /* Shared texture managment - if another client has played with - * texture space, figure out which if any of our textures have been - * ejected, and update our global LRU. - */ - - for ( i = 0 ; i < intel->nr_heaps ; i++ ) { - DRI_AGE_TEXTURES( intel->texture_heaps[ i ] ); - } - if (dPriv && intel->lastStamp != dPriv->lastStamp) { intelWindowMoved( intel ); intel->lastStamp = dPriv->lastStamp; diff --git a/src/mesa/drivers/dri/i915/intel_context.h b/src/mesa/drivers/dri/i915/intel_context.h index 20e2660dc3..d3885b25b2 100644 --- a/src/mesa/drivers/dri/i915/intel_context.h +++ b/src/mesa/drivers/dri/i915/intel_context.h @@ -47,8 +47,6 @@ #define DV_PF_565 (2<<8) #define DV_PF_8888 (3<<8) -#define INTEL_CONTEXT(ctx) ((intelContextPtr)(ctx)) - typedef struct intel_context intelContext; typedef struct intel_context *intelContextPtr; typedef struct intel_texture_object *intelTextureObjectPtr; @@ -72,30 +70,34 @@ extern void intelFallback( intelContextPtr intel, GLuint bit, GLboolean mode ); #define INTEL_TEX_MAXLEVELS 10 + struct intel_texture_object { - driTextureObject base; /* the parent class */ + struct gl_texture_object base; /* The "parent" object */ - GLuint texelBytes; - GLuint age; - GLuint Pitch; - GLuint Height; - GLuint TextureOffset; - GLubyte *BufAddr; + /* The mipmap tree must include at least these levels once + * validated: + */ + GLuint firstLevel; + GLuint lastLevel; - GLuint min_level; - GLuint max_level; - GLuint depth_pitch; + /* 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 { - const struct gl_texture_image *image; - GLuint offset; /* into BufAddr */ - GLuint height; - GLuint internalFormat; - } image[6][INTEL_TEX_MAXLEVELS]; - - GLuint dirty; - GLuint firstLevel,lastLevel; + + +struct intel_texture_image { + struct gl_texture_image base; + + /* These aren't stored in gl_texture_image + */ + GLuint level; + GLuint face; + + struct intel_mipmap_tree *mt; }; @@ -179,12 +181,9 @@ struct intel_context GLboolean hw_stencil; GLboolean hw_stipple; - /* Texture object bookkeeping + /* AGP memory buffer manager: */ - GLuint nr_heaps; - driTexHeap * texture_heaps[1]; - driTextureObject swapped; - GLuint lastStamp; + struct bufmgr *bm; struct intel_texture_object *CurrentTexObj[MAX_TEXTURE_UNITS]; @@ -212,7 +211,6 @@ struct intel_context GLuint numClipRects; /* cliprects for that buffer */ drm_clip_rect_t *pClipRects; - int dirtyAge; int perf_boxes; int do_irqs; @@ -228,6 +226,8 @@ struct intel_context __DRIscreenPrivate *driScreen; intelScreenPrivate *intelScreen; drmI830Sarea *sarea; + + GLuint lastStamp; /** * Configuration cache @@ -512,6 +512,25 @@ extern void intel_dump_batchbuffer( long offset, extern void intelInitPixelFuncs( struct dd_function_table *functions ); +/* Inline conversion functions. These are better-typed than the macros used previously: + */ +static inline struct intel_context *intel_context( GLcontext *ctx ) +{ + return (struct intel_context *)ctx; +} + +static inline struct intel_texture_object *intel_texture_object( struct gl_texture_object *obj ) +{ + return (struct intel_texture_object *)obj; +} + +static inline struct intel_texture_image *intel_texture_image( struct gl_texture_image *img ) +{ + return (struct intel_texture_image *)img; +} + +#define INTEL_CONTEXT(ctx) intel_context(ctx) + #endif diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c index e3ad40b873..ebe2f760be 100644 --- a/src/mesa/drivers/dri/i915/intel_ioctl.c +++ b/src/mesa/drivers/dri/i915/intel_ioctl.c @@ -91,15 +91,6 @@ void intelWaitIrq( intelContextPtr intel, int seq ) -static void age_intel( intelContextPtr intel, int age ) -{ - GLuint i; - - for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) - if (intel->CurrentTexObj[i]) - intel->CurrentTexObj[i]->age = age; -} - void intel_dump_batchbuffer( long offset, int *ptr, int count ) @@ -263,8 +254,6 @@ void intelFlushBatchLocked( intelContextPtr intel, } - age_intel(intel, intel->sarea->last_enqueue); - /* FIXME: use hardware contexts to avoid 'losing' hardware after * each buffer flush. */ @@ -402,6 +391,11 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) drmI830MemAlloc alloc; int ret; + /* This won't work with the current state of the texture memory + * manager: + */ + assert(0); + if (0) fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); @@ -412,11 +406,6 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) LOCK_HARDWARE(intel); - /* Make sure the global heap is initialized - */ - if (intel->texture_heaps[0]) - driAgeTextures( intel->texture_heaps[0] ); - ret = drmCommandWriteRead( intel->driFd, DRM_I830_ALLOC, @@ -431,13 +420,6 @@ void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) if (0) fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); - /* Need to propogate this information (agp memory in use) to our - * local texture lru. The kernel has already updated the global - * lru. An alternative would have been to allocate memory the - * usual way and then notify the kernel to pin the allocation. - */ - if (intel->texture_heaps[0]) - driAgeTextures( intel->texture_heaps[0] ); UNLOCK_HARDWARE(intel); diff --git a/src/mesa/drivers/dri/i915/intel_pixel.c b/src/mesa/drivers/dri/i915/intel_pixel.c index a79bed45fb..2c47b2f5d0 100644 --- a/src/mesa/drivers/dri/i915/intel_pixel.c +++ b/src/mesa/drivers/dri/i915/intel_pixel.c @@ -39,7 +39,7 @@ static GLboolean -check_color( const GLcontext *ctx, GLenum type, GLenum format, +check_color( GLcontext *ctx, GLenum type, GLenum format, const struct gl_pixelstore_attrib *packing, const void *pixels, GLint sz, GLint pitch ) { @@ -96,7 +96,7 @@ check_color_per_fragment_ops( const GLcontext *ctx ) static GLboolean -clip_pixelrect( const GLcontext *ctx, +clip_pixelrect( GLcontext *ctx, const GLframebuffer *buffer, GLint *x, GLint *y, GLsizei *width, GLsizei *height, diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c index c4a2e53b3d..7896f02b94 100644 --- a/src/mesa/drivers/dri/i915/intel_screen.c +++ b/src/mesa/drivers/dri/i915/intel_screen.c @@ -338,12 +338,16 @@ static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; switch (intelScreen->deviceID) { +#if 0 + /* Don't deal with i830 until texture work complete: + */ case PCI_CHIP_845_G: case PCI_CHIP_I830_M: case PCI_CHIP_I855_GM: case PCI_CHIP_I865_G: return i830CreateContext( mesaVis, driContextPriv, sharedContextPrivate ); +#endif case PCI_CHIP_I915_G: case PCI_CHIP_I915_GM: diff --git a/src/mesa/drivers/dri/i915/intel_tex.c b/src/mesa/drivers/dri/i915/intel_tex.c index d256dbf7cb..d1a12f7275 100644 --- a/src/mesa/drivers/dri/i915/intel_tex.c +++ b/src/mesa/drivers/dri/i915/intel_tex.c @@ -1,830 +1,75 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "glheader.h" -#include "mtypes.h" -#include "imports.h" -#include "macros.h" -#include "simple_list.h" -#include "enums.h" -#include "image.h" -#include "texstore.h" -#include "texformat.h" -#include "teximage.h" -#include "texmem.h" #include "texobj.h" -#include "swrast/swrast.h" - -#include "mm.h" - -#include "intel_screen.h" -#include "intel_batchbuffer.h" #include "intel_context.h" +#include "intel_mipmap_tree.h" #include "intel_tex.h" -#include "intel_ioctl.h" - - - -static GLboolean -intelValidateClientStorage( intelContextPtr intel, GLenum target, - GLint internalFormat, - GLint srcWidth, GLint srcHeight, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) - -{ - GLcontext *ctx = &intel->ctx; - int texelBytes; - - if (0) - fprintf(stderr, "intformat %s format %s type %s\n", - _mesa_lookup_enum_by_nr( internalFormat ), - _mesa_lookup_enum_by_nr( format ), - _mesa_lookup_enum_by_nr( type )); - - if (!ctx->Unpack.ClientStorage) - return 0; - - if (ctx->_ImageTransferState || - texImage->IsCompressed || - texObj->GenerateMipmap) - return 0; - - - /* This list is incomplete - */ - switch ( internalFormat ) { - case GL_RGBA: - if ( format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV ) { - texImage->TexFormat = &_mesa_texformat_argb8888; - texelBytes = 4; - } - else - return 0; - break; - - case GL_RGB: - if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { - texImage->TexFormat = &_mesa_texformat_rgb565; - texelBytes = 2; - } - else - return 0; - break; - - case GL_YCBCR_MESA: - if ( format == GL_YCBCR_MESA && - type == GL_UNSIGNED_SHORT_8_8_REV_APPLE ) { - texImage->TexFormat = &_mesa_texformat_ycbcr_rev; - texelBytes = 2; - } - else if ( format == GL_YCBCR_MESA && - (type == GL_UNSIGNED_SHORT_8_8_APPLE || - type == GL_UNSIGNED_BYTE)) { - texImage->TexFormat = &_mesa_texformat_ycbcr; - texelBytes = 2; - } - else - return 0; - break; - - - default: - return 0; - } - - /* Could deal with these packing issues, but currently don't: - */ - if (packing->SkipPixels || - packing->SkipRows || - packing->SwapBytes || - packing->LsbFirst) { - return 0; - } - - { - GLint srcRowStride = _mesa_image_row_stride(packing, srcWidth, - format, type); - - - if (0) - fprintf(stderr, "%s: srcRowStride %d/%x\n", - __FUNCTION__, srcRowStride, srcRowStride); - - /* Could check this later in upload, pitch restrictions could be - * relaxed, but would need to store the image pitch somewhere, - * as packing details might change before image is uploaded: - */ - if (!intelIsAgpMemory( intel, pixels, srcHeight * srcRowStride ) || - (srcRowStride & 63)) - return 0; - - - /* Have validated that _mesa_transfer_teximage would be a straight - * memcpy at this point. NOTE: future calls to TexSubImage will - * overwrite the client data. This is explicitly mentioned in the - * extension spec. - */ - texImage->Data = (void *)pixels; - texImage->IsClientData = GL_TRUE; - texImage->RowStride = srcRowStride / texelBytes; - return 1; - } -} - - - -static void intelTexImage1D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - driTextureObject * t = (driTextureObject *) texObj->DriverData; - - assert(t); - intelFlush( ctx ); - driSwapOutTextureObject( t ); - - texImage->IsClientData = GL_FALSE; - - _mesa_store_teximage1d( ctx, target, level, internalFormat, - width, border, format, type, - pixels, packing, texObj, texImage ); - - t->dirty_images[0] |= (1 << level); -} - -static void intelTexSubImage1D( GLcontext *ctx, - GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - driTextureObject * t = (driTextureObject *) texObj->DriverData; - - assert(t); - intelFlush( ctx ); - driSwapOutTextureObject( t ); - - _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, - format, type, pixels, packing, texObj, - texImage); -} - -/* Handles 2D, CUBE, RECT: - */ -static void intelTexImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - driTextureObject * t = (driTextureObject *) texObj->DriverData; - GLuint face; - - /* which cube face or ordinary 2D image */ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; - ASSERT(face < 6); - break; - default: - face = 0; - } - - assert(t); - intelFlush( ctx ); - driSwapOutTextureObject( t ); - texImage->IsClientData = GL_FALSE; - - if (intelValidateClientStorage( INTEL_CONTEXT(ctx), target, - internalFormat, - width, height, - format, type, pixels, - packing, texObj, texImage)) { - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "%s: Using client storage\n", __FUNCTION__); - } - else { - _mesa_store_teximage2d( ctx, target, level, internalFormat, - width, height, border, format, type, - pixels, packing, texObj, texImage ); - - t->dirty_images[face] |= (1 << level); - } -} - -static void intelTexSubImage2D( GLcontext *ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - driTextureObject * t = (driTextureObject *) texObj->DriverData; - GLuint face; - - /* which cube face or ordinary 2D image */ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; - ASSERT(face < 6); - break; - default: - face = 0; - } - - if (texImage->IsClientData && - (char *)pixels == (char *)texImage->Data + - ((xoffset + yoffset * texImage->RowStride) * - texImage->TexFormat->TexelBytes)) { - - /* Notification only - no upload required */ - } - else { - assert( t ); /* this _should_ be true */ - intelFlush( ctx ); - driSwapOutTextureObject( t ); - - _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, - height, format, type, pixels, packing, texObj, - texImage); - - t->dirty_images[face] |= (1 << level); - } -} -static void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) +static GLboolean intelIsTextureResident(GLcontext *ctx, + struct gl_texture_object *texObj) { - driTextureObject * t = (driTextureObject *) texObj->DriverData; - GLuint face; - - /* which cube face or ordinary 2D image */ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; - ASSERT(face < 6); - break; - default: - face = 0; - } - - assert(t); - intelFlush( ctx ); - - driSwapOutTextureObject( t ); - texImage->IsClientData = GL_FALSE; - - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "%s: Using normal storage\n", __FUNCTION__); +#if 0 + struct intel_context *intel = intel_context(ctx); + struct intel_texture_object *intelObj = intel_texture_object(texObj); - _mesa_store_compressed_teximage2d(ctx, target, level, internalFormat, width, - height, border, imageSize, data, texObj, texImage); - - t->dirty_images[face] |= (1 << level); + return + intelObj->mt && + intelObj->mt->region && + intel_is_region_resident(intel, intelObj->mt->region); +#endif + return 1; } -static void intelCompressedTexSubImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - driTextureObject * t = (driTextureObject *) texObj->DriverData; - GLuint face; - - - /* which cube face or ordinary 2D image */ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; - ASSERT(face < 6); - break; - default: - face = 0; - } - assert( t ); /* this _should_ be true */ - intelFlush( ctx ); - driSwapOutTextureObject( t ); - - _mesa_store_compressed_texsubimage2d(ctx, target, level, xoffset, yoffset, width, - height, format, imageSize, data, texObj, texImage); - - t->dirty_images[face] |= (1 << level); -} - - -static void intelTexImage3D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) +static struct gl_texture_image *intelNewTextureImage( GLcontext *ctx ) { - driTextureObject * t = (driTextureObject *) texObj->DriverData; - - assert(t); - driSwapOutTextureObject( t ); - texImage->IsClientData = GL_FALSE; - - _mesa_store_teximage3d(ctx, target, level, internalFormat, - width, height, depth, border, - format, type, pixels, - &ctx->Unpack, texObj, texImage); - - t->dirty_images[0] |= (1 << level); + (void) ctx; + return (struct gl_texture_image *)CALLOC_STRUCT(intel_texture_image); } -static void -intelTexSubImage3D( GLcontext *ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - const GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) +static struct gl_texture_object *intelNewTextureObject( GLcontext *ctx, + GLuint name, + GLenum target ) { - driTextureObject * t = (driTextureObject *) texObj->DriverData; - - assert( t ); /* this _should_ be true */ - driSwapOutTextureObject( t ); + struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); - _mesa_store_texsubimage3d(ctx, target, level, xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texObj, texImage); + _mesa_initialize_texture_object(&obj->base, name, target); - t->dirty_images[0] |= (1 << level); + return &obj->base; } - - -static void intelDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) +static void intelFreeTextureImageData( GLcontext *ctx, + struct gl_texture_image *texImage ) { - driTextureObject * t = (driTextureObject *) tObj->DriverData; + struct intel_context *intel = intel_context(ctx); + struct intel_texture_image *intelImage = intel_texture_image(texImage); - if ( t != NULL ) { - intelFlush( ctx ); - driDestroyTextureObject( t ); + if (intelImage->mt) { + intel_miptree_release(intel, intelImage->mt); + intelImage->mt = NULL; } - /* Free mipmap images and the texture object itself */ - _mesa_delete_texture_object(ctx, tObj); -} - - -static const struct gl_texture_format * -intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, - GLenum format, GLenum type ) -{ - intelContextPtr intel = INTEL_CONTEXT( ctx ); - const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 && - intel->intelScreen->tex.size > 4*1024*1024); - - switch ( internalFormat ) { - case 4: - case GL_RGBA: - case GL_COMPRESSED_RGBA: - if ( format == GL_BGRA ) { - if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { - return &_mesa_texformat_argb8888; - } - else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { - return &_mesa_texformat_argb4444; - } - else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { - return &_mesa_texformat_argb1555; - } - } - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; - - case 3: - case GL_RGB: - case GL_COMPRESSED_RGB: - if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { - return &_mesa_texformat_rgb565; - } - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; - - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; - - case GL_RGBA4: - case GL_RGBA2: - return &_mesa_texformat_argb4444; - - case GL_RGB5_A1: - return &_mesa_texformat_argb1555; - - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; - - case GL_RGB5: - case GL_RGB4: - case GL_R3_G3_B2: - return &_mesa_texformat_rgb565; - - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - case GL_COMPRESSED_ALPHA: - return &_mesa_texformat_a8; - - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case GL_COMPRESSED_LUMINANCE: - return &_mesa_texformat_l8; - - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - case GL_COMPRESSED_LUMINANCE_ALPHA: - return &_mesa_texformat_al88; - - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - case GL_COMPRESSED_INTENSITY: - return &_mesa_texformat_i8; - - case GL_YCBCR_MESA: - if (type == GL_UNSIGNED_SHORT_8_8_MESA || - type == GL_UNSIGNED_BYTE) - return &_mesa_texformat_ycbcr; - else - return &_mesa_texformat_ycbcr_rev; - - case GL_COMPRESSED_RGB_FXT1_3DFX: - return &_mesa_texformat_rgb_fxt1; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - return &_mesa_texformat_rgba_fxt1; - - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - return &_mesa_texformat_rgb_dxt1; - - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return &_mesa_texformat_rgba_dxt1; - - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - return &_mesa_texformat_rgba_dxt3; - - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - return &_mesa_texformat_rgba_dxt5; - - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - return &_mesa_texformat_depth_component16; - - default: - fprintf(stderr, "unexpected texture format %s in %s\n", - _mesa_lookup_enum_by_nr(internalFormat), - __FUNCTION__); - return NULL; + if (texImage->Data) { + free(texImage->Data); + texImage->Data = NULL; } - - return NULL; /* never get here */ -} - - - -void intelDestroyTexObj(intelContextPtr intel, intelTextureObjectPtr t) -{ - unsigned i; - - if ( intel == NULL ) - return; - - if ( t->age > intel->dirtyAge ) - intel->dirtyAge = t->age; - - for ( i = 0 ; i < MAX_TEXTURE_UNITS ; i++ ) { - if ( t == intel->CurrentTexObj[ i ] ) - intel->CurrentTexObj[ i ] = NULL; - } -} - - - -/* Upload an image from mesa's internal copy. Image may be 1D, 2D or - * 3D. Cubemaps are expanded elsewhere. - */ -static void intelUploadTexImage( intelContextPtr intel, - intelTextureObjectPtr t, - const struct gl_texture_image *image, - const GLuint offset ) -{ - - if (!image || !image->Data) - return; - - if (image->Depth == 1 && image->IsClientData) { - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "Blit uploading\n"); - - /* Do it with a blit. - */ - intelEmitCopyBlitLocked( intel, - image->TexFormat->TexelBytes, - image->RowStride, /* ? */ - intelGetMemoryOffsetMESA( NULL, 0, image->Data ), - t->Pitch / image->TexFormat->TexelBytes, - intelGetMemoryOffsetMESA( NULL, 0, t->BufAddr + offset ), - 0, 0, - 0, 0, - image->Width, - image->Height); - } - else if (image->IsCompressed) { - GLuint row_len = image->Width * 2; - GLubyte *dst = (GLubyte *)(t->BufAddr + offset); - GLubyte *src = (GLubyte *)image->Data; - GLuint j; - - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, - "Upload image %dx%dx%d offset %xm row_len %x " - "pitch %x depth_pitch %x\n", - image->Width, image->Height, image->Depth, offset, - row_len, t->Pitch, t->depth_pitch); - - switch (image->InternalFormat) { - case GL_COMPRESSED_RGB_FXT1_3DFX: - case GL_COMPRESSED_RGBA_FXT1_3DFX: - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { - __memcpy(dst, src, row_len ); - src += row_len; - } - break; - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - for (j = 0 ; j < image->Height/4 ; j++, dst += (t->Pitch)) { - __memcpy(dst, src, (image->Width*4) ); - src += image->Width*4; - } - break; - default: - fprintf(stderr,"Internal Compressed format not supported %d\n", image->InternalFormat); - break; - } - } - else { - GLuint row_len = image->Width * image->TexFormat->TexelBytes; - GLubyte *dst = (GLubyte *)(t->BufAddr + offset); - GLubyte *src = (GLubyte *)image->Data; - GLuint d, j; - - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, - "Upload image %dx%dx%d offset %xm row_len %x " - "pitch %x depth_pitch %x\n", - image->Width, image->Height, image->Depth, offset, - row_len, t->Pitch, t->depth_pitch); - - if (row_len == t->Pitch) { - for (d = 0; d < image->Depth; d++) { - memcpy( dst, src, t->Pitch * image->Height ); - dst += t->depth_pitch; - src += row_len * image->Height; - } - } - else { - for (d = 0 ; d < image->Depth ; d++) { - for (j = 0 ; j < image->Height ; j++) { - __memcpy(dst, src, row_len ); - src += row_len; - dst += t->Pitch; - } - - dst += t->depth_pitch - (t->Pitch * image->Height); - } - } - } -} - - - -int intelUploadTexImages( intelContextPtr intel, - intelTextureObjectPtr t, - GLuint face) -{ - const int numLevels = t->base.lastLevel - t->base.firstLevel + 1; - const struct gl_texture_image *firstImage = t->image[face][t->base.firstLevel].image; - int pitch = firstImage->RowStride * firstImage->TexFormat->TexelBytes; - - /* Can we texture out of the existing client data? */ - if ( numLevels == 1 && - firstImage->IsClientData && - (pitch & 3) == 0) { - - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "AGP texturing from client memory\n"); - - t->TextureOffset = intelAgpOffsetFromVirtual( intel, firstImage->Data ); - t->BufAddr = 0; - t->dirty = ~0; - return GL_TRUE; - } - else { - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "Uploading client data to agp\n"); - - INTEL_FIREVERTICES( intel ); - LOCK_HARDWARE( intel ); - - if ( t->base.memBlock == NULL ) { - int heap; - - heap = driAllocateTexture( intel->texture_heaps, intel->nr_heaps, - (driTextureObject *) t ); - if ( heap == -1 ) { - UNLOCK_HARDWARE( intel ); - return GL_FALSE; - } - - /* Set the base offset of the texture image */ - t->BufAddr = intel->intelScreen->tex.map + t->base.memBlock->ofs; - t->TextureOffset = intel->intelScreen->tex.offset + t->base.memBlock->ofs; - t->dirty = ~0; - } - - - /* Let the world know we've used this memory recently. - */ - driUpdateTextureLRU( (driTextureObject *) t ); - - - /* Upload any images that are new */ - if (t->base.dirty_images[face]) { - int i; - - intelWaitForIdle( intel ); - - for (i = 0 ; i < numLevels ; i++) { - int level = i + t->base.firstLevel; - - if (t->base.dirty_images[face] & (1<<level)) { - - const struct gl_texture_image *image = t->image[face][i].image; - GLuint offset = t->image[face][i].offset; - - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "upload level %d, offset %x\n", - level, offset); - - intelUploadTexImage( intel, t, image, offset ); - } - } - t->base.dirty_images[face] = 0; - intel->perf_boxes |= I830_BOX_TEXTURE_LOAD; - } - - UNLOCK_HARDWARE( intel ); - return GL_TRUE; - } -} - -/** - * Allocate a new texture object. - * Called via ctx->Driver.NewTextureObject. - * Note: this function will be called during context creation to - * allocate the default texture objects. - * Note: we could use containment here to 'derive' the driver-specific - * texture object from the core mesa gl_texture_object. Not done at this time. - */ -static struct gl_texture_object * -intelNewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) -{ - struct gl_texture_object *obj = _mesa_new_texture_object(ctx, name, target); - INTEL_CONTEXT(ctx)->vtbl.alloc_tex_obj( obj ); - return obj; } -void intelInitTextureFuncs( struct dd_function_table *functions ) +void intelInitTextureFuncs(struct dd_function_table * functions) { - functions->NewTextureObject = intelNewTextureObject; - functions->ChooseTextureFormat = intelChooseTextureFormat; - functions->TexImage1D = intelTexImage1D; - functions->TexImage2D = intelTexImage2D; - functions->TexImage3D = intelTexImage3D; - functions->TexSubImage1D = intelTexSubImage1D; - functions->TexSubImage2D = intelTexSubImage2D; - functions->TexSubImage3D = intelTexSubImage3D; - functions->CopyTexImage1D = _swrast_copy_teximage1d; - functions->CopyTexImage2D = _swrast_copy_teximage2d; - functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d; - functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d; - functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d; - functions->DeleteTexture = intelDeleteTexture; - functions->UpdateTexturePalette = NULL; - functions->IsTextureResident = driIsTextureResident; - functions->TestProxyTexImage = _mesa_test_proxy_teximage; - functions->DeleteTexture = intelDeleteTexture; - functions->CompressedTexImage2D = intelCompressedTexImage2D; - functions->CompressedTexSubImage2D = intelCompressedTexSubImage2D; + functions->ChooseTextureFormat = intelChooseTextureFormat; + functions->TexImage1D = intelTexImage1D; + functions->TexImage2D = intelTexImage2D; + functions->TexSubImage1D = intelTexSubImage1D; + functions->TexSubImage2D = intelTexSubImage2D; + functions->NewTextureObject = intelNewTextureObject; + functions->NewTextureImage = intelNewTextureImage; + functions->DeleteTexture = _mesa_delete_texture_object; + functions->FreeTexImageData = intelFreeTextureImageData; + functions->TextureMemCpy = _mesa_memcpy; + functions->UpdateTexturePalette = 0; + functions->IsTextureResident = intelIsTextureResident; } diff --git a/src/mesa/drivers/dri/i915/intel_tex.h b/src/mesa/drivers/dri/i915/intel_tex.h index 0a1f697e9d..9ce775270f 100644 --- a/src/mesa/drivers/dri/i915/intel_tex.h +++ b/src/mesa/drivers/dri/i915/intel_tex.h @@ -35,8 +35,54 @@ void intelInitTextureFuncs( struct dd_function_table *functions ); -void intelDestroyTexObj( intelContextPtr intel, intelTextureObjectPtr t ); -int intelUploadTexImages( intelContextPtr intel, intelTextureObjectPtr t, - GLuint face ); +const struct gl_texture_format * +intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ); + +void intelTexImage2D(GLcontext *ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexSubImage2D(GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexImage1D(GLcontext *ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexSubImage1D(GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +GLuint intel_validate_mipmap_tree( struct intel_context *intel, + struct intel_texture_object *intelObj ); + + + #endif diff --git a/src/mesa/drivers/dri/i915/intel_tex_format.c b/src/mesa/drivers/dri/i915/intel_tex_format.c new file mode 100644 index 0000000000..30da841987 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_tex_format.c @@ -0,0 +1,145 @@ +#include "intel_context.h" +#include "intel_tex.h" +#include "texformat.h" +#include "enums.h" + +/* It works out that this function is fine for all the supported + * hardware. However, there is still a need to map the formats onto + * hardware descriptors. + */ +const struct gl_texture_format * +intelChooseTextureFormat( GLcontext *ctx, GLint internalFormat, + GLenum format, GLenum type ) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + const GLboolean do32bpt = ( intel->intelScreen->cpp == 4 && + intel->intelScreen->tex.size > 4*1024*1024); + + switch ( internalFormat ) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA: + if ( format == GL_BGRA ) { + if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) { + return &_mesa_texformat_argb8888; + } + else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) { + return &_mesa_texformat_argb4444; + } + else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) { + return &_mesa_texformat_argb1555; + } + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) { + return &_mesa_texformat_rgb565; + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; + + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + return &_mesa_texformat_rgb565; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: + return &_mesa_texformat_a8; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: + return &_mesa_texformat_l8; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: + return &_mesa_texformat_al88; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: + return &_mesa_texformat_i8; + + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || + type == GL_UNSIGNED_BYTE) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + + case GL_COMPRESSED_RGB_FXT1_3DFX: + return &_mesa_texformat_rgb_fxt1; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return &_mesa_texformat_rgba_fxt1; + + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return &_mesa_texformat_rgb_dxt1; + + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return &_mesa_texformat_rgba_dxt1; + + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return &_mesa_texformat_rgba_dxt3; + + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return &_mesa_texformat_rgba_dxt5; + + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + return &_mesa_texformat_depth_component16; + + default: + fprintf(stderr, "unexpected texture format %s in %s\n", + _mesa_lookup_enum_by_nr(internalFormat), + __FUNCTION__); + return NULL; + } + + return NULL; /* never get here */ +} diff --git a/src/mesa/drivers/dri/i915/intel_tex_image.c b/src/mesa/drivers/dri/i915/intel_tex_image.c new file mode 100644 index 0000000000..0cb553c554 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_tex_image.c @@ -0,0 +1,315 @@ + +#include <stdlib.h> +#include <stdio.h> + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "enums.h" +#include "colortab.h" +#include "convolve.h" +#include "context.h" +#include "simple_list.h" +#include "texcompress.h" +#include "texformat.h" +#include "texobj.h" +#include "texstore.h" + +#include "intel_context.h" +#include "intel_mipmap_tree.h" +#include "intel_tex.h" +#include "intel_ioctl.h" + + +/* Functions to store texture images. Where possible, mipmap_tree's + * will be created or further instantiated with image data, otherwise + * images will be stored in malloc'd memory. A validation step is + * required to pull those images into a mipmap tree, or otherwise + * decide a fallback is required. + */ + + +static int logbase2(int n) +{ + GLint i = 1; + GLint log2 = 0; + + while (n > i) { + i *= 2; + log2++; + } + + return log2; +} + + +/* Otherwise, store it in memory if (Border != 0) or (any dimension == + * 1). + * + * Otherwise, if max_level >= level >= min_level, create tree with + * space for textures from min_level down to max_level. + * + * Otherwise, create tree with space for textures from (level + * 0)..(1x1). Consider pruning this tree at a validation if the + * saving is worth it. + */ +static void guess_and_alloc_mipmap_tree( struct intel_context *intel, + struct intel_texture_object *intelObj, + struct intel_texture_image *intelImage ) +{ + GLuint firstLevel; + GLuint lastLevel; + GLuint width = intelImage->base.Width; + GLuint height = intelImage->base.Height; + GLuint depth = intelImage->base.Depth; + GLuint l2width, l2height, l2depth; + GLuint i; + + if (intelImage->base.Border) + return; + + if (intelImage->level > intelObj->base.BaseLevel && + (intelImage->base.Width == 1 || + (intelObj->base.Target != GL_TEXTURE_1D && + intelImage->base.Height == 1) || + (intelObj->base.Target == GL_TEXTURE_3D && + intelImage->base.Depth == 1))) + return; + + /* If this image disrespects BaseLevel, allocate from level zero. + * Usually BaseLevel == 0, so it's unlikely to happen. + */ + if (intelImage->level < intelObj->base.BaseLevel) + firstLevel = 0; + else + firstLevel = intelObj->base.BaseLevel; + + + /* Figure out image dimensions at start level. + */ + for (i = intelImage->level; i > firstLevel; i--) { + width <<= 1; + if (height != 1) height <<= 1; + if (depth != 1) depth <<= 1; + } + + /* Guess a reasonable value for lastLevel. This is probably going + * to be wrong fairly often and might mean that we have to look at + * resizable buffers, or require that buffers implement lazy + * pagetable arrangements. + */ + if ((intelObj->base.MinFilter == GL_NEAREST || + intelObj->base.MinFilter == GL_LINEAR) && + intelImage->level == firstLevel) { + lastLevel = firstLevel; + } + else { + l2width = logbase2(width); + l2height = logbase2(height); + l2depth = logbase2(depth); + lastLevel = firstLevel + MAX2(MAX2(l2width,l2height),l2depth); + } + + + intelObj->mt = intel_miptree_create( intel, + intelObj->base.Target, + intelImage->base.InternalFormat, + firstLevel, + lastLevel, + width, + height, + depth, + intelImage->base.TexFormat->TexelBytes, + intelImage->base.IsCompressed ); +} + + + + +static GLuint target_to_face( GLenum target ) +{ + switch (target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + return ((GLuint) target - + (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); + default: + return 0; + } +} + + +static void intelTexImage(GLcontext *ctx, + GLint dims, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_texture_object *intelObj = intel_texture_object(texObj); + struct intel_texture_image *intelImage = intel_texture_image(texImage); + GLint postConvWidth = width; + GLint postConvHeight = height; + GLint texelBytes, sizeInBytes; + GLuint dstRowStride; + + intelImage->face = target_to_face( target ); + intelImage->level = level; + + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, + &postConvHeight); + } + + /* choose the texture format */ + texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat, + format, type); + + assert(texImage->TexFormat); + + if (dims == 1) { + texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df; + } + else { + texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D; + texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df; + } + texelBytes = texImage->TexFormat->TexelBytes; + + + /* Minimum pitch of 32 bytes */ + if (postConvWidth * texelBytes < 32) { + postConvWidth = 32 / texelBytes; + texImage->RowStride = postConvWidth; + } + + assert(texImage->RowStride == postConvWidth); + + /* Release the reference to a potentially orphaned buffer. + * Release any old malloced memory. + */ + if (intelImage->mt) { + intel_miptree_release(intel, intelImage->mt); + intelImage->mt = NULL; + assert(!texImage->Data); + } + else if (texImage->Data) { + free(texImage->Data); + } + + pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, + format, type, + pixels, packing, "glTexImage"); + if (!pixels) + return; + + if (!intelObj->mt) { + guess_and_alloc_mipmap_tree(intel, intelObj, intelImage); + } + + LOCK_HARDWARE(intel); + + if (intelObj->mt && + intel_miptree_match_image(intelObj->mt, &intelImage->base, + intelImage->face, intelImage->level)) { + + texImage->Data = intel_miptree_image_map(intel, + intelObj->mt, + intelImage->face, + intelImage->level, + &dstRowStride); + } + else { + /* Allocate regular memory and store the image there temporarily. */ + if (texImage->IsCompressed) { + sizeInBytes = texImage->CompressedSize; + dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,width); + } + else { + sizeInBytes = postConvWidth * postConvHeight * texelBytes; + dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes; + } + + texImage->Data = malloc(sizeInBytes); + } + + /* Copy data. Would like to know when it's ok for us to eg. use + * the blitter to copy. Or, use the hardware to do the format + * conversion and copy: + */ + if (!texImage->TexFormat->StoreImage(ctx, dims, + texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, 0 /* dstImageStride */, + width, height, 1, + format, type, pixels, packing)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + } + + _mesa_unmap_teximage_pbo(ctx, packing); + + if (intelImage->mt) { + intel_miptree_image_unmap(intel, intelImage->mt); + texImage->Data = NULL; + } + + UNLOCK_HARDWARE(intel); + +#if 0 + /* GL_SGIS_generate_mipmap -- this can be accelerated now. + */ + if (level == texObj->BaseLevel && + texObj->GenerateMipmap) { + intel_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } +#endif +} + + +void intelTexImage2D(GLcontext *ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexImage( ctx, 2, target, level, + internalFormat, width, height, border, + format, type, pixels, + packing, texObj, texImage ); +} + +void intelTexImage1D(GLcontext *ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexImage( ctx, 1, target, level, + internalFormat, width, 1, border, + format, type, pixels, + packing, texObj, texImage ); +} + + + + + diff --git a/src/mesa/drivers/dri/i915/intel_tex_subimage.c b/src/mesa/drivers/dri/i915/intel_tex_subimage.c new file mode 100644 index 0000000000..5c5e4a2b31 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_tex_subimage.c @@ -0,0 +1,115 @@ + + +#include "mtypes.h" +#include "texobj.h" +#include "texstore.h" + +#include "intel_context.h" +#include "intel_tex.h" +#include "intel_mipmap_tree.h" + + +static void intelTexSubimage (GLcontext *ctx, + GLint dims, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint width, GLint height, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_texture_image *intelImage = intel_texture_image(texImage); + GLuint dstImageStride = 0; + GLuint dstRowStride; + + pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, format, type, + pixels, packing, "glTexSubImage2D"); + if (!pixels) + return; + + LOCK_HARDWARE(intel); + + /* Map buffer if necessary. Need to lock to prevent other contexts + * from uploading the buffer under us. + */ + if (intelImage->mt) + texImage->Data = intel_miptree_image_map(intel, + intelImage->mt, + intelImage->face, + intelImage->level, + &dstRowStride ); + + + if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, 0, + dstRowStride, dstImageStride, + width, height, 1, + format, type, pixels, packing)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); + } + +#if 0 + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } +#endif + + _mesa_unmap_teximage_pbo(ctx, packing); + + if (intelImage->mt) { + intel_miptree_image_unmap(intel, intelImage->mt); + texImage->Data = NULL; + } + + UNLOCK_HARDWARE(intel); +} + + + + + + +void intelTexSubImage2D(GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + + intelTexSubimage(ctx, 2, + target, level, xoffset, yoffset, width, + height, format, type, pixels, packing, texObj, + texImage); + +} + + +void intelTexSubImage1D(GLcontext *ctx, + GLenum target, + GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexSubimage(ctx, 1, + target, level, xoffset, 0, width, + 1, format, type, pixels, packing, texObj, + texImage); + +} diff --git a/src/mesa/drivers/dri/i915/intel_tex_validate.c b/src/mesa/drivers/dri/i915/intel_tex_validate.c new file mode 100644 index 0000000000..e99f91cc77 --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_tex_validate.c @@ -0,0 +1,198 @@ +#include "mtypes.h" +#include "macros.h" + +#include "intel_context.h" +#include "intel_mipmap_tree.h" +#include "intel_tex.h" + + +/** + * Compute which mipmap levels that really need to be sent to the hardware. + * This depends on the base image size, GL_TEXTURE_MIN_LOD, + * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. + */ +static void intel_calculate_first_last_level( struct intel_texture_object *intelObj ) +{ + struct gl_texture_object *tObj = &intelObj->base; + const struct gl_texture_image * const baseImage = + tObj->Image[0][tObj->BaseLevel]; + + /* These must be signed values. MinLod and MaxLod can be negative numbers, + * and having firstLevel and lastLevel as signed prevents the need for + * extra sign checks. + */ + int firstLevel; + int lastLevel; + + /* Yes, this looks overly complicated, but it's all needed. + */ + switch (tObj->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { + /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. + */ + firstLevel = lastLevel = tObj->BaseLevel; + } + else { + firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5); + firstLevel = MAX2(firstLevel, tObj->BaseLevel); + lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5); + lastLevel = MAX2(lastLevel, tObj->BaseLevel); + lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); + lastLevel = MIN2(lastLevel, tObj->MaxLevel); + lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ + } + break; + case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_4D_SGIS: + firstLevel = lastLevel = 0; + break; + default: + return; + } + + /* save these values */ + intelObj->firstLevel = firstLevel; + intelObj->lastLevel = lastLevel; +} + +static void copy_image_data_to_tree( struct intel_context *intel, + struct intel_mipmap_tree *mt, + struct intel_texture_image *intelImage ) +{ + if (intelImage->mt) { + /* Copy potentially with the blitter: + */ + intel_miptree_image_copy(intel, + mt, + intelImage->face, + intelImage->level, + intelImage->mt); + + intel_miptree_release(intel, intelImage->mt); + } + else { + assert(intelImage->base.Data != NULL); + + /* More straightforward upload. + */ + intel_miptree_image_data(intel, + mt, + intelImage->face, + intelImage->level, + intelImage->base.Data, + intelImage->base.RowStride); + + free(intelImage->base.Data); + intelImage->base.Data = NULL; + } + + intelImage->mt = intel_miptree_reference(mt); +} + + +/* + */ +GLuint intel_validate_mipmap_tree( struct intel_context *intel, + struct intel_texture_object *intelObj ) +{ + GLuint face, i; + GLuint nr_faces = 0; + struct intel_texture_image *firstImage; + + /* We know/require this is true by now: + */ + assert(intelObj->base.Complete); + + /* What levels must the tree include at a minimum? + */ + intel_calculate_first_last_level( intelObj ); + firstImage = intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); + + /* Fallback case: + */ + if (firstImage->base.Border) { + if (intelObj->mt) { + intel_miptree_release(intel, intelObj->mt); + intelObj->mt = NULL; + } + return 0; + } + + + /* If both firstImage and intelObj have a tree which can contain + * all active images, favour firstImage. + */ + if (firstImage->mt && + firstImage->mt != intelObj->mt && + firstImage->mt->first_level <= intelObj->firstLevel && + firstImage->mt->last_level >= intelObj->lastLevel) { + + if (intelObj->mt) + intel_miptree_release(intel, intelObj->mt); + + intelObj->mt = intel_miptree_reference(firstImage->mt); + } + + /* Check tree can hold all active levels. Check tree matches + * target, imageFormat, etc. + */ + if (intelObj->mt && + ((intelObj->mt->first_level > intelObj->firstLevel) || + (intelObj->mt->last_level < intelObj->lastLevel) || + (intelObj->mt->internal_format != firstImage->base.InternalFormat))) { + intel_miptree_release(intel, intelObj->mt); + intelObj->mt = NULL; + } + + + /* May need to create a new tree: + */ + if (!intelObj->mt) { + assert(!firstImage->mt); + intelObj->mt = intel_miptree_create(intel, + intelObj->base.Target, + firstImage->base.InternalFormat, + intelObj->firstLevel, + intelObj->lastLevel, + firstImage->base.Width, + firstImage->base.Height, + firstImage->base.Depth, + firstImage->base.TexFormat->TexelBytes, + firstImage->base.IsCompressed); + } + + assert(intelObj->mt); + + assert(firstImage->mt == intelObj->mt || + firstImage->mt == NULL); + + nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + + for (face = 0; face < nr_faces; face++) { + for (i = intelObj->firstLevel; i < intelObj->lastLevel; i++) { + struct intel_texture_image *intelImage = + intel_texture_image(intelObj->base.Image[face][i]); + + /* Need to import images in main memory or held in other trees. + */ + if (intelObj->mt != intelImage->mt) { + copy_image_data_to_tree(intel, + intelObj->mt, + intelImage); + } + } + } + + return GL_TRUE; +} + + + + + + + |