st/vega: Move vertex transformation to shader.
authorChia-I Wu <olv@lunarg.com>
Thu, 2 Dec 2010 16:44:43 +0000 (00:44 +0800)
committerChia-I Wu <olv@lunarg.com>
Fri, 3 Dec 2010 06:23:04 +0000 (14:23 +0800)
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
src/gallium/state_trackers/vega/mask.c
src/gallium/state_trackers/vega/path.c
src/gallium/state_trackers/vega/path.h
src/gallium/state_trackers/vega/renderer.c
src/gallium/state_trackers/vega/renderer.h
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/shader.h

index 164af30ef3b75f38324fb39c4dbaf13e3605ef12..318ea94bdfba1b853755433e6ce9f1146e21e2af 100644 (file)
@@ -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);
index 17912cb552db31f13e016d2c10d19644c7617114..dfd0600e444c2c5d7fdb2eb34f76c86ad777397e 100644 (file)
@@ -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);
index 31a043ea9b77c90ccbbe7bda9dc766068f632921..d7253befd035049d0ea1a107876f3091fed79413 100644 (file)
@@ -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;
    }
index 772ab2a0a53adad48a12dc2228b9604f2cc4f5eb..d84b1f083cee32d7d4c3cd8b591037e6cb46a993 100644 (file)
@@ -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);
index 080bcf6fb3fd0aff67b275debb2a8eab9420e1bc..3a332498b9ab8a7847426472d49c2c4bc3c187eb 100644 (file)
@@ -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);
index a21d78af252ecee3e213b146c96f7598907b546f..fe7199365804f9a3e04477f6f9dee3064f46a34c 100644 (file)
@@ -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,
index 3d397f9ed4c16bf8c2eaaf5ad20055b89010786e..db410e3dadba6b3a365b1bf777819bd0868a803e 100644 (file)
@@ -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.
  */
index ff4466cd87c710d68a87f411c1c9ed540bae6fa5..8b97e537efed09398e5a2b73a3c4647cb87ab32f 100644 (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_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);