r600g: fix RSQ of negative value on Cayman
[mesa.git] / src / gallium / drivers / r600 / r600_blit.c
index 5f39e0d54e1f736eda0bd0628cc7ca328be09402..09fb6239221433550b3efed3108a1a8b4ca623f5 100644 (file)
@@ -62,29 +62,25 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op
        util_blitter_save_rasterizer(rctx->blitter, rctx->states[R600_PIPE_STATE_RASTERIZER]);
 
        if (op & R600_SAVE_FRAGMENT_STATE) {
-               if (rctx->states[R600_PIPE_STATE_VIEWPORT]) {
-                       util_blitter_save_viewport(rctx->blitter, &rctx->viewport);
-               }
+               util_blitter_save_viewport(rctx->blitter, &rctx->viewport.state);
                util_blitter_save_fragment_shader(rctx->blitter, rctx->ps_shader);
                util_blitter_save_blend(rctx->blitter, rctx->states[R600_PIPE_STATE_BLEND]);
                util_blitter_save_depth_stencil_alpha(rctx->blitter, rctx->states[R600_PIPE_STATE_DSA]);
-               if (rctx->states[R600_PIPE_STATE_STENCIL_REF]) {
-                       util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref);
-               }
+               util_blitter_save_stencil_ref(rctx->blitter, &rctx->stencil_ref.pipe_state);
                 util_blitter_save_sample_mask(rctx->blitter, rctx->sample_mask.sample_mask);
        }
 
        if (op & R600_SAVE_FRAMEBUFFER)
-               util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer);
+               util_blitter_save_framebuffer(rctx->blitter, &rctx->framebuffer.state);
 
        if (op & R600_SAVE_TEXTURES) {
                util_blitter_save_fragment_sampler_states(
-                       rctx->blitter, rctx->ps_samplers.n_samplers,
-                       (void**)rctx->ps_samplers.samplers);
+                       rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].states.enabled_mask),
+                       (void**)rctx->samplers[PIPE_SHADER_FRAGMENT].states.states);
 
                util_blitter_save_fragment_sampler_views(
-                       rctx->blitter, util_last_bit(rctx->ps_samplers.views.enabled_mask),
-                       (struct pipe_sampler_view**)rctx->ps_samplers.views.views);
+                       rctx->blitter, util_last_bit(rctx->samplers[PIPE_SHADER_FRAGMENT].views.enabled_mask),
+                       (struct pipe_sampler_view**)rctx->samplers[PIPE_SHADER_FRAGMENT].views.views);
        }
 
        if ((op & R600_DISABLE_RENDER_COND) && rctx->current_render_cond) {
@@ -260,6 +256,8 @@ static void r600_blit_decompress_color(struct pipe_context *ctx,
        struct r600_context *rctx = (struct r600_context *)ctx;
        unsigned layer, level, checked_last_layer, max_layer;
 
+       assert(rctx->chip_class != CAYMAN);
+
        if (!rtex->dirty_level_mask)
                return;
 
@@ -304,6 +302,13 @@ void r600_decompress_color_textures(struct r600_context *rctx,
        unsigned i;
        unsigned mask = textures->compressed_colortex_mask;
 
+       /* Cayman cannot decompress an MSAA colorbuffer,
+        * but it can read it compressed, so skip this. */
+       assert(rctx->chip_class != CAYMAN);
+       if (rctx->chip_class == CAYMAN) {
+               return;
+       }
+
        while (mask) {
                struct pipe_sampler_view *view;
                struct r600_texture *tex;
@@ -322,29 +327,46 @@ void r600_decompress_color_textures(struct r600_context *rctx,
        }
 }
 
+/* Helper for decompressing a portion of a color or depth resource before
+ * blitting if any decompression is needed.
+ * The driver doesn't decompress resources automatically while u_blitter is
+ * rendering. */
+static bool r600_decompress_subresource(struct pipe_context *ctx,
+                                       struct pipe_resource *tex,
+                                       unsigned level,
+                                       unsigned first_layer, unsigned last_layer)
+{
+       struct r600_context *rctx = (struct r600_context *)ctx;
+       struct r600_texture *rtex = (struct r600_texture*)tex;
+
+       if (rtex->is_depth && !rtex->is_flushing_texture) {
+               if (!r600_init_flushed_depth_texture(ctx, tex, NULL))
+                       return false; /* error */
+
+               r600_blit_decompress_depth(ctx, rtex, NULL,
+                                          level, level,
+                                          first_layer, last_layer,
+                                          0, u_max_sample(tex));
+       } else if (rctx->chip_class != CAYMAN && rtex->fmask_size && rtex->cmask_size) {
+               r600_blit_decompress_color(ctx, rtex, level, level,
+                                          first_layer, last_layer);
+       }
+       return true;
+}
+
 static void r600_copy_first_sample(struct pipe_context *ctx,
                                   const struct pipe_resolve_info *info)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_texture *rsrc = (struct r600_texture*)info->src.res;
        struct pipe_surface *dst_view, dst_templ;
        struct pipe_sampler_view src_templ, *src_view;
        struct pipe_box box;
 
-       if (rsrc->is_depth && !rsrc->is_flushing_texture) {
-               if (!r600_init_flushed_depth_texture(ctx, info->src.res, NULL))
-                       return; /* error */
-
-               /* Decompress the first sample only. */
-               r600_blit_decompress_depth(ctx, rsrc, NULL,
-                                          0, 0,
-                                          info->src.layer, info->src.layer,
-                                          0, 0);
-       }
-       if (rsrc->fmask_size && rsrc->cmask_size) {
-               r600_blit_decompress_color(ctx, rsrc,
-                                          0, 0,
-                                          info->src.layer, info->src.layer);
+       /* The driver doesn't decompress resources automatically while
+        * u_blitter is rendering. */
+       if (!r600_decompress_subresource(ctx, info->src.res, 0,
+                                        info->src.layer, info->src.layer)) {
+               return; /* error */
        }
 
        /* this is correct for upside-down blits too */
@@ -399,6 +421,8 @@ static void r600_color_resolve(struct pipe_context *ctx,
        struct pipe_screen *screen = ctx->screen;
        struct pipe_resource *tmp, templ;
        struct pipe_box box;
+       unsigned sample_mask =
+               rctx->chip_class == CAYMAN ? ~0 : ((1ull << MAX2(1, info->src.res->nr_samples)) - 1);
 
        assert((info->mask & PIPE_MASK_RGBA) == PIPE_MASK_RGBA);
 
@@ -407,7 +431,7 @@ static void r600_color_resolve(struct pipe_context *ctx,
                util_blitter_custom_resolve_color(rctx->blitter,
                                                  info->dst.res, info->dst.level, info->dst.layer,
                                                  info->src.res, info->src.layer,
-                                                 rctx->custom_blend_resolve);
+                                                 sample_mask, rctx->custom_blend_resolve);
                r600_blitter_end(ctx);
                return;
        }
@@ -432,7 +456,7 @@ static void r600_color_resolve(struct pipe_context *ctx,
        util_blitter_custom_resolve_color(rctx->blitter,
                                          tmp, 0, 0,
                                          info->src.res, info->src.layer,
-                                         rctx->custom_blend_resolve);
+                                         sample_mask, rctx->custom_blend_resolve);
        r600_blitter_end(ctx);
 
        /* this is correct for upside-down blits too */
@@ -485,7 +509,7 @@ static void r600_clear(struct pipe_context *ctx, unsigned buffers,
                       double depth, unsigned stencil)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
-       struct pipe_framebuffer_state *fb = &rctx->framebuffer;
+       struct pipe_framebuffer_state *fb = &rctx->framebuffer.state;
 
        r600_blitter_begin(ctx, R600_CLEAR);
        util_blitter_clear(rctx->blitter, fb->width, fb->height,
@@ -657,7 +681,6 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
                                      const struct pipe_box *src_box)
 {
        struct r600_context *rctx = (struct r600_context *)ctx;
-       struct r600_texture *rsrc = (struct r600_texture*)src;
        struct texture_orig_info orig_info[2];
        struct pipe_box sbox;
        const struct pipe_box *psbox = src_box;
@@ -675,19 +698,11 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
        assert(u_max_sample(dst) == u_max_sample(src));
        last_sample = u_max_sample(dst);
 
-       /* This must be done before entering u_blitter to avoid recursion. */
-       if (rsrc->is_depth && !rsrc->is_flushing_texture) {
-               if (!r600_init_flushed_depth_texture(ctx, src, NULL))
-                       return; /* error */
-
-               r600_blit_decompress_depth(ctx, rsrc, NULL,
-                                          src_level, src_level,
-                                          src_box->z, src_box->z + src_box->depth - 1,
-                                          0, u_max_sample(src));
-       }
-       if (rsrc->fmask_size && rsrc->cmask_size) {
-               r600_blit_decompress_color(ctx, rsrc, src_level, src_level,
-                                          src_box->z, src_box->z + src_box->depth - 1);
+       /* The driver doesn't decompress resources automatically while
+        * u_blitter is rendering. */
+       if (!r600_decompress_subresource(ctx, src, src_level,
+                                        src_box->z, src_box->z + src_box->depth - 1)) {
+               return; /* error */
        }
 
        restore_orig[0] = restore_orig[1] = FALSE;
@@ -748,11 +763,20 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
                restore_orig[1] = TRUE;
        }
 
-       for (i = 0; i <= last_sample; i++) {
+       /* XXX Properly implement multisample textures on Cayman. In the meantime,
+        * copy only the first sample (which is the only one that doesn't return garbage). */
+       if (rctx->chip_class == CAYMAN) {
                r600_blitter_begin(ctx, R600_COPY_TEXTURE);
-               util_blitter_copy_texture(rctx->blitter, dst, dst_level, 1 << i, dstx, dsty, dstz,
-                                         src, src_level, i, psbox);
+               util_blitter_copy_texture(rctx->blitter, dst, dst_level, ~0, dstx, dsty, dstz,
+                                         src, src_level, 0, psbox);
                r600_blitter_end(ctx);
+       } else {
+               for (i = 0; i <= last_sample; i++) {
+                       r600_blitter_begin(ctx, R600_COPY_TEXTURE);
+                       util_blitter_copy_texture(rctx->blitter, dst, dst_level, 1 << i, dstx, dsty, dstz,
+                                                 src, src_level, i, psbox);
+                       r600_blitter_end(ctx);
+               }
        }
 
        if (restore_orig[0])