aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/gallium/auxiliary/util/u_blitter.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/gallium/auxiliary/util/u_blitter.c')
-rw-r--r--mesalib/src/gallium/auxiliary/util/u_blitter.c153
1 files changed, 114 insertions, 39 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c
index 47d0227a9..b31ac2d5c 100644
--- a/mesalib/src/gallium/auxiliary/util/u_blitter.c
+++ b/mesalib/src/gallium/auxiliary/util/u_blitter.c
@@ -78,6 +78,8 @@ struct blitter_context_priv
/* FS which outputs a depth from a texture,
where the index is PIPE_TEXTURE_* to be sampled. */
void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES];
+ void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES];
/* Blend state. */
void *blend_write_color; /**< blend state with writemask of RGBA */
@@ -112,6 +114,7 @@ struct blitter_context_priv
boolean has_geometry_shader;
boolean vertex_has_integers;
boolean has_stream_out;
+ boolean has_stencil_export;
};
static void blitter_draw_rectangle(struct blitter_context *blitter,
@@ -163,6 +166,10 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
pipe->screen->get_param(pipe->screen,
PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
+ ctx->has_stencil_export =
+ pipe->screen->get_param(pipe->screen,
+ PIPE_CAP_SHADER_STENCIL_EXPORT);
+
/* blend state objects */
memset(&blend, 0, sizeof(blend));
ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
@@ -314,6 +321,10 @@ void util_blitter_destroy(struct blitter_context *blitter)
pipe->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]);
+ if (ctx->fs_texfetch_depthstencil[i])
+ pipe->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]);
}
for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
@@ -653,32 +664,6 @@ void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
}
}
-/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
-static unsigned
-pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
-{
- switch (pipe_tex_target) {
- case PIPE_TEXTURE_1D:
- return TGSI_TEXTURE_1D;
- case PIPE_TEXTURE_2D:
- return TGSI_TEXTURE_2D;
- case PIPE_TEXTURE_RECT:
- return TGSI_TEXTURE_RECT;
- case PIPE_TEXTURE_3D:
- return TGSI_TEXTURE_3D;
- case PIPE_TEXTURE_CUBE:
- return TGSI_TEXTURE_CUBE;
- case PIPE_TEXTURE_1D_ARRAY:
- return TGSI_TEXTURE_1D_ARRAY;
- case PIPE_TEXTURE_2D_ARRAY:
- return TGSI_TEXTURE_2D_ARRAY;
- default:
- assert(0 && "unexpected texture target");
- return TGSI_TEXTURE_UNKNOWN;
- }
-}
-
-
static INLINE
void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
unsigned tex_target)
@@ -689,7 +674,7 @@ void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_col[tex_target]) {
- unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
ctx->fs_texfetch_col[tex_target] =
util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR);
@@ -708,7 +693,7 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!ctx->fs_texfetch_depth[tex_target]) {
- unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
ctx->fs_texfetch_depth[tex_target] =
util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
@@ -718,6 +703,46 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
return ctx->fs_texfetch_depth[tex_target];
}
+static INLINE
+void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
+ unsigned tex_target)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+
+ assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
+
+ /* Create the fragment shader on-demand. */
+ if (!ctx->fs_texfetch_depthstencil[tex_target]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_depthstencil[tex_target] =
+ util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ return ctx->fs_texfetch_depthstencil[tex_target];
+}
+
+static INLINE
+void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
+ unsigned tex_target)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+
+ assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
+
+ /* Create the fragment shader on-demand. */
+ if (!ctx->fs_texfetch_stencil[tex_target]) {
+ unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(tex_target);
+
+ ctx->fs_texfetch_stencil[tex_target] =
+ util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
+ TGSI_INTERPOLATE_LINEAR);
+ }
+
+ return ctx->fs_texfetch_stencil[tex_target];
+}
+
static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
@@ -892,7 +917,7 @@ void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
src_templ->u.tex.last_level = srclevel;
src_templ->u.tex.first_layer = 0;
src_templ->u.tex.last_layer =
- src->target == PIPE_TEXTURE_3D ? src->depth0 - 1
+ src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
: src->array_size - 1;
src_templ->swizzle_r = PIPE_SWIZZLE_RED;
src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
@@ -916,6 +941,8 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
struct pipe_sampler_view src_templ, *src_view;
unsigned bind;
boolean is_stencil, is_depth;
+ const struct util_format_description *src_desc =
+ util_format_description(src->format);
/* Give up if textures are not set. */
assert(dst && src);
@@ -925,8 +952,8 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
assert(src->target < PIPE_MAX_TEXTURE_TYPES);
/* Is this a ZS format? */
- is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
- is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
+ is_depth = util_format_has_depth(src_desc);
+ is_stencil = util_format_has_stencil(src_desc);
if (is_depth || is_stencil)
bind = PIPE_BIND_DEPTH_STENCIL;
@@ -935,7 +962,7 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
/* Check if we can sample from and render to the surfaces. */
/* (assuming copying a stencil buffer is not possible) */
- if ((!ignore_stencil && is_stencil) ||
+ if ((!ignore_stencil && is_stencil && !ctx->has_stencil_export) ||
!screen->is_format_supported(screen, dst->format, dst->target,
dst->nr_samples, bind) ||
!screen->is_format_supported(screen, src->format, src->target,
@@ -976,6 +1003,21 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
enum pipe_texture_target src_target = src->texture->target;
unsigned width = srcbox->width;
unsigned height = srcbox->height;
+ boolean is_stencil, is_depth;
+ const struct util_format_description *src_desc =
+ util_format_description(src->format);
+
+ is_depth = util_format_has_depth(src_desc);
+ is_stencil = util_format_has_stencil(src_desc);
+
+ /* If you want a fallback for stencil copies,
+ * use util_blitter_copy_texture. */
+ if (is_stencil && !ctx->has_stencil_export) {
+ is_stencil = FALSE;
+
+ if (!is_depth)
+ return;
+ }
/* Sanity checks. */
if (dst->texture == src->texture &&
@@ -997,12 +1039,25 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
fb_state.width = dst->width;
fb_state.height = dst->height;
- if (util_format_is_depth_or_stencil(dst->format)) {
+ if (is_depth || is_stencil) {
pipe->bind_blend_state(pipe, ctx->blend_keep_color);
- 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_target));
+
+ if (is_depth && is_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_target));
+ } else if (is_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_target));
+ } 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_target));
+ }
fb_state.nr_cbufs = 0;
fb_state.zsbuf = dst;
@@ -1017,9 +1072,29 @@ void util_blitter_copy_texture_view(struct blitter_context *blitter,
fb_state.zsbuf = 0;
}
- pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+ if (is_depth && is_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};
+
+ templ = *src;
+ templ.format = util_format_stencil_only(templ.format);
+ assert(templ.format != PIPE_FORMAT_NONE);
+
+ views[0] = src;
+ views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);
+
+ pipe->set_fragment_sampler_views(pipe, 2, views);
+ pipe->bind_fragment_sampler_states(pipe, 2, samplers);
+
+ pipe_sampler_view_reference(&views[1], NULL);
+ } else {
+ pipe->set_fragment_sampler_views(pipe, 1, &src);
+ pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
+ }
+
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
- pipe->set_fragment_sampler_views(pipe, 1, &src);
pipe->set_framebuffer_state(pipe, &fb_state);
blitter_set_common_draw_rect_state(ctx);