summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/r300_context.h8
-rw-r--r--src/gallium/drivers/r300/r300_emit.c16
-rw-r--r--src/gallium/drivers/r300/r300_texture.c35
3 files changed, 42 insertions, 17 deletions
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 4d73567bbea..cee0734d213 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];
+ /* A pitch for each mip-level */
+ unsigned pitch[PIPE_MAX_TEXTURE_LEVELS];
+
/* Size of one zslice or face based on the texture target */
unsigned layer_size[PIPE_MAX_TEXTURE_LEVELS];
@@ -197,6 +200,11 @@ struct r300_texture {
/* Total size of this texture, in bytes. */
unsigned size;
+ /* Whether this texture has non-power-of-two dimensions.
+ * It can be either a regular texture or a rectangle one.
+ */
+ boolean is_npot;
+
/* Pipe buffer backing this texture. */
struct pipe_buffer* buffer;
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 3b0b41e486f..be38fbc619e 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -285,21 +285,22 @@ void r300_emit_fb_state(struct r300_context* r300,
struct pipe_framebuffer_state* fb)
{
struct r300_texture* tex;
- unsigned pixpitch;
+ struct pipe_surface* surf;
int i;
CS_LOCALS(r300);
BEGIN_CS((10 * fb->nr_cbufs) + (fb->zsbuf ? 10 : 0) + 4);
for (i = 0; i < fb->nr_cbufs; i++) {
- tex = (struct r300_texture*)fb->cbufs[i]->texture;
+ surf = fb->cbufs[i];
+ tex = (struct r300_texture*)surf->texture;
assert(tex && tex->buffer && "cbuf is marked, but NULL!");
- pixpitch = r300_texture_get_stride(tex, 0) / tex->tex.block.size;
+ /* XXX I still need to figure out how to set the mipmap level here */
OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1);
OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1);
- OUT_CS_RELOC(tex->buffer, pixpitch |
+ OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] |
r300_translate_colorformat(tex->tex.format), 0,
RADEON_GEM_DOMAIN_VRAM, 0);
@@ -308,9 +309,9 @@ void r300_emit_fb_state(struct r300_context* r300,
}
if (fb->zsbuf) {
- tex = (struct r300_texture*)fb->zsbuf->texture;
+ surf = fb->zsbuf;
+ tex = (struct r300_texture*)surf->texture;
assert(tex && tex->buffer && "zsbuf is marked, but NULL!");
- pixpitch = r300_texture_get_stride(tex, 0) / tex->tex.block.size;
OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1);
OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0);
@@ -318,7 +319,8 @@ void r300_emit_fb_state(struct r300_context* r300,
OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format));
OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1);
- OUT_CS_RELOC(tex->buffer, pixpitch, 0, RADEON_GEM_DOMAIN_VRAM, 0);
+ OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level], 0,
+ RADEON_GEM_DOMAIN_VRAM, 0);
}
OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT,
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 3e90fea6c8a..7199918a849 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -33,21 +33,15 @@ static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500)
{
struct r300_texture_state* state = &tex->state;
struct pipe_texture *pt = &tex->tex;
- unsigned stride;
state->format0 = R300_TX_WIDTH((pt->width[0] - 1) & 0x7ff) |
R300_TX_HEIGHT((pt->height[0] - 1) & 0x7ff);
- if (!util_is_power_of_two(pt->width[0]) ||
- !util_is_power_of_two(pt->height[0])) {
-
+ if (tex->is_npot) {
/* rectangles love this */
state->format0 |= R300_TX_PITCH_EN;
-
- stride = r300_texture_get_stride(tex, 0) / pt->block.size;
- state->format2 = (stride - 1) & 0x1fff;
- }
- else {
+ state->format2 = (tex->pitch[0] - 1) & 0x1fff;
+ } else {
/* power of two textures (3D, mipmaps, and no pitch) */
state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth[0]) & 0xf) |
R300_TX_NUM_LEVELS(pt->last_level & 0xf);
@@ -143,6 +137,12 @@ static void r300_setup_miptree(struct r300_texture* tex)
tex->size = tex->offset[i] + size;
tex->layer_size[i] = layer_size;
+ if (tex->is_npot) {
+ tex->pitch[i] = stride / base->block.size;
+ } else {
+ tex->pitch[i] = base->width[i];
+ }
+
debug_printf("r300: Texture miptree: Level %d "
"(%dx%dx%d px, pitch %d bytes)\n",
i, base->width[i], base->height[i], base->depth[i],
@@ -150,6 +150,12 @@ static void r300_setup_miptree(struct r300_texture* tex)
}
}
+static void r300_setup_flags(struct r300_texture* tex)
+{
+ tex->is_npot = !util_is_power_of_two(tex->tex.width[0]) ||
+ !util_is_power_of_two(tex->tex.height[0]);
+}
+
/* Create a new texture. */
static struct pipe_texture*
r300_texture_create(struct pipe_screen* screen,
@@ -165,8 +171,8 @@ static struct pipe_texture*
pipe_reference_init(&tex->tex.reference, 1);
tex->tex.screen = screen;
+ r300_setup_flags(tex);
r300_setup_miptree(tex);
-
r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
tex->buffer = screen->buffer_create(screen, 1024,
@@ -234,6 +240,13 @@ static struct pipe_texture*
{
struct r300_texture* tex;
+ /* Support only 2D textures without mipmaps */
+ if (base->target != PIPE_TEXTURE_2D ||
+ base->depth[0] != 1 ||
+ base->last_level != 0) {
+ return NULL;
+ }
+
tex = CALLOC_STRUCT(r300_texture);
if (!tex) {
return NULL;
@@ -244,7 +257,9 @@ static struct pipe_texture*
tex->tex.screen = screen;
tex->stride_override = *stride;
+ tex->pitch[0] = *stride / base->block.size;
+ r300_setup_flags(tex);
r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500);
pipe_buffer_reference(&tex->buffer, buffer);