diff options
author | Igor Oliveira <igor.oliveira@openbossa.org> | 2010-07-11 17:53:31 -0400 |
---|---|---|
committer | Igor Oliveira <igor.oliveira@openbossa.org> | 2010-07-11 22:18:25 -0400 |
commit | 5ba35782a0aa8cda1db3bc5f23c0133c5cb523bb (patch) | |
tree | b746225d7d39b2c9586d61ecf5fb3f726bd55065 | |
parent | f9799a5ce4512accafb08de07b0f998b83027d2d (diff) |
DRM/Gallium3D: implement stroke styles using to_shape helper from cairo, and
use cairo_matrix_* to convert the cairo coordinate system to gallium coordinate system
-rw-r--r-- | src/drm/cairo-drm-gallium-surface.c | 440 |
1 files changed, 260 insertions, 180 deletions
diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c index 415067ed..3b25b585 100644 --- a/src/drm/cairo-drm-gallium-surface.c +++ b/src/drm/cairo-drm-gallium-surface.c @@ -68,8 +68,6 @@ #define MAX_CONTANTS 20 -int draw_operation = 0; - typedef enum _shader_type shadertype_t; typedef struct _gallium_paint gallium_paint_t; @@ -120,6 +118,7 @@ struct _gallium_surface { struct pipe_resource *texture; struct pipe_transfer *map_transfer; gallium_paint_t paint; + cairo_matrix_t gallium_ctm; struct pipe_resource *vbuf; struct pipe_vertex_element velem[2]; @@ -659,6 +658,8 @@ struct _gallium_stroke { float maxx; float maxy; + cairo_matrix_t *gallium_ctm; + float line_width; }; @@ -679,13 +680,14 @@ _gallium_init_path () } path->count = 0; - path->minx = path->miny = path->maxx = path->maxy = 0; + path->minx = path->miny = 1.0; + path->maxx = path->maxy = 0.0; CLEAN: return path; } -static cairo_status_t +static void _gallium_finish_path (gallium_path_t *path) { if (path->count != 0) @@ -709,7 +711,7 @@ _gallium_init_stroke() } static cairo_status_t -_gallium_append_point (gallium_path_t *path, const cairo_point_t *point) +_gallium_append_point (gallium_path_t *path, double x, double y) { cairo_status_t status = CAIRO_STATUS_SUCCESS; @@ -725,8 +727,8 @@ _gallium_append_point (gallium_path_t *path, const cairo_point_t *point) 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->points[path->count] = x; + path->points[path->count + 1] = y; printf("%f %f", path->points[path->count], path->points[path->count +1]); @@ -756,12 +758,15 @@ draw_path (gallium_surface_t *surface, int vert_size = path->count * sizeof(float); int num_vert = path->count * 0.5; - if (path->buf == NULL) { - path->buf = pipe_buffer_create(device->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, vert_size); - pipe_buffer_write(device->pipe, path->buf, 0, vert_size, path->points); - device->pipe->set_constant_buffer(device->pipe, PIPE_SHADER_VERTEX, 0, path->buf); + if (path->buf != NULL) { + pipe_resource_reference(&path->buf, NULL); } + path->buf= pipe_user_buffer_create(device->pipe->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 @@ -826,11 +831,15 @@ static cairo_status_t _gallium_move_to (void *closure, const cairo_point_t *point) { gallium_stroke_t *stroke = closure; - printf("move to\n"); + + const double x = _cairo_fixed_to_double(point->x); + const double y = _cairo_fixed_to_double(point->y); //if (path->ctm_inverse) // cairo_matrix_transform_point (path->ctm_inverse, point->x, point->y); + cairo_matrix_transform_point (stroke->gallium_ctm, &x, &y); + stroke->current_path = _gallium_init_path(); if ((stroke->list_head.next == NULL) && @@ -842,7 +851,7 @@ _gallium_move_to (void *closure, const cairo_point_t *point) LIST_ADDTAIL(&stroke->current_path->list, &stroke->list_head); } - _gallium_append_point(stroke->current_path, point); + _gallium_append_point(stroke->current_path, x, y); return CAIRO_STATUS_SUCCESS; } @@ -850,13 +859,16 @@ static cairo_status_t _gallium_line_to (void *closure, const cairo_point_t *point) { gallium_stroke_t *stroker = closure; - gallium_path_t *path = stroker->current_path; - printf("line to\n"); + + const double x = _cairo_fixed_to_double(point->x); + const double y = _cairo_fixed_to_double(point->y); //if (path->ctm_inverse) // cairo_matrix_transform_point (path->ctm_inverse, point->x, point->y); - _gallium_append_point(path, point); + cairo_matrix_transform_point (stroker->gallium_ctm, &x, &y); + + _gallium_append_point(stroker->current_path, x, y); return CAIRO_STATUS_SUCCESS; } @@ -869,11 +881,9 @@ _gallium_close_path (void *closure) printf("close path\n"); if (stroker->current_path->count != 0) { - cairo_point_t close_point_path; - close_point_path.x = _cairo_fixed_from_double (stroker->current_path->points[0]); - close_point_path.y = _cairo_fixed_from_double (stroker->current_path->points[1]); - - _gallium_append_point(stroker->current_path, &close_point_path); + _gallium_append_point(stroker->current_path, + stroker->current_path->points[0], + stroker->current_path->points[1]); status = CAIRO_STATUS_SUCCESS; } @@ -931,187 +941,64 @@ _gallium_path_from_cairo (gallium_stroke_t *gallium_stroke, const cairo_path_fix } static cairo_status_t -_gallium_surface_clip (gallium_surface_t *abstract_surface, - cairo_clip_t *clip) +add_triangle (void *closure, const cairo_point_t triangle[3]) { - if (clip != NULL) { - gallium_surface_t *surface = abstract_surface; - gallium_stroke_t *gallium_stroke; - gallium_device_t *device = gallium_device(surface); - struct pipe_depth_stencil_alpha_state st; - struct pipe_scissor_state scissor; - - gallium_stroke = _gallium_init_stroke(); - _gallium_path_from_cairo(gallium_stroke, &clip->path->path); - - st.depth.writemask = 1; - st.depth.func = PIPE_FUNC_ALWAYS; - st.depth.enabled = 1; - cso_set_depth_stencil_alpha(device->cso, &st); - device->pipe->clear(device->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); - - surface->rasterizer.gl_rasterization_rules = 1; - surface->rasterizer.scissor = 1; - - scissor.minx = gallium_stroke->current_path->minx; - scissor.miny = gallium_stroke->current_path->miny; - scissor.maxx = gallium_stroke->current_path->maxx; - scissor.maxy = gallium_stroke->current_path->maxy; + gallium_stroke_t *stroke = closure; - //_gallium_finish_path(gallium_path); - _gallium_draw_quad(device->pipe, scissor.minx, scissor.miny, scissor.maxx, scissor.maxy); - } + _gallium_move_to(stroke, &triangle[0]); + _gallium_line_to(stroke, &triangle[1]); + _gallium_line_to(stroke, &triangle[2]); return CAIRO_STATUS_SUCCESS; } -static cairo_int_status_t -gallium_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_clip_t *clip) +//XXX: fix triangle fan +static cairo_status_t +add_triangle_fan (void *closure, + const cairo_point_t *midpt, + const cairo_point_t *points, + int npoints) { - gallium_surface_t *surface = abstract_surface; - gallium_device_t *device = gallium_device(surface); - gallium_shader_t *shader = gallium_device(surface)->shader; - cairo_status_t status; - - if (surface->fallback == NULL) { - /* XXX insert magic */ - surface->fallback = gallium_surface_map_to_image (surface); - } - - status = _gallium_surface_clip (surface, clip); - if (unlikely (status)) - return status; - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _gallium_surface_paint_solid(surface, source, shader); - } else { - status = _cairo_surface_paint (surface->fallback, op, source, clip); - } - - _gallium_set_states(surface); - - cso_set_vertex_elements (device->cso, 2, surface->velem); - - util_draw_vertex_buffer (device->pipe, - surface->vbuf, 0, - PIPE_PRIM_QUADS, - 4, - 2); - - gallium_surface_flush(abstract_surface); + int i; - return status; -} - -static cairo_int_status_t -gallium_surface_mask (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - cairo_clip_t *clip) -{ - gallium_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + gallium_stroke_t *stroke = closure; + printf("\n number points:%d\n", npoints); - if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; - float alpha = surface->paint.solid_color[4]; + for (i = 0; i < npoints; i++) { + if (i == 0) + _gallium_move_to(stroke, &points[i]); - surface->paint.solid_color[4] = solid_mask->color.alpha; - status = gallium_surface_paint(abstract_surface, op, source, clip); - surface->paint.solid_color[4] = alpha; + _gallium_line_to(stroke, &points[i]); } - return status; + return 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) +static cairo_status_t +add_convex_quad (void *closure, const cairo_point_t quad[4]) { - gallium_surface_t *surface = abstract_surface; - gallium_stroke_t *gallium_stroke; - gallium_device_t *device = gallium_device(surface); - gallium_shader_t *shader = device->shader; - cairo_status_t status; - - status = _gallium_surface_clip (surface, clip); - if (unlikely (status)) - return status; - - gallium_stroke = _gallium_init_stroke(); - - //gallium_path->ctm_inverse = ctm_inverse; - - _gallium_path_from_cairo(gallium_stroke, path); - - gallium_stroke->line_width = style->line_width; - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - _gallium_surface_paint_solid(abstract_surface, source, shader); - } + gallium_stroke_t *stroke = closure; - surface->rasterizer.line_width = gallium_stroke->line_width; + printf("\n convex quad\n"); - _gallium_set_states(abstract_surface); - { - struct list_head *head, *next; + _gallium_move_to(stroke, &quad[0]); + _gallium_line_to(stroke, &quad[1]); + _gallium_line_to(stroke, &quad[2]); + _gallium_line_to(stroke, &quad[3]); - for (head = gallium_stroke->list_head.next; head != &gallium_stroke->list_head; head = next) { - gallium_path_t *gallium_path = LIST_ENTRY (gallium_path_t, head, list); - - draw_path(abstract_surface, gallium_path, PIPE_PRIM_LINE_STRIP); - _gallium_finish_path(gallium_path); + return CAIRO_STATUS_SUCCESS; - gallium_surface_flush(abstract_surface); - next = head->next; - } - } - return status; } -// implement clip static cairo_int_status_t -gallium_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - cairo_clip_t *clip) +_gallium_fill (void *abstract_surface, + gallium_stroke_t *gallium_stroke, + cairo_fill_rule_t fill_rule) { gallium_surface_t *surface = abstract_surface; - gallium_stroke_t *gallium_stroke; gallium_device_t *device = gallium_device(surface); - gallium_shader_t *shader = device->shader; struct pipe_depth_stencil_alpha_state st; struct pipe_stencil_ref sr; - cairo_status_t status; - - status = _gallium_surface_clip (surface, clip); - if (unlikely (status)) - return status; - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - _gallium_surface_paint_solid(abstract_surface, source, shader); - } - - _gallium_set_states(abstract_surface); - - gallium_stroke = _gallium_init_stroke(); - _gallium_path_from_cairo(gallium_stroke, path); struct pipe_surface *zsurface; struct pipe_resource *resource; @@ -1139,8 +1026,9 @@ gallium_surface_fill (void *abstract_surface, _gallium_set_states(abstract_surface); { - cso_save_blend(device->cso); struct pipe_blend_state blend; + + cso_save_blend(device->cso); memset(&blend, 0, sizeof(struct pipe_blend_state)); blend.rt[0].colormask = 0; /*disable colorwrites*/ @@ -1183,7 +1071,6 @@ gallium_surface_fill (void *abstract_surface, gallium_stroke->miny = MIN2(gallium_stroke->miny, gallium_path->miny); gallium_stroke->maxy = MAX2(gallium_stroke->maxy, gallium_path->maxy); - gallium_surface_flush(abstract_surface); next = head->next; } } @@ -1220,7 +1107,6 @@ gallium_surface_fill (void *abstract_surface, gallium_stroke->miny = MIN2(gallium_stroke->miny, gallium_path->miny); gallium_stroke->maxy = MAX2(gallium_stroke->maxy, gallium_path->maxy); - gallium_surface_flush(abstract_surface); next = head->next; } } @@ -1253,7 +1139,6 @@ gallium_surface_fill (void *abstract_surface, gallium_path_t *gallium_path = LIST_ENTRY (gallium_path_t, head, list); draw_path(abstract_surface, gallium_path, PIPE_PRIM_TRIANGLE_FAN); - gallium_surface_flush(abstract_surface); next = head->next; } @@ -1282,7 +1167,6 @@ gallium_surface_fill (void *abstract_surface, gallium_stroke->miny = MIN2(gallium_stroke->miny, gallium_path->miny); gallium_stroke->maxy = MAX2(gallium_stroke->maxy, gallium_path->maxy); - gallium_surface_flush(abstract_surface); next = head->next; } } @@ -1310,10 +1194,204 @@ gallium_surface_fill (void *abstract_surface, cso_restore_depth_stencil_alpha(device->cso); printf("filling"); + return CAIRO_STATUS_SUCCESS; +} + + +static cairo_status_t +_gallium_surface_clip (gallium_surface_t *abstract_surface, + cairo_clip_t *clip) +{ + if (clip != NULL) { + gallium_surface_t *surface = abstract_surface; + gallium_stroke_t *gallium_stroke; + gallium_device_t *device = gallium_device(surface); + struct pipe_depth_stencil_alpha_state st; + struct pipe_scissor_state scissor; + + gallium_stroke = _gallium_init_stroke(); + _gallium_path_from_cairo(gallium_stroke, &clip->path->path); + + st.depth.writemask = 1; + st.depth.func = PIPE_FUNC_ALWAYS; + st.depth.enabled = 1; + cso_set_depth_stencil_alpha(device->cso, &st); + device->pipe->clear(device->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); + + surface->rasterizer.gl_rasterization_rules = 1; + surface->rasterizer.scissor = 1; + + scissor.minx = gallium_stroke->current_path->minx; + scissor.miny = gallium_stroke->current_path->miny; + scissor.maxx = gallium_stroke->current_path->maxx; + scissor.maxy = gallium_stroke->current_path->maxy; + + //_gallium_finish_path(gallium_path); + _gallium_draw_quad(device->pipe, scissor.minx, scissor.miny, scissor.maxx, scissor.maxy); + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +gallium_surface_paint (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_clip_t *clip) +{ + gallium_surface_t *surface = abstract_surface; + gallium_device_t *device = gallium_device(surface); + gallium_shader_t *shader = gallium_device(surface)->shader; + cairo_status_t status; + + if (surface->fallback == NULL) { + /* XXX insert magic */ + surface->fallback = gallium_surface_map_to_image (surface); + } + + status = _gallium_surface_clip (surface, clip); + if (unlikely (status)) + return status; + + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + status = _gallium_surface_paint_solid(surface, source, shader); + } else { + status = _cairo_surface_paint (surface->fallback, op, source, clip); + } + + _gallium_set_states(surface); + + cso_set_vertex_elements (device->cso, 2, surface->velem); + + util_draw_vertex_buffer (device->pipe, + surface->vbuf, 0, + PIPE_PRIM_QUADS, + 4, + 2); + + gallium_surface_flush(abstract_surface); + + return status; +} + +static cairo_int_status_t +gallium_surface_mask (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + const cairo_pattern_t *mask, + cairo_clip_t *clip) +{ + gallium_surface_t *surface = abstract_surface; + cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + + if (mask->type == CAIRO_PATTERN_TYPE_SOLID) { + cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask; + float alpha = surface->paint.solid_color[4]; + + surface->paint.solid_color[4] = solid_mask->color.alpha; + status = gallium_surface_paint(abstract_surface, op, source, clip); + surface->paint.solid_color[4] = alpha; + } + return status; } 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) +{ + gallium_surface_t *surface = abstract_surface; + gallium_stroke_t *gallium_stroke; + gallium_device_t *device = gallium_device(surface); + gallium_shader_t *shader = device->shader; + cairo_status_t status; + + const cairo_fill_rule_t rule = CAIRO_FILL_RULE_WINDING; + + status = _gallium_surface_clip (surface, clip); + if (unlikely (status)) + return status; + + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + _gallium_surface_paint_solid(abstract_surface, source, shader); + } + + _gallium_set_states(abstract_surface); + + gallium_stroke = _gallium_init_stroke(); + gallium_stroke->gallium_ctm = &surface->gallium_ctm; + _cairo_path_fixed_stroke_to_shaper(path, + style, ctm, ctm_inverse, + tolerance, + add_triangle, + add_triangle_fan, + add_convex_quad, + gallium_stroke); + + { + struct list_head *head, *next; + + for (head = gallium_stroke->list_head.next; head != &gallium_stroke->list_head; head = next) { + gallium_path_t *gallium_path = LIST_ENTRY (gallium_path_t, head, list); + + draw_path(abstract_surface, gallium_path, PIPE_PRIM_TRIANGLE_FAN); + _gallium_finish_path(gallium_path); + + next = head->next; + } + } + + gallium_surface_flush(abstract_surface); + + + return CAIRO_STATUS_SUCCESS; +} + +// implement clip +static cairo_int_status_t +gallium_surface_fill (void *abstract_surface, + cairo_operator_t op, + const cairo_pattern_t *source, + cairo_path_fixed_t *path, + cairo_fill_rule_t fill_rule, + double tolerance, + cairo_antialias_t antialias, + cairo_clip_t *clip) +{ + gallium_surface_t *surface = abstract_surface; + gallium_stroke_t *gallium_stroke; + gallium_device_t *device = gallium_device(surface); + gallium_shader_t *shader = device->shader; + cairo_status_t status; + + status = _gallium_surface_clip (surface, clip); + if (unlikely (status)) + return status; + + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + _gallium_surface_paint_solid(abstract_surface, source, shader); + } + + _gallium_set_states(abstract_surface); + + gallium_stroke = _gallium_init_stroke(); + gallium_stroke->gallium_ctm = &surface->gallium_ctm; + _gallium_path_from_cairo(gallium_stroke, path); + + _gallium_fill(abstract_surface, gallium_stroke, fill_rule); + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t gallium_surface_glyphs (void *abstract_surface, cairo_operator_t op, const cairo_pattern_t *source, @@ -1533,6 +1611,8 @@ gallium_surface_create_internal (gallium_device_t *device, device->shader = shader_create(device); + cairo_matrix_init_scale (&surface->gallium_ctm, 1.0/width, 1.0/height); + return &surface->drm.base; } |