Ejemplo n.º 1
0
static void radeonTexSubImage2D( 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 )
{
   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
   radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;

/*     fprintf(stderr, "%s\n", __FUNCTION__); */

   assert( t ); /* this _should_ be true */
   if ( t ) {
      radeonSwapOutTexObj( rmesa, t );
   }
   else {
      t = radeonAllocTexObj(texObj);
      if (!t) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
         return;
      }
      texObj->DriverData = t;
   }

   _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
			     height, format, type, pixels, packing, texObj,
			     texImage);

   t->dirty_images |= (1 << level);
}
Ejemplo n.º 2
0
static void radeonTexImage2D( 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 )
{
   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
   radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;

/*     fprintf(stderr, "%s\n", __FUNCTION__); */

   if ( t ) {
      radeonSwapOutTexObj( rmesa, t );
   }
   else {
      t = radeonAllocTexObj( texObj );
      if (!t) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
         return;
      }
      texObj->DriverData = t;
   }

   /* Note, this will call radeonChooseTextureFormat */
   _mesa_store_teximage2d(ctx, target, level, internalFormat,
                          width, height, border, format, type, pixels,
                          &ctx->Unpack, texObj, texImage);

   t->dirty_images |= (1 << level);
}
/**
 * Texture space has been invalidated.
 *
 * \param rmesa Radeon context.
 * \param heap texture heap number.
 * 
 * Swaps out every texture in the specified heap.
 */
void radeonAgeTextures( radeonContextPtr rmesa, int heap )
{
   radeonTexObjPtr t, tmp;

   foreach_s ( t, tmp, &rmesa->texture.objects[heap] ) 
      radeonSwapOutTexObj( rmesa, t );
}
Ejemplo n.º 4
0
static void radeonTexParameter( GLcontext *ctx, GLenum target,
				struct gl_texture_object *texObj,
				GLenum pname, const GLfloat *params )
{
   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
   radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;

   if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
      fprintf( stderr, "%s( %s )\n", __FUNCTION__,
	       _mesa_lookup_enum_by_nr( pname ) );
   }

   if ( ( target != GL_TEXTURE_2D ) &&
	( target != GL_TEXTURE_1D ) )
      return;

   switch ( pname ) {
   case GL_TEXTURE_MIN_FILTER:
   case GL_TEXTURE_MAG_FILTER:
   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
      radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
      radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
      break;

   case GL_TEXTURE_WRAP_S:
   case GL_TEXTURE_WRAP_T:
      radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
      break;

   case GL_TEXTURE_BORDER_COLOR:
      radeonSetTexBorderColor( t, texObj->BorderColor );
      break;

   case GL_TEXTURE_BASE_LEVEL:
   case GL_TEXTURE_MAX_LEVEL:
   case GL_TEXTURE_MIN_LOD:
   case GL_TEXTURE_MAX_LOD:
      /* This isn't the most efficient solution but there doesn't appear to
       * be a nice alternative for Radeon.  Since there's no LOD clamping,
       * we just have to rely on loading the right subset of mipmap levels
       * to simulate a clamped LOD.
       */
      radeonSwapOutTexObj( rmesa, t );
      break;

   default:
      return;
   }

   /* Mark this texobj as dirty (one bit per tex unit)
    */
   t->dirty_state = TEX_ALL;
}
/**
 * \brief Load a texture image.
 *
 * \param ctx GL context.
 * \param texObj texture object
 * \param target target texture.
 * \param level level of detail number.
 * \param internalFormat internal format.
 * \param width texture image width.
 * \param height texture image height.
 * \param border border width.
 * \param format pixel format.
 * \param type pixel data type.
 * \param pixels image data.
 * \param packing passed to _mesa_store_teximage2d() unchanged.
 * \param texImage passed to _mesa_store_teximage2d() unchanged.
 * 
 * If there is a device specific texture object associated with the given
 * texture object then swaps that texture out. Calls _mesa_store_teximage2d()
 * with all other parameters unchanged.
 */
static void radeonTexImage2D( 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 )
{
   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
   radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;

   if ( t ) 
      radeonSwapOutTexObj( rmesa, t );

   /* Note, this will call radeonChooseTextureFormat */
   _mesa_store_teximage2d(ctx, target, level, internalFormat,
                          width, height, border, format, type, pixels,
                          &ctx->Unpack, texObj, texImage);
}
/**
 * \brief Upload texture images.
 *
 * This might require removing our own and/or other client's texture objects to
 * make room for these images.
 *
 * \param rmesa Radeon context.
 * \param tObj texture object to upload.
 *
 * Sets the matching hardware texture format. Calculates which mipmap levels to
 * send, depending of the base image size, GL_TEXTURE_MIN_LOD,
 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL and the
 * Radeon offset rules. Kicks out textures until the requested texture fits,
 * sets the texture hardware state and, while holding the hardware lock,
 * uploads any images that are new.
 */
static void radeonSetTexImages( radeonContextPtr rmesa,
				struct gl_texture_object *tObj )
{
   radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
   GLint totalSize;
   GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0;
   GLint x, y, width, height;
   GLint i;
   GLint firstLevel, lastLevel, numLevels;
   GLint log2Width, log2Height;
   GLuint txformat = 0;

   /* This code cannot be reached once we have lost focus
    */
   assert(rmesa->radeonScreen->buffers);

   /* Set the hardware texture format
    */
   switch (baseImage->TexFormat->MesaFormat) {
   case MESA_FORMAT_I8:
      txformat = RADEON_TXFORMAT_I8;
      texelsPerDword = 4;
      blitPitch = 64;
      break;
   case MESA_FORMAT_RGBA8888:
      txformat = RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
      texelsPerDword = 1;
      blitPitch = 16;
      break;
   case MESA_FORMAT_RGB565:
      txformat = RADEON_TXFORMAT_RGB565;
      texelsPerDword = 2;
      blitPitch = 32;
      break;
   default:
      _mesa_problem(NULL, "unexpected texture format in radeonTexImage2D");
      return;
   }

   t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
		       RADEON_TXFORMAT_ALPHA_IN_MAP);
   t->pp_txformat |= txformat;


   /* Select the larger of the two widths for our global texture image
    * coordinate space.  As the Radeon has very strict offset rules, we
    * can't upload mipmaps directly and have to reference their location
    * from the aligned start of the whole image.
    */
   blitWidth = MAX2( baseImage->Width, blitPitch );

   /* Calculate mipmap offsets and dimensions.
    */
   totalSize = 0;
   x = 0;
   y = 0;

   /* Compute which mipmap levels we really want to send 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.
    * Yes, this looks overly complicated, but it's all needed.
    */
   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 */

   /* save these values */
   t->firstLevel = firstLevel;
   t->lastLevel = lastLevel;

   numLevels = lastLevel - firstLevel + 1;

   log2Width = tObj->Image[0][firstLevel]->WidthLog2;
   log2Height = tObj->Image[0][firstLevel]->HeightLog2;

   for ( i = 0 ; i < numLevels ; i++ ) {
      const struct gl_texture_image *texImage = tObj->Image[0][i + firstLevel];
      if ( !texImage )
	 break;

      width = texImage->Width;
      height = texImage->Height;

      /* Texture images have a minimum pitch of 32 bytes (half of the
       * 64-byte minimum pitch for blits).  For images that have a
       * width smaller than this, we must pad each texture image
       * scanline out to this amount.
       */
      if ( width < blitPitch / 2 ) {
	 width = blitPitch / 2;
      }

      totalSize += width * height * baseImage->TexFormat->TexelBytes;
      ASSERT( (totalSize & 31) == 0 );

      while ( width < blitWidth && height > 1 ) {
	 width *= 2;
	 height /= 2;
      }

      ASSERT(i < RADEON_MAX_TEXTURE_LEVELS);
      t->image[i].x = x;
      t->image[i].y = y;
      t->image[i].width  = width;
      t->image[i].height = height;

      /* While blits must have a pitch of at least 64 bytes, mipmaps
       * must be aligned on a 32-byte boundary (just like each texture
       * image scanline).
       */
      if ( width >= blitWidth ) {
	 y += height;
      } else {
	 x += width;
	 if ( x >= blitWidth ) {
	    x = 0;
	    y++;
	 }
      }
   }

   /* Align the total size of texture memory block.
    */
   t->totalSize = (totalSize + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;

   /* Hardware state:
    */
   t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
   t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;

   t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
		       RADEON_TXFORMAT_HEIGHT_MASK);
   t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
		      (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
   t->dirty_state = TEX_ALL;

   /* Update the local texture LRU.
    */
   move_to_head( &rmesa->texture.objects[0], t );

   LOCK_HARDWARE( rmesa );

   /* Kick out textures until the requested texture fits */
   while ( !t->memBlock ) {
      t->memBlock = mmAllocMem( rmesa->texture.heap[0], t->totalSize, 12, 0);
	 
      if (!t->memBlock)
	 radeonSwapOutTexObj( rmesa, rmesa->texture.objects[0].prev );
	 
   }

   /* Set the base offset of the texture image */
   t->bufAddr = rmesa->radeonScreen->texOffset[0] + t->memBlock->ofs;
   t->pp_txoffset = t->bufAddr;

   /* Upload any images that are new 
    */
   for ( i = 0 ; i < numLevels ; i++ ) {
      if ( t->dirty_images & (1 << i) ) {
	 radeonUploadSubImage( rmesa, t, i, 0, 0,
			       t->image[i].width, t->image[i].height );
      }
   }

   rmesa->texture.age[0] = ++rmesa->sarea->texAge[0]; 
   UNLOCK_HARDWARE( rmesa );
   t->dirty_images = 0;
}