r300g: Fix bad formatting parameters in calls to debug_printf
[mesa.git] / src / gallium / drivers / r300 / r300_texture.c
index 8251a597eab1471d54c89ae7a0075f2a7afdb1a5..7c041d17f71eee9825c423aed2a839559605246b 100644 (file)
 
 #include "r300_texture.h"
 
-static int minify(int i)
+static void r300_setup_texture_state(struct r300_texture* tex,
+                                     unsigned width,
+                                     unsigned height,
+                                     unsigned levels)
 {
-    return MAX2(1, i >> 1);
+    struct r300_texture_state* state = &tex->state;
+
+    state->format0 = R300_TX_WIDTH((width - 1) & 0x7ff) |
+        R300_TX_HEIGHT((height - 1) & 0x7ff) |
+        R300_TX_NUM_LEVELS(levels) |
+        R300_TX_PITCH_EN;
+
+    /* XXX */
+    state->format1 = r300_translate_texformat(tex->tex.format);
+
+    state->format2 = r300_texture_get_stride(tex, 0);
+
+    /* Assume (somewhat foolishly) that oversized textures will
+     * not be permitted by the state tracker. */
+    if (width > 2048) {
+        state->format2 |= R500_TXWIDTH_BIT11;
+    }
+    if (height > 2048) {
+        state->format2 |= R500_TXHEIGHT_BIT11;
+    }
+
+    debug_printf("r300: Set texture state (%dx%d, %d levels)\n",
+            width, height, levels);
+}
+
+/**
+ * Return the stride, in bytes, of the texture images of the given texture
+ * at the given level.
+ */
+unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level)
+{
+    if (tex->stride_override)
+        return tex->stride_override;
+
+    if (level > tex->tex.last_level) {
+        debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__, level, tex->tex.last_level);
+        return 0;
+    }
+
+    return align(pf_get_stride(&tex->tex.block, tex->tex.width[level]), 32);
 }
 
 static void r300_setup_miptree(struct r300_texture* tex)
 {
     struct pipe_texture* base = &tex->tex;
-    int stride, size, offset;
+    int stride, size;
     int i;
 
     for (i = 0; i <= base->last_level; i++) {
@@ -41,16 +83,23 @@ static void r300_setup_miptree(struct r300_texture* tex)
         }
 
         base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]);
-        base->nblocksy[i] = pf_get_nblocksy(&base->block, base->width[i]);
-
-        /* Radeons enjoy things in multiples of 32. */
-        /* XXX NPOT -> 64, not 32 */
-        stride = (base->nblocksx[i] * base->block.size + 63) & ~63;
+        base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]);
+
+        /* Radeons enjoy things in multiples of 64.
+         *
+         * XXX
+         * POT, uncompressed, unmippmapped textures can be aligned to 32,
+         * instead of 64. */
+        stride = r300_texture_get_stride(tex, i);
         size = stride * base->nblocksy[i] * base->depth[i];
 
-        /* XXX 64 for NPOT */
-        tex->offset[i] = (tex->size + 63) & ~63;
+        tex->offset[i] = align(tex->size, 32);
         tex->size = tex->offset[i] + size;
+
+        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],
+                stride);
     }
 }
 
@@ -59,8 +108,6 @@ static struct pipe_texture*
     r300_texture_create(struct pipe_screen* screen,
                         const struct pipe_texture* template)
 {
-    /* XXX struct r300_screen* r300screen = r300_screen(screen); */
-
     struct r300_texture* tex = CALLOC_STRUCT(r300_texture);
 
     if (!tex) {
@@ -68,12 +115,15 @@ static struct pipe_texture*
     }
 
     tex->tex = *template;
-    tex->tex.refcount = 1;
+    pipe_reference_init(&tex->tex.reference, 1);
     tex->tex.screen = screen;
 
     r300_setup_miptree(tex);
 
-    tex->buffer = screen->buffer_create(screen, 64,
+    r300_setup_texture_state(tex, template->width[0], template->height[0],
+                             template->last_level);
+
+    tex->buffer = screen->buffer_create(screen, 1024,
                                         PIPE_BUFFER_USAGE_PIXEL,
                                         tex->size);
 
@@ -85,24 +135,13 @@ static struct pipe_texture*
     return (struct pipe_texture*)tex;
 }
 
-static void r300_texture_release(struct pipe_screen* screen,
-                                 struct pipe_texture** texture)
+static void r300_texture_destroy(struct pipe_texture* texture)
 {
-    if (!*texture) {
-        return;
-    }
-
-    (*texture)->refcount--;
-
-    if ((*texture)->refcount <= 0) {
-        struct r300_texture* tex = (struct r300_texture*)*texture;
+    struct r300_texture* tex = (struct r300_texture*)texture;
 
-        pipe_buffer_reference(screen, &tex->buffer, NULL);
+    pipe_buffer_reference(&tex->buffer, NULL);
 
-        FREE(tex);
-    }
-
-    *texture = NULL;
+    FREE(tex);
 }
 
 static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
@@ -120,32 +159,22 @@ static struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
     offset = tex->offset[level];
 
     if (surface) {
-        surface->refcount = 1;
+        pipe_reference_init(&surface->reference, 1);
         pipe_texture_reference(&surface->texture, texture);
         surface->format = texture->format;
         surface->width = texture->width[level];
         surface->height = texture->height[level];
         surface->offset = offset;
         surface->usage = flags;
-        surface->status = PIPE_SURFACE_STATUS_DEFINED;
     }
 
     return surface;
 }
 
-static void r300_tex_surface_release(struct pipe_screen* screen,
-                                     struct pipe_surface** surface)
+static void r300_tex_surface_destroy(struct pipe_surface* s)
 {
-    struct pipe_surface* s = *surface;
-
-    s->refcount--;
-
-    if (s->refcount <= 0) {
-        pipe_texture_reference(&s->texture, NULL);
-        FREE(s);
-    }
-
-    *surface = NULL;
+    pipe_texture_reference(&s->texture, NULL);
+    FREE(s);
 }
 
 static struct pipe_texture*
@@ -156,6 +185,7 @@ static struct pipe_texture*
 {
     struct r300_texture* tex;
 
+    /* XXX we should start doing mips now... */
     if (base->target != PIPE_TEXTURE_2D ||
         base->last_level != 0 ||
         base->depth[0] != 1) {
@@ -168,12 +198,15 @@ static struct pipe_texture*
     }
 
     tex->tex = *base;
-    tex->tex.refcount = 1;
+    pipe_reference_init(&tex->tex.reference, 1);
     tex->tex.screen = screen;
 
-    tex->stride = *stride;
+    tex->stride_override = *stride;
 
-    pipe_buffer_reference(screen, &tex->buffer, buffer);
+    /* XXX */
+    r300_setup_texture_state(tex, tex->tex.width[0], tex->tex.height[0], 0);
+
+    pipe_buffer_reference(&tex->buffer, buffer);
 
     return (struct pipe_texture*)tex;
 }
@@ -181,8 +214,26 @@ static struct pipe_texture*
 void r300_init_screen_texture_functions(struct pipe_screen* screen)
 {
     screen->texture_create = r300_texture_create;
-    screen->texture_release = r300_texture_release;
+    screen->texture_destroy = r300_texture_destroy;
     screen->get_tex_surface = r300_get_tex_surface;
-    screen->tex_surface_release = r300_tex_surface_release;
+    screen->tex_surface_destroy = r300_tex_surface_destroy;
     screen->texture_blanket = r300_texture_blanket;
 }
+
+boolean r300_get_texture_buffer(struct pipe_texture* texture,
+                                struct pipe_buffer** buffer,
+                                unsigned* stride)
+{
+    struct r300_texture* tex = (struct r300_texture*)texture;
+    if (!tex) {
+        return FALSE;
+    }
+
+    pipe_buffer_reference(buffer, tex->buffer);
+
+    if (stride) {
+        *stride = r300_texture_get_stride(tex, 0);
+    }
+
+    return TRUE;
+}