st/vega: Fix paint coordinates transformations.
authorChia-I Wu <olv@lunarg.com>
Tue, 30 Nov 2010 18:30:59 +0000 (02:30 +0800)
committerChia-I Wu <olv@lunarg.com>
Wed, 1 Dec 2010 03:31:00 +0000 (11:31 +0800)
Depending on whether vgDrawPath(mode), vgDrawImage, or vgDrawGlyph[s] is
called, different paint-to-user and user-to-surface matrices should be
used to derive the sample points for the paint.

This fixes "paint" demo.

src/gallium/state_trackers/vega/image.c
src/gallium/state_trackers/vega/matrix.h
src/gallium/state_trackers/vega/paint.c
src/gallium/state_trackers/vega/paint.h
src/gallium/state_trackers/vega/path.c
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/shader.h
src/gallium/state_trackers/vega/vg_context.c
src/gallium/state_trackers/vega/vg_context.h

index b1bda3ff54bc0a879a5fadf1023e4830dd7439bf..fc87536883aa7adc02f87bca5a11a357e52de0cf 100644 (file)
@@ -523,11 +523,18 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy,
 void image_draw(struct vg_image *img, struct matrix *matrix)
 {
    struct vg_context *ctx = vg_current_context();
+   struct matrix paint_matrix;
    VGfloat x1, y1;
    VGfloat x2, y2;
    VGfloat x3, y3;
    VGfloat x4, y4;
 
+   if (vg_get_paint_matrix(ctx,
+                           &ctx->state.vg.fill_paint_to_user_matrix,
+                           matrix,
+                           &paint_matrix))
+      return;
+
    x1 = 0;
    y1 = 0;
    x2 = img->width;
@@ -544,6 +551,7 @@ void image_draw(struct vg_image *img, struct matrix *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);
    shader_set_image(ctx->shader, img);
    shader_bind(ctx->shader);
 
index 4c207f912a8558bad7113ed439ce183e1e2f534c..bed2b3193d02b149e6456258330bb687fb7104c1 100644 (file)
@@ -129,7 +129,7 @@ static INLINE void matrix_make_affine(struct matrix *matrix)
 }
 
 static INLINE void matrix_mult(struct matrix *dst,
-                               struct matrix *src)
+                               const struct matrix *src)
 {
    VGfloat m11 = dst->m[0]*src->m[0] + dst->m[3]*src->m[1] + dst->m[6]*src->m[2];
    VGfloat m12 = dst->m[0]*src->m[3] + dst->m[3]*src->m[4] + dst->m[6]*src->m[5];
index c0c8cddabe94d2edd506a2f7bc93665d3a71143c..467d39297548b3b4961aa97f065df33377a80aec 100644 (file)
@@ -261,9 +261,10 @@ static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
    map[7] = 4.f;
 }
 
-static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint,
+                                                const struct matrix *inv,
+                                                void *buffer)
 {
-   struct vg_context *ctx = paint->base.ctx;
    VGfloat *map = (VGfloat*)buffer;
 
    map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
@@ -277,15 +278,10 @@ static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *bu
    map[7] = 4.f;
    {
       struct matrix mat;
-      struct matrix inv;
       matrix_load_identity(&mat);
+      /* VEGA_LINEAR_GRADIENT_SHADER expects the first point to be at (0, 0) */
       matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
-      memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
-             sizeof(struct matrix));
-      matrix_invert(&inv);
-      matrix_mult(&inv, &mat);
-      memcpy(&mat, &inv,
-             sizeof(struct matrix));
+      matrix_mult(&mat, inv);
 
       map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
       map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -298,10 +294,11 @@ static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *bu
 }
 
 
-static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint,
+                                                const struct matrix *inv,
+                                                void *buffer)
 {
    VGfloat *radialCoords = paint->gradient.radial.vals;
-   struct vg_context *ctx = paint->base.ctx;
 
    VGfloat *map = (VGfloat*)buffer;
 
@@ -318,15 +315,9 @@ static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *bu
 
    {
       struct matrix mat;
-      struct matrix inv;
       matrix_load_identity(&mat);
       matrix_translate(&mat, -radialCoords[2], -radialCoords[3]);
-      memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
-             sizeof(struct matrix));
-      matrix_invert(&inv);
-      matrix_mult(&inv, &mat);
-      memcpy(&mat, &inv,
-             sizeof(struct matrix));
+      matrix_mult(&mat, inv);
 
       map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
       map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -340,10 +331,10 @@ static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *bu
 }
 
 
-static INLINE void  paint_pattern_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void  paint_pattern_buffer(struct vg_paint *paint,
+                                         const struct matrix *inv,
+                                         void *buffer)
 {
-   struct vg_context *ctx = paint->base.ctx;
-
    VGfloat *map = (VGfloat *)buffer;
    memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
 
@@ -353,17 +344,8 @@ static INLINE void  paint_pattern_buffer(struct vg_paint *paint, void *buffer)
    map[7] = paint->pattern.sampler_view->texture->height0;
    {
       struct matrix mat;
-      memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
-             sizeof(struct matrix));
-      matrix_invert(&mat);
-      {
-         struct matrix pm;
-         memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix,
-                sizeof(struct matrix));
-         matrix_invert(&pm);
-         matrix_mult(&pm, &mat);
-         memcpy(&mat, &pm, sizeof(struct matrix));
-      }
+
+      memcpy(&mat, inv, sizeof(*inv));
 
       map[8]  = mat.m[0]; map[9]  = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
       map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -695,6 +677,7 @@ VGint paint_constant_buffer_size(struct vg_paint *paint)
 }
 
 void paint_fill_constant_buffer(struct vg_paint *paint,
+                                const struct matrix *mat,
                                 void *buffer)
 {
    switch(paint->type) {
@@ -702,13 +685,13 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
       paint_color_buffer(paint, buffer);
       break;
    case VG_PAINT_TYPE_LINEAR_GRADIENT:
-      paint_linear_gradient_buffer(paint, buffer);
+      paint_linear_gradient_buffer(paint, mat, buffer);
       break;
    case VG_PAINT_TYPE_RADIAL_GRADIENT:
-      paint_radial_gradient_buffer(paint, buffer);
+      paint_radial_gradient_buffer(paint, mat, buffer);
       break;
    case VG_PAINT_TYPE_PATTERN:
-      paint_pattern_buffer(paint, buffer);
+      paint_pattern_buffer(paint, mat, buffer);
       break;
 
    default:
index 012cd3e561896f67a0df4be761468c5ab19be84e..2e09b839a4ad731082ae8f80fb2ca3cdc74fafa8 100644 (file)
@@ -111,7 +111,9 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa
                           struct pipe_sampler_view **sampler_views);
 
 VGint paint_constant_buffer_size(struct vg_paint *paint);
+
 void paint_fill_constant_buffer(struct vg_paint *paint,
+                                const struct matrix *mat,
                                 void *buffer);
 
 
index 62eb62418d388fe614b139f664d1eb3590da74d9..06c96a355029aefd62ef9e618bd837860951622a 100644 (file)
@@ -1532,6 +1532,7 @@ void path_render(struct path *p, VGbitfield paintModes,
                  struct matrix *mat)
 {
    struct vg_context *ctx = vg_current_context();
+   struct matrix paint_matrix;
 
    vg_validate_state(ctx);
 
@@ -1543,19 +1544,29 @@ void path_render(struct path *p, VGbitfield paintModes,
            mat->m[3], mat->m[4], mat->m[5],
            mat->m[6], mat->m[7], mat->m[8]);
 #endif
-   if (paintModes & VG_FILL_PATH) {
+   if ((paintModes & VG_FILL_PATH) &&
+       vg_get_paint_matrix(ctx,
+                           &ctx->state.vg.fill_paint_to_user_matrix,
+                           mat,
+                           &paint_matrix)) {
       /* First the fill */
       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);
    }
 
-   if (paintModes & VG_STROKE_PATH){
+   if ((paintModes & VG_STROKE_PATH) &&
+       vg_get_paint_matrix(ctx,
+                           &ctx->state.vg.stroke_paint_to_user_matrix,
+                           mat,
+                           &paint_matrix)) {
       /* 8.7.5: "line width less than or equal to 0 prevents stroking from
        *  taking place."*/
       if (ctx->state.vg.stroke.line_width.f <= 0)
          return;
       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);
    }
index 39c4bb0dfd6396ec0eb2ec27cdcaa875190f0ce8..a77587c6bfff472eb01bf23ef0ebf45f560abc60 100644 (file)
@@ -50,6 +50,8 @@ struct shader {
    struct vg_paint *paint;
    struct vg_image *image;
 
+   struct matrix paint_matrix;
+
    VGboolean drawing_image;
    VGImageMode image_mode;
 
@@ -119,7 +121,8 @@ static VGint setup_constant_buffer(struct shader *shader)
       memset(shader->constants, 0, sizeof(VGfloat) * 8);
    }
 
-   paint_fill_constant_buffer(shader->paint, shader->constants + 8);
+   paint_fill_constant_buffer(shader->paint,
+         &shader->paint_matrix, shader->constants + 8);
 
    return param_bytes;
 }
@@ -324,3 +327,19 @@ void shader_set_image(struct shader *shader, struct vg_image *img)
 {
    shader->image = img;
 }
+
+/**
+ * Set the transformation to map a pixel to the paint coordinates.
+ */
+void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat)
+{
+   const struct st_framebuffer *stfb = shader->context->draw_buffer;
+   const VGfloat px_center_offset = 0.5f;
+
+   memcpy(&shader->paint_matrix, mat, sizeof(*mat));
+
+   /* make it window-to-paint for the shaders */
+   matrix_translate(&shader->paint_matrix, px_center_offset,
+         stfb->height - 1.0f + px_center_offset);
+   matrix_scale(&shader->paint_matrix, 1.0f, -1.0f);
+}
index f906631b50ec2562945e2661fd6a6c85cbcc62cf..ff4466cd87c710d68a87f411c1c9ed540bae6fa5 100644 (file)
@@ -33,6 +33,7 @@ struct shader;
 struct vg_paint;
 struct vg_context;
 struct vg_image;
+struct matrix;
 
 struct shader *shader_create(struct vg_context *context);
 void shader_destroy(struct shader *shader);
@@ -53,6 +54,8 @@ VGboolean shader_drawing_image(struct shader *shader);
 
 void shader_set_image(struct shader *shader, struct vg_image *img);
 
+void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat);
+
 void shader_bind(struct shader *shader);
 
 #endif
index 4d088b965df6e6bbe1e333282bc35e7966b1355f..65adadd1fe917310ba143a28b24b893acbd8100b 100644 (file)
@@ -509,3 +509,28 @@ void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
    if (dest_surface)
       pipe_surface_reference(&dest_surface, NULL);
 }
+
+/**
+ * A transformation from window coordinates to paint coordinates.
+ */
+VGboolean vg_get_paint_matrix(struct vg_context *ctx,
+                              const struct matrix *paint_to_user,
+                              const struct matrix *user_to_surface,
+                              struct matrix *mat)
+{
+   struct matrix tmp;
+
+   /* get user-to-paint matrix */
+   memcpy(mat, paint_to_user, sizeof(*paint_to_user));
+   if (!matrix_invert(mat))
+      return VG_FALSE;
+
+   /* get surface-to-user matrix */
+   memcpy(&tmp, user_to_surface, sizeof(*user_to_surface));
+   if (!matrix_invert(&tmp))
+      return VG_FALSE;
+
+   matrix_mult(mat, &tmp);
+
+   return VG_TRUE;
+}
index 07f3ca76beba52b25856091cf8babdc6a3214bf2..5d0bca33c525044a0ba48e2aa8084bd9a9213e02 100644 (file)
@@ -162,6 +162,10 @@ void vg_set_error(struct vg_context *ctx,
 void vg_prepare_blend_surface(struct vg_context *ctx);
 void vg_prepare_blend_surface_from_mask(struct vg_context *ctx);
 
+VGboolean vg_get_paint_matrix(struct vg_context *ctx,
+                              const struct matrix *paint_to_user,
+                              const struct matrix *user_to_surface,
+                              struct matrix *mat);
 
 static INLINE VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
 {