#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_vb.h"
#include "r128_tris.h"
#include "r128_tex.h"
#include "context.h"
#include "macros.h"
#include "simple_list.h"
#include "texformat.h"
#include "imports.h"
#define TEX_0 1
#define TEX_1 2
void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t )
{
unsigned i;
if ( rmesa != NULL )
{
for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ )
{
if ( t == rmesa->CurrentTexObj[ i ] ) {
assert( t->base.bound & (1 << i) );
rmesa->CurrentTexObj[ i ] = NULL;
}
}
}
}
static void uploadSubImage( r128ContextPtr rmesa, r128TexObjPtr t,
GLint level,
GLint x, GLint y, GLint width, GLint height )
{
struct gl_texture_image *image;
int texelsPerDword = 0;
int imageWidth, imageHeight;
int remaining, rows;
int format, dwords;
CARD32 pitch, offset;
int i;
if ( ( level < 0 ) || ( level > R128_MAX_TEXTURE_LEVELS ) )
return;
image = t->base.tObj->Image[level];
if ( !image )
return;
switch ( image->TexFormat->TexelBytes ) {
case 1: texelsPerDword = 4; break;
case 2: texelsPerDword = 2; break;
case 4: texelsPerDword = 1; break;
}
#if 1
x = 0;
y = 0;
width = image->Width;
height = image->Height;
#endif
imageWidth = image->Width;
imageHeight = image->Height;
format = t->textureFormat >> 16;
if ( imageWidth < texelsPerDword ) {
int factor;
factor = texelsPerDword / imageWidth;
imageWidth = texelsPerDword;
imageHeight /= factor;
if ( imageHeight == 0 ) {
imageHeight = 1;
}
}
if ( imageWidth >= 8 ) {
pitch = imageWidth >> 3;
} else {
int factor;
int y2;
int start, end;
start = (y * imageWidth) & ~7;
end = (y + height) * imageWidth;
if ( end - start < 8 ) {
x = 0;
y = start / 8;
width = end - start;
height = 1;
} else {
factor = 8 / imageWidth;
y2 = y + height - 1;
y /= factor;
y2 /= factor;
x = 0;
width = 8;
height = y2 - y + 1;
}
pitch = 1;
}
dwords = width * height / texelsPerDword;
offset = t->bufAddr + t->image[level - t->base.firstLevel].offset;
#if ENABLE_PERF_BOXES
rmesa->c_textureBytes += (dwords << 2);
#endif
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n",
width, height, image->Width, image->Height, x, y );
fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d "
"level: %d format: %x\n",
(GLuint)offset, (GLuint)pitch, dwords, level, format );
}
if ( dwords <= R128_BUFFER_MAX_DWORDS / 2 ) {
rows = height;
} else {
rows = (R128_BUFFER_MAX_DWORDS * texelsPerDword) / (2 * width);
}
for ( i = 0, remaining = height ;
remaining > 0 ;
remaining -= rows, y += rows, i++ )
{
CARD32 *dst;
drmBufPtr buffer;
assert(image->Data);
height = MIN2(remaining, rows);
LOCK_HARDWARE( rmesa );
buffer = r128GetBufferLocked( rmesa );
dst = (CARD32 *)((char *)buffer->address + R128_HOSTDATA_BLIT_OFFSET);
{
const GLubyte *src = (const GLubyte *) image->Data +
(y * image->Width + x) * image->TexFormat->TexelBytes;
const GLuint bytes = width * height * image->TexFormat->TexelBytes;
memcpy(dst, src, bytes);
}
r128FireBlitLocked( rmesa, buffer,
offset, pitch, format,
x, y, width, height );
UNLOCK_HARDWARE( rmesa );
}
rmesa->new_state |= R128_NEW_CONTEXT;
rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
}
void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t )
{
const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
GLint i;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p, %p )\n",
__FUNCTION__, (void *)rmesa->glCtx, (void *)t );
}
assert(t);
LOCK_HARDWARE( rmesa );
if ( !t->base.memBlock ) {
int heap;
heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( rmesa );
return;
}
t->bufAddr = rmesa->r128Screen->texOffset[heap]
+ t->base.memBlock->ofs;
if ( t->setup.tex_cntl & R128_MIP_MAP_DISABLE ) {
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
t->setup.tex_offset[i] = t->bufAddr;
}
} else {
for ( i = 0; i < numLevels; i++ ) {
const int j = numLevels - i - 1;
t->setup.tex_offset[j] = t->bufAddr + t->image[i].offset;
}
}
}
driUpdateTextureLRU( (driTextureObject *) t );
UNLOCK_HARDWARE( rmesa );
if ( t->base.dirty_images[0] ) {
for ( i = 0 ; i < numLevels; i++ ) {
const GLint j = t->base.firstLevel + i;
if ( t->base.dirty_images[0] & (1 << j) ) {
uploadSubImage( rmesa, t, j, 0, 0,
t->image[i].width, t->image[i].height );
}
}
rmesa->setup.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
rmesa->dirty |= R128_UPLOAD_CONTEXT;
t->base.dirty_images[0] = 0;
}
}