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.
This commit is contained in:
Chia-I Wu
2010-12-03 00:44:43 +08:00
parent 29bea39fde
commit a84a1e344f
8 changed files with 116 additions and 54 deletions

View File

@@ -546,11 +546,7 @@ void image_draw(struct vg_image *img, struct matrix *matrix)
x4 = 0; x4 = 0;
y4 = img->height; y4 = img->height;
matrix_map_point(matrix, x1, y1, &x1, &y1); shader_set_surface_matrix(ctx->shader, matrix);
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_drawing_image(ctx->shader, VG_TRUE); shader_set_drawing_image(ctx->shader, VG_TRUE);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
shader_set_paint_matrix(ctx->shader, &paint_matrix); shader_set_paint_matrix(ctx->shader, &paint_matrix);

View File

@@ -435,14 +435,14 @@ static void mask_layer_render_to(struct vg_mask_layer *layer,
PIPE_BIND_RENDER_TARGET); PIPE_BIND_RENDER_TARGET);
surf = pipe->create_surface(pipe, view->texture, &surf_tmpl); 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) { if (paint_modes & VG_FILL_PATH) {
path_fill(path, mat); path_fill(path);
} }
if (paint_modes & VG_STROKE_PATH){ if (paint_modes & VG_STROKE_PATH){
path_stroke(path, mat); path_stroke(path);
} }
pipe_surface_reference(&surf, NULL); pipe_surface_reference(&surf, NULL);

View File

@@ -1565,10 +1565,11 @@ void path_render(struct path *p, VGbitfield paintModes,
mat, mat,
&paint_matrix)) { &paint_matrix)) {
/* First the fill */ /* First the fill */
shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
shader_set_paint_matrix(ctx->shader, &paint_matrix); shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader); shader_bind(ctx->shader);
path_fill(p, mat); path_fill(p);
} }
if ((paintModes & VG_STROKE_PATH) && if ((paintModes & VG_STROKE_PATH) &&
@@ -1580,18 +1581,23 @@ void path_render(struct path *p, VGbitfield paintModes,
* taking place."*/ * taking place."*/
if (ctx->state.vg.stroke.line_width.f <= 0) if (ctx->state.vg.stroke.line_width.f <= 0)
return; return;
shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint); shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint);
shader_set_paint_matrix(ctx->shader, &paint_matrix); shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader); 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 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; struct array *polys = polygon_array->array;
if (!polygon_array || !polys || !polys->num_elements) { 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(); struct vg_context *ctx = vg_current_context();
VGFillRule old_fill = ctx->state.vg.fill_rule; 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)) { if (stroke && !path_is_empty(stroke)) {
ctx->state.vg.fill_rule = VG_NON_ZERO; ctx->state.vg.fill_rule = VG_NON_ZERO;
path_fill(stroke, mat); path_fill(stroke);
ctx->state.vg.fill_rule = old_fill; ctx->state.vg.fill_rule = old_fill;
} }

View File

@@ -105,8 +105,8 @@ VGboolean path_interpolate(struct path *dst,
void path_clear(struct path *p, VGbitfield capabilities); void path_clear(struct path *p, VGbitfield capabilities);
void path_render(struct path *p, VGbitfield paintModes, struct matrix *mat); void path_render(struct path *p, VGbitfield paintModes, struct matrix *mat);
void path_fill(struct path *p, struct matrix *mat); void path_fill(struct path *p);
void path_stroke(struct path *p, struct matrix *mat); void path_stroke(struct path *p);
void path_move_to(struct path *p, float x, float y); void path_move_to(struct path *p, float x, float y);
void path_line_to(struct path *p, float x, float y); void path_line_to(struct path *p, float x, float y);

View File

@@ -83,9 +83,10 @@ struct renderer {
struct pipe_depth_stencil_alpha_state dsa; struct pipe_depth_stencil_alpha_state dsa;
struct pipe_framebuffer_state fb; struct pipe_framebuffer_state fb;
} g3d; } g3d;
struct matrix projection;
struct matrix mvp;
struct pipe_resource *vs_cbuf; struct pipe_resource *vs_cbuf;
VGfloat vs_cbuf_data[8];
struct pipe_resource *fs_cbuf; struct pipe_resource *fs_cbuf;
VGfloat fs_cbuf_data[32]; VGfloat fs_cbuf_data[32];
@@ -141,6 +142,49 @@ static VGboolean renderer_can_support(struct renderer *renderer,
res->format, res->target, 0, bindings, 0); 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 * Create a simple vertex shader that passes through position and the given
* attribute. * 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) static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
{ {
struct ureg_program *ureg; struct ureg_program *ureg;
struct ureg_src src[2], constants[2]; struct ureg_src src[2], constants[3];
struct ureg_dst dst[2], tmp; struct ureg_dst dst[2], tmp;
int i; int i;
@@ -156,16 +200,18 @@ static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
if (!ureg) if (!ureg)
return NULL; return NULL;
/* position in surface coordinates */ /* position is in user coordinates */
src[0] = ureg_DECL_vs_input(ureg, 0); src[0] = ureg_DECL_vs_input(ureg, 0);
dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
tmp = ureg_DECL_temporary(ureg); 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); constants[i] = ureg_DECL_constant(ureg, i);
/* transform to clipped coordinates */ /* transform to clipped coordinates */
ureg_MUL(ureg, tmp, src[0], constants[0]); ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
ureg_ADD(ureg, tmp, ureg_src(tmp), constants[1]); 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)); ureg_MOV(ureg, dst[0], ureg_src(tmp));
if (semantic_name >= 0) { if (semantic_name >= 0) {
@@ -567,6 +613,8 @@ VGboolean renderer_copy_begin(struct renderer *renderer,
renderer_set_fs(renderer, RENDERER_FS_TEXTURE); renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
renderer_set_vs(renderer, RENDERER_VS_TEXTURE); renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
renderer_set_mvp(renderer, NULL);
/* remember the texture size */ /* remember the texture size */
renderer->u.copy.tex_width = src->texture->width0; renderer->u.copy.tex_width = src->texture->width0;
renderer->u.copy.tex_height = src->texture->height0; 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_fs(renderer, RENDERER_FS_TEXTURE);
renderer_set_vs(renderer, RENDERER_VS_TEXTURE); renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
renderer_set_mvp(renderer, NULL);
/* remember the texture size */ /* remember the texture size */
renderer->u.drawtex.tex_width = src->texture->width0; renderer->u.drawtex.tex_width = src->texture->width0;
renderer->u.drawtex.tex_height = src->texture->height0; 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_blend(renderer, 0);
renderer_set_fs(renderer, RENDERER_FS_SCISSOR); renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
renderer_set_mvp(renderer, NULL);
renderer->u.scissor.restore_dsa = restore_dsa; renderer->u.scissor.restore_dsa = restore_dsa;
renderer->state = RENDERER_STATE_SCISSOR; 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_fs(renderer, RENDERER_FS_COLOR);
renderer_set_vs(renderer, RENDERER_VS_COLOR); renderer_set_vs(renderer, RENDERER_VS_COLOR);
renderer_set_mvp(renderer, NULL);
renderer->state = RENDERER_STATE_CLEAR; renderer->state = RENDERER_STATE_CLEAR;
return VG_TRUE; return VG_TRUE;
@@ -868,6 +922,8 @@ VGboolean renderer_filter_begin(struct renderer *renderer,
renderer->u.filter.use_sampler = VG_FALSE; renderer->u.filter.use_sampler = VG_FALSE;
} }
renderer_set_mvp(renderer, NULL);
renderer->state = RENDERER_STATE_FILTER; renderer->state = RENDERER_STATE_FILTER;
return VG_TRUE; return VG_TRUE;
@@ -1286,8 +1342,7 @@ void renderer_validate(struct renderer *renderer,
if (dirty & FRAMEBUFFER_DIRTY) { if (dirty & FRAMEBUFFER_DIRTY) {
struct pipe_framebuffer_state *fb = &renderer->g3d.fb; struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
struct pipe_resource *cbuf; struct matrix *proj = &renderer->projection;
VGfloat vs_consts[8];
memset(fb, 0, sizeof(struct pipe_framebuffer_state)); memset(fb, 0, sizeof(struct pipe_framebuffer_state));
fb->width = stfb->width; fb->width = stfb->width;
@@ -1299,34 +1354,9 @@ void renderer_validate(struct renderer *renderer,
cso_set_framebuffer(renderer->cso, fb); cso_set_framebuffer(renderer->cso, fb);
vg_set_viewport(renderer, VEGA_Y0_BOTTOM); vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
/* surface coordinates to clipped coordinates */ matrix_load_identity(proj);
vs_consts[0] = 2.0f / fb->width; matrix_translate(proj, -1.0f, -1.0f);
vs_consts[1] = 2.0f / fb->height; matrix_scale(proj, 2.0f / fb->width, 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));
}
/* we also got a new depth buffer */ /* we also got a new depth buffer */
if (dirty & DEPTH_STENCIL_DIRTY) { if (dirty & DEPTH_STENCIL_DIRTY) {
@@ -1349,18 +1379,32 @@ void renderer_validate_for_shader(struct renderer *renderer,
const struct pipe_sampler_state **samplers, const struct pipe_sampler_state **samplers,
struct pipe_sampler_view **views, struct pipe_sampler_view **views,
VGint num_samplers, VGint num_samplers,
const struct matrix *modelview,
void *fs, void *fs,
const void *const_buffer, const void *const_buffer,
VGint const_buffer_len) 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, renderer_set_custom_fs(renderer, fs,
samplers, views, num_samplers, samplers, views, num_samplers,
const_buffer, const_buffer_len); const_buffer, const_buffer_len);
} }
void renderer_validate_for_mask_rendering(struct renderer *renderer, 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_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
renderer_set_blend(renderer, ~0); renderer_set_blend(renderer, ~0);
renderer_set_fs(renderer, RENDERER_FS_WHITE); renderer_set_fs(renderer, RENDERER_FS_WHITE);

View File

@@ -41,6 +41,7 @@ struct pipe_sampler_view;
struct pipe_surface; struct pipe_surface;
struct pipe_vertex_element; struct pipe_vertex_element;
struct pipe_vertex_buffer; struct pipe_vertex_buffer;
struct matrix;
struct renderer *renderer_create(struct vg_context *owner); struct renderer *renderer_create(struct vg_context *owner);
void renderer_destroy(struct renderer *); void renderer_destroy(struct renderer *);
@@ -54,12 +55,14 @@ void renderer_validate_for_shader(struct renderer *renderer,
const struct pipe_sampler_state **samplers, const struct pipe_sampler_state **samplers,
struct pipe_sampler_view **views, struct pipe_sampler_view **views,
VGint num_samplers, VGint num_samplers,
const struct matrix *modelview,
void *fs, void *fs,
const void *const_buffer, const void *const_buffer,
VGint const_buffer_len); VGint const_buffer_len);
void renderer_validate_for_mask_rendering(struct renderer *renderer, 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, VGboolean renderer_copy_begin(struct renderer *renderer,
struct pipe_surface *dst, struct pipe_surface *dst,

View File

@@ -50,6 +50,7 @@ struct shader {
struct vg_paint *paint; struct vg_paint *paint;
struct vg_image *image; struct vg_image *image;
struct matrix modelview;
struct matrix paint_matrix; struct matrix paint_matrix;
VGboolean drawing_image; VGboolean drawing_image;
@@ -299,6 +300,7 @@ void shader_bind(struct shader *shader)
renderer_validate_for_shader(ctx->renderer, renderer_validate_for_shader(ctx->renderer,
(const struct pipe_sampler_state **) samplers, (const struct pipe_sampler_state **) samplers,
sampler_views, num_samplers, sampler_views, num_samplers,
&shader->modelview,
shader->fs, (const void *) shader->constants, param_bytes); 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; 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. * Set the transformation to map a pixel to the paint coordinates.
*/ */

View File

@@ -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_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_set_paint_matrix(struct shader *shader, const struct matrix *mat);
void shader_bind(struct shader *shader); void shader_bind(struct shader *shader);