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;
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);
}
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];
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];
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;
}
-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;
{
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;
}
-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));
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;
}
void paint_fill_constant_buffer(struct vg_paint *paint,
+ const struct matrix *mat,
void *buffer)
{
switch(paint->type) {
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:
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);
struct matrix *mat)
{
struct vg_context *ctx = vg_current_context();
+ struct matrix paint_matrix;
vg_validate_state(ctx);
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);
}
struct vg_paint *paint;
struct vg_image *image;
+ struct matrix paint_matrix;
+
VGboolean drawing_image;
VGImageMode image_mode;
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;
}
{
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);
+}
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);
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
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;
+}
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)
{