summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2012-09-12 23:37:17 +0200
committerMarek Olšák <[email protected]>2012-09-30 18:57:56 +0200
commit0b0697e80dd442d7e7cb23641ad8f58f82df120d (patch)
tree3f842d9000c8c26fc3812f08276846af4772b579
parent84d2f2295e8274c1b3676b59fedfc173836d378e (diff)
gallium/u_blitter: add gallium blit implementation
The original blit function is extended and the otAher functions reuse it. Tested-by: Michel Dänzer <[email protected]> Reviewed-by: Brian Paul <[email protected]>
-rw-r--r--src/gallium/auxiliary/util/u_blitter.c284
-rw-r--r--src/gallium/auxiliary/util/u_blitter.h66
-rw-r--r--src/gallium/drivers/i915/i915_surface.c4
-rw-r--r--src/gallium/drivers/r300/r300_blit.c8
-rw-r--r--src/gallium/drivers/r300/r300_context.h3
-rw-r--r--src/gallium/drivers/r300/r300_render.c3
-rw-r--r--src/gallium/drivers/r600/r600_blit.c38
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h2
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c2
-rw-r--r--src/gallium/drivers/radeonsi/r600_blit.c4
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.
@@ -416,6 +413,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,
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);
}