From a84a1e344f544ec4da61809d4f09853a94d93e07 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 3 Dec 2010 00:44:43 +0800 Subject: [PATCH] st/vega: Move vertex transformation to shader. It was done in path-to-polygon conversion. That meant that the results were invalidated when the transformation was modified, and CPU had to recreate the vertex buffer with new vertices. It could be a performance hit for apps that animate. --- src/gallium/state_trackers/vega/image.c | 6 +- src/gallium/state_trackers/vega/mask.c | 6 +- src/gallium/state_trackers/vega/path.c | 18 ++-- src/gallium/state_trackers/vega/path.h | 4 +- src/gallium/state_trackers/vega/renderer.c | 118 ++++++++++++++------- src/gallium/state_trackers/vega/renderer.h | 5 +- src/gallium/state_trackers/vega/shader.c | 11 ++ src/gallium/state_trackers/vega/shader.h | 2 + 8 files changed, 116 insertions(+), 54 deletions(-) diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 164af30ef3b..318ea94bdfb 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -546,11 +546,7 @@ void image_draw(struct vg_image *img, struct matrix *matrix) x4 = 0; y4 = img->height; - matrix_map_point(matrix, x1, y1, &x1, &y1); - matrix_map_point(matrix, x2, y2, &x2, &y2); - matrix_map_point(matrix, x3, y3, &x3, &y3); - matrix_map_point(matrix, x4, y4, &x4, &y4); - + shader_set_surface_matrix(ctx->shader, matrix); shader_set_drawing_image(ctx->shader, VG_TRUE); shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); shader_set_paint_matrix(ctx->shader, &paint_matrix); diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 17912cb552d..dfd0600e444 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -435,14 +435,14 @@ static void mask_layer_render_to(struct vg_mask_layer *layer, PIPE_BIND_RENDER_TARGET); surf = pipe->create_surface(pipe, view->texture, &surf_tmpl); - renderer_validate_for_mask_rendering(ctx->renderer, surf); + renderer_validate_for_mask_rendering(ctx->renderer, surf, mat); if (paint_modes & VG_FILL_PATH) { - path_fill(path, mat); + path_fill(path); } if (paint_modes & VG_STROKE_PATH){ - path_stroke(path, mat); + path_stroke(path); } pipe_surface_reference(&surf, NULL); diff --git a/src/gallium/state_trackers/vega/path.c b/src/gallium/state_trackers/vega/path.c index 31a043ea9b7..d7253befd03 100644 --- a/src/gallium/state_trackers/vega/path.c +++ b/src/gallium/state_trackers/vega/path.c @@ -1565,10 +1565,11 @@ void path_render(struct path *p, VGbitfield paintModes, mat, &paint_matrix)) { /* First the fill */ + shader_set_surface_matrix(ctx->shader, mat); shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); shader_set_paint_matrix(ctx->shader, &paint_matrix); shader_bind(ctx->shader); - path_fill(p, mat); + path_fill(p); } if ((paintModes & VG_STROKE_PATH) && @@ -1580,18 +1581,23 @@ void path_render(struct path *p, VGbitfield paintModes, * taking place."*/ if (ctx->state.vg.stroke.line_width.f <= 0) return; + shader_set_surface_matrix(ctx->shader, mat); shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint); shader_set_paint_matrix(ctx->shader, &paint_matrix); shader_bind(ctx->shader); - path_stroke(p, mat); + path_stroke(p); } } -void path_fill(struct path *p, struct matrix *mat) +void path_fill(struct path *p) { struct vg_context *ctx = vg_current_context(); + struct matrix identity; + + matrix_load_identity(&identity); + { - struct polygon_array *polygon_array = path_get_fill_polygons(p, mat); + struct polygon_array *polygon_array = path_get_fill_polygons(p, &identity); struct array *polys = polygon_array->array; if (!polygon_array || !polys || !polys->num_elements) { @@ -1601,7 +1607,7 @@ void path_fill(struct path *p, struct matrix *mat) } } -void path_stroke(struct path *p, struct matrix *mat) +void path_stroke(struct path *p) { struct vg_context *ctx = vg_current_context(); VGFillRule old_fill = ctx->state.vg.fill_rule; @@ -1613,7 +1619,7 @@ void path_stroke(struct path *p, struct matrix *mat) if (stroke && !path_is_empty(stroke)) { ctx->state.vg.fill_rule = VG_NON_ZERO; - path_fill(stroke, mat); + path_fill(stroke); ctx->state.vg.fill_rule = old_fill; } diff --git a/src/gallium/state_trackers/vega/path.h b/src/gallium/state_trackers/vega/path.h index 772ab2a0a53..d84b1f083ce 100644 --- a/src/gallium/state_trackers/vega/path.h +++ b/src/gallium/state_trackers/vega/path.h @@ -105,8 +105,8 @@ VGboolean path_interpolate(struct path *dst, void path_clear(struct path *p, VGbitfield capabilities); void path_render(struct path *p, VGbitfield paintModes, struct matrix *mat); -void path_fill(struct path *p, struct matrix *mat); -void path_stroke(struct path *p, struct matrix *mat); +void path_fill(struct path *p); +void path_stroke(struct path *p); void path_move_to(struct path *p, float x, float y); void path_line_to(struct path *p, float x, float y); diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 080bcf6fb3f..3a332498b9a 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -83,9 +83,10 @@ struct renderer { struct pipe_depth_stencil_alpha_state dsa; struct pipe_framebuffer_state fb; } g3d; + struct matrix projection; + struct matrix mvp; struct pipe_resource *vs_cbuf; - VGfloat vs_cbuf_data[8]; struct pipe_resource *fs_cbuf; VGfloat fs_cbuf_data[32]; @@ -141,6 +142,49 @@ static VGboolean renderer_can_support(struct renderer *renderer, res->format, res->target, 0, bindings, 0); } +/** + * Set the model-view-projection matrix used by vertex shaders. + */ +static void renderer_set_mvp(struct renderer *renderer, + const struct matrix *mvp) +{ + struct matrix *cur = &renderer->mvp; + struct pipe_resource *cbuf; + VGfloat consts[3][4]; + VGint i; + + /* projection only */ + if (!mvp) + mvp = &renderer->projection; + + /* re-upload only if necessary */ + if (memcmp(cur, mvp, sizeof(*mvp)) == 0) + return; + + /* 3x3 matrix to 3 constant vectors (no Z) */ + for (i = 0; i < 3; i++) { + consts[i][0] = mvp->m[i + 0]; + consts[i][1] = mvp->m[i + 3]; + consts[i][2] = 0.0f; + consts[i][3] = mvp->m[i + 6]; + } + + cbuf = renderer->vs_cbuf; + pipe_resource_reference(&cbuf, NULL); + cbuf = pipe_buffer_create(renderer->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, + sizeof(consts)); + if (cbuf) { + pipe_buffer_write(renderer->pipe, cbuf, + 0, sizeof(consts), consts); + } + renderer->pipe->set_constant_buffer(renderer->pipe, + PIPE_SHADER_VERTEX, 0, cbuf); + + memcpy(cur, mvp, sizeof(*mvp)); + renderer->vs_cbuf = cbuf; +} + /** * Create a simple vertex shader that passes through position and the given * attribute. @@ -148,7 +192,7 @@ static VGboolean renderer_can_support(struct renderer *renderer, static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name) { struct ureg_program *ureg; - struct ureg_src src[2], constants[2]; + struct ureg_src src[2], constants[3]; struct ureg_dst dst[2], tmp; int i; @@ -156,16 +200,18 @@ static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name) if (!ureg) return NULL; - /* position in surface coordinates */ + /* position is in user coordinates */ src[0] = ureg_DECL_vs_input(ureg, 0); dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); tmp = ureg_DECL_temporary(ureg); - for (i = 0; i < 2; i++) + for (i = 0; i < Elements(constants); i++) constants[i] = ureg_DECL_constant(ureg, i); /* transform to clipped coordinates */ - ureg_MUL(ureg, tmp, src[0], constants[0]); - ureg_ADD(ureg, tmp, ureg_src(tmp), constants[1]); + ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]); + ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]); + ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]); + ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]); ureg_MOV(ureg, dst[0], ureg_src(tmp)); if (semantic_name >= 0) { @@ -567,6 +613,8 @@ VGboolean renderer_copy_begin(struct renderer *renderer, renderer_set_fs(renderer, RENDERER_FS_TEXTURE); renderer_set_vs(renderer, RENDERER_VS_TEXTURE); + renderer_set_mvp(renderer, NULL); + /* remember the texture size */ renderer->u.copy.tex_width = src->texture->width0; renderer->u.copy.tex_height = src->texture->height0; @@ -638,6 +686,8 @@ VGboolean renderer_drawtex_begin(struct renderer *renderer, renderer_set_fs(renderer, RENDERER_FS_TEXTURE); renderer_set_vs(renderer, RENDERER_VS_TEXTURE); + renderer_set_mvp(renderer, NULL); + /* remember the texture size */ renderer->u.drawtex.tex_width = src->texture->width0; renderer->u.drawtex.tex_height = src->texture->height0; @@ -710,6 +760,8 @@ VGboolean renderer_scissor_begin(struct renderer *renderer, renderer_set_blend(renderer, 0); renderer_set_fs(renderer, RENDERER_FS_SCISSOR); + renderer_set_mvp(renderer, NULL); + renderer->u.scissor.restore_dsa = restore_dsa; renderer->state = RENDERER_STATE_SCISSOR; @@ -763,6 +815,8 @@ VGboolean renderer_clear_begin(struct renderer *renderer) renderer_set_fs(renderer, RENDERER_FS_COLOR); renderer_set_vs(renderer, RENDERER_VS_COLOR); + renderer_set_mvp(renderer, NULL); + renderer->state = RENDERER_STATE_CLEAR; return VG_TRUE; @@ -868,6 +922,8 @@ VGboolean renderer_filter_begin(struct renderer *renderer, renderer->u.filter.use_sampler = VG_FALSE; } + renderer_set_mvp(renderer, NULL); + renderer->state = RENDERER_STATE_FILTER; return VG_TRUE; @@ -1286,8 +1342,7 @@ void renderer_validate(struct renderer *renderer, if (dirty & FRAMEBUFFER_DIRTY) { struct pipe_framebuffer_state *fb = &renderer->g3d.fb; - struct pipe_resource *cbuf; - VGfloat vs_consts[8]; + struct matrix *proj = &renderer->projection; memset(fb, 0, sizeof(struct pipe_framebuffer_state)); fb->width = stfb->width; @@ -1299,34 +1354,9 @@ void renderer_validate(struct renderer *renderer, cso_set_framebuffer(renderer->cso, fb); vg_set_viewport(renderer, VEGA_Y0_BOTTOM); - /* surface coordinates to clipped coordinates */ - vs_consts[0] = 2.0f / fb->width; - vs_consts[1] = 2.0f / fb->height; - vs_consts[2] = 1.0f; - vs_consts[3] = 1.0f; - vs_consts[4] = -1.0f; - vs_consts[5] = -1.0f; - vs_consts[6] = 0.0f; - vs_consts[7] = 0.0f; - - /* upload if needed */ - cbuf = renderer->vs_cbuf; - if (!cbuf || - memcmp(renderer->vs_cbuf_data, vs_consts, sizeof(vs_consts)) != 0) { - pipe_resource_reference(&cbuf, NULL); - cbuf = pipe_buffer_create(renderer->pipe->screen, - PIPE_BIND_CONSTANT_BUFFER, - sizeof(vs_consts)); - if (cbuf) { - pipe_buffer_write(renderer->pipe, cbuf, 0, - sizeof(vs_consts), vs_consts); - } - renderer->pipe->set_constant_buffer(renderer->pipe, - PIPE_SHADER_VERTEX, 0, cbuf); - - renderer->vs_cbuf = cbuf; - memcpy(renderer->vs_cbuf_data, vs_consts, sizeof(vs_consts)); - } + matrix_load_identity(proj); + matrix_translate(proj, -1.0f, -1.0f); + matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height); /* we also got a new depth buffer */ if (dirty & DEPTH_STENCIL_DIRTY) { @@ -1349,18 +1379,32 @@ void renderer_validate_for_shader(struct renderer *renderer, const struct pipe_sampler_state **samplers, struct pipe_sampler_view **views, VGint num_samplers, + const struct matrix *modelview, void *fs, const void *const_buffer, VGint const_buffer_len) { + struct matrix mvp = renderer->projection; + + /* will be used in POLYGON_STENCIL and POLYGON_FILL */ + matrix_mult(&mvp, modelview); + renderer_set_mvp(renderer, &mvp); + renderer_set_custom_fs(renderer, fs, samplers, views, num_samplers, const_buffer, const_buffer_len); } void renderer_validate_for_mask_rendering(struct renderer *renderer, - struct pipe_surface *dst) + struct pipe_surface *dst, + const struct matrix *modelview) { + struct matrix mvp = renderer->projection; + + /* will be used in POLYGON_STENCIL and POLYGON_FILL */ + matrix_mult(&mvp, modelview); + renderer_set_mvp(renderer, &mvp); + renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE); renderer_set_blend(renderer, ~0); renderer_set_fs(renderer, RENDERER_FS_WHITE); diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h index a21d78af252..fe719936580 100644 --- a/src/gallium/state_trackers/vega/renderer.h +++ b/src/gallium/state_trackers/vega/renderer.h @@ -41,6 +41,7 @@ struct pipe_sampler_view; struct pipe_surface; struct pipe_vertex_element; struct pipe_vertex_buffer; +struct matrix; struct renderer *renderer_create(struct vg_context *owner); void renderer_destroy(struct renderer *); @@ -54,12 +55,14 @@ void renderer_validate_for_shader(struct renderer *renderer, const struct pipe_sampler_state **samplers, struct pipe_sampler_view **views, VGint num_samplers, + const struct matrix *modelview, void *fs, const void *const_buffer, VGint const_buffer_len); void renderer_validate_for_mask_rendering(struct renderer *renderer, - struct pipe_surface *dst); + struct pipe_surface *dst, + const struct matrix *modelview); VGboolean renderer_copy_begin(struct renderer *renderer, struct pipe_surface *dst, diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index 3d397f9ed4c..db410e3dadb 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -50,6 +50,7 @@ struct shader { struct vg_paint *paint; struct vg_image *image; + struct matrix modelview; struct matrix paint_matrix; VGboolean drawing_image; @@ -299,6 +300,7 @@ void shader_bind(struct shader *shader) renderer_validate_for_shader(ctx->renderer, (const struct pipe_sampler_state **) samplers, sampler_views, num_samplers, + &shader->modelview, shader->fs, (const void *) shader->constants, param_bytes); } @@ -327,6 +329,15 @@ void shader_set_image(struct shader *shader, struct vg_image *img) shader->image = img; } +/** + * Set the transformation to map a vertex to the surface coordinates. + */ +void shader_set_surface_matrix(struct shader *shader, + const struct matrix *mat) +{ + shader->modelview = *mat; +} + /** * Set the transformation to map a pixel to the paint coordinates. */ diff --git a/src/gallium/state_trackers/vega/shader.h b/src/gallium/state_trackers/vega/shader.h index ff4466cd87c..8b97e537efe 100644 --- a/src/gallium/state_trackers/vega/shader.h +++ b/src/gallium/state_trackers/vega/shader.h @@ -54,6 +54,8 @@ VGboolean shader_drawing_image(struct shader *shader); void shader_set_image(struct shader *shader, struct vg_image *img); +void shader_set_surface_matrix(struct shader *shader, + const struct matrix *mat); void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat); void shader_bind(struct shader *shader); -- 2.30.2