From 0b0697e80dd442d7e7cb23641ad8f58f82df120d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Wed, 12 Sep 2012 23:37:17 +0200 Subject: [PATCH] gallium/u_blitter: add gallium blit implementation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The original blit function is extended and the otAher functions reuse it. Tested-by: Michel Dänzer Reviewed-by: Brian Paul --- src/gallium/auxiliary/util/u_blitter.c | 284 +++++++++++++------ src/gallium/auxiliary/util/u_blitter.h | 66 +++-- src/gallium/drivers/i915/i915_surface.c | 4 +- src/gallium/drivers/r300/r300_blit.c | 8 +- src/gallium/drivers/r300/r300_context.h | 3 +- src/gallium/drivers/r300/r300_render.c | 3 +- src/gallium/drivers/r600/r600_blit.c | 38 +-- src/gallium/drivers/r600/r600_pipe.h | 2 +- src/gallium/drivers/r600/r600_state_common.c | 2 +- src/gallium/drivers/radeonsi/r600_blit.c | 4 +- 10 files changed, 258 insertions(+), 156 deletions(-) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index a47fba6e1eb..2d20d708e7b 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -27,7 +27,7 @@ /** * @file * Blitter utility to facilitate acceleration of the clear, clear_render_target, - * clear_depth_stencil, and resource_copy_region functions. + * clear_depth_stencil, resource_copy_region, and blit functions. * * @author Marek Olšák */ @@ -88,8 +88,7 @@ struct blitter_context_priv void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES]; /* Blend state. */ - void *blend_write_color; /**< blend state with writemask of RGBA */ - void *blend_keep_color; /**< blend state with writemask of 0 */ + void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */ /* Depth stencil alpha state. */ void *dsa_write_depth_stencil; @@ -104,11 +103,10 @@ struct blitter_context_priv void *velem_state_readbuf; /* Sampler state. */ - void *sampler_state; + void *sampler_state, *sampler_state_linear; /* Rasterizer state. */ - void *rs_state; - void *rs_discard_state; + void *rs_state, *rs_state_scissor, *rs_discard_state; /* Viewport state. */ struct pipe_viewport_state viewport; @@ -182,10 +180,11 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) /* blend state objects */ memset(&blend, 0, sizeof(blend)); - ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend); - blend.rt[0].colormask = PIPE_MASK_RGBA; - ctx->blend_write_color = pipe->create_blend_state(pipe, &blend); + for (i = 0; i <= PIPE_MASK_RGBA; i++) { + blend.rt[0].colormask = i; + ctx->blend[i] = pipe->create_blend_state(pipe, &blend); + } /* depth stencil alpha state objects */ memset(&dsa, 0, sizeof(dsa)); @@ -221,6 +220,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) sampler_state.normalized_coords = 1; ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state); + sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state); + /* rasterizer state */ memset(&rs_state, 0, sizeof(rs_state)); rs_state.cull_face = PIPE_FACE_NONE; @@ -229,7 +232,11 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) rs_state.depth_clip = 1; ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); + rs_state.scissor = 1; + ctx->rs_state_scissor = pipe->create_rasterizer_state(pipe, &rs_state); + if (ctx->has_stream_out) { + rs_state.scissor = 0; rs_state.rasterizer_discard = 1; ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state); } @@ -304,8 +311,9 @@ void util_blitter_destroy(struct blitter_context *blitter) struct pipe_context *pipe = blitter->pipe; int i; - pipe->delete_blend_state(pipe, ctx->blend_write_color); - pipe->delete_blend_state(pipe, ctx->blend_keep_color); + for (i = 0; i <= PIPE_MASK_RGBA; i++) { + pipe->delete_blend_state(pipe, ctx->blend[i]); + } pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); @@ -313,6 +321,7 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); pipe->delete_rasterizer_state(pipe, ctx->rs_state); + pipe->delete_rasterizer_state(pipe, ctx->rs_state_scissor); if (ctx->rs_discard_state) pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state); pipe->delete_vs_state(pipe, ctx->vs); @@ -345,6 +354,7 @@ void util_blitter_destroy(struct blitter_context *blitter) } pipe->delete_sampler_state(pipe, ctx->sampler_state); + pipe->delete_sampler_state(pipe, ctx->sampler_state_linear); u_upload_destroy(ctx->upload); FREE(ctx); } @@ -524,8 +534,7 @@ static void blitter_restore_textures(struct blitter_context_priv *ctx) } static void blitter_set_rectangle(struct blitter_context_priv *ctx, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, + int x1, int y1, int x2, int y2, float depth) { int i; @@ -583,8 +592,7 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx, static void get_texcoords(struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, + int x1, int y1, int x2, int y2, float out[4]) { struct pipe_resource *tex = src->texture; @@ -625,8 +633,7 @@ static void blitter_set_texcoords(struct blitter_context_priv *ctx, struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, unsigned layer, unsigned sample, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2) + int x1, int y1, int x2, int y2) { unsigned i; float coord[4]; @@ -895,11 +902,13 @@ void util_blitter_cache_all_shaders(struct blitter_context *blitter) } } -static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx) +static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx, + boolean scissor) { struct pipe_context *pipe = ctx->base.pipe; - pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor + : ctx->rs_state); pipe->bind_vs_state(pipe, ctx->vs); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); @@ -908,9 +917,7 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx) } static void blitter_draw(struct blitter_context_priv *ctx, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, - float depth) + int x1, int y1, int x2, int y2, float depth) { struct pipe_resource *buf = NULL; unsigned offset = 0; @@ -926,9 +933,7 @@ static void blitter_draw(struct blitter_context_priv *ctx, } void util_blitter_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, - float depth, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { @@ -973,9 +978,9 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, if (custom_blend) { pipe->bind_blend_state(pipe, custom_blend); } else if (clear_buffers & PIPE_CLEAR_COLOR) { - pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]); } else { - pipe->bind_blend_state(pipe, ctx->blend_keep_color); + pipe->bind_blend_state(pipe, ctx->blend[0]); } if (custom_dsa) { @@ -1003,7 +1008,7 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format)); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, width, height); blitter->draw_rectangle(blitter, 0, 0, width, height, depth, UTIL_BLITTER_ATTRIB_COLOR, color); @@ -1037,7 +1042,7 @@ void util_blitter_custom_clear_depth(struct blitter_context *blitter, } static -boolean is_overlap(unsigned dstx, unsigned dsty, unsigned dstz, +boolean is_overlap(int dstx, int dsty, int dstz, const struct pipe_box *srcbox) { struct pipe_box src = *srcbox; @@ -1096,10 +1101,12 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ, src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA; } -boolean util_blitter_is_copy_supported(struct blitter_context *blitter, - const struct pipe_resource *dst, - const struct pipe_resource *src, - unsigned mask) +static boolean is_blit_generic_supported(struct blitter_context *blitter, + const struct pipe_resource *dst, + enum pipe_format dst_format, + const struct pipe_resource *src, + enum pipe_format src_format, + unsigned mask) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_screen *screen = ctx->base.pipe->screen; @@ -1108,7 +1115,7 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, unsigned bind; boolean is_stencil; const struct util_format_description *desc = - util_format_description(dst->format); + util_format_description(dst_format); is_stencil = util_format_has_stencil(desc); @@ -1122,7 +1129,7 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, else bind = PIPE_BIND_RENDER_TARGET; - if (!screen->is_format_supported(screen, dst->format, dst->target, + if (!screen->is_format_supported(screen, dst_format, dst->target, dst->nr_samples, bind)) { return FALSE; } @@ -1133,18 +1140,18 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, return FALSE; } - if (!screen->is_format_supported(screen, src->format, src->target, + if (!screen->is_format_supported(screen, src_format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { return FALSE; } /* Check stencil sampler support for stencil copy. */ - if (util_format_has_stencil(util_format_description(src->format))) { + if (util_format_has_stencil(util_format_description(src_format))) { enum pipe_format stencil_format = - util_format_stencil_only(src->format); + util_format_stencil_only(src_format); assert(stencil_format != PIPE_FORMAT_NONE); - if (stencil_format != src->format && + if (stencil_format != src_format && !screen->is_format_supported(screen, stencil_format, src->target, src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) { return FALSE; @@ -1155,13 +1162,32 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, return TRUE; } +boolean util_blitter_is_copy_supported(struct blitter_context *blitter, + const struct pipe_resource *dst, + const struct pipe_resource *src, + unsigned mask) +{ + return is_blit_generic_supported(blitter, dst, dst->format, + src, src->format, mask); +} + +boolean util_blitter_is_blit_supported(struct blitter_context *blitter, + const struct pipe_blit_info *info) +{ + return is_blit_generic_supported(blitter, + info->dst.resource, info->dst.format, + info->src.resource, info->src.format, + info->mask); +} + void util_blitter_copy_texture(struct blitter_context *blitter, struct pipe_resource *dst, - unsigned dst_level, unsigned dst_sample_mask, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - unsigned src_level, unsigned src_sample, - const struct pipe_box *srcbox) + unsigned src_level, + const struct pipe_box *srcbox, unsigned mask, + boolean copy_all_samples) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; @@ -1180,44 +1206,53 @@ void util_blitter_copy_texture(struct blitter_context *blitter, src_view = pipe->create_sampler_view(pipe, src, &src_templ); /* Copy. */ - util_blitter_copy_texture_view(blitter, dst_view, dst_sample_mask, dstx, - dsty, src_view, src_sample, srcbox, - src->width0, src->height0, PIPE_MASK_RGBAZS); + util_blitter_blit_generic(blitter, dst_view, dstx, dsty, + abs(srcbox->width), abs(srcbox->height), + src_view, srcbox, src->width0, src->height0, + mask, PIPE_TEX_FILTER_NEAREST, NULL, + copy_all_samples); pipe_surface_reference(&dst_view, NULL); pipe_sampler_view_reference(&src_view, NULL); } -void util_blitter_copy_texture_view(struct blitter_context *blitter, - struct pipe_surface *dst, - unsigned dst_sample_mask, - unsigned dstx, unsigned dsty, - struct pipe_sampler_view *src, - unsigned src_sample, - const struct pipe_box *srcbox, - unsigned src_width0, unsigned src_height0, - unsigned mask) +void util_blitter_blit_generic(struct blitter_context *blitter, + struct pipe_surface *dst, + int dstx, int dsty, + unsigned dst_width, unsigned dst_height, + struct pipe_sampler_view *src, + const struct pipe_box *srcbox, + unsigned src_width0, unsigned src_height0, + unsigned mask, unsigned filter, + const struct pipe_scissor_state *scissor, + boolean copy_all_samples) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; struct pipe_framebuffer_state fb_state; enum pipe_texture_target src_target = src->texture->target; - int abs_width = abs(srcbox->width); - int abs_height = abs(srcbox->height); - boolean blit_stencil, blit_depth; + boolean has_depth, has_stencil, has_color; + boolean blit_stencil, blit_depth, blit_color; + void *sampler_state; const struct util_format_description *src_desc = util_format_description(src->format); - - blit_depth = util_format_has_depth(src_desc) && (mask & PIPE_MASK_Z); - blit_stencil = util_format_has_stencil(src_desc) && (mask & PIPE_MASK_S); - - /* If you want a fallback for stencil copies, - * use util_blitter_copy_texture. */ - if (blit_stencil && !ctx->has_stencil_export) { - blit_stencil = FALSE; - - if (!blit_depth) - return; + const struct util_format_description *dst_desc = + util_format_description(dst->format); + + has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS && + dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS; + has_depth = util_format_has_depth(src_desc) && + util_format_has_depth(dst_desc); + has_stencil = util_format_has_stencil(src_desc) && + util_format_has_stencil(dst_desc); + + blit_color = has_color && (mask & PIPE_MASK_RGBA); + blit_depth = has_depth && (mask & PIPE_MASK_Z); + blit_stencil = has_stencil && (mask & PIPE_MASK_S) && + ctx->has_stencil_export; + + if (!blit_stencil && !blit_depth && !blit_color) { + return; } /* Sanity checks. */ @@ -1241,7 +1276,7 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, fb_state.height = dst->height; if (blit_depth || blit_stencil) { - pipe->bind_blend_state(pipe, ctx->blend_keep_color); + pipe->bind_blend_state(pipe, ctx->blend[0]); if (blit_depth && blit_stencil) { pipe->bind_depth_stencil_alpha_state(pipe, @@ -1266,7 +1301,7 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, fb_state.nr_cbufs = 0; fb_state.zsbuf = dst; } else { - pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_texfetch_col(ctx, src->texture->target, @@ -1277,11 +1312,22 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, fb_state.zsbuf = 0; } + /* Set the linear filter only for scaled color non-MSAA blits. */ + if (filter == PIPE_TEX_FILTER_LINEAR && + !blit_depth && !blit_stencil && + src->texture->nr_samples <= 1 && + (dst_width != abs(srcbox->width) || dst_height != abs(srcbox->height))) { + sampler_state = ctx->sampler_state_linear; + } else { + sampler_state = ctx->sampler_state; + } + + /* Set samplers. */ if (blit_depth && blit_stencil) { /* Setup two samplers, one for depth and the other one for stencil. */ struct pipe_sampler_view templ; struct pipe_sampler_view *views[2]; - void *samplers[2] = {ctx->sampler_state, ctx->sampler_state}; + void *samplers[2] = {sampler_state, sampler_state}; templ = *src; templ.format = util_format_stencil_only(templ.format); @@ -1306,19 +1352,22 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, view = pipe->create_sampler_view(pipe, src->texture, &templ); pipe->set_fragment_sampler_views(pipe, 1, &view); - pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state); + pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state); pipe_sampler_view_reference(&view, NULL); } else { pipe->set_fragment_sampler_views(pipe, 1, &src); - pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state); + pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state); } pipe->bind_vertex_elements_state(pipe, ctx->velem_state); pipe->set_framebuffer_state(pipe, &fb_state); - pipe->set_sample_mask(pipe, dst_sample_mask); - blitter_set_common_draw_rect_state(ctx); + if (scissor) { + pipe->set_scissor_state(pipe, scissor); + } + + blitter_set_common_draw_rect_state(ctx, scissor != NULL); blitter_set_dst_dimensions(ctx, dst->width, dst->height); if ((src_target == PIPE_TEXTURE_1D || @@ -1337,25 +1386,82 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f); /* Draw. */ - blitter->draw_rectangle(blitter, dstx, dsty, dstx+abs_width, dsty+abs_height, 0, + pipe->set_sample_mask(pipe, ~0); + blitter->draw_rectangle(blitter, dstx, dsty, + dstx+dst_width, dsty+dst_height, 0, UTIL_BLITTER_ATTRIB_TEXCOORD, &coord); } else { /* Draw the quad with the generic codepath. */ - blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, - src_sample, - srcbox->x, srcbox->y, - srcbox->x + srcbox->width, srcbox->y + srcbox->height); - blitter_draw(ctx, dstx, dsty, dstx+abs_width, dsty+abs_height, 0); + if (copy_all_samples && + src->texture->nr_samples == dst->texture->nr_samples && + dst->texture->nr_samples > 1) { + /* MSAA copy. */ + unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1; + + for (i = 0; i <= max_sample; i++) { + pipe->set_sample_mask(pipe, 1 << i); + blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, + i, srcbox->x, srcbox->y, + srcbox->x + srcbox->width, + srcbox->y + srcbox->height); + blitter_draw(ctx, dstx, dsty, + dstx+dst_width, dsty+dst_height, 0); + } + } else { + pipe->set_sample_mask(pipe, ~0); + blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, 0, + srcbox->x, srcbox->y, + srcbox->x + srcbox->width, + srcbox->y + srcbox->height); + blitter_draw(ctx, dstx, dsty, dstx+dst_width, dsty+dst_height, 0); + } } blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_textures(ctx); blitter_restore_fb_state(ctx); + if (scissor) { + pipe->set_scissor_state(pipe, &ctx->base.saved_scissor); + } blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } +void +util_blitter_blit(struct blitter_context *blitter, + const struct pipe_blit_info *info) +{ + struct pipe_resource *dst = info->dst.resource; + struct pipe_resource *src = info->src.resource; + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_surface *dst_view, dst_templ; + struct pipe_sampler_view src_templ, *src_view; + + /* Initialize the surface. */ + util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level, + info->dst.box.z, &info->src.box); + dst_templ.format = info->dst.format; + dst_view = pipe->create_surface(pipe, dst, &dst_templ); + + /* Initialize the sampler view. */ + util_blitter_default_src_texture(&src_templ, src, info->src.level); + src_templ.format = info->src.format; + src_view = pipe->create_sampler_view(pipe, src, &src_templ); + + /* Copy. */ + util_blitter_blit_generic(blitter, dst_view, + info->dst.box.x, info->dst.box.y, + info->dst.box.width, info->dst.box.height, + src_view, &info->src.box, src->width0, src->height0, + info->mask, info->filter, + info->scissor_enable ? &info->scissor : NULL, TRUE); + + pipe_surface_reference(&dst_view, NULL); + pipe_sampler_view_reference(&src_view, NULL); +} + /* Clear a region of a color surface to a constant value. */ void util_blitter_clear_render_target(struct blitter_context *blitter, struct pipe_surface *dstsurf, @@ -1379,7 +1485,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, blitter_disable_render_cond(ctx); /* bind states */ - pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); @@ -1393,7 +1499,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0, UTIL_BLITTER_ATTRIB_COLOR, color); @@ -1431,7 +1537,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, blitter_disable_render_cond(ctx); /* bind states */ - pipe->bind_blend_state(pipe, ctx->blend_keep_color); + pipe->bind_blend_state(pipe, ctx->blend[0]); if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) { sr.ref_value[0] = stencil & 0xff; pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil); @@ -1461,7 +1567,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth, UTIL_BLITTER_ATTRIB_NONE, NULL); @@ -1496,7 +1602,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, blitter_disable_render_cond(ctx); /* bind states */ - pipe->bind_blend_state(pipe, ctx->blend_write_color); + pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]); pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); @@ -1516,7 +1622,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, sample_mask); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height); blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth, UTIL_BLITTER_ATTRIB_NONE, NULL); @@ -1641,7 +1747,7 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, fb_state.zsbuf = NULL; pipe->set_framebuffer_state(pipe, &fb_state); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, src->width0, src->height0); blitter->draw_rectangle(blitter, 0, 0, src->width0, src->height0, 0, 0, NULL); @@ -1690,7 +1796,7 @@ void util_blitter_custom_color(struct blitter_context *blitter, pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); - blitter_set_common_draw_rect_state(ctx); + blitter_set_common_draw_rect_state(ctx, FALSE); blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height); blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height, 0, 0, NULL); diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 43b732699e3..026e88b5154 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -74,7 +74,7 @@ struct blitter_context * a rectangular point sprite. */ void (*draw_rectangle)(struct blitter_context *blitter, - unsigned x1, unsigned y1, unsigned x2, unsigned y2, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *color); @@ -94,6 +94,7 @@ struct blitter_context struct pipe_framebuffer_state saved_fb_state; /**< framebuffer state */ struct pipe_stencil_ref saved_stencil_ref; /**< stencil ref */ struct pipe_viewport_state saved_viewport; + struct pipe_scissor_state saved_scissor; boolean is_sample_mask_saved; unsigned saved_sample_mask; @@ -137,9 +138,7 @@ struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter) /* The default function to draw a rectangle. This can only be used * inside of the draw_rectangle callback if the driver overrides it. */ void util_blitter_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, - float depth, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib); @@ -180,19 +179,13 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, const struct pipe_resource *dst, const struct pipe_resource *src, unsigned mask); + +boolean util_blitter_is_blit_supported(struct blitter_context *blitter, + const struct pipe_blit_info *info); + /** * Copy a block of pixels from one surface to another. * - * You can copy from any color format to any other color format provided - * the former can be sampled from and the latter can be rendered to. Otherwise, - * a software fallback path is taken and both surfaces must be of the same - * format. - * - * Only one sample of a multisample texture can be copied and is specified by - * src_sample. If the destination is a multisample resource, dst_sample_mask - * specifies the sample mask. For single-sample resources, set dst_sample_mask - * to ~0. - * * These states must be saved in the blitter in addition to the state objects * already required to be saved: * - fragment shader @@ -201,19 +194,21 @@ boolean util_blitter_is_copy_supported(struct blitter_context *blitter, * - fragment sampler states * - fragment sampler textures * - framebuffer state + * - sample mask */ void util_blitter_copy_texture(struct blitter_context *blitter, struct pipe_resource *dst, - unsigned dst_level, unsigned dst_sample_mask, + unsigned dst_level, unsigned dstx, unsigned dsty, unsigned dstz, struct pipe_resource *src, - unsigned src_level, unsigned src_sample, - const struct pipe_box *srcbox); + unsigned src_level, + const struct pipe_box *srcbox, unsigned mask, + boolean copy_all_samples); /** - * Same as util_blitter_copy_texture, but dst and src are pipe_surface and - * pipe_sampler_view, respectively. The mipmap level and dstz are part of - * the views. + * Same as util_blitter_copy_texture with the capabilities of util_blitter_blit, + * but dst and src are pipe_surface and pipe_sampler_view, respectively. + * The mipmap level and dstz are part of the views. * * Drivers can use this to change resource properties (like format, width, * height) by changing how the views interpret them, instead of changing @@ -227,18 +222,20 @@ void util_blitter_copy_texture(struct blitter_context *blitter, * * The mask is a combination of the PIPE_MASK_* flags. * Set to PIPE_MASK_RGBAZS if unsure. - * - * NOTE: There are no checks whether the blit is actually supported. */ -void util_blitter_copy_texture_view(struct blitter_context *blitter, - struct pipe_surface *dst, - unsigned dst_sample_mask, - unsigned dstx, unsigned dsty, - struct pipe_sampler_view *src, - unsigned src_sample, - const struct pipe_box *srcbox, - unsigned src_width0, unsigned src_height0, - unsigned mask); +void util_blitter_blit_generic(struct blitter_context *blitter, + struct pipe_surface *dst, + int dstx, int dsty, + unsigned dst_width, unsigned dst_height, + struct pipe_sampler_view *src, + const struct pipe_box *srcbox, + unsigned src_width0, unsigned src_height0, + unsigned mask, unsigned filter, + const struct pipe_scissor_state *scissor, + boolean copy_all_samples); + +void util_blitter_blit(struct blitter_context *blitter, + const struct pipe_blit_info *info); /** * Helper function to initialize a view for copy_texture_view. @@ -415,6 +412,13 @@ void util_blitter_save_viewport(struct blitter_context *blitter, blitter->saved_viewport = *state; } +static INLINE +void util_blitter_save_scissor(struct blitter_context *blitter, + struct pipe_scissor_state *state) +{ + blitter->saved_scissor = *state; +} + static INLINE void util_blitter_save_fragment_sampler_states( struct blitter_context *blitter, diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index 5f0783f0305..99837fe7658 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -86,8 +86,8 @@ i915_surface_copy_render(struct pipe_context *pipe, i915->saved_nr_sampler_views, i915->saved_sampler_views); - util_blitter_copy_texture(i915->blitter, dst, dst_level, ~0, dstx, dsty, dstz, - src, src_level, 0, src_box); + util_blitter_copy_texture(i915->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box, PIPE_MASK_RGBAZS, TRUE); } static void diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index f2c67c0a113..3e8217622c5 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -577,9 +577,11 @@ static void r300_resource_copy_region(struct pipe_context *pipe, src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0); r300_blitter_begin(r300, R300_COPY); - util_blitter_copy_texture_view(r300->blitter, dst_view, ~0, dstx, dsty, - src_view, 0, src_box, - src_width0, src_height0, PIPE_MASK_RGBAZS); + util_blitter_blit_generic(r300->blitter, dst_view, dstx, dsty, + abs(src_box->width), abs(src_box->height), + src_view, src_box, + src_width0, src_height0, PIPE_MASK_RGBAZS, + PIPE_TEX_FILTER_NEAREST, NULL, FALSE); r300_blitter_end(r300); pipe_surface_reference(&dst_view, NULL); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index fe253089094..7d3b12d45d8 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -722,8 +722,7 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300); void r300_draw_flush_vbuf(struct r300_context *r300); void r500_emit_index_bias(struct r300_context *r300, int index_bias); void r300_blitter_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib); diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index ceda1269707..e388260894c 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -1172,8 +1172,7 @@ void r300_draw_flush_vbuf(struct r300_context *r300) * would be computed and stored twice, which makes the clear/copy codepaths * somewhat inefficient. Instead we use a rectangular point sprite. */ void r300_blitter_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) diff --git a/src/gallium/drivers/r600/r600_blit.c b/src/gallium/drivers/r600/r600_blit.c index 3da583c5d09..536b2a19bde 100644 --- a/src/gallium/drivers/r600/r600_blit.c +++ b/src/gallium/drivers/r600/r600_blit.c @@ -379,10 +379,11 @@ static void r600_copy_first_sample(struct pipe_context *ctx, /* Copy the first sample into dst. */ r600_blitter_begin(ctx, R600_COPY_TEXTURE); - util_blitter_copy_texture_view(rctx->blitter, dst_view, ~0, info->dst.x0, - info->dst.y0, src_view, 0, &box, - info->src.res->width0, info->src.res->height0, - info->mask); + util_blitter_blit_generic(rctx->blitter, dst_view, info->dst.x0, + info->dst.y0, abs(box.width), abs(box.height), + src_view, &box, + info->src.res->width0, info->src.res->height0, + info->mask, PIPE_TEX_FILTER_NEAREST, NULL, FALSE); r600_blitter_end(ctx); pipe_surface_reference(&dst_view, NULL); @@ -460,8 +461,8 @@ static void r600_color_resolve(struct pipe_context *ctx, r600_blitter_begin(ctx, R600_COPY_TEXTURE); util_blitter_copy_texture(rctx->blitter, info->dst.res, info->dst.level, - ~0, info->dst.x0, info->dst.y0, info->dst.layer, - tmp, 0, 0, &box); + info->dst.x0, info->dst.y0, info->dst.layer, + tmp, 0, &box, PIPE_MASK_RGBAZS, FALSE); r600_blitter_end(ctx); pipe_resource_reference(&tmp, NULL); @@ -678,7 +679,6 @@ static void r600_resource_copy_region(struct pipe_context *ctx, struct pipe_box sbox; const struct pipe_box *psbox = src_box; boolean restore_orig[2]; - unsigned last_sample, i; memset(orig_info, 0, sizeof(orig_info)); @@ -689,7 +689,6 @@ 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); /* The driver doesn't decompress resources automatically while * u_blitter is rendering. */ @@ -756,21 +755,14 @@ static void r600_resource_copy_region(struct pipe_context *ctx, restore_orig[1] = TRUE; } - /* 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, ~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); - } - } + /* XXX Multisample texturing is unimplemented on Cayman. In the meantime, + * copy only the first sample (which is the only one that is uncompressed + * and therefore doesn't return garbage). */ + r600_blitter_begin(ctx, R600_COPY_TEXTURE); + util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, psbox, PIPE_MASK_RGBAZS, + rctx->chip_class != CAYMAN); + r600_blitter_end(ctx); if (restore_orig[0]) r600_reset_blittable_to_orig(src, src_level, &orig_info[0]); diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index e66766a9844..315253ac730 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -643,7 +643,7 @@ void r600_sampler_states_dirty(struct r600_context *rctx, void r600_set_max_scissor(struct r600_context *rctx); void r600_constant_buffers_dirty(struct r600_context *rctx, struct r600_constbuf_state *state); void r600_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib); uint32_t r600_translate_stencil_op(int s_op); uint32_t r600_translate_fill(uint32_t func); diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 95beaa1cc7e..b1a0f66d2ef 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -1343,7 +1343,7 @@ static void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info } void r600_draw_rectangle(struct blitter_context *blitter, - unsigned x1, unsigned y1, unsigned x2, unsigned y2, float depth, + int x1, int y1, int x2, int y2, float depth, enum blitter_attrib_type type, const union pipe_color_union *attrib) { struct r600_context *rctx = (struct r600_context*)util_blitter_get_pipe(blitter); diff --git a/src/gallium/drivers/radeonsi/r600_blit.c b/src/gallium/drivers/radeonsi/r600_blit.c index 4406204b512..e599deb8647 100644 --- a/src/gallium/drivers/radeonsi/r600_blit.c +++ b/src/gallium/drivers/radeonsi/r600_blit.c @@ -249,8 +249,8 @@ static void r600_hw_copy_region(struct pipe_context *ctx, struct r600_context *rctx = (struct r600_context *)ctx; r600_blitter_begin(ctx, R600_COPY); - util_blitter_copy_texture(rctx->blitter, dst, dst_level, ~0, dstx, dsty, dstz, - src, src_level, 0, src_box); + util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz, + src, src_level, src_box, PIPE_MASK_RGBAZS, TRUE); r600_blitter_end(ctx); } -- 2.30.2