diff options
Diffstat (limited to 'mesalib/src/gallium')
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blitter.c | 286 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_blitter.h | 24 | ||||
-rw-r--r-- | mesalib/src/gallium/auxiliary/util/u_upload_mgr.c | 36 |
3 files changed, 164 insertions, 182 deletions
diff --git a/mesalib/src/gallium/auxiliary/util/u_blitter.c b/mesalib/src/gallium/auxiliary/util/u_blitter.c index b0d538de6..f5cc5cb3b 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.c +++ b/mesalib/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,22 @@ 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 src_width0, unsigned src_height0, 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(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 { out[0] = x1; out[1] = y1; out[2] = x2; @@ -535,76 +531,52 @@ static void set_texcoords_in_vertices(const float coord[4], out[1] = coord[3]; /*t3.t*/ } -static void blitter_set_texcoords_2d(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2) +static void blitter_set_texcoords(struct blitter_context_priv *ctx, + struct pipe_sampler_view *src, + unsigned src_width0, unsigned src_height0, + unsigned layer, + unsigned x1, unsigned y1, + unsigned x2, unsigned y2) { unsigned i; float coord[4]; + float face_coord[4][2]; - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); - set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); + get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord); - for (i = 0; i < 4; i++) { - ctx->vertices[i][1][2] = 0; /*r*/ - ctx->vertices[i][1][3] = 1; /*q*/ + if (src->texture->target == PIPE_TEXTURE_CUBE) { + set_texcoords_in_vertices(coord, &face_coord[0][0], 2); + util_map_texcoords2d_onto_cubemap(layer, + /* pointer, stride in floats */ + &face_coord[0][0], 2, + &ctx->vertices[0][1][0], 8); + } else { + set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); } -} - -static void blitter_set_texcoords_3d(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, - unsigned zslice, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2, - boolean normalized) -{ - int i; - float r = normalized ? zslice / (float)u_minify(src->depth0, level) : zslice; - - blitter_set_texcoords_2d(ctx, src, level, 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, - unsigned zslice, - unsigned x1, unsigned x2) -{ - int i; - float r = zslice; - - blitter_set_texcoords_2d(ctx, src, level, x1, 0, x2, 0); - - for (i = 0; i < 4; i++) - ctx->vertices[i][1][1] = r; /*r*/ -} - -static void blitter_set_texcoords_cube(struct blitter_context_priv *ctx, - struct pipe_resource *src, - unsigned level, unsigned face, - unsigned x1, unsigned y1, - unsigned x2, unsigned y2) -{ - int i; - float coord[4]; - float st[4][2]; + /* Set the layer. */ + switch (src->texture->target) { + case PIPE_TEXTURE_3D: + { + float r = layer / (float)u_minify(src->texture->depth0, + src->u.tex.first_level); + for (i = 0; i < 4; i++) + ctx->vertices[i][1][2] = r; /*r*/ + } + break; - get_texcoords(src, level, x1, y1, x2, y2, TRUE, coord); - set_texcoords_in_vertices(coord, &st[0][0], 2); + case PIPE_TEXTURE_1D_ARRAY: + for (i = 0; i < 4; i++) + ctx->vertices[i][1][1] = layer; /*t*/ + break; - util_map_texcoords2d_onto_cubemap(face, - /* pointer, stride in floats */ - &st[0][0], 2, - &ctx->vertices[0][1][0], 8); + case PIPE_TEXTURE_2D_ARRAY: + for (i = 0; i < 4; i++) + ctx->vertices[i][1][2] = layer; /*r*/ + break; - for (i = 0; i < 4; i++) - ctx->vertices[i][1][3] = 1; /*q*/ + default:; + } } static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx, @@ -615,31 +587,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 +811,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 +838,60 @@ 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, + src->width0, src->height0); + + 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, + unsigned src_width0, unsigned src_height0) +{ + 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 +900,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, src_width0, src_height0, 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,24 +959,14 @@ 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); - break; - case PIPE_TEXTURE_2D_ARRAY: case PIPE_TEXTURE_3D: - blitter_set_texcoords_3d(ctx, src, srclevel, srcbox->z, - srcbox->x, srcbox->y, - srcbox->x + width, srcbox->y + height, - src->target == PIPE_TEXTURE_3D); - break; - case PIPE_TEXTURE_CUBE: - blitter_set_texcoords_cube(ctx, src, srclevel, srcbox->z, - srcbox->x, srcbox->y, - srcbox->x + width, srcbox->y + height); + blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z, + srcbox->y, srcbox->x, + srcbox->x + width, srcbox->y + height); break; default: @@ -1028,9 +987,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/mesalib/src/gallium/auxiliary/util/u_blitter.h b/mesalib/src/gallium/auxiliary/util/u_blitter.h index 798096e74..3e1457ae0 100644 --- a/mesalib/src/gallium/auxiliary/util/u_blitter.h +++ b/mesalib/src/gallium/auxiliary/util/u_blitter.h @@ -190,6 +190,30 @@ 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 interpret them, instead of changing + * pipe_resource directly. This is usually needed to accelerate copying of + * compressed formats. + * + * src_width0 and src_height0 are sampler_view-private properties that + * override pipe_resource. The blitter uses them for computation of texture + * coordinates. The dst dimensions are supplied through pipe_surface::width + * and height. + * + * 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, + unsigned src_width0, unsigned src_height0); + +/** * 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 diff --git a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c index 71fe53e3a..a2319d0c4 100644 --- a/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c +++ b/mesalib/src/gallium/auxiliary/util/u_upload_mgr.c @@ -131,8 +131,9 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, upload->bind, PIPE_USAGE_STREAM, size ); - if (upload->buffer == NULL) - goto fail; + if (upload->buffer == NULL) { + return PIPE_ERROR_OUT_OF_MEMORY; + } /* Map the new buffer. */ upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer, @@ -140,17 +141,16 @@ u_upload_alloc_buffer( struct u_upload_mgr *upload, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_FLUSH_EXPLICIT, &upload->transfer); - + if (upload->map == NULL) { + upload->size = 0; + pipe_resource_reference(&upload->buffer, NULL); + return PIPE_ERROR_OUT_OF_MEMORY; + } + upload->size = size; upload->offset = 0; - return 0; - -fail: - if (upload->buffer) - pipe_resource_reference( &upload->buffer, NULL ); - - return PIPE_ERROR_OUT_OF_MEMORY; + return PIPE_OK; } enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, @@ -170,7 +170,7 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) { enum pipe_error ret = u_upload_alloc_buffer(upload, alloc_offset + alloc_size); - if (ret) + if (ret != PIPE_OK) return ret; *flushed = TRUE; @@ -187,6 +187,11 @@ enum pipe_error u_upload_alloc( struct u_upload_mgr *upload, PIPE_TRANSFER_FLUSH_EXPLICIT | PIPE_TRANSFER_UNSYNCHRONIZED, &upload->transfer); + if (!upload->map) { + pipe_resource_reference(outbuf, NULL); + *ptr = NULL; + return PIPE_ERROR_OUT_OF_MEMORY; + } } assert(offset < upload->buffer->width0); @@ -214,7 +219,7 @@ enum pipe_error u_upload_data( struct u_upload_mgr *upload, enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size, out_offset, outbuf, flushed, (void**)&ptr); - if (ret) + if (ret != PIPE_OK) return ret; memcpy(ptr, data, size); @@ -247,8 +252,7 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, &transfer); if (map == NULL) { - ret = PIPE_ERROR_OUT_OF_MEMORY; - goto done; + return PIPE_ERROR_OUT_OF_MEMORY; } if (0) @@ -261,9 +265,7 @@ enum pipe_error u_upload_buffer( struct u_upload_mgr *upload, out_offset, outbuf, flushed ); -done: - if (map) - pipe_buffer_unmap( upload->pipe, transfer ); + pipe_buffer_unmap( upload->pipe, transfer ); return ret; } |