summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Oliveira <itrindade.oliveira@gmail.com>2010-06-05 14:18:40 -0400
committerIgor Oliveira <igor.oliveira@openbossa.org>2010-06-10 09:44:37 -0400
commit119d13f6f734b28a29e53c9832086043c401abf0 (patch)
treed7e17b95074e3813ebc84797e4e859c351ba7729
parent7be27feac3db6a32c1c2155c5cfccf19f38b19d5 (diff)
DRM/Gallium3D: Path initial implementation
Support to all paths and line width missing: Some features in cairo_stroke_style_t
-rw-r--r--src/drm/cairo-drm-gallium-surface.c230
1 files changed, 209 insertions, 21 deletions
diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c
index 4d92a97e..0fc395ed 100644
--- a/src/drm/cairo-drm-gallium-surface.c
+++ b/src/drm/cairo-drm-gallium-surface.c
@@ -182,7 +182,7 @@ format_is_supported_destination (gallium_device_t *device,
return device->screen->is_format_supported (device->screen,
format,
PIPE_TEXTURE_2D,
- 0,
+ 0,
PIPE_BIND_RENDER_TARGET,
0);
}
@@ -431,7 +431,6 @@ setup_shader(gallium_shader_t *shader, shadertype_t type)
cso_set_fragment_shader_handle(shader->device->cso, shader->fs);
}
-
static INLINE void
unpack_color (const unsigned *src,
unsigned w, unsigned h,
@@ -658,31 +657,220 @@ gallium_surface_mask (void *abstract_surface,
clip);
}
+#define MIN_POINTS 10
+
+typedef struct _gallium_path {
+ cairo_matrix_t *ctm_inverse;
+ double *points;
+ int count;
+
+ struct pipe_resource *buf;
+} gallium_path_t;
+
+static cairo_status_t
+_gallium_init_path (gallium_path_t *path)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ path = (gallium_path_t *) malloc(sizeof(gallium_path_t));
+ if (path == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEAN;
+ }
+
+ path->points = (double *) malloc(sizeof(double) * MIN_POINTS * 2);
+ if (path->points == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEAN;
+ }
+ path->count = 0;
+
+CLEAN:
+ return status;
+}
+
+static cairo_status_t
+_gallium_finish_path (gallium_path_t *path)
+{
+ if (path->count != 0)
+ free(path->points);
+ free(path->buf);
+ free(path);
+}
+
+static cairo_status_t
+_gallium_append_point (gallium_path_t *path, const cairo_point_t *point)
+{
+ cairo_status_t status = CAIRO_STATUS_SUCCESS;
+
+ if (path->count >= MIN_POINTS) {
+ double *new_points = (double *) malloc (sizeof(double) * (path->count + 2));
+ if (new_points == NULL) {
+ status = CAIRO_STATUS_NO_MEMORY;
+ goto CLEAN;
+ }
+
+ memcpy(new_points, path->points, path->count * 2 * sizeof(double));
+ free(path->points);
+ path->points = new_points;
+ }
+
+ path->points[path->count] = _cairo_fixed_to_double (point->x);
+ path->points[path->count + 1] = _cairo_fixed_to_double (point->y);
+
+ path->count += 2;
+
+CLEAN:
+ return status;
+}
+
+static void
+draw_path (gallium_device_t *device,
+ gallium_path_t *path,
+ const cairo_stroke_style_t *style)
+{
+ const int components = 2;
+ struct pipe_context *ctx = device->pipe;
+ struct pipe_vertex_buffer vbuffer;
+ struct pipe_vertex_element velement;
+ struct pipe_rasterizer_state rasterizer;
+ int vert_size = components * path->count * sizeof(float);
+
+ path->buf= pipe_user_buffer_create(ctx->screen,
+ path->points,
+ vert_size,
+ PIPE_BIND_VERTEX_BUFFER);
+
+ memset(&vbuffer, 0, sizeof(vbuffer));
+ vbuffer.buffer = path->buf;
+ // We just have x and y components
+ vbuffer.stride = components * sizeof(float);
+ vbuffer.buffer_offset = 0;
+ vbuffer.max_index = path->count - 1;
+ ctx->set_vertex_buffers(ctx, 1, &vbuffer);
+
+ memset(&velement, 0, sizeof(velement));
+ velement.src_offset = 0;
+ velement.instance_divisor = 0;
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
+ cso_set_vertex_elements(device->cso, 1, &velement);
+
+ rasterizer.line_width = style->line_width;
+
+ cso_save_rasterizer(device->cso);
+ cso_set_rasterizer(device->cso, &rasterizer);
+
+ ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLE_FAN,
+ 0, path->count);
+
+ cso_restore_rasterizer(device->cso);
+}
+
+static cairo_status_t
+_gallium_move_to_line_to (void *closure, const cairo_point_t *point)
+{
+ gallium_path_t *path = closure;
+
+ if (path->ctm_inverse)
+ cairo_matrix_transform_point (path->ctm_inverse, point->x, point->y);
+
+ _gallium_append_point(path, point);
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_gallium_close_path (void *closure)
+{
+ cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
+ gallium_path_t *path = closure;
+
+ if (path->count != 0) {
+ cairo_point_t close_point_path;
+ close_point_path.x = path->points[0];
+ close_point_path.y = path->points[1];
+ _gallium_append_point(path, &close_point_path);
+ status = CAIRO_STATUS_SUCCESS;
+ }
+
+ return status;
+}
+
+static cairo_status_t
+_gallium_curve_to (void *closure,
+ const cairo_point_t *p0,
+ const cairo_point_t *p1,
+ const cairo_point_t *p2)
+{
+ gallium_path_t *path = closure;
+ cairo_spline_t *spline = (cairo_spline_t *) malloc (sizeof(cairo_spline_t));
+
+ cairo_point_t initial_point;
+
+ if (path->count != 0) {
+ initial_point.x = path->points[0];
+ initial_point.y = path->points[1];
+ } else {
+ initial_point.x = 0;
+ initial_point.y = 0;
+ }
+
+ if (path->ctm_inverse) {
+ cairo_matrix_transform_point (path->ctm_inverse, initial_point.x, initial_point.y);
+ cairo_matrix_transform_point (path->ctm_inverse, p0->x, p0->y);
+ cairo_matrix_transform_point (path->ctm_inverse, p1->x, p1->y);
+ cairo_matrix_transform_point (path->ctm_inverse, p2->x, p2->y);
+ }
+
+ _cairo_spline_init(spline,
+ _gallium_move_to_line_to,
+ path,
+ &initial_point, p0, p1, p2);
+ return _cairo_spline_decompose(spline, 0.25);
+}
+
+static void
+_gallium_path_from_cairo (gallium_path_t *gallium_path, const cairo_path_fixed_t *path)
+{
+ cairo_status_t status;
+
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _gallium_move_to_line_to,
+ _gallium_move_to_line_to,
+ _gallium_curve_to,
+ 0,
+ gallium_path);
+
+ assert (status == CAIRO_STATUS_SUCCESS);
+}
+
static cairo_int_status_t
gallium_surface_stroke (void *abstract_surface,
- cairo_operator_t op,
- const cairo_pattern_t *source,
- cairo_path_fixed_t *path,
- const cairo_stroke_style_t *style,
- const cairo_matrix_t *ctm,
- const cairo_matrix_t *ctm_inverse,
- double tolerance,
- cairo_antialias_t antialias,
- cairo_clip_t *clip)
+ cairo_operator_t op,
+ const cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ const cairo_stroke_style_t *style,
+ const cairo_matrix_t *ctm,
+ const cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias,
+ cairo_clip_t *clip)
{
gallium_surface_t *surface = abstract_surface;
+ gallium_path_t *gallium_path;
+ gallium_device_t *device = gallium_device(surface);
- if (surface->fallback == NULL) {
- /* XXX insert magic */
- surface->fallback = gallium_surface_map_to_image (surface);
- }
+ _gallium_init_path(gallium_path);
+
+ gallium_path->ctm_inverse = ctm_inverse;
- return _cairo_surface_stroke (surface->fallback,
- op, source,
- path, style,
- ctm, ctm_inverse,
- tolerance, antialias,
- clip);
+ _gallium_path_from_cairo(gallium_path, path);
+ draw_path(device, gallium_path, style);
+ _gallium_finish_path(gallium_path);
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t