diff options
author | Marek Olšák <[email protected]> | 2012-09-13 00:45:05 +0200 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2012-09-30 18:57:57 +0200 |
commit | fc887d687b0598e09de76be885652d96e20ae07e (patch) | |
tree | 2abc8b44a3d0a02461ee3649382ef773d50f9e98 | |
parent | 95b777e688e438813e892b0948b8cead5197a323 (diff) |
r600g: implement blit
Tested-by: Michel Dänzer <[email protected]>
Reviewed-by: Brian Paul <[email protected]>
-rw-r--r-- | src/gallium/drivers/r600/evergreen_state.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_blit.c | 144 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_pipe.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state.c | 11 | ||||
-rw-r--r-- | src/gallium/drivers/r600/r600_state_common.c | 2 |
5 files changed, 140 insertions, 23 deletions
diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 7bedfec0503..4928361a451 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -1157,6 +1157,8 @@ static void evergreen_set_scissor_state(struct pipe_context *ctx, struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state); uint32_t tl, br; + rctx->scissor = *state; + if (rstate == NULL) return; diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 536b2a19bde..9ebb043168a 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -41,6 +41,9 @@ enum r600_blitter_op /* bitmask */ R600_COPY_TEXTURE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | R600_DISABLE_RENDER_COND, + R600_BLIT = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_SAVE_TEXTURES | + R600_DISABLE_RENDER_COND, + R600_DECOMPRESS = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND, R600_COLOR_RESOLVE = R600_SAVE_FRAGMENT_STATE | R600_SAVE_FRAMEBUFFER | R600_DISABLE_RENDER_COND @@ -63,6 +66,7 @@ static void r600_blitter_begin(struct pipe_context *ctx, enum r600_blitter_op op if (op & R600_SAVE_FRAGMENT_STATE) { util_blitter_save_viewport(rctx->blitter, &rctx->viewport.state); + util_blitter_save_scissor(rctx->blitter, &rctx->scissor); 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]); @@ -392,20 +396,42 @@ static void r600_copy_first_sample(struct pipe_context *ctx, static boolean is_simple_resolve(const struct pipe_resolve_info *info) { - unsigned dst_width = u_minify(info->dst.res->width0, info->dst.level); - unsigned dst_height = u_minify(info->dst.res->height0, info->dst.level); - - return info->dst.res->format == info->src.res->format && - dst_width == info->src.res->width0 && - dst_height == info->src.res->height0 && - info->dst.x0 == 0 && - info->dst.y0 == 0 && - info->dst.x1 == dst_width && - info->dst.y1 == dst_height && - info->src.x0 == 0 && - info->src.y0 == 0 && - info->src.x1 == dst_width && - info->src.y1 == dst_height; + unsigned dst_width = u_minify(info->dst.res->width0, info->dst.level); + unsigned dst_height = u_minify(info->dst.res->height0, info->dst.level); + + return info->dst.res->format == info->src.res->format && + dst_width == info->src.res->width0 && + dst_height == info->src.res->height0 && + info->dst.x0 == 0 && + info->dst.y0 == 0 && + info->dst.x1 == dst_width && + info->dst.y1 == dst_height && + info->src.x0 == 0 && + info->src.y0 == 0 && + info->src.x1 == dst_width && + info->src.y1 == dst_height; +} + +static boolean is_simple_msaa_resolve(const struct pipe_blit_info *info) +{ + unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); + unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); + + return info->dst.resource->format == info->src.resource->format && + info->dst.resource->format == info->dst.format && + info->src.resource->format == info->src.format && + !info->scissor_enable && + info->mask == PIPE_MASK_RGBA && + dst_width == info->src.resource->width0 && + dst_height == info->src.resource->height0 && + info->dst.box.x == 0 && + info->dst.box.y == 0 && + info->dst.box.width == dst_width && + info->dst.box.height == dst_height && + info->src.box.x == 0 && + info->src.box.y == 0 && + info->src.box.width == dst_width && + info->src.box.height == dst_height; } static void r600_color_resolve(struct pipe_context *ctx, @@ -771,6 +797,95 @@ static void r600_resource_copy_region(struct pipe_context *ctx, r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]); } +static void r600_msaa_color_resolve(struct pipe_context *ctx, + const struct pipe_blit_info *info) +{ + struct r600_context *rctx = (struct r600_context *)ctx; + struct pipe_screen *screen = ctx->screen; + struct pipe_resource *tmp, templ; + struct pipe_blit_info blit; + unsigned sample_mask = + rctx->chip_class == CAYMAN ? ~0 : + ((1ull << MAX2(1, info->src.resource->nr_samples)) - 1); + + assert(info->src.level == 0); + assert(info->src.box.depth == 1); + assert(info->dst.box.depth == 1); + + if (is_simple_msaa_resolve(info)) { + r600_blitter_begin(ctx, R600_COLOR_RESOLVE); + util_blitter_custom_resolve_color(rctx->blitter, + info->dst.resource, info->dst.level, + info->dst.box.z, + info->src.resource, info->src.box.z, + sample_mask, rctx->custom_blend_resolve); + r600_blitter_end(ctx); + return; + } + + /* resolve into a temporary texture, then blit */ + templ.target = PIPE_TEXTURE_2D; + templ.format = info->src.resource->format; + templ.width0 = info->src.resource->width0; + templ.height0 = info->src.resource->height0; + templ.depth0 = 1; + templ.array_size = 1; + templ.last_level = 0; + templ.nr_samples = 0; + templ.usage = PIPE_USAGE_STATIC; + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + templ.flags = 0; + + tmp = screen->resource_create(screen, &templ); + + /* resolve */ + r600_blitter_begin(ctx, R600_COLOR_RESOLVE); + util_blitter_custom_resolve_color(rctx->blitter, + tmp, 0, 0, + info->src.resource, info->src.box.z, + sample_mask, rctx->custom_blend_resolve); + r600_blitter_end(ctx); + + /* blit */ + blit = *info; + blit.src.resource = tmp; + blit.src.box.z = 0; + + r600_blitter_begin(ctx, R600_BLIT); + util_blitter_blit(rctx->blitter, &blit); + r600_blitter_end(ctx); + + pipe_resource_reference(&tmp, NULL); +} + +static void r600_blit(struct pipe_context *ctx, + const struct pipe_blit_info *info) +{ + struct r600_context *rctx = (struct r600_context*)ctx; + + assert(util_blitter_is_blit_supported(rctx->blitter, info)); + + if (info->src.resource->nr_samples > 1 && + info->dst.resource->nr_samples <= 1 && + !util_format_is_depth_or_stencil(info->src.resource->format) && + !util_format_is_pure_integer(info->src.resource->format)) { + r600_msaa_color_resolve(ctx, info); + return; + } + + /* The driver doesn't decompress resources automatically while + * u_blitter is rendering. */ + if (!r600_decompress_subresource(ctx, info->src.resource, info->src.level, + info->src.box.z, + info->src.box.z + info->src.box.depth - 1)) { + return; /* error */ + } + + r600_blitter_begin(ctx, R600_BLIT); + util_blitter_blit(rctx->blitter, info); + r600_blitter_end(ctx); +} + void r600_init_blit_functions(struct r600_context *rctx) { rctx->context.clear = r600_clear; @@ -778,4 +893,5 @@ void r600_init_blit_functions(struct r600_context *rctx) rctx->context.clear_depth_stencil = r600_clear_depth_stencil; rctx->context.resource_copy_region = r600_resource_copy_region; rctx->context.resource_resolve = r600_resource_resolve; + rctx->context.blit = r600_blit; } diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 315253ac730..75e3c24bd4d 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -379,6 +379,7 @@ struct r600_context { unsigned db_shader_control; unsigned pa_sc_line_stipple; /* for saving when using blitter */ + struct pipe_scissor_state scissor; struct r600_pipe_shader_selector *ps_shader; struct r600_pipe_shader_selector *vs_shader; struct r600_pipe_rasterizer *rasterizer; @@ -479,9 +480,8 @@ struct r600_context { unsigned streamout_append_bitmask; /* There is no scissor enable bit on r6xx, so we must use a workaround. - * These track the current scissor state. */ + * This tracks if the scissor is enabled. */ bool scissor_enable; - struct pipe_scissor_state scissor_state; /* With rasterizer discard, there doesn't have to be a pixel shader. * In that case, we bind this one: */ diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 60c861fc8e0..3347e6d872f 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -593,7 +593,8 @@ boolean r600_is_format_supported(struct pipe_screen *screen, return FALSE; /* MSAA integer colorbuffers hang. */ - if (util_format_is_pure_integer(format)) + if (util_format_is_pure_integer(format) && + !util_format_is_depth_or_stencil(format)) return FALSE; switch (sample_count) { @@ -1156,12 +1157,10 @@ static void r600_pipe_set_scissor_state(struct pipe_context *ctx, { struct r600_context *rctx = (struct r600_context *)ctx; - if (rctx->chip_class == R600) { - rctx->scissor_state = *state; + rctx->scissor = *state; - if (!rctx->scissor_enable) - return; - } + if (rctx->chip_class == R600 && !rctx->scissor_enable) + return; r600_set_scissor_state(rctx, state); } diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index b1a0f66d2ef..2796b9d969d 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -350,7 +350,7 @@ static void r600_bind_rs_state(struct pipe_context *ctx, void *state) rctx->scissor_enable = rs->scissor_enable; if (rs->scissor_enable) { - r600_set_scissor_state(rctx, &rctx->scissor_state); + r600_set_scissor_state(rctx, &rctx->scissor); } else { r600_set_max_scissor(rctx); } |