X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_blit.c;h=841e9c01e7ee3b8d83ee45d8d2ad3f08282a5604;hb=adfbba476db1fc55006efb748656ebb1a481d143;hp=999a3e50995e929aaf66601d9b04727d85f55855;hpb=e3ddafd1d32192f4638d4930627ad66624325561;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 999a3e50995..841e9c01e7e 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -37,12 +37,12 @@ #include "pipe/p_debug.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "pipe/p_util.h" -#include "pipe/p_winsys.h" #include "pipe/p_shader_tokens.h" -#include "util/u_draw_quad.h" #include "util/u_blit.h" +#include "util/u_draw_quad.h" +#include "util/u_math.h" +#include "util/u_memory.h" #include "util/u_simple_shaders.h" #include "cso_cache/cso_context.h" @@ -65,6 +65,8 @@ struct blit_state void *fs; struct pipe_buffer *vbuf; /**< quad vertices */ + unsigned vbuf_slot; + float vertices[4][2][4]; /**< vertex/texcoords for quad */ }; @@ -103,6 +105,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) ctx->rasterizer.cull_mode = PIPE_WINDING_NONE; ctx->rasterizer.bypass_clipping = 1; /*ctx->rasterizer.bypass_vs = 1;*/ + ctx->rasterizer.gl_rasterization_rules = 1; /* samplers */ memset(&ctx->sampler, 0, sizeof(ctx->sampler)); @@ -136,17 +139,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso) /* fragment shader */ ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader); - - ctx->vbuf = pipe->winsys->buffer_create(pipe->winsys, - 32, - PIPE_BUFFER_USAGE_VERTEX, - sizeof(ctx->vertices)); - if (!ctx->vbuf) { - FREE(ctx); - ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs); - ctx->pipe->delete_vs_state(ctx->pipe, ctx->vs); - return NULL; - } + ctx->vbuf = NULL; /* init vertex data that doesn't change */ for (i = 0; i < 4; i++) { @@ -173,21 +166,41 @@ util_destroy_blit(struct blit_state *ctx) FREE((void*) ctx->vert_shader.tokens); FREE((void*) ctx->frag_shader.tokens); - pipe->winsys->buffer_destroy(pipe->winsys, ctx->vbuf); + pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL); FREE(ctx); } +static unsigned get_next_slot( struct blit_state *ctx ) +{ + const unsigned max_slots = 4096 / sizeof ctx->vertices; + + if (ctx->vbuf_slot >= max_slots) + util_blit_flush( ctx ); + + if (!ctx->vbuf) { + ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, + 32, + PIPE_BUFFER_USAGE_VERTEX, + max_slots * sizeof ctx->vertices); + } + + return ctx->vbuf_slot++ * sizeof ctx->vertices; +} + + + /** * Setup vertex data for the textured quad we'll draw. * Note: y=0=top */ -static void +static unsigned setup_vertex_data(struct blit_state *ctx, float x0, float y0, float x1, float y1, float z) { void *buf; + unsigned offset; ctx->vertices[0][0][0] = x0; ctx->vertices[0][0][1] = y0; @@ -213,15 +226,67 @@ setup_vertex_data(struct blit_state *ctx, ctx->vertices[3][1][0] = 0.0f; ctx->vertices[3][1][1] = 1.0f; - buf = ctx->pipe->winsys->buffer_map(ctx->pipe->winsys, ctx->vbuf, - PIPE_BUFFER_USAGE_CPU_WRITE); + offset = get_next_slot( ctx ); + + buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + + memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices)); - memcpy(buf, ctx->vertices, sizeof(ctx->vertices)); + pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf); - ctx->pipe->winsys->buffer_unmap(ctx->pipe->winsys, ctx->vbuf); + return offset; } +/** + * Setup vertex data for the textured quad we'll draw. + * Note: y=0=top + */ +static unsigned +setup_vertex_data_tex(struct blit_state *ctx, + float x0, float y0, float x1, float y1, + float s0, float t0, float s1, float t1, + float z) +{ + void *buf; + unsigned offset; + + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = s0; /*s*/ + ctx->vertices[0][1][1] = t0; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y0; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = s1; /*s*/ + ctx->vertices[1][1][1] = t0; /*t*/ + + ctx->vertices[2][0][0] = x1; + ctx->vertices[2][0][1] = y1; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = s1; + ctx->vertices[2][1][1] = t1; + + ctx->vertices[3][0][0] = x0; + ctx->vertices[3][0][1] = y1; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = s0; + ctx->vertices[3][1][1] = t1; + + offset = get_next_slot( ctx ); + + buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf, + PIPE_BUFFER_USAGE_CPU_WRITE); + + memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices)); + + pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf); + + return offset; +} /** * Copy pixel block from src surface to dst surface. * Overlapping regions are acceptable. @@ -246,6 +311,7 @@ util_blit_pixels(struct blit_state *ctx, const int srcH = abs(srcY1 - srcY0); const int srcLeft = MIN2(srcX0, srcX1); const int srcTop = MIN2(srcY0, srcY1); + unsigned offset; assert(filter == PIPE_TEX_MIPFILTER_NEAREST || filter == PIPE_TEX_MIPFILTER_LINEAR); @@ -264,8 +330,22 @@ util_blit_pixels(struct blit_state *ctx, dstY1 = tmp; } - assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE)); - assert(screen->is_format_supported(screen, dst->format, PIPE_SURFACE)); + assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + + if(dst->format == src->format && (dstX1 - dstX0) == srcW && (dstY1 - dstY0) == srcH) { + /* FIXME: this will most surely fail for overlapping rectangles */ + pipe->surface_copy(pipe, FALSE, + dst, dstX0, dstY0, /* dest */ + src, srcX0, srcY0, /* src */ + srcW, srcH); /* size */ + return; + } + + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); /* * XXX for now we're always creating a temporary texture. @@ -281,7 +361,7 @@ util_blit_pixels(struct blit_state *ctx, texTemp.height[0] = srcH; texTemp.depth[0] = 1; texTemp.compressed = 0; - texTemp.cpp = pf_get_bits(src->format) / 8; + pf_get_block(src->format, &texTemp.block); tex = screen->texture_create(screen, &texTemp); if (!tex) @@ -334,16 +414,16 @@ util_blit_pixels(struct blit_state *ctx, memset(&fb, 0, sizeof(fb)); fb.width = dst->width; fb.height = dst->height; - fb.num_cbufs = 1; + fb.nr_cbufs = 1; fb.cbufs[0] = dst; cso_set_framebuffer(ctx->cso, &fb); /* draw quad */ - setup_vertex_data(ctx, - (float) dstX0, (float) dstY0, - (float) dstX1, (float) dstY1, z); + offset = setup_vertex_data(ctx, + (float) dstX0, (float) dstY0, + (float) dstX1, (float) dstY1, z); - util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, + util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ @@ -362,3 +442,114 @@ util_blit_pixels(struct blit_state *ctx, screen->texture_release(screen, &tex); } + +/* Release vertex buffer at end of frame to avoid synchronous + * rendering. + */ +void util_blit_flush( struct blit_state *ctx ) +{ + pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL); + ctx->vbuf_slot = 0; +} + + + +/** + * Copy pixel block from src texture to dst surface. + * Overlapping regions are acceptable. + * + * XXX Should support selection of level. + * XXX need some control over blitting Z and/or stencil. + */ +void +util_blit_pixels_tex(struct blit_state *ctx, + struct pipe_texture *tex, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, uint filter) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_framebuffer_state fb; + float s0, t0, s1, t1; + unsigned offset; + + assert(filter == PIPE_TEX_MIPFILTER_NEAREST || + filter == PIPE_TEX_MIPFILTER_LINEAR); + + assert(tex->width[0] != 0); + assert(tex->height[0] != 0); + + s0 = srcX0 / (float)tex->width[0]; + s1 = srcX1 / (float)tex->width[0]; + t0 = srcY0 / (float)tex->height[0]; + t1 = srcY1 / (float)tex->height[0]; + + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_depth_stencil_alpha(ctx->cso); + cso_save_rasterizer(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_sampler_textures(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + cso_save_viewport(ctx->cso); + + /* set misc state we care about */ + cso_set_blend(ctx->cso, &ctx->blend); + cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil); + cso_set_rasterizer(ctx->cso, &ctx->rasterizer); + cso_set_viewport(ctx->cso, &ctx->viewport); + + /* sampler */ + ctx->sampler.min_img_filter = filter; + ctx->sampler.mag_img_filter = filter; + cso_single_sampler(ctx->cso, 0, &ctx->sampler); + cso_single_sampler_done(ctx->cso); + + /* texture */ + cso_set_sampler_textures(ctx->cso, 1, &tex); + + /* shaders */ + cso_set_fragment_shader_handle(ctx->cso, ctx->fs); + cso_set_vertex_shader_handle(ctx->cso, ctx->vs); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst->width; + fb.height = dst->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst; + cso_set_framebuffer(ctx->cso, &fb); + + /* draw quad */ + offset = setup_vertex_data_tex(ctx, + (float) dstX0, (float) dstY0, + (float) dstX1, (float) dstY1, + s0, t0, s1, t1, + z); + + util_draw_vertex_buffer(ctx->pipe, + ctx->vbuf, offset, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_depth_stencil_alpha(ctx->cso); + cso_restore_rasterizer(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_sampler_textures(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_viewport(ctx->cso); +}