static void gen2_emit_texture(struct intel_batchbuffer *batch,
			      struct igt_buf *src,
			      int unit)
{
	uint32_t tiling;

	tiling = 0;
	if (src->tiling != I915_TILING_NONE)
		tiling = TM0S1_TILED_SURFACE;
	if (src->tiling == I915_TILING_Y)
		tiling |= TM0S1_TILE_WALK;

	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
	OUT_RELOC(src->bo, I915_GEM_DOMAIN_SAMPLER, 0, 0);
	OUT_BATCH((igt_buf_height(src) - 1) << TM0S1_HEIGHT_SHIFT |
		  (igt_buf_width(src) - 1) << TM0S1_WIDTH_SHIFT |
		  MAPSURF_32BIT | MT_32BIT_ARGB8888 | tiling);
	OUT_BATCH((src->stride / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
	OUT_BATCH(FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT |
		  FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT |
		  MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);
	OUT_BATCH(0);	/* default color */

	OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
		  ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
		  TEXCOORDTYPE_CARTESIAN |
		  ENABLE_ADDR_V_CNTL | TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER) |
		  ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER));
}
Exemplo n.º 2
0
intelTextureObjectPtr i830AllocTexObj( struct gl_texture_object *texObj )
{
   i830TextureObjectPtr t = CALLOC_STRUCT( i830_texture_object );
   if ( !t ) 
      return NULL;

   texObj->DriverData = t;
   t->intel.base.tObj = texObj;
   t->intel.dirty = I830_UPLOAD_TEX_ALL;
   make_empty_list( &t->intel.base );

   t->Setup[I830_TEXREG_TM0LI] = 0; /* not used */
   t->Setup[I830_TEXREG_TM0S0] = 0;
   t->Setup[I830_TEXREG_TM0S1] = 0;
   t->Setup[I830_TEXREG_TM0S2] = 0;
   t->Setup[I830_TEXREG_TM0S3] = 0;
   t->Setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
				MAP_UNIT(0) |
				ENABLE_TEXCOORD_PARAMS |
				TEXCOORDS_ARE_NORMAL |
				TEXCOORDTYPE_CARTESIAN |
				ENABLE_ADDR_V_CNTL |
				TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
				ENABLE_ADDR_U_CNTL |
				TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));

   
   i830SetTexWrapping( t, texObj->WrapS, texObj->WrapT );
   i830SetTexFilter( t, texObj->MinFilter, texObj->MagFilter, 
		     texObj->MaxAnisotropy );
   i830SetTexBorderColor( t, texObj->_BorderChan );

   return &t->intel;
}
Exemplo n.º 3
0
/**
 * Set the texture wrap modes.
 * 
 * The i830M (and related graphics cores) do not support GL_CLAMP.  The Intel
 * drivers for "other operating systems" implement GL_CLAMP as
 * GL_CLAMP_TO_EDGE, so the same is done here.
 * 
 * \param t Texture object whose wrap modes are to be set
 * \param swrap Wrap mode for the \a s texture coordinate
 * \param twrap Wrap mode for the \a t texture coordinate
 */
static void i830SetTexWrapping(i830TextureObjectPtr tex,
			       GLenum swrap, 
			       GLenum twrap)
{
   tex->Setup[I830_TEXREG_MCS] &= ~(TEXCOORD_ADDR_U_MASK|TEXCOORD_ADDR_V_MASK);

   switch( swrap ) {
   case GL_REPEAT:
      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP);
      break;
   case GL_CLAMP:
   case GL_CLAMP_TO_EDGE:
      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP);
      break;
   case GL_CLAMP_TO_BORDER:
      tex->Setup[I830_TEXREG_MCS] |= 
			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP_BORDER);
      break;
   case GL_MIRRORED_REPEAT:
      tex->Setup[I830_TEXREG_MCS] |= 
			TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_MIRROR);
      break;
   default:
      break;
   }

   switch( twrap ) {
   case GL_REPEAT:
      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP);
      break;
   case GL_CLAMP:
   case GL_CLAMP_TO_EDGE:
      tex->Setup[I830_TEXREG_MCS] |= TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP);
      break;
   case GL_CLAMP_TO_BORDER:
      tex->Setup[I830_TEXREG_MCS] |= 
			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP_BORDER);
      break;
   case GL_MIRRORED_REPEAT:
      tex->Setup[I830_TEXREG_MCS] |=
			TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_MIRROR);
      break;
   default:
      break;
   }
}
Exemplo n.º 4
0
/* Set up an arbitary piece of memory as a rectangular texture
 * (including the front or back buffer).
 */
static void set_tex_rect_source( i830ContextPtr i830,
				 GLuint offset,
				 GLuint width, 
				 GLuint height,
				 GLuint pitch, /* in bytes */
				 GLuint textureFormat )
{
   GLint numLevels = 1;
   GLuint *setup = i830->meta.Tex[0];

/*    fprintf(stderr, "%s: offset: %x w: %d h: %d pitch %d format %x\n", */
/* 	   __FUNCTION__, offset, width, height, pitch, textureFormat ); */

   setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 | 
			       (LOAD_TEXTURE_MAP0 << 0) | 4);
   setup[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | offset);
   setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
			       ((width - 1) << TM0S1_WIDTH_SHIFT) |
			       textureFormat);
   setup[I830_TEXREG_TM0S2] = ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT));   
   setup[I830_TEXREG_TM0S3] &= ~TM0S3_MAX_MIP_MASK;
   setup[I830_TEXREG_TM0S3] &= ~TM0S3_MIN_MIP_MASK;
   setup[I830_TEXREG_TM0S3] |= ((numLevels - 1)*4) << TM0S3_MIN_MIP_SHIFT;

   setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
			     MAP_UNIT(0) |
			     ENABLE_TEXCOORD_PARAMS |
			     TEXCOORDS_ARE_IN_TEXELUNITS |
			     TEXCOORDTYPE_CARTESIAN |
			     ENABLE_ADDR_V_CNTL |
			     TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
			     ENABLE_ADDR_U_CNTL |
			     TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));

   i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
}
/* Set up an arbitary piece of memory as a rectangular texture
 * (including the front or back buffer).
 */
static GLboolean
set_tex_rect_source(struct intel_context *intel,
                    dri_bo *buffer,
                    GLuint offset,
                    GLuint pitch, GLuint height, GLenum format, GLenum type)
{
   struct i830_context *i830 = i830_context(&intel->ctx);
   GLuint *setup = i830->meta.Tex[0];
   GLint numLevels = 1;
   GLuint textureFormat;
   GLuint cpp;

   /* A full implementation of this would do the upload through
    * glTexImage2d, and get all the conversion operations at that
    * point.  We are restricted, but still at least have access to the
    * fragment program swizzle.
    */
   switch (format) {
   case GL_BGRA:
      switch (type) {
      case GL_UNSIGNED_INT_8_8_8_8_REV:
      case GL_UNSIGNED_BYTE:
         textureFormat = (MAPSURF_32BIT | MT_32BIT_ARGB8888);
         cpp = 4;
         break;
      default:
         return GL_FALSE;
      }
      break;
   case GL_RGBA:
      switch (type) {
      case GL_UNSIGNED_INT_8_8_8_8_REV:
      case GL_UNSIGNED_BYTE:
         textureFormat = (MAPSURF_32BIT | MT_32BIT_ABGR8888);
         cpp = 4;
         break;
      default:
         return GL_FALSE;
      }
      break;
   case GL_BGR:
      switch (type) {
      case GL_UNSIGNED_SHORT_5_6_5_REV:
         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
         cpp = 2;
         break;
      default:
         return GL_FALSE;
      }
      break;
   case GL_RGB:
      switch (type) {
      case GL_UNSIGNED_SHORT_5_6_5:
         textureFormat = (MAPSURF_16BIT | MT_16BIT_RGB565);
         cpp = 2;
         break;
      default:
         return GL_FALSE;
      }
      break;

   default:
      return GL_FALSE;
   }

   i830->meta.tex_buffer[0] = buffer;
   i830->meta.tex_offset[0] = offset;

   setup[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
                               (LOAD_TEXTURE_MAP0 << 0) | 4);
   setup[I830_TEXREG_TM0S1] = (((height - 1) << TM0S1_HEIGHT_SHIFT) |
                               ((pitch - 1) << TM0S1_WIDTH_SHIFT) |
                               textureFormat);
   setup[I830_TEXREG_TM0S2] =
      (((((pitch * cpp) / 4) -
         1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);

   setup[I830_TEXREG_TM0S3] =
      ((((numLevels -
          1) *
         4) << TM0S3_MIN_MIP_SHIFT) | (FILTER_NEAREST <<
                                       TM0S3_MIN_FILTER_SHIFT) |
       (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT) | (FILTER_NEAREST <<
                                                     TM0S3_MAG_FILTER_SHIFT));

   setup[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(0));

   setup[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
                             MAP_UNIT(0) |
                             ENABLE_TEXCOORD_PARAMS |
                             TEXCOORDS_ARE_IN_TEXELUNITS |
                             TEXCOORDTYPE_CARTESIAN |
                             ENABLE_ADDR_V_CNTL |
                             TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_WRAP) |
                             ENABLE_ADDR_U_CNTL |
                             TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_WRAP));

   i830->meta.emitted &= ~I830_UPLOAD_TEX(0);
   return GL_TRUE;
}
/* 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
i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
{
   GLcontext *ctx = &intel->ctx;
   struct i830_context *i830 = i830_context(ctx);
   struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_texture_image *firstImage;
   GLuint *state = i830->state.Tex[unit], format, pitch;

   memset(state, 0, sizeof(state));

   /*We need to refcount these. */

   if (i830->state.tex_buffer[unit] != NULL) {
       dri_bo_unreference(i830->state.tex_buffer[unit]);
       i830->state.tex_buffer[unit] = NULL;
   }

   if (!intelObj->imageOverride && !intel_finalize_mipmap_tree(intel, unit))
      return GL_FALSE;

   /* Get first image here, since intelObj->firstLevel will get set in
    * the intel_finalize_mipmap_tree() call above.
    */
   firstImage = tObj->Image[0][intelObj->firstLevel];

   if (intelObj->imageOverride) {
      i830->state.tex_buffer[unit] = NULL;
      i830->state.tex_offset[unit] = intelObj->textureOffset;

      switch (intelObj->depthOverride) {
      case 32:
	 format = MAPSURF_32BIT | MT_32BIT_ARGB8888;
	 break;
      case 24:
      default:
	 format = MAPSURF_32BIT | MT_32BIT_XRGB8888;
	 break;
      case 16:
	 format = MAPSURF_16BIT | MT_16BIT_RGB565;
	 break;
      }

      pitch = intelObj->pitchOverride;
   } else {
      dri_bo_reference(intelObj->mt->region->buffer);
      i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
      i830->state.tex_offset[unit] = intel_miptree_image_offset(intelObj->mt,
								0, intelObj->
								firstLevel);

      format = translate_texture_format(firstImage->TexFormat->MesaFormat);
      pitch = intelObj->mt->pitch * intelObj->mt->cpp;
   }

   state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
                               (LOAD_TEXTURE_MAP0 << unit) | 4);

/*    state[I830_TEXREG_TM0S0] = (TM0S0_USE_FENCE | */
/* 			       t->intel.TextureOffset); */


   state[I830_TEXREG_TM0S1] =
      (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
       ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);

   state[I830_TEXREG_TM0S2] =
      ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);

   {
      if (tObj->Target == GL_TEXTURE_CUBE_MAP)
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
                                    CUBE_NEGX_ENABLE |
                                    CUBE_POSX_ENABLE |
                                    CUBE_NEGY_ENABLE |
                                    CUBE_POSY_ENABLE |
                                    CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
      else
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
   }




   {
      GLuint minFilt, mipFilt, magFilt;

      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;
      }

      if (tObj->MaxAnisotropy > 1.0) {
         minFilt = FILTER_ANISOTROPIC;
         magFilt = FILTER_ANISOTROPIC;
      }
      else {
         switch (tObj->MagFilter) {
         case GL_NEAREST:
            magFilt = FILTER_NEAREST;
            break;
         case GL_LINEAR:
            magFilt = FILTER_LINEAR;
            break;
         default:
            return GL_FALSE;
         }
      }

      state[I830_TEXREG_TM0S3] = i830->lodbias_tm0s3[unit];

#if 0
      /* YUV conversion:
       */
      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
         state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
#endif

      state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
                                    intelObj->firstLevel) *
                                   4) << TM0S3_MIN_MIP_SHIFT;

      state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
                                   (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
                                   (magFilt << TM0S3_MAG_FILTER_SHIFT));
   }

   {
      GLenum ws = tObj->WrapS;
      GLenum wt = tObj->WrapT;


      /* 3D textures not available on i830
       */
      if (tObj->Target == GL_TEXTURE_3D)
         return GL_FALSE;

      state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
                                MAP_UNIT(unit) |
                                ENABLE_TEXCOORD_PARAMS |
                                ss3 |
                                ENABLE_ADDR_V_CNTL |
                                TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
                                | ENABLE_ADDR_U_CNTL |
                                TEXCOORD_ADDR_U_MODE(translate_wrap_mode
                                                     (ws)));
   }


   state[I830_TEXREG_TM0S4] = INTEL_PACKCOLOR8888(tObj->_BorderChan[0],
                                                  tObj->_BorderChan[1],
                                                  tObj->_BorderChan[2],
                                                  tObj->_BorderChan[3]);


   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
   /* memcmp was already disabled, but definitely won't work as the
    * region might now change and that wouldn't be detected:
    */
   I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
   return GL_TRUE;
}
Exemplo n.º 7
0
static void i830_texture_setup(PicturePtr picture, PixmapPtr pixmap, int unit)
{

	ScrnInfoPtr scrn = xf86Screens[picture->pDrawable->pScreen->myNum];
	intel_screen_private *intel = intel_get_screen_private(scrn);
	uint32_t format, tiling_bits, pitch, filter;
	uint32_t wrap_mode;
	uint32_t texcoordtype;

	pitch = intel_pixmap_pitch(pixmap);
	intel->scale_units[unit][0] = pixmap->drawable.width;
	intel->scale_units[unit][1] = pixmap->drawable.height;
	intel->transform[unit] = picture->transform;

	if (intel_transform_is_affine(intel->transform[unit]))
		texcoordtype = TEXCOORDTYPE_CARTESIAN;
	else
		texcoordtype = TEXCOORDTYPE_HOMOGENEOUS;

	switch (picture->repeatType) {
	case RepeatNone:
		wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
		break;
	case RepeatNormal:
		wrap_mode = TEXCOORDMODE_WRAP;
		break;
	case RepeatPad:
		wrap_mode = TEXCOORDMODE_CLAMP;
		break;
	case RepeatReflect:
		wrap_mode = TEXCOORDMODE_MIRROR;
		break;
	default:
		FatalError("Unknown repeat type %d\n", picture->repeatType);
	}

	switch (picture->filter) {
	case PictFilterNearest:
		filter = ((FILTER_NEAREST << TM0S3_MAG_FILTER_SHIFT) |
			  (FILTER_NEAREST << TM0S3_MIN_FILTER_SHIFT));
		break;
	case PictFilterBilinear:
		filter = ((FILTER_LINEAR << TM0S3_MAG_FILTER_SHIFT) |
			  (FILTER_LINEAR << TM0S3_MIN_FILTER_SHIFT));
		break;
	default:
		filter = 0;
		FatalError("Bad filter 0x%x\n", picture->filter);
	}
	filter |= (MIPFILTER_NONE << TM0S3_MIP_FILTER_SHIFT);

	if (intel_pixmap_tiled(pixmap)) {
		tiling_bits = TM0S1_TILED_SURFACE;
		if (intel_get_pixmap_private(pixmap)->tiling
				== I915_TILING_Y)
			tiling_bits |= TM0S1_TILE_WALK;
	} else
		tiling_bits = 0;

	format = i8xx_get_card_format(intel, picture);

	assert(intel->in_batch_atomic);

	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
		  LOAD_TEXTURE_MAP(unit) | 4);
	OUT_RELOC_PIXMAP(pixmap, I915_GEM_DOMAIN_SAMPLER, 0, 0);
	OUT_BATCH(((pixmap->drawable.height -
		    1) << TM0S1_HEIGHT_SHIFT) | ((pixmap->drawable.width -
						  1) <<
						 TM0S1_WIDTH_SHIFT) |
		  format | tiling_bits);
	OUT_BATCH((pitch / 4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
	OUT_BATCH(filter);
	OUT_BATCH(0);	/* default color */
	OUT_BATCH(_3DSTATE_MAP_COORD_SET_CMD | TEXCOORD_SET(unit) |
		  ENABLE_TEXCOORD_PARAMS | TEXCOORDS_ARE_NORMAL |
		  texcoordtype | ENABLE_ADDR_V_CNTL |
		  TEXCOORD_ADDR_V_MODE(wrap_mode) |
		  ENABLE_ADDR_U_CNTL | TEXCOORD_ADDR_U_MODE(wrap_mode));
	/* map texel stream */
	OUT_BATCH(_3DSTATE_MAP_COORD_SETBIND_CMD);
	if (unit == 0)
		OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
			  TEXBIND_SET1(TEXCOORDSRC_KEEP) |
			  TEXBIND_SET2(TEXCOORDSRC_KEEP) |
			  TEXBIND_SET3(TEXCOORDSRC_KEEP));
	else
		OUT_BATCH(TEXBIND_SET0(TEXCOORDSRC_VTXSET_0) |
			  TEXBIND_SET1(TEXCOORDSRC_VTXSET_1) |
			  TEXBIND_SET2(TEXCOORDSRC_KEEP) |
			  TEXBIND_SET3(TEXCOORDSRC_KEEP));
	OUT_BATCH(_3DSTATE_MAP_TEX_STREAM_CMD | (unit << 16) |
		  DISABLE_TEX_STREAM_BUMP |
		  ENABLE_TEX_STREAM_COORD_SET |
		  TEX_STREAM_COORD_SET(unit) |
		  ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(unit));
}
Exemplo n.º 8
0
/* 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
i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
{
   GLcontext *ctx = &intel->ctx;
   struct i830_context *i830 = i830_context(ctx);
   struct gl_texture_unit *tUnit = &ctx->Texture.Unit[unit];
   struct gl_texture_object *tObj = tUnit->_Current;
   struct intel_texture_object *intelObj = intel_texture_object(tObj);
   struct gl_texture_image *firstImage;
   GLuint *state = i830->state.Tex[unit], format, pitch;
   GLint lodbias;
   GLubyte border[4];
   GLuint dst_x, dst_y;

   memset(state, 0, sizeof(state));

   /*We need to refcount these. */

   if (i830->state.tex_buffer[unit] != NULL) {
       drm_intel_bo_unreference(i830->state.tex_buffer[unit]);
       i830->state.tex_buffer[unit] = NULL;
   }

   if (!intel_finalize_mipmap_tree(intel, unit))
      return GL_FALSE;

   /* Get first image here, since intelObj->firstLevel will get set in
    * the intel_finalize_mipmap_tree() call above.
    */
   firstImage = tObj->Image[0][intelObj->firstLevel];

   intel_miptree_get_image_offset(intelObj->mt, intelObj->firstLevel, 0, 0,
				  &dst_x, &dst_y);

   drm_intel_bo_reference(intelObj->mt->region->buffer);
   i830->state.tex_buffer[unit] = intelObj->mt->region->buffer;
   pitch = intelObj->mt->region->pitch * intelObj->mt->cpp;

   /* XXX: This calculation is probably broken for tiled images with
    * a non-page-aligned offset.
    */
   i830->state.tex_offset[unit] = dst_x * intelObj->mt->cpp + dst_y * pitch;

   format = translate_texture_format(firstImage->TexFormat,
				     firstImage->InternalFormat);

   state[I830_TEXREG_TM0LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_2 |
                               (LOAD_TEXTURE_MAP0 << unit) | 4);

   state[I830_TEXREG_TM0S1] =
      (((firstImage->Height - 1) << TM0S1_HEIGHT_SHIFT) |
       ((firstImage->Width - 1) << TM0S1_WIDTH_SHIFT) | format);

   if (intelObj->mt->region->tiling != I915_TILING_NONE) {
      state[I830_TEXREG_TM0S1] |= TM0S1_TILED_SURFACE;
      if (intelObj->mt->region->tiling == I915_TILING_Y)
	 state[I830_TEXREG_TM0S1] |= TM0S1_TILE_WALK;
   }

   state[I830_TEXREG_TM0S2] =
      ((((pitch / 4) - 1) << TM0S2_PITCH_SHIFT) | TM0S2_CUBE_FACE_ENA_MASK);

   {
      if (tObj->Target == GL_TEXTURE_CUBE_MAP)
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit) |
                                    CUBE_NEGX_ENABLE |
                                    CUBE_POSX_ENABLE |
                                    CUBE_NEGY_ENABLE |
                                    CUBE_POSY_ENABLE |
                                    CUBE_NEGZ_ENABLE | CUBE_POSZ_ENABLE);
      else
         state[I830_TEXREG_CUBE] = (_3DSTATE_MAP_CUBE | MAP_UNIT(unit));
   }




   {
      GLuint minFilt, mipFilt, magFilt;

      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;
      }

      if (tObj->MaxAnisotropy > 1.0) {
         minFilt = FILTER_ANISOTROPIC;
         magFilt = FILTER_ANISOTROPIC;
      }
      else {
         switch (tObj->MagFilter) {
         case GL_NEAREST:
            magFilt = FILTER_NEAREST;
            break;
         case GL_LINEAR:
            magFilt = FILTER_LINEAR;
            break;
         default:
            return GL_FALSE;
         }
      }

      lodbias = (int) ((tUnit->LodBias + tObj->LodBias) * 16.0);
      if (lodbias < -64)
          lodbias = -64;
      if (lodbias > 63)
          lodbias = 63;
      
      state[I830_TEXREG_TM0S3] = ((lodbias << TM0S3_LOD_BIAS_SHIFT) & 
                                  TM0S3_LOD_BIAS_MASK);
#if 0
      /* YUV conversion:
       */
      if (firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR ||
          firstImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV)
         state[I830_TEXREG_TM0S3] |= SS2_COLORSPACE_CONVERSION;
#endif

      state[I830_TEXREG_TM0S3] |= ((intelObj->lastLevel -
                                    intelObj->firstLevel) *
                                   4) << TM0S3_MIN_MIP_SHIFT;

      state[I830_TEXREG_TM0S3] |= ((minFilt << TM0S3_MIN_FILTER_SHIFT) |
                                   (mipFilt << TM0S3_MIP_FILTER_SHIFT) |
                                   (magFilt << TM0S3_MAG_FILTER_SHIFT));
   }

   {
      GLenum ws = tObj->WrapS;
      GLenum wt = tObj->WrapT;


      /* 3D textures not available on i830
       */
      if (tObj->Target == GL_TEXTURE_3D)
         return GL_FALSE;

      state[I830_TEXREG_MCS] = (_3DSTATE_MAP_COORD_SET_CMD |
                                MAP_UNIT(unit) |
                                ENABLE_TEXCOORD_PARAMS |
                                ss3 |
                                ENABLE_ADDR_V_CNTL |
                                TEXCOORD_ADDR_V_MODE(translate_wrap_mode(wt))
                                | ENABLE_ADDR_U_CNTL |
                                TEXCOORD_ADDR_U_MODE(translate_wrap_mode
                                                     (ws)));
   }

   /* convert border color from float to ubyte */
   CLAMPED_FLOAT_TO_UBYTE(border[0], tObj->BorderColor.f[0]);
   CLAMPED_FLOAT_TO_UBYTE(border[1], tObj->BorderColor.f[1]);
   CLAMPED_FLOAT_TO_UBYTE(border[2], tObj->BorderColor.f[2]);
   CLAMPED_FLOAT_TO_UBYTE(border[3], tObj->BorderColor.f[3]);

   state[I830_TEXREG_TM0S4] = PACK_COLOR_8888(border[3],
					      border[0],
					      border[1],
					      border[2]);

   I830_ACTIVESTATE(i830, I830_UPLOAD_TEX(unit), GL_TRUE);
   /* memcmp was already disabled, but definitely won't work as the
    * region might now change and that wouldn't be detected:
    */
   I830_STATECHANGE(i830, I830_UPLOAD_TEX(unit));
   return GL_TRUE;
}