summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Olšák <maraeo@gmail.com>2009-10-25 05:05:27 +0100
committerJoakim Sindholt <opensource@zhasha.com>2009-10-25 08:06:19 +0100
commit118dfe16887d1ec4d3b96d49b76fffa0d2924132 (patch)
tree51b60cf0c95c8b6a67e2b538791daf35e9a68091
parent94a63dccdd79268cf37587c93e3dec0d02dad457 (diff)
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.
-rw-r--r--src/gallium/drivers/r300/r300_context.h3
-rw-r--r--src/gallium/drivers/r300/r300_screen.c59
-rw-r--r--src/gallium/drivers/r300/r300_texture.c39
-rw-r--r--src/gallium/drivers/r300/r300_texture.h3
4 files changed, 51 insertions, 53 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 30b80fa9db8..4d73567bbea 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -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).
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c
index 1d9f91d0f73..f581f0ca091 100644
--- a/src/gallium/drivers/r300/r300_screen.c
+++ b/src/gallium/drivers/r300/r300_screen.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 3c8ff24e17d..37c7910d800 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -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;
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index 55d1a0ac5cf..35e06a9acb5 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -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)
{