[Mesa-dev] Mesa (master): u_blitter: add a copy_texture function which uses views and not resources
Marek Olšák
maraeo at gmail.com
Sun Nov 6 05:46:30 PST 2011
Hi Stéphane,
The patch changes how mipmap levels are accessed. Previously, a
sampler state was created that had min_lod == max_lod == lod_bias ==
the desired mipmap level. Now the sampler state has min_lod == max_lod
== 0, and the first_level and last_level fields of pipe_sampler_view
and the "level" field of pipe_surface are used instead.
Other than that, there should be no difference IIRC.
Marek
2011/11/5 Stéphane Marchesin <stephane.marchesin at gmail.com>:
> Hi Marek,
>
> Christopher (CME on IRC) reports that this change regresses i915g in
> wine. Nothing stikes me as wrong, do you have any idea?
>
> Stéphane
>
>
> On Sun, Oct 23, 2011 at 11:33, Marek Olšák
> <mareko at kemper.freedesktop.org> wrote:
>> Module: Mesa
>> Branch: master
>> Commit: 37b62cc35435a704d33c1814fbdbd0e807699e21
>> URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=37b62cc35435a704d33c1814fbdbd0e807699e21
>>
>> Author: Marek Olšák <maraeo at gmail.com>
>> Date: Fri Oct 21 02:09:40 2011 +0200
>>
>> u_blitter: add a copy_texture function which uses views and not resources
>>
>> The views (sampler views and surfaces) are great tools for changing resource
>> properties without having to change pipe_resource.
>>
>> ---
>>
>> src/gallium/auxiliary/util/u_blitter.c | 214 +++++++++++++++-----------------
>> src/gallium/auxiliary/util/u_blitter.h | 18 +++
>> 2 files changed, 117 insertions(+), 115 deletions(-)
>>
>> diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
>> index b0d538d..ac5b20a 100644
>> --- a/src/gallium/auxiliary/util/u_blitter.c
>> +++ b/src/gallium/auxiliary/util/u_blitter.c
>> @@ -59,7 +59,6 @@ struct blitter_context_priv
>> float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
>>
>> /* Templates for various state objects. */
>> - struct pipe_sampler_state template_sampler_state;
>>
>> /* Constant state objects. */
>> /* Vertex shaders. */
>> @@ -92,8 +91,8 @@ struct blitter_context_priv
>> void *velem_uint_state;
>> void *velem_sint_state;
>>
>> - /* Sampler state for clamping to a miplevel. */
>> - void *sampler_state[PIPE_MAX_TEXTURE_LEVELS * 2];
>> + /* Sampler state. */
>> + void *sampler_state;
>>
>> /* Rasterizer state. */
>> void *rs_state;
>> @@ -126,7 +125,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
>> struct pipe_blend_state blend;
>> struct pipe_depth_stencil_alpha_state dsa;
>> struct pipe_rasterizer_state rs_state;
>> - struct pipe_sampler_state *sampler_state;
>> + struct pipe_sampler_state sampler_state;
>> struct pipe_vertex_element velem[2];
>> unsigned i;
>>
>> @@ -192,13 +191,12 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
>> pipe->create_depth_stencil_alpha_state(pipe, &dsa);
>>
>> /* sampler state */
>> - sampler_state = &ctx->template_sampler_state;
>> - sampler_state->wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> - sampler_state->wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> - sampler_state->wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> - sampler_state->normalized_coords = TRUE;
>> - /* The sampler state objects which sample from a specified mipmap level
>> - * are created on-demand. */
>> + memset(&sampler_state, 0, sizeof(sampler_state));
>> + sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> + sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> + sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
>> + sampler_state.normalized_coords = 1;
>> + ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
>>
>> /* rasterizer state */
>> memset(&rs_state, 0, sizeof(rs_state));
>> @@ -292,10 +290,7 @@ void util_blitter_destroy(struct blitter_context *blitter)
>> pipe->delete_fs_state(pipe, ctx->fs_col_int[i]);
>> }
>>
>> - for (i = 0; i < PIPE_MAX_TEXTURE_LEVELS * 2; i++)
>> - if (ctx->sampler_state[i])
>> - pipe->delete_sampler_state(pipe, ctx->sampler_state[i]);
>> -
>> + pipe->delete_sampler_state(pipe, ctx->sampler_state);
>> pipe_resource_reference(&ctx->vbuf, NULL);
>> FREE(ctx);
>> }
>> @@ -497,21 +492,21 @@ static void blitter_set_clear_color(struct blitter_context_priv *ctx,
>> }
>> }
>>
>> -static void get_texcoords(struct pipe_resource *src,
>> - unsigned level,
>> +static void get_texcoords(struct pipe_sampler_view *src,
>> unsigned x1, unsigned y1,
>> unsigned x2, unsigned y2,
>> - boolean normalized, float out[4])
>> + float out[4])
>> {
>> - if(normalized)
>> - {
>> - out[0] = x1 / (float)u_minify(src->width0, level);
>> - out[1] = y1 / (float)u_minify(src->height0, level);
>> - out[2] = x2 / (float)u_minify(src->width0, level);
>> - out[3] = y2 / (float)u_minify(src->height0, level);
>> - }
>> - else
>> - {
>> + struct pipe_resource *tex = src->texture;
>> + unsigned level = src->u.tex.first_level;
>> + boolean normalized = tex->target != PIPE_TEXTURE_RECT;
>> +
>> + if (normalized) {
>> + out[0] = x1 / (float)u_minify(tex->width0, level);
>> + out[1] = y1 / (float)u_minify(tex->height0, level);
>> + out[2] = x2 / (float)u_minify(tex->width0, level);
>> + out[3] = y2 / (float)u_minify(tex->height0, level);
>> + } else {
>> out[0] = x1;
>> out[1] = y1;
>> out[2] = x2;
>> @@ -536,15 +531,14 @@ static void set_texcoords_in_vertices(const float coord[4],
>> }
>>
>> static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
>> - struct pipe_resource *src,
>> - unsigned level,
>> + struct pipe_sampler_view *src,
>> unsigned x1, unsigned y1,
>> unsigned x2, unsigned y2)
>> {
>> unsigned i;
>> float coord[4];
>>
>> - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord);
>> + get_texcoords(src, x1, y1, x2, y2, coord);
>> set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
>>
>> for (i = 0; i < 4; i++) {
>> @@ -554,40 +548,39 @@ static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx,
>> }
>>
>> static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx,
>> - struct pipe_resource *src,
>> - unsigned level,
>> + struct pipe_sampler_view *src,
>> unsigned zslice,
>> unsigned x1, unsigned y1,
>> - unsigned x2, unsigned y2,
>> - boolean normalized)
>> + unsigned x2, unsigned y2)
>> {
>> + struct pipe_resource *tex = src->texture;
>> + unsigned level = src->u.tex.first_level;
>> + boolean is_array = tex->target != PIPE_TEXTURE_2D_ARRAY;
>> + float r = is_array ? zslice : zslice / (float)u_minify(tex->depth0, level);
>> int i;
>> - float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice;
>>
>> - blitter_set_texcoords_2d(ctx, src, level, x1, y1, x2, y2);
>> + blitter_set_texcoords_2d(ctx, src, x1, y1, x2, y2);
>>
>> for (i = 0; i < 4; i++)
>> ctx->vertices[i][1][2] = r; /*r*/
>> }
>>
>> static void blitter_set_texcoords_1d_array(struct blitter_context_priv *ctx,
>> - struct pipe_resource *src,
>> - unsigned level,
>> + struct pipe_sampler_view *src,
>> unsigned zslice,
>> unsigned x1, unsigned x2)
>> {
>> int i;
>> - float r = zslice;
>>
>> - blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0);
>> + blitter_set_texcoords_2d(ctx, src, x1, 0, x2, 0);
>>
>> for (i = 0; i < 4; i++)
>> - ctx->vertices[i][1][1] = r; /*r*/
>> + ctx->vertices[i][1][1] = zslice; /*r*/
>> }
>>
>> static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
>> - struct pipe_resource *src,
>> - unsigned level, unsigned face,
>> + struct pipe_sampler_view *src,
>> + unsigned face,
>> unsigned x1, unsigned y1,
>> unsigned x2, unsigned y2)
>> {
>> @@ -595,7 +588,7 @@ static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx,
>> float coord[4];
>> float st[4][2];
>>
>> - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord);
>> + get_texcoords(src, x1, y1, x2, y2, coord);
>> set_texcoords_in_vertices(coord, &st[0][0], 2);
>>
>> util_map_texcoords2d_onto_cubemap(face,
>> @@ -615,31 +608,6 @@ static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
>> }
>>
>> static INLINE
>> -void **blitter_get_sampler_state(struct blitter_context_priv *ctx,
>> - int miplevel, boolean normalized)
>> -{
>> - struct pipe_context *pipe = ctx->base.pipe;
>> - struct pipe_sampler_state *sampler_state = &ctx->template_sampler_state;
>> -
>> - assert(miplevel < PIPE_MAX_TEXTURE_LEVELS);
>> -
>> - /* Create the sampler state on-demand. */
>> - if (!ctx->sampler_state[miplevel * 2 + normalized]) {
>> - sampler_state->lod_bias = miplevel;
>> - sampler_state->min_lod = miplevel;
>> - sampler_state->max_lod = miplevel;
>> - sampler_state->normalized_coords = normalized;
>> -
>> - ctx->sampler_state[miplevel * 2 + normalized] = pipe->create_sampler_state(pipe,
>> - sampler_state);
>> - }
>> -
>> - /* Return void** so that it can be passed to bind_fragment_sampler_states
>> - * directly. */
>> - return &ctx->sampler_state[miplevel * 2 + normalized];
>> -}
>> -
>> -static INLINE
>> void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
>> boolean int_format)
>> {
>> @@ -864,27 +832,16 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> struct pipe_context *pipe = ctx->base.pipe;
>> struct pipe_screen *screen = pipe->screen;
>> struct pipe_surface *dstsurf, surf_templ;
>> - struct pipe_framebuffer_state fb_state;
>> struct pipe_sampler_view viewTempl, *view;
>> unsigned bind;
>> - unsigned width = srcbox->width;
>> - unsigned height = srcbox->height;
>> boolean is_stencil, is_depth;
>> - boolean normalized;
>>
>> /* Give up if textures are not set. */
>> assert(dst && src);
>> if (!dst || !src)
>> return;
>>
>> - /* Sanity checks. */
>> - if (dst == src) {
>> - assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
>> - dstx, dstx + width, dsty, dsty + height));
>> - }
>> assert(src->target < PIPE_MAX_TEXTURE_TYPES);
>> - /* XXX should handle 3d regions */
>> - assert(srcbox->depth == 1);
>>
>> /* Is this a ZS format? */
>> is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
>> @@ -902,22 +859,58 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> dst->nr_samples, bind) ||
>> !screen->is_format_supported(screen, src->format, src->target,
>> src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
>> - ctx->base.running = TRUE;
>> + blitter_set_running_flag(ctx);
>> util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
>> src, srclevel, srcbox);
>> - ctx->base.running = FALSE;
>> + blitter_unset_running_flag(ctx);
>> return;
>> }
>>
>> - /* Get surface. */
>> + /* Initialize the surface. */
>> memset(&surf_templ, 0, sizeof(surf_templ));
>> u_surface_default_template(&surf_templ, dst, bind);
>> surf_templ.format = util_format_linear(dst->format);
>> surf_templ.u.tex.level = dstlevel;
>> surf_templ.u.tex.first_layer = dstz;
>> - surf_templ.u.tex.last_layer = dstz;
>> + surf_templ.u.tex.last_layer = dstz + srcbox->depth - 1;
>> dstsurf = pipe->create_surface(pipe, dst, &surf_templ);
>>
>> + /* Initialize the sampler view. */
>> + u_sampler_view_default_template(&viewTempl, src,
>> + util_format_linear(src->format));
>> + viewTempl.u.tex.first_level = srclevel;
>> + viewTempl.u.tex.last_level = srclevel;
>> + view = pipe->create_sampler_view(pipe, src, &viewTempl);
>> +
>> + /* Copy. */
>> + util_blitter_copy_texture_view(blitter, dstsurf, dstx, dsty, view, srcbox);
>> +
>> + pipe_surface_reference(&dstsurf, NULL);
>> + pipe_sampler_view_reference(&view, NULL);
>> +}
>> +
>> +void util_blitter_copy_texture_view(struct blitter_context *blitter,
>> + struct pipe_surface *dst,
>> + unsigned dstx, unsigned dsty,
>> + struct pipe_sampler_view *src,
>> + const struct pipe_box *srcbox)
>> +{
>> + 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;
>> + unsigned width = srcbox->width;
>> + unsigned height = srcbox->height;
>> +
>> + /* Sanity checks. */
>> + if (dst->texture == src->texture &&
>> + dst->u.tex.level == src->u.tex.first_level) {
>> + assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
>> + dstx, dstx + width, dsty, dsty + height));
>> + }
>> + /* XXX should handle 3d regions */
>> + assert(srcbox->depth == 1);
>> +
>> /* Check whether the states are properly saved. */
>> blitter_set_running_flag(ctx);
>> blitter_check_saved_vertex_states(ctx);
>> @@ -926,60 +919,55 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> blitter_check_saved_fb_state(ctx);
>>
>> /* Initialize framebuffer state. */
>> - fb_state.width = dstsurf->width;
>> - fb_state.height = dstsurf->height;
>> + fb_state.width = dst->width;
>> + fb_state.height = dst->height;
>>
>> - if (is_depth) {
>> + if (util_format_is_depth_or_stencil(dst->format)) {
>> 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));
>> + blitter_get_fs_texfetch_depth(ctx, src_target));
>>
>> fb_state.nr_cbufs = 0;
>> - fb_state.zsbuf = dstsurf;
>> + fb_state.zsbuf = dst;
>> } else {
>> pipe->bind_blend_state(pipe, ctx->blend_write_color);
>> pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
>> pipe->bind_fs_state(pipe,
>> - blitter_get_fs_texfetch_col(ctx, src->target));
>> + blitter_get_fs_texfetch_col(ctx, src_target));
>>
>> fb_state.nr_cbufs = 1;
>> - fb_state.cbufs[0] = dstsurf;
>> + fb_state.cbufs[0] = dst;
>> fb_state.zsbuf = 0;
>> }
>>
>> - normalized = src->target != PIPE_TEXTURE_RECT;
>> -
>> - /* Initialize sampler view. */
>> - u_sampler_view_default_template(&viewTempl, src, util_format_linear(src->format));
>> - view = pipe->create_sampler_view(pipe, src, &viewTempl);
>> -
>> /* Set rasterizer state, shaders, and textures. */
>> pipe->bind_rasterizer_state(pipe, ctx->rs_state);
>> pipe->bind_vs_state(pipe, ctx->vs);
>> if (ctx->has_geometry_shader)
>> pipe->bind_gs_state(pipe, NULL);
>> - pipe->bind_fragment_sampler_states(pipe, 1,
>> - blitter_get_sampler_state(ctx, srclevel, normalized));
>> + 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, &view);
>> + pipe->set_fragment_sampler_views(pipe, 1, &src);
>> pipe->set_framebuffer_state(pipe, &fb_state);
>>
>> - blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
>> + blitter_set_dst_dimensions(ctx, dst->width, dst->height);
>>
>> - switch (src->target) {
>> + switch (src_target) {
>> /* Draw the quad with the draw_rectangle callback. */
>> case PIPE_TEXTURE_1D:
>> case PIPE_TEXTURE_2D:
>> case PIPE_TEXTURE_RECT:
>> {
>> /* Set texture coordinates. - use a pipe color union
>> - * for interface purposes
>> + * for interface purposes.
>> + * XXX pipe_color_union is a wrong name since we use that to set
>> + * texture coordinates too.
>> */
>> union pipe_color_union coord;
>> - get_texcoords(src, srclevel, srcbox->x, srcbox->y,
>> - srcbox->x+width, srcbox->y+height, normalized, coord.f);
>> + get_texcoords(src, srcbox->x, srcbox->y,
>> + srcbox->x+width, srcbox->y+height, coord.f);
>>
>> /* Draw. */
>> blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
>> @@ -990,22 +978,21 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> /* Draw the quad with the generic codepath. */
>> default:
>> /* Set texture coordinates. */
>> - switch (src->target) {
>> + switch (src_target) {
>> case PIPE_TEXTURE_1D_ARRAY:
>> - blitter_set_texcoords_1d_array(ctx, src, srclevel, srcbox->y,
>> - srcbox->x, srcbox->x + width);
>> + blitter_set_texcoords_1d_array(ctx, src, srcbox->y, srcbox->x,
>> + srcbox->x + width);
>> break;
>>
>> case PIPE_TEXTURE_2D_ARRAY:
>> case PIPE_TEXTURE_3D:
>> - blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z,
>> + blitter_set_texcoords_3d(ctx, src, srcbox->z,
>> srcbox->x, srcbox->y,
>> - srcbox->x + width, srcbox->y + height,
>> - src->target == PIPE_TEXTURE_3D);
>> + srcbox->x + width, srcbox->y + height);
>> break;
>>
>> case PIPE_TEXTURE_CUBE:
>> - blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z,
>> + blitter_set_texcoords_cube(ctx, src, srcbox->z,
>> srcbox->x, srcbox->y,
>> srcbox->x + width, srcbox->y + height);
>> break;
>> @@ -1028,9 +1015,6 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> blitter_restore_textures(ctx);
>> blitter_restore_fb_state(ctx);
>> blitter_unset_running_flag(ctx);
>> -
>> - pipe_surface_reference(&dstsurf, NULL);
>> - pipe_sampler_view_reference(&view, NULL);
>> }
>>
>> /* Clear a region of a color surface to a constant value. */
>> diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h
>> index 798096e..55b2421 100644
>> --- a/src/gallium/auxiliary/util/u_blitter.h
>> +++ b/src/gallium/auxiliary/util/u_blitter.h
>> @@ -190,6 +190,24 @@ void util_blitter_copy_texture(struct blitter_context *blitter,
>> boolean ignore_stencil);
>>
>> /**
>> + * 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.
>> + *
>> + * Drivers can use this to change resource properties (like format, width,
>> + * height) by changing how the views can interpret them, instead of changing
>> + * pipe_resource directly. This is usually needed to accelerate copying of
>> + * compressed formats.
>> + *
>> + * 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 dstx, unsigned dsty,
>> + struct pipe_sampler_view *src,
>> + const struct pipe_box *srcbox);
>> +
>> +/**
>> * Clear a region of a (color) surface to a constant value.
>> *
>> * These states must be saved in the blitter in addition to the state objects
>>
>> _______________________________________________
>> mesa-commit mailing list
>> mesa-commit at lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/mesa-commit
>>
>
More information about the mesa-dev
mailing list