r300g: added support for 3D textures

Mipmaps not tested. Also, I am not sure why piglit/texturing/tex3d needs
to have color tolerance +-1 to pass. The classic Mesa driver doesn't
need that.
This commit is contained in:
Marek Olšák 2009-10-25 05:05:27 +01:00 committed by Joakim Sindholt
parent 94a63dccdd
commit 118dfe1688
4 changed files with 51 additions and 53 deletions

View file

@ -181,6 +181,9 @@ struct r300_texture {
/* Offsets into the buffer. */
unsigned offset[PIPE_MAX_TEXTURE_LEVELS];
/* Size of one zslice or face based on the texture target */
unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS];
/**
* If non-zero, override the natural texture layout with
* a custom stride (in bytes).

View file

@ -119,32 +119,13 @@ static int r300_get_param(struct pipe_screen* pscreen, int param)
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
if (r300screen->caps->is_r500) {
/* 13 == 4096x4096 */
return 13;
} else {
/* 12 == 2048x2048 */
return 12;
}
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
/* So, technically, the limit is the same as above, but some math
* shows why this is silly. Assuming RGBA, 4cpp, we can see that
* 4096*4096*4096 = 64.0 GiB exactly, so it's not exactly
* practical. However, if at some point a game really wants this,
* then we can remove or raise this limit. */
if (r300screen->caps->is_r500) {
/* 9 == 256x256x256 */
return 9;
} else {
/* 8 == 128*128*128 */
return 8;
}
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
if (r300screen->caps->is_r500) {
/* 13 == 4096x4096 */
/* 13 == 4096 */
return 13;
} else {
/* 12 == 2048x2048 */
/* 12 == 2048 */
return 12;
}
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
@ -191,8 +172,8 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param)
}
}
static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage,
boolean is_r500)
static boolean check_tex_format(enum pipe_format format, uint32_t usage,
boolean is_r500)
{
uint32_t retval = 0;
@ -286,7 +267,6 @@ static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage,
return (retval >= usage);
}
/* XXX moar targets */
static boolean r300_is_format_supported(struct pipe_screen* pscreen,
enum pipe_format format,
enum pipe_texture_target target,
@ -294,15 +274,17 @@ static boolean r300_is_format_supported(struct pipe_screen* pscreen,
unsigned geom_flags)
{
switch (target) {
case PIPE_TEXTURE_1D: /* handle 1D textures as 2D ones */
case PIPE_TEXTURE_2D:
return check_tex_2d_format(format, tex_usage,
r300_screen(pscreen)->caps->is_r500);
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_3D:
return check_tex_format(format, tex_usage,
r300_screen(pscreen)->caps->is_r500);
case PIPE_TEXTURE_CUBE:
debug_printf("r300: Implementation error: Unsupported format "
"target: %d\n", target);
break;
default:
debug_printf("r300: Fatal: This is not a format target: %d\n",
target);
@ -322,22 +304,9 @@ r300_get_tex_transfer(struct pipe_screen *screen,
{
struct r300_texture *tex = (struct r300_texture *)texture;
struct r300_transfer *trans;
unsigned offset = 0; /* in bytes */
unsigned offset;
/* XXX Add support for these things */
if (texture->target == PIPE_TEXTURE_CUBE) {
debug_printf("PIPE_TEXTURE_CUBE is not yet supported.\n");
/* offset = tex->image_offset[level][face]; */
}
else if (texture->target == PIPE_TEXTURE_3D) {
debug_printf("PIPE_TEXTURE_3D is not yet supported.\n");
/* offset = tex->image_offset[level][zslice]; */
}
else {
offset = tex->offset[level];
assert(face == 0);
assert(zslice == 0);
}
offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */
trans = CALLOC_STRUCT(r300_transfer);
if (trans) {
@ -352,6 +321,12 @@ r300_get_tex_transfer(struct pipe_screen *screen,
trans->transfer.nblocksy = texture->nblocksy[level];
trans->transfer.stride = r300_texture_get_stride(tex, level);
trans->transfer.usage = usage;
/* XXX not sure whether it's required to set these two,
the driver doesn't use them */
trans->transfer.zslice = zslice;
trans->transfer.face = face;
trans->offset = offset;
}
return &trans->transfer;

View file

@ -36,7 +36,7 @@ static void r300_setup_texture_state(struct r300_texture* tex)
state->format0 = R300_TX_WIDTH((pt->width[0] - 1) & 0x7ff) |
R300_TX_HEIGHT((pt->height[0] - 1) & 0x7ff) |
R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) |
R300_TX_NUM_LEVELS(pt->last_level) |
R300_TX_NUM_LEVELS(pt->last_level & 0xf) |
R300_TX_PITCH_EN;
/* XXX */
@ -48,7 +48,8 @@ static void r300_setup_texture_state(struct r300_texture* tex)
state->format1 |= R300_TX_FORMAT_3D;
}
state->format2 = (r300_texture_get_stride(tex, 0) / pt->block.size) - 1;
state->format2 = ((r300_texture_get_stride(tex, 0) / pt->block.size) - 1)
& 0x1fff;
/* Don't worry about accidentally setting this bit on non-r500;
* the kernel should catch it. */
@ -63,6 +64,26 @@ static void r300_setup_texture_state(struct r300_texture* tex)
pt->width[0], pt->height[0], pt->last_level);
}
unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
unsigned zslice, unsigned face)
{
unsigned offset = tex->offset[level];
switch (tex->tex.target) {
case PIPE_TEXTURE_3D:
assert(face == 0);
return offset + zslice * tex->layer_size[level];
case PIPE_TEXTURE_CUBE:
assert(zslice == 0);
return offset + face * tex->layer_size[level];
default:
assert(zslice == 0 && face == 0);
return offset;
}
}
/**
* Return the stride, in bytes, of the texture images of the given texture
* at the given level.
@ -84,7 +105,7 @@ unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level)
static void r300_setup_miptree(struct r300_texture* tex)
{
struct pipe_texture* base = &tex->tex;
int stride, size;
int stride, size, layer_size;
int i;
for (i = 0; i <= base->last_level; i++) {
@ -98,10 +119,12 @@ static void r300_setup_miptree(struct r300_texture* tex)
base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]);
stride = r300_texture_get_stride(tex, i);
size = stride * base->nblocksy[i] * base->depth[i];
layer_size = stride * base->nblocksy[i];
size = layer_size * base->depth[i];
tex->offset[i] = align(tex->size, 32);
tex->size = tex->offset[i] + size;
tex->layer_size[i] = layer_size;
debug_printf("r300: Texture miptree: Level %d "
"(%dx%dx%d px, pitch %d bytes)\n",
@ -161,8 +184,7 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
struct pipe_surface* surface = CALLOC_STRUCT(pipe_surface);
unsigned offset;
/* XXX this is certainly dependent on tex target */
offset = tex->offset[level];
offset = r300_texture_get_offset(tex, level, zslice, face);
if (surface) {
pipe_reference_init(&surface->reference, 1);
@ -191,11 +213,6 @@ static struct pipe_texture*
{
struct r300_texture* tex;
if (base->target != PIPE_TEXTURE_2D ||
base->depth[0] != 1) {
return NULL;
}
tex = CALLOC_STRUCT(r300_texture);
if (!tex) {
return NULL;

View file

@ -33,6 +33,9 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen);
unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level);
unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level,
unsigned zslice, unsigned face);
/* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */
static INLINE uint32_t r300_translate_texformat(enum pipe_format format)
{