r300g: add precalculating of pixel pitch, add a new NPOT flag
authorMarek Olšák <maraeo@gmail.com>
Fri, 30 Oct 2009 17:19:25 +0000 (18:19 +0100)
committerJoakim Sindholt <opensource@zhasha.com>
Sat, 31 Oct 2009 06:30:48 +0000 (07:30 +0100)
src/gallium/drivers/r300/r300_context.h
src/gallium/drivers/r300/r300_emit.c
src/gallium/drivers/r300/r300_texture.c

index 4d73567bbea05883e90d68c135908d2c435aa772..cee0734d2132c5a9bc2ac8f6d28c681df67a1201 100644 (file)
@@ -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;
 
index 3b0b41e486f94070c1bff00d1c8b4936cb4a6687..be38fbc619e6018fb09342742674eb76fde4fd61 100644 (file)
@@ -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,
index 3e90fea6c8a52d958907d6e600ac97cf86f89e49..7199918a8498e1f899970aa65ba60181ba593a75 100644 (file)
@@ -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);