diff options
Diffstat (limited to 'mesalib/src/gallium/auxiliary/util')
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blitter.c | 636 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blitter.h | 92 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_dump.h | 6 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_dump_state.c | 73 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_surface.c | 30 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_surface.h | 11 |
6 files changed, 633 insertions, 215 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index 35b8edba7..4ad7a6be4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/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; @@ -121,8 +119,13 @@ struct blitter_context_priv boolean vertex_has_integers; boolean has_stream_out; boolean has_stencil_export; -}; + boolean has_texture_multisample; + /* The Draw module overrides these functions. + * Always create the blitter before Draw. */ + void (*bind_fs_state)(struct pipe_context *, void *); + void (*delete_fs_state)(struct pipe_context *, void *); +}; struct blitter_context *util_blitter_create(struct pipe_context *pipe) { @@ -141,6 +144,9 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->base.pipe = pipe; ctx->base.draw_rectangle = util_blitter_draw_rectangle; + ctx->bind_fs_state = pipe->bind_fs_state; + ctx->delete_fs_state = pipe->delete_fs_state; + /* init state objects for them to be considered invalid */ ctx->base.saved_blend_state = INVALID_PTR; ctx->base.saved_dsa_state = INVALID_PTR; @@ -169,12 +175,16 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT); + ctx->has_texture_multisample = + pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE); + /* 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)); @@ -210,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; @@ -218,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); } @@ -293,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); @@ -302,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); @@ -317,23 +337,24 @@ void util_blitter_destroy(struct blitter_context *blitter) for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]); if (ctx->fs_texfetch_depth[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]); if (ctx->fs_texfetch_depthstencil[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]); if (ctx->fs_texfetch_stencil[i]) - pipe->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); + ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]); } for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) { if (ctx->fs_col[i]) - pipe->delete_fs_state(pipe, ctx->fs_col[i]); + ctx->delete_fs_state(pipe, ctx->fs_col[i]); if (ctx->fs_col_int[i]) - pipe->delete_fs_state(pipe, ctx->fs_col_int[i]); + ctx->delete_fs_state(pipe, ctx->fs_col_int[i]); } pipe->delete_sampler_state(pipe, ctx->sampler_state); + pipe->delete_sampler_state(pipe, ctx->sampler_state_linear); u_upload_destroy(ctx->upload); FREE(ctx); } @@ -427,7 +448,7 @@ static void blitter_restore_fragment_states(struct blitter_context_priv *ctx) struct pipe_context *pipe = ctx->base.pipe; /* Fragment shader. */ - pipe->bind_fs_state(pipe, ctx->base.saved_fs); + ctx->bind_fs_state(pipe, ctx->base.saved_fs); ctx->base.saved_fs = INVALID_PTR; /* Depth, stencil, alpha. */ @@ -456,6 +477,26 @@ static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx) assert(ctx->base.saved_fb_state.nr_cbufs != ~0); } +static void blitter_disable_render_cond(struct blitter_context_priv *ctx) +{ + struct pipe_context *pipe = ctx->base.pipe; + + if (ctx->base.saved_render_cond_query) { + pipe->render_condition(pipe, NULL, 0); + } +} + +static void blitter_restore_render_cond(struct blitter_context_priv *ctx) +{ + struct pipe_context *pipe = ctx->base.pipe; + + if (ctx->base.saved_render_cond_query) { + pipe->render_condition(pipe, ctx->base.saved_render_cond_query, + ctx->base.saved_render_cond_mode); + ctx->base.saved_render_cond_query = NULL; + } +} + static void blitter_restore_fb_state(struct blitter_context_priv *ctx) { struct pipe_context *pipe = ctx->base.pipe; @@ -493,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; @@ -552,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; @@ -594,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]; @@ -653,9 +691,8 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, ctx->dst_height = height; } -static INLINE -void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, - boolean int_format) +static void *blitter_get_fs_col(struct blitter_context_priv *ctx, + unsigned num_cbufs, boolean int_format) { struct pipe_context *pipe = ctx->base.pipe; @@ -678,32 +715,32 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs, } } -static INLINE -void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, - struct pipe_resource *tex) +static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_col_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_col_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex); } return *shader; } else { - void **shader = &ctx->fs_texfetch_col[tex->target]; + void **shader = &ctx->fs_texfetch_col[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader(pipe, tgsi_tex, @@ -716,19 +753,20 @@ void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_depth_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_depth_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_depth(pipe, tgsi_tex); @@ -736,11 +774,11 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_depth[tex->target]; + void **shader = &ctx->fs_texfetch_depth[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex, @@ -753,19 +791,20 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_depthstencil_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_depthstencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex); @@ -773,11 +812,11 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_depthstencil[tex->target]; + void **shader = &ctx->fs_texfetch_depthstencil[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex, @@ -790,19 +829,20 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx, static INLINE void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, - struct pipe_resource *tex) + enum pipe_texture_target target, + unsigned nr_samples) { struct pipe_context *pipe = ctx->base.pipe; - assert(tex->target < PIPE_MAX_TEXTURE_TYPES); + assert(target < PIPE_MAX_TEXTURE_TYPES); - if (tex->nr_samples > 1) { - void **shader = &ctx->fs_texfetch_stencil_msaa[tex->target]; + if (nr_samples > 1) { + void **shader = &ctx->fs_texfetch_stencil_msaa[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, - tex->nr_samples); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, + nr_samples); *shader = util_make_fs_blit_msaa_stencil(pipe, tgsi_tex); @@ -810,11 +850,11 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, return *shader; } else { - void **shader = &ctx->fs_texfetch_stencil[tex->target]; + void **shader = &ctx->fs_texfetch_stencil[target]; /* Create the fragment shader on-demand. */ if (!*shader) { - unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex->target, 0); + unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0); *shader = util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex, @@ -825,11 +865,50 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx, } } -static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx) +void util_blitter_cache_all_shaders(struct blitter_context *blitter) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_screen *screen = blitter->pipe->screen; + unsigned num_cbufs, i, target, max_samples; + boolean has_arraytex; + + num_cbufs = MAX2(screen->get_param(screen, + PIPE_CAP_MAX_RENDER_TARGETS), 1); + max_samples = ctx->has_texture_multisample ? 2 : 1; + has_arraytex = screen->get_param(screen, + PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0; + + for (i = 0; i < num_cbufs; i++) { + blitter_get_fs_col(ctx, i, FALSE); + blitter_get_fs_col(ctx, i, TRUE); + } + + /* It only matters if i <= 1 or > 1. */ + for (i = 1; i <= max_samples; i++) { + for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) { + if (!has_arraytex && + (target == PIPE_TEXTURE_1D_ARRAY || + target == PIPE_TEXTURE_2D_ARRAY)) { + continue; + } + + blitter_get_fs_texfetch_col(ctx, target, i); + blitter_get_fs_texfetch_depth(ctx, target, i); + if (ctx->has_stencil_export) { + blitter_get_fs_texfetch_depthstencil(ctx, target, i); + blitter_get_fs_texfetch_stencil(ctx, target, i); + } + } + } +} + +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); @@ -838,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; @@ -856,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) { @@ -897,14 +972,15 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); + blitter_disable_render_cond(ctx); /* bind states */ 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) { @@ -929,16 +1005,17 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, } else { pipe->bind_vertex_elements_state(pipe, ctx->velem_state); } - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format)); + 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); blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } @@ -965,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; @@ -1024,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; @@ -1036,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); @@ -1050,25 +1129,29 @@ 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; } } if (src) { - if (!screen->is_format_supported(screen, src->format, src->target, + if (src->nr_samples > 1 && !ctx->has_texture_multisample) { + return FALSE; + } + + 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; @@ -1079,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; @@ -1104,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. */ @@ -1158,49 +1269,65 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter, blitter_check_saved_fragment_states(ctx); blitter_check_saved_textures(ctx); blitter_check_saved_fb_state(ctx); + blitter_disable_render_cond(ctx); /* Initialize framebuffer state. */ fb_state.width = dst->width; 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, ctx->dsa_write_depth_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_depthstencil(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_depthstencil(ctx, src->texture->target, + src->texture->nr_samples)); } else if (blit_depth) { pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_depth(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_depth(ctx, src->texture->target, + src->texture->nr_samples)); } else { /* is_stencil */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_stencil(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_stencil(ctx, src->texture->target, + src->texture->nr_samples)); } 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); - pipe->bind_fs_state(pipe, - blitter_get_fs_texfetch_col(ctx, src->texture)); + ctx->bind_fs_state(pipe, + blitter_get_fs_texfetch_col(ctx, src->texture->target, + src->texture->nr_samples)); fb_state.nr_cbufs = 1; fb_state.cbufs[0] = dst; 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); @@ -1225,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 || @@ -1256,24 +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, @@ -1294,11 +1482,12 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); + 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); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1310,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); @@ -1318,6 +1507,7 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_fb_state(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } @@ -1344,9 +1534,10 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); + 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); @@ -1364,7 +1555,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, /* hmm that should be illegal probably, or make it a no-op somewhere */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1376,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); @@ -1384,6 +1575,7 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_fb_state(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } @@ -1407,11 +1599,12 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); + 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); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); /* set a framebuffer state */ @@ -1429,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); @@ -1437,6 +1630,7 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_fb_state(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } @@ -1478,6 +1672,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); + blitter_disable_render_cond(ctx); vb.buffer = src; vb.buffer_offset = srcx; @@ -1496,6 +1691,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4); blitter_restore_vertex_states(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); pipe_so_target_reference(&so_target, NULL); } @@ -1518,12 +1714,13 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, blitter_set_running_flag(ctx); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); + blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, custom_blend); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->set_sample_mask(pipe, sample_mask); memset(&surf_tmpl, 0, sizeof(surf_tmpl)); @@ -1550,13 +1747,14 @@ 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); blitter_restore_fb_state(ctx); blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); pipe_surface_reference(&srcsurf, NULL); @@ -1580,11 +1778,12 @@ void util_blitter_custom_color(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); + blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, custom_blend); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); + ctx->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE)); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1); @@ -1597,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); @@ -1605,5 +1804,146 @@ void util_blitter_custom_color(struct blitter_context *blitter, blitter_restore_vertex_states(ctx); blitter_restore_fragment_states(ctx); blitter_restore_fb_state(ctx); + blitter_restore_render_cond(ctx); blitter_unset_running_flag(ctx); } + +/* Return whether this is an RGBA, Z, S, or combined ZS format. + */ +static unsigned get_format_mask(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description(format); + + assert(desc); + + if (util_format_has_depth(desc)) { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_ZS; + } else { + return PIPE_MASK_Z; + } + } else { + if (util_format_has_stencil(desc)) { + return PIPE_MASK_S; + } else { + return PIPE_MASK_RGBA; + } + } +} + +/* Return if the box is totally inside the resource. + */ +static boolean is_box_inside_resource(const struct pipe_resource *res, + const struct pipe_box *box, + unsigned level) +{ + unsigned width = 1, height = 1, depth = 1; + + switch (res->target) { + case PIPE_BUFFER: + width = res->width0; + height = 1; + depth = 1; + break; + case PIPE_TEXTURE_1D: + width = u_minify(res->width0, level); + height = 1; + depth = 1; + break; + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = 1; + break; + case PIPE_TEXTURE_3D: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = u_minify(res->depth0, level); + break; + case PIPE_TEXTURE_CUBE: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = 6; + break; + case PIPE_TEXTURE_1D_ARRAY: + width = u_minify(res->width0, level); + height = 1; + depth = res->array_size; + break; + case PIPE_TEXTURE_2D_ARRAY: + width = u_minify(res->width0, level); + height = u_minify(res->height0, level); + depth = res->array_size; + break; + case PIPE_MAX_TEXTURE_TYPES:; + } + + return box->x >= 0 && + box->x + box->width <= width && + box->y >= 0 && + box->y + box->height <= height && + box->z >= 0 && + box->z + box->depth <= depth; +} + +static unsigned get_sample_count(const struct pipe_resource *res) +{ + return res->nr_samples ? res->nr_samples : 1; +} + +boolean util_try_blit_via_copy_region(struct pipe_context *ctx, + const struct pipe_blit_info *blit) +{ + unsigned mask = get_format_mask(blit->dst.format); + + /* No format conversions. */ + if (blit->src.resource->format != blit->src.format || + blit->dst.resource->format != blit->dst.format || + !util_is_format_compatible( + util_format_description(blit->src.resource->format), + util_format_description(blit->dst.resource->format))) { + return FALSE; + } + + /* No masks, no filtering, no scissor. */ + if ((blit->mask & mask) != mask || + blit->filter != PIPE_TEX_FILTER_NEAREST || + blit->scissor_enable) { + return FALSE; + } + + /* No flipping. */ + if (blit->src.box.width < 0 || + blit->src.box.height < 0 || + blit->src.box.depth < 0) { + return FALSE; + } + + /* No scaling. */ + if (blit->src.box.width != blit->dst.box.width || + blit->src.box.height != blit->dst.box.height || + blit->src.box.depth != blit->dst.box.depth) { + return FALSE; + } + + /* No out-of-bounds access. */ + if (!is_box_inside_resource(blit->src.resource, &blit->src.box, + blit->src.level) || + !is_box_inside_resource(blit->dst.resource, &blit->dst.box, + blit->dst.level)) { + return FALSE; + } + + /* Sample counts must match. */ + if (get_sample_count(blit->src.resource) != + get_sample_count(blit->dst.resource)) { + return FALSE; + } + + ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level, + blit->dst.box.x, blit->dst.box.y, blit->dst.box.z, + blit->src.resource, blit->src.level, + &blit->src.box); + return TRUE; +} diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 680407381..40636c616 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/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; @@ -108,6 +109,9 @@ struct blitter_context int saved_num_so_targets; struct pipe_stream_output_target *saved_so_targets[PIPE_MAX_SO_BUFFERS]; + + struct pipe_query *saved_render_cond_query; + uint saved_render_cond_mode; }; /** @@ -120,6 +124,8 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe); */ void util_blitter_destroy(struct blitter_context *blitter); +void util_blitter_cache_all_shaders(struct blitter_context *blitter); + /** * Return the pipe context associated with a blitter context. */ @@ -132,12 +138,22 @@ 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); +/** + * Try to do a blit using resource_copy_region. The function calls + * resource_copy_region if the blit description is compatible with it. + * + * It returns TRUE if the blit was done using resource_copy_region. + * + * It returns FALSE otherwise and the caller must fall back to a more generic + * codepath for the blit operation. (e.g. by using u_blitter) + */ +boolean util_try_blit_via_copy_region(struct pipe_context *ctx, + const struct pipe_blit_info *blit); + /* * These states must be saved before any of the following functions are called: * - vertex buffers @@ -175,19 +191,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 @@ -196,19 +206,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 @@ -222,18 +234,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. @@ -411,6 +425,13 @@ void util_blitter_save_viewport(struct blitter_context *blitter, } 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, int num_sampler_states, @@ -473,6 +494,15 @@ util_blitter_save_sample_mask(struct blitter_context *blitter, blitter->saved_sample_mask = sample_mask; } +static INLINE void +util_blitter_save_render_condition(struct blitter_context *blitter, + struct pipe_query *query, + uint mode) +{ + blitter->saved_render_cond_query = query; + blitter->saved_render_cond_mode = mode; +} + #ifdef __cplusplus } #endif diff --git a/mesalib/src/gallium/auxiliary/util/u_dump.h b/mesalib/src/gallium/auxiliary/util/u_dump.h index 87d84bead..71750a635 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dump.h +++ b/mesalib/src/gallium/auxiliary/util/u_dump.h @@ -165,6 +165,12 @@ util_dump_vertex_element(FILE *stream, void util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state); +void +util_dump_box(FILE *stream, const struct pipe_box *box); + +void +util_dump_blit_info(FILE *stream, const struct pipe_blit_info *info); + /* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_dump_state.c b/mesalib/src/gallium/auxiliary/util/u_dump_state.c index c346a0ba5..f5d8b4373 100644 --- a/mesalib/src/gallium/auxiliary/util/u_dump_state.c +++ b/mesalib/src/gallium/auxiliary/util/u_dump_state.c @@ -762,3 +762,76 @@ util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state) util_dump_struct_end(stream); } + +void util_dump_box(FILE *stream, const struct pipe_box *box) +{ + if(!box) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_box"); + + util_dump_member(stream, int, box, x); + util_dump_member(stream, int, box, y); + util_dump_member(stream, int, box, z); + util_dump_member(stream, int, box, width); + util_dump_member(stream, int, box, height); + util_dump_member(stream, int, box, depth); + + util_dump_struct_end(stream); +} + +void util_dump_blit_info(FILE *stream, const struct pipe_blit_info *info) +{ + char mask[7]; + + if (!info) { + util_dump_null(stream); + return; + } + + util_dump_struct_begin(stream, "pipe_blit_info"); + + util_dump_member_begin(stream, "dst"); + util_dump_struct_begin(stream, "dst"); + util_dump_member(stream, ptr, &info->dst, resource); + util_dump_member(stream, uint, &info->dst, level); + util_dump_member(stream, format, &info->dst, format); + util_dump_member_begin(stream, "box"); + util_dump_box(stream, &info->dst.box); + util_dump_member_end(stream); + util_dump_struct_end(stream); + util_dump_member_end(stream); + + util_dump_member_begin(stream, "src"); + util_dump_struct_begin(stream, "src"); + util_dump_member(stream, ptr, &info->src, resource); + util_dump_member(stream, uint, &info->src, level); + util_dump_member(stream, format, &info->src, format); + util_dump_member_begin(stream, "box"); + util_dump_box(stream, &info->src.box); + util_dump_member_end(stream); + util_dump_struct_end(stream); + util_dump_member_end(stream); + + mask[0] = (info->mask & PIPE_MASK_R) ? 'R' : '-'; + mask[1] = (info->mask & PIPE_MASK_G) ? 'G' : '-'; + mask[2] = (info->mask & PIPE_MASK_B) ? 'B' : '-'; + mask[3] = (info->mask & PIPE_MASK_A) ? 'A' : '-'; + mask[4] = (info->mask & PIPE_MASK_Z) ? 'Z' : '-'; + mask[5] = (info->mask & PIPE_MASK_S) ? 'S' : '-'; + mask[6] = 0; + + util_dump_member_begin(stream, "mask"); + util_dump_string(stream, mask); + util_dump_member_end(stream); + util_dump_member(stream, uint, info, filter); + + util_dump_member(stream, bool, info, scissor_enable); + util_dump_member_begin(stream, "scissor"); + util_dump_scissor_state(stream, &info->scissor); + util_dump_member_end(stream); + + util_dump_struct_end(stream); +} diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.c b/mesalib/src/gallium/auxiliary/util/u_surface.c index fcfff148f..7fd6b3675 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.c +++ b/mesalib/src/gallium/auxiliary/util/u_surface.c @@ -66,11 +66,9 @@ u_surface_default_template(struct pipe_surface *surf, * \return TRUE for success, FALSE if failure */ boolean -util_create_rgba_surface(struct pipe_context *pipe, - uint width, uint height, - uint bind, - struct pipe_resource **textureOut, - struct pipe_surface **surfaceOut) +util_create_rgba_texture(struct pipe_context *pipe, + uint width, uint height, uint bind, + struct pipe_resource **textureOut) { static const enum pipe_format rgbaFormats[] = { PIPE_FORMAT_B8G8R8A8_UNORM, @@ -113,33 +111,11 @@ util_create_rgba_surface(struct pipe_context *pipe, /* create surface */ u_surface_default_template(&surf_templ, *textureOut, bind); - /* create surface / view into texture */ - *surfaceOut = pipe->create_surface(pipe, - *textureOut, - &surf_templ); - if (!*surfaceOut) { - pipe_resource_reference(textureOut, NULL); - return FALSE; - } - return TRUE; } /** - * Release the surface and texture from util_create_rgba_surface(). - */ -void -util_destroy_rgba_surface(struct pipe_resource *texture, - struct pipe_surface *surface) -{ - pipe_surface_reference(&surface, NULL); - pipe_resource_reference(&texture, NULL); -} - - - -/** * Fallback function for pipe->resource_copy_region(). * Note: (X,Y)=(0,0) is always the upper-left corner. */ diff --git a/mesalib/src/gallium/auxiliary/util/u_surface.h b/mesalib/src/gallium/auxiliary/util/u_surface.h index 1117b78da..6bcb63f3d 100644 --- a/mesalib/src/gallium/auxiliary/util/u_surface.h +++ b/mesalib/src/gallium/auxiliary/util/u_surface.h @@ -44,16 +44,9 @@ u_surface_default_template(struct pipe_surface *view, unsigned bind); extern boolean -util_create_rgba_surface(struct pipe_context *ctx, +util_create_rgba_texture(struct pipe_context *ctx, uint width, uint height, uint bind, - struct pipe_resource **textureOut, - struct pipe_surface **surfaceOut); - - -extern void -util_destroy_rgba_surface(struct pipe_resource *texture, - struct pipe_surface *surface); - + struct pipe_resource **textureOut); extern void |