vc4: Add support for rebasing texture levels so firstlevel == 0.
authorEric Anholt <eric@anholt.net>
Fri, 3 Oct 2014 05:14:03 +0000 (22:14 -0700)
committerEric Anholt <eric@anholt.net>
Sun, 19 Oct 2014 07:42:33 +0000 (08:42 +0100)
GLES2 doesn't have GL_TEXTURE_BASE_LEVEL, so the hardware doesn't.  Fixes
piglit levelclamp, tex-miplevel-selection, and texture-storage/2D mipmap
rendering.

src/gallium/drivers/vc4/vc4_context.c
src/gallium/drivers/vc4/vc4_program.c
src/gallium/drivers/vc4/vc4_resource.c
src/gallium/drivers/vc4/vc4_resource.h
src/gallium/drivers/vc4/vc4_state.c

index cc57486..87f0251 100644 (file)
@@ -253,6 +253,12 @@ vc4_setup_rcl(struct vc4_context *vc4)
                         assert(!coords_emitted);
                 }
         }
+
+        if (vc4->resolve & PIPE_CLEAR_COLOR0)
+                ctex->writes++;
+
+        if (vc4->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))
+                ztex->writes++;
 }
 
 void
index 66dff97..7a2a975 100644 (file)
@@ -2265,7 +2265,8 @@ write_texture_p0(struct vc4_context *vc4,
 
         cl_reloc(vc4, &vc4->uniforms, rsc->bo,
                  VC4_SET_FIELD(rsc->slices[0].offset >> 12, VC4_TEX_P0_OFFSET) |
-                 VC4_SET_FIELD(texture->u.tex.last_level, VC4_TEX_P0_MIPLVLS) |
+                 VC4_SET_FIELD(texture->u.tex.last_level -
+                               texture->u.tex.first_level, VC4_TEX_P0_MIPLVLS) |
                  VC4_SET_FIELD(texture->target == PIPE_TEXTURE_CUBE,
                                VC4_TEX_P0_CMMODE) |
                  VC4_SET_FIELD(rsc->vc4_format & 7, VC4_TEX_P0_TYPE));
index 7006af3..803d357 100644 (file)
@@ -83,6 +83,9 @@ vc4_resource_transfer_map(struct pipe_context *pctx,
         if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
                 vc4_flush_for_bo(pctx, rsc->bo);
 
+        if (usage & PIPE_TRANSFER_WRITE)
+                rsc->writes++;
+
         trans = util_slab_alloc(&vc4->transfer_pool);
         if (!trans)
                 return NULL;
@@ -168,6 +171,7 @@ vc4_resource_destroy(struct pipe_screen *pscreen,
                      struct pipe_resource *prsc)
 {
         struct vc4_resource *rsc = vc4_resource(prsc);
+        pipe_resource_reference(&rsc->shadow_parent, NULL);
         vc4_bo_unreference(&rsc->bo);
         free(rsc);
 }
@@ -297,7 +301,7 @@ get_resource_texture_format(struct pipe_resource *prsc)
         return format;
 }
 
-static struct pipe_resource *
+struct pipe_resource *
 vc4_resource_create(struct pipe_screen *pscreen,
                     const struct pipe_resource *tmpl)
 {
@@ -478,6 +482,37 @@ vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
 }
 
 void
+vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
+                                    struct pipe_sampler_view *view)
+{
+        struct vc4_resource *shadow = vc4_resource(view->texture);
+        struct vc4_resource *orig = vc4_resource(shadow->shadow_parent);
+        assert(orig);
+
+        if (shadow->writes == orig->writes)
+                return;
+
+        for (int i = 0; i <= shadow->base.b.last_level; i++) {
+                struct pipe_box box = {
+                        .x = 0,
+                        .y = 0,
+                        .z = 0,
+                        .width = u_minify(shadow->base.b.width0, i),
+                        .height = u_minify(shadow->base.b.height0, i),
+                        .depth = 1,
+                };
+
+                util_resource_copy_region(pctx,
+                                          &shadow->base.b, i, 0, 0, 0,
+                                          &orig->base.b,
+                                          view->u.tex.first_level + i,
+                                          &box);
+        }
+
+        shadow->writes = orig->writes;
+}
+
+void
 vc4_resource_screen_init(struct pipe_screen *pscreen)
 {
         pscreen->resource_create = vc4_resource_create;
index 01f481d..7cc16a4 100644 (file)
@@ -61,6 +61,16 @@ struct vc4_resource {
         bool tiled;
         /** One of VC4_TEXTURE_TYPE_* */
         enum vc4_texture_data_type vc4_format;
+
+        /**
+         * Number of times the resource has been written to.
+         *
+         * This is used to track when we need to update this shadow resource
+         * from its parent in the case of GL_TEXTURE_BASE_LEVEL (which we
+         * can't support in hardware).
+         */
+        uint64_t writes;
+        struct pipe_resource *shadow_parent;
 };
 
 static INLINE struct vc4_resource *
@@ -83,5 +93,9 @@ vc4_transfer(struct pipe_transfer *ptrans)
 
 void vc4_resource_screen_init(struct pipe_screen *pscreen);
 void vc4_resource_context_init(struct pipe_context *pctx);
+struct pipe_resource *vc4_resource_create(struct pipe_screen *pscreen,
+                                          const struct pipe_resource *tmpl);
+void vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
+                                         struct pipe_sampler_view *view);
 
 #endif /* VC4_RESOURCE_H */
index 099006b..d3219b3 100644 (file)
@@ -483,7 +483,28 @@ vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
                 return NULL;
 
         *so = *cso;
+
         pipe_reference(NULL, &prsc->reference);
+
+        /* There is no hardware level clamping, and the start address of a
+         * texture may be misaligned, so in that case we have to copy to a
+         * temporary.
+         */
+        if (so->u.tex.first_level) {
+                struct vc4_resource *shadow_parent = vc4_resource(prsc);
+                struct pipe_resource tmpl = shadow_parent->base.b;
+                struct vc4_resource *clone;
+
+                tmpl.width0 = u_minify(tmpl.width0, so->u.tex.first_level);
+                tmpl.height0 = u_minify(tmpl.height0, so->u.tex.first_level);
+                tmpl.last_level = so->u.tex.last_level - so->u.tex.first_level;
+
+                prsc = vc4_resource_create(pctx->screen, &tmpl);
+                clone = vc4_resource(prsc);
+                clone->shadow_parent = &shadow_parent->base.b;
+                /* Flag it as needing update of the contents from the parent. */
+                clone->writes = shadow_parent->writes - 1;
+        }
         so->texture = prsc;
         so->reference.count = 1;
         so->context = pctx;
@@ -514,8 +535,11 @@ vc4_set_sampler_views(struct pipe_context *pctx, unsigned shader,
         vc4->dirty |= VC4_DIRTY_TEXSTATE;
 
         for (i = 0; i < nr; i++) {
-                if (views[i])
+                if (views[i]) {
                         new_nr = i + 1;
+                        if (views[i]->u.tex.first_level != 0)
+                                vc4_update_shadow_baselevel_texture(pctx, views[i]);
+                }
                 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
                 stage_tex->dirty_samplers |= (1 << i);
         }