#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "macros.h"
#include "simple_list.h"
#include "radeon_context.h"
#include "radeon_ioctl.h"
#include "radeon_tex.h"
void
radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
{
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, (void *)t, (void *)t->base.tObj );
}
if ( rmesa != NULL ) {
unsigned i;
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] );
}
}
}
}
static void radeonUploadRectSubImage( radeonContextPtr rmesa,
radeonTexObjPtr t,
struct gl_texture_image *texImage,
GLint x, GLint y,
GLint width, GLint height )
{
const struct gl_texture_format *texFormat = texImage->TexFormat;
int blit_format, dstPitch, done;
switch ( texFormat->TexelBytes ) {
case 1:
blit_format = RADEON_GMC_DST_8BPP_CI;
break;
case 2:
blit_format = RADEON_GMC_DST_16BPP;
break;
case 4:
blit_format = RADEON_GMC_DST_32BPP;
break;
default:
fprintf( stderr, "radeonUploadRectSubImage: unknown blit_format (texelbytes=%d)\n",
texFormat->TexelBytes);
return;
}
t->image[0][0].data = texImage->Data;
width = texImage->Width;
height = texImage->Height;
dstPitch = t->pp_txpitch + 32;
{
for (done = 0; done < height ; ) {
struct radeon_dma_region region;
int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
int src_pitch;
char *tex;
src_pitch = texImage->RowStride * texFormat->TexelBytes;
tex = (char *)texImage->Data + done * src_pitch;
memset(®ion, 0, sizeof(region));
radeonAllocDmaRegion( rmesa, ®ion, lines * dstPitch, 1024 );
if (0)
fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
__FUNCTION__, src_pitch, dstPitch);
if (src_pitch == dstPitch) {
memcpy( region.address, tex, lines * src_pitch );
}
else {
char *buf = region.address;
int i;
for (i = 0 ; i < lines ; i++) {
memcpy( buf, tex, src_pitch );
buf += dstPitch;
tex += src_pitch;
}
}
radeonEmitWait( rmesa, RADEON_WAIT_3D );
radeonEmitBlit( rmesa,
blit_format,
dstPitch, GET_START( ®ion ),
dstPitch, t->bufAddr,
0, 0,
0, done,
width, lines );
radeonEmitWait( rmesa, RADEON_WAIT_2D );
radeonReleaseDmaRegion( rmesa, ®ion, __FUNCTION__ );
done += lines;
}
}
}
static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t,
GLint hwlevel,
GLint x, GLint y, GLint width, GLint height,
GLuint face )
{
struct gl_texture_image *texImage = NULL;
GLuint offset;
GLint imageWidth, imageHeight;
GLint ret;
drmRadeonTexture tex;
drmRadeonTexImage tmp;
const int level = hwlevel + t->base.firstLevel;
if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n",
__FUNCTION__, (void *)t, (void *)t->base.tObj, level, width, height, face );
}
ASSERT(face < 6);
if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
_mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
return;
}
switch (face) {
case 0:
texImage = t->base.tObj->Image[level];
break;
case 1:
texImage = t->base.tObj->NegX[level];
break;
case 2:
texImage = t->base.tObj->PosY[level];
break;
case 3:
texImage = t->base.tObj->NegY[level];
break;
case 4:
texImage = t->base.tObj->PosZ[level];
break;
case 5:
texImage = t->base.tObj->NegZ[level];
break;
}
if ( !texImage ) {
if ( RADEON_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
return;
}
if ( !texImage->Data ) {
if ( RADEON_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
return;
}
if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
assert(level == 0);
assert(hwlevel == 0);
if ( RADEON_DEBUG & DEBUG_TEXTURE )
fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
radeonUploadRectSubImage( rmesa, t, texImage, x, y, width, height );
return;
}
imageWidth = texImage->Width;
imageHeight = texImage->Height;
offset = t->bufAddr;
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
GLint imageX = 0;
GLint imageY = 0;
GLint blitX = t->image[face][hwlevel].x;
GLint blitY = t->image[face][hwlevel].y;
GLint blitWidth = t->image[face][hwlevel].width;
GLint blitHeight = t->image[face][hwlevel].height;
fprintf( stderr, " upload image: %d,%d at %d,%d\n",
imageWidth, imageHeight, imageX, imageY );
fprintf( stderr, " upload blit: %d,%d at %d,%d\n",
blitWidth, blitHeight, blitX, blitY );
fprintf( stderr, " blit ofs: 0x%07x level: %d/%d\n",
(GLuint)offset, hwlevel, level );
}
t->image[face][hwlevel].data = texImage->Data;
tex.offset = offset;
tex.pitch = BLIT_WIDTH_BYTES / 64;
tex.format = RADEON_TXFORMAT_I8;
if (texImage->TexFormat->TexelBytes) {
tex.width = imageWidth * texImage->TexFormat->TexelBytes;
tex.height = imageHeight;
}
else {
tex.width = imageWidth;
tex.height = imageHeight;
if (tex.height < 4)
tex.height = 4;
}
tex.image = &tmp;
memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) );
LOCK_HARDWARE( rmesa );
do {
ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
&tex, sizeof(drmRadeonTexture) );
} while ( ret && errno == EAGAIN );
UNLOCK_HARDWARE( rmesa );
if ( ret ) {
fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
fprintf( stderr, " offset=0x%08x\n",
offset );
fprintf( stderr, " image width=%d height=%d\n",
imageWidth, imageHeight );
fprintf( stderr, " blit width=%d height=%d data=%p\n",
t->image[face][hwlevel].width, t->image[face][hwlevel].height,
t->image[face][hwlevel].data );
exit( 1 );
}
}
int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t, GLuint face )
{
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
(void *)rmesa->glCtx, (void *)t->base.tObj, t->base.totalSize,
t->base.firstLevel, t->base.lastLevel );
}
if ( !t || t->base.totalSize == 0 )
return 0;
LOCK_HARDWARE( rmesa );
if ( t->base.memBlock == NULL ) {
int heap;
heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( rmesa );
return -1;
}
t->bufAddr = rmesa->radeonScreen->texOffset[heap]
+ t->base.memBlock->ofs;
t->pp_txoffset = t->bufAddr;
t->dirty_state = TEX_ALL;
}
driUpdateTextureLRU( (driTextureObject *) t );
UNLOCK_HARDWARE( rmesa );
if (t->base.dirty_images[face]) {
int i;
for ( i = 0 ; i < numLevels ; i++ ) {
if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
t->image[face][i].height, face );
}
}
t->base.dirty_images[face] = 0;
}
return 0;
}