-/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.7 2002/12/16 16:18:59 dawes Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
*/
#include <errno.h>
-#include "glheader.h"
-#include "imports.h"
-#include "context.h"
-#include "macros.h"
-#include "simple_list.h"
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_tex.h"
+#include <unistd.h> /* for usleep() */
+
/**
* Destroy any device-dependent state associated with the texture. This may
for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) {
if ( t == rmesa->state.texture.unit[i].texobj ) {
rmesa->state.texture.unit[i].texobj = NULL;
- remove_from_list( &rmesa->hw.tex[i] );
- make_empty_list( &rmesa->hw.tex[i] );
}
}
}
/* Blit to framebuffer
*/
- radeonEmitBlit( rmesa,
- blit_format,
- dstPitch, GET_START( ®ion ),
- dstPitch, t->bufAddr,
- 0, 0,
- 0, done,
+ radeonEmitBlit( rmesa,
+ blit_format,
+ dstPitch, GET_START( ®ion ),
+ dstPitch, t->bufAddr,
+ 0, 0,
+ 0, done,
width, lines );
radeonEmitWait( rmesa, RADEON_WAIT_2D );
imageWidth = texImage->Width;
imageHeight = texImage->Height;
- offset = t->bufAddr;
+ offset = t->bufAddr + t->base.totalSize * face / 6;
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
GLint imageX = 0;
* We used to use 1, 2 and 4-byte texels and used to use the texture
* width to dictate the blit width - but that won't work for compressed
* textures. (Brian)
+ * NOTE: can't do that with texture tiling. (sroland)
*/
tex.offset = offset;
- tex.pitch = BLIT_WIDTH_BYTES / 64;
- tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
+ tex.image = &tmp;
+ /* copy (x,y,width,height,data) */
+ memcpy( &tmp, &t->image[face][hwlevel], sizeof(drm_radeon_tex_image_t) );
+
if (texImage->TexFormat->TexelBytes) {
- tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */
+ /* use multi-byte upload scheme */
tex.height = imageHeight;
+ tex.width = imageWidth;
+ tex.format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK;
+ tex.pitch = MAX2((texImage->Width * texImage->TexFormat->TexelBytes) / 64, 1);
+ tex.offset += tmp.x & ~1023;
+ tmp.x = tmp.x % 1024;
+ if (t->tile_bits & RADEON_TXO_MICRO_TILE_X2) {
+ /* need something like "tiled coordinates" ? */
+ tmp.y = tmp.x / (tex.pitch * 128) * 2;
+ tmp.x = tmp.x % (tex.pitch * 128) / 2 / texImage->TexFormat->TexelBytes;
+ tex.pitch |= RADEON_DST_TILE_MICRO >> 22;
+ }
+ else {
+ tmp.x = tmp.x >> (texImage->TexFormat->TexelBytes >> 1);
+ }
+ if ((t->tile_bits & RADEON_TXO_MACRO_TILE) &&
+ (texImage->Width * texImage->TexFormat->TexelBytes >= 256)) {
+ /* radeon switches off macro tiling for small textures/mipmaps it seems */
+ tex.pitch |= RADEON_DST_TILE_MACRO >> 22;
+ }
}
else {
- tex.width = imageWidth; /* compressed */
- tex.height = imageHeight;
- if (tex.height < 4)
- tex.height = 4;
+ /* In case of for instance 8x8 texture (2x2 dxt blocks), padding after the first two blocks is
+ needed (only with dxt1 since 2 dxt3/dxt5 blocks already use 32 Byte). */
+ /* set tex.height to 1/4 since 1 "macropixel" (dxt-block) has 4 real pixels. Needed
+ so the kernel module reads the right amount of data. */
+ tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
+ tex.pitch = (BLIT_WIDTH_BYTES / 64);
+ tex.height = (imageHeight + 3) / 4;
+ tex.width = (imageWidth + 3) / 4;
+ switch (t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK) {
+ case RADEON_TXFORMAT_DXT1:
+ tex.width *= 8;
+ break;
+ case RADEON_TXFORMAT_DXT23:
+ case RADEON_TXFORMAT_DXT45:
+ tex.width *= 16;
+ break;
+ }
}
- tex.image = &tmp;
-
- /* copy (x,y,width,height,data) */
- memcpy( &tmp, &t->image[face][hwlevel], sizeof(drm_radeon_tex_image_t) );
LOCK_HARDWARE( rmesa );
do {
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
&tex, sizeof(drm_radeon_texture_t) );
- } while ( ret && errno == EAGAIN );
+ } while ( ret == -EAGAIN );
UNLOCK_HARDWARE( rmesa );
int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t, GLuint face )
{
- const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+ int numLevels;
+
+ if ( !t || t->base.totalSize == 0 || t->image_override )
+ return 0;
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
t->base.firstLevel, t->base.lastLevel );
}
- if ( !t || t->base.totalSize == 0 )
- return 0;
+ numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+
+ if (RADEON_DEBUG & DEBUG_SYNC) {
+ fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
+ radeonFinish( rmesa->glCtx );
+ }
LOCK_HARDWARE( rmesa );
+ t->base.memBlock->ofs;
t->pp_txoffset = t->bufAddr;
+ if (!(t->base.tObj->Image[0][0]->IsClientData)) {
+ /* hope it's safe to add that here... */
+ t->pp_txoffset |= t->tile_bits;
+ }
/* Mark this texobj as dirty on all units:
*/
t->base.dirty_images[face] = 0;
}
+ if (RADEON_DEBUG & DEBUG_SYNC) {
+ fprintf(stderr, "%s: Syncing\n", __FUNCTION__ );
+ radeonFinish( rmesa->glCtx );
+ }
+
return 0;
}