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.tags/android-x86-2.2
| @@ -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); | |||
| @@ -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]; | |||
| @@ -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: | |||
| @@ -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); | |||
| @@ -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); | |||
| } | |||
| @@ -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); | |||
| } | |||
| @@ -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 | |||
| @@ -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; | |||
| } | |||
| @@ -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) | |||
| { | |||