From 886b98b55aecc6e87f9218df42a3225969c1688f Mon Sep 17 00:00:00 2001 From: Igor Oliveira Date: Wed, 30 Jun 2010 07:40:36 -0400 Subject: DRM/Gallium3D: several fix to gallium 3D path and shader infrastructure --- src/drm/cairo-drm-gallium-surface.c | 258 ++++++++++++++++++++++++------------ 1 file changed, 170 insertions(+), 88 deletions(-) diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c index a284e5f8..cb6069a3 100644 --- a/src/drm/cairo-drm-gallium-surface.c +++ b/src/drm/cairo-drm-gallium-surface.c @@ -66,12 +66,15 @@ #define MAX_CONTANTS 20 +int draw_operation = 0; + typedef enum _shader_type shadertype_t; typedef struct _gallium_paint gallium_paint_t; typedef struct _gallium_surface gallium_surface_t; typedef struct _gallium_shader gallium_shader_t; typedef struct _gallium_device gallium_device_t; +typedef struct _gallium_path gallium_path_t; struct _gallium_device { cairo_drm_device_t drm; @@ -417,21 +420,22 @@ shader_destroy(gallium_shader_t *shader) static void setup_shader(gallium_shader_t *shader, shadertype_t type) { + void *vs, *fs; { const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_GENERIC }; const uint semantic_indexes[] = {0, 0}; - shader->vs = util_make_vertex_passthrough_shader(shader->device->pipe, - 2, - semantic_names, - semantic_indexes); + vs = util_make_vertex_passthrough_shader(shader->device->pipe, + 1, + semantic_names, + semantic_indexes); } - cso_set_vertex_shader_handle(shader->device->cso, shader->vs); + cso_set_vertex_shader_handle(shader->device->cso, vs); - shader->fs = shader_from_cache(shader->device, type, shader->fs); - cso_set_fragment_shader_handle(shader->device->cso, shader->fs); + fs = shader_from_cache(shader->device, type, shader->fs); + cso_set_fragment_shader_handle(shader->device->cso, fs); } static INLINE void @@ -553,6 +557,19 @@ gallium_surface_release_source_image (void *abstract_surface, } } +static void +_gallium_set_states(void *abstract_surface) +{ + gallium_surface_t *surface = abstract_surface; + gallium_device_t *device = gallium_device (surface); + + cso_set_framebuffer (device->cso, &device->framebuffer); + cso_set_blend (device->cso, &surface->blend); + cso_set_depth_stencil_alpha (device->cso, &surface->depthstencil); + cso_set_rasterizer (device->cso, &surface->rasterizer); + cso_set_viewport (device->cso, &device->viewport); +} + static cairo_status_t gallium_surface_flush (void *abstract_surface) { @@ -560,29 +577,10 @@ gallium_surface_flush (void *abstract_surface) gallium_device_t *device = gallium_device (surface); cairo_status_t status; - printf("fudeo"); - - { - cso_set_framebuffer (device->cso, &device->framebuffer); - cso_set_blend (device->cso, &surface->blend); - cso_set_depth_stencil_alpha (device->cso, &surface->depthstencil); - cso_set_rasterizer (device->cso, &surface->rasterizer); - cso_set_viewport (device->cso, &device->viewport); - - cso_set_vertex_elements (device->cso, 2, surface->velem); - - util_draw_vertex_buffer (device->pipe, - surface->vbuf, 0, - PIPE_PRIM_QUADS, - 4, - 2); - } - if (surface->fallback == NULL) { device->pipe->flush (device->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - printf("flush\n"); return CAIRO_STATUS_SUCCESS; } @@ -599,22 +597,41 @@ gallium_surface_flush (void *abstract_surface) cairo_device_release (&device->drm.base); } - printf("flushing"); - status = cairo_surface_status (surface->fallback); cairo_surface_destroy (surface->fallback); surface->fallback = NULL; - debug_dump_surface_bmp(device->pipe, "result.bmp", device->framebuffer.cbufs[0]); - return status; } -#define MIN_POINTS 10 +static void +_gallium_surface_paint_get_solid(gallium_surface_t *surface, const cairo_pattern_t *pattern) +{ + cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; + + surface->paint.solid_color[0] = solid->color.red; + surface->paint.solid_color[1] = solid->color.green; + surface->paint.solid_color[2] = solid->color.blue; + surface->paint.solid_color[3] = solid->color.alpha; +} + + +static cairo_status_t +_gallium_surface_paint_solid (gallium_surface_t *surface, + const cairo_pattern_t *pattern, + gallium_shader_t *shader) +{ + _gallium_surface_paint_get_solid(surface, pattern); + setup_constant_buffer(shader, &surface->paint.solid_color[0], 4*sizeof(float)); + setup_shader(shader, SOLID_FILL); + return CAIRO_STATUS_SUCCESS; +} + +#define MIN_POINTS 50 -typedef struct _gallium_path { +struct _gallium_path { cairo_matrix_t *ctm_inverse; - double *points; + float *points; int count; float minx; @@ -625,22 +642,19 @@ typedef struct _gallium_path { float width; struct pipe_resource *buf; -} gallium_path_t; +}; -static cairo_status_t -_gallium_init_path (gallium_path_t *path) +static gallium_path_t * +_gallium_init_path () { - cairo_status_t status = CAIRO_STATUS_SUCCESS; - + gallium_path_t *path = NULL; 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); + path->points = (float *) malloc(sizeof(float) * MIN_POINTS * 2); if (path->points == NULL) { - status = CAIRO_STATUS_NO_MEMORY; goto CLEAN; } path->count = 0; @@ -648,7 +662,7 @@ _gallium_init_path (gallium_path_t *path) path->minx = path->miny = path->maxx = path->maxy = 0; CLEAN: - return status; + return path; } static cairo_status_t @@ -666,13 +680,13 @@ _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)); + float *new_points = (float *) malloc (sizeof(float) * (path->count + 2)); if (new_points == NULL) { status = CAIRO_STATUS_NO_MEMORY; goto CLEAN; } - memcpy(new_points, path->points, path->count * 2 * sizeof(double)); + memcpy(new_points, path->points, path->count * sizeof(float)); free(path->points); path->points = new_points; } @@ -680,41 +694,41 @@ _gallium_append_point (gallium_path_t *path, const cairo_point_t *point) path->points[path->count] = _cairo_fixed_to_double (point->x); path->points[path->count + 1] = _cairo_fixed_to_double (point->y); - path->count += 2; - path->minx = MIN2(path->points[path->count], path->minx); path->maxx = MAX2(path->points[path->count], path->maxx); path->miny = MIN2(path->points[path->count + 1], path->miny); path->maxy = MAX2(path->points[path->count + 1], path->maxy); + path->count += 2; + CLEAN: return status; } static void -draw_path (gallium_device_t *device, +draw_path (gallium_surface_t *surface, gallium_path_t *path) { const int components = 2; + gallium_device_t *device= gallium_device(surface); struct pipe_context *ctx = device->pipe; - gallium_surface_t *surface = gallium_device(device); struct pipe_vertex_buffer vbuffer; struct pipe_vertex_element velement; struct pipe_rasterizer_state rasterizer; - int vert_size = components * path->count * sizeof(float); + int vert_size = path->count * sizeof(float); + int num_vert = path->count * 0.5; - path->buf= pipe_user_buffer_create(ctx->screen, - path->points, - vert_size, - PIPE_BIND_VERTEX_BUFFER); + 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); 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; + vbuffer.max_index = num_vert - 1; ctx->set_vertex_buffers(ctx, 1, &vbuffer); memset(&velement, 0, sizeof(velement)); @@ -724,14 +738,16 @@ draw_path (gallium_device_t *device, velement.src_format = PIPE_FORMAT_R32G32_FLOAT; cso_set_vertex_elements(device->cso, 1, &velement); + _gallium_set_states(surface); + memset(&rasterizer, &surface->rasterizer, sizeof(struct pipe_rasterizer_state)); rasterizer.line_width = path->width; cso_save_rasterizer(device->cso); cso_set_rasterizer(device->cso, &rasterizer); - ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLE_FAN, - 0, path->count); + ctx->draw_arrays(ctx, PIPE_PRIM_LINE_STRIP, + 0, num_vert); cso_restore_rasterizer(device->cso); } @@ -747,31 +763,30 @@ _gallium_draw_quad(gallium_surface_t *surface, float vertices[4][2][4] = { { { x0, y0, 0.0f, 1.0f }, - { 0.0f, 0.0f, 0.0f, 1.0f } + { 0.0f, 0.0f, 0.0f, 1.0f} }, { - { x0, y1, 0.0f, 1.0f }, + { x0, y0 + y1, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, { - { x1, y1, 0.0f, 1.0f }, + { x0 + x1, y0 + y1, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } }, { - { x0, 0.0f, 0.0f, 1.0f }, + { x0 + x1, y0, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } } - }; + }; buf = pipe_user_buffer_create (device->pipe->screen, vertices, sizeof(vertices), PIPE_BIND_VERTEX_BUFFER); - if (buf != NULL) { cso_set_vertex_elements (device->cso, 2, surface->velem); util_draw_vertex_buffer (device->pipe, buf, 0, - PIPE_PRIM_TRIANGLE_FAN, + PIPE_PRIM_QUADS, 4, 2); @@ -783,21 +798,24 @@ static cairo_status_t _gallium_move_to_line_to (void *closure, const cairo_point_t *point) { gallium_path_t *path = closure; + printf("line to\n"); - if (path->ctm_inverse) - cairo_matrix_transform_point (path->ctm_inverse, point->x, point->y); + //if (path->ctm_inverse) + // cairo_matrix_transform_point (path->ctm_inverse, point->x, point->y); _gallium_append_point(path, point); return CAIRO_STATUS_SUCCESS; } +//XXX:make it works static cairo_status_t _gallium_close_path (void *closure) { cairo_status_t status = CAIRO_STATUS_NO_MEMORY; gallium_path_t *path = closure; + printf("close path\n"); if (path->count != 0) { cairo_point_t close_point_path; close_point_path.x = path->points[0]; @@ -852,7 +870,7 @@ _gallium_path_from_cairo (gallium_path_t *gallium_path, const cairo_path_fixed_t _gallium_move_to_line_to, _gallium_move_to_line_to, _gallium_curve_to, - 0, + _gallium_close_path, gallium_path); assert (status == CAIRO_STATUS_SUCCESS); @@ -869,7 +887,7 @@ _gallium_surface_clip (gallium_surface_t *abstract_surface, struct pipe_depth_stencil_alpha_state st; struct pipe_scissor_state scissor; - _gallium_init_path(gallium_path); + gallium_path = _gallium_init_path(); _gallium_path_from_cairo(gallium_path, &clip->path->path); st.depth.writemask = 1; @@ -893,17 +911,6 @@ _gallium_surface_clip (gallium_surface_t *abstract_surface, return CAIRO_STATUS_SUCCESS; } -static void -_gallium_surface_paint_solid(gallium_surface_t *surface, const cairo_pattern_t *pattern) -{ - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *)pattern; - - surface->paint.solid_color[0] = solid->color.red; - surface->paint.solid_color[1] = solid->color.green; - surface->paint.solid_color[2] = solid->color.blue; - surface->paint.solid_color[3] = solid->color.alpha; -} - static cairo_int_status_t gallium_surface_paint (void *abstract_surface, cairo_operator_t op, @@ -911,6 +918,7 @@ gallium_surface_paint (void *abstract_surface, 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; @@ -924,14 +932,21 @@ gallium_surface_paint (void *abstract_surface, return status; if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - _gallium_surface_paint_solid(surface, source); - setup_constant_buffer(shader, &surface->paint.solid_color[0], 4*sizeof(float)); - setup_shader(shader, SOLID_FILL); - status = CAIRO_STATUS_SUCCESS; + 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; @@ -974,13 +989,14 @@ gallium_surface_stroke (void *abstract_surface, gallium_surface_t *surface = abstract_surface; gallium_path_t *gallium_path; 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_init_path(gallium_path); + gallium_path = _gallium_init_path(); gallium_path->ctm_inverse = ctm_inverse; @@ -988,9 +1004,15 @@ gallium_surface_stroke (void *abstract_surface, gallium_path->width = style->line_width; - draw_path(device, gallium_path); + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + _gallium_surface_paint_solid(abstract_surface, source, shader); + } + + draw_path(abstract_surface, gallium_path); _gallium_finish_path(gallium_path); + gallium_surface_flush(abstract_surface); + return status; } @@ -1008,38 +1030,98 @@ gallium_surface_fill (void *abstract_surface, gallium_surface_t *surface = abstract_surface; gallium_path_t *gallium_path; 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; - _gallium_init_path(gallium_path); + if (source->type == CAIRO_PATTERN_TYPE_SOLID) { + _gallium_surface_paint_solid(abstract_surface, source, shader); + } + + _gallium_set_states(abstract_surface); + + gallium_path = _gallium_init_path(); _gallium_path_from_cairo(gallium_path, path); + struct pipe_surface *zsurface; + struct pipe_resource *resource; + { + struct pipe_resource template; + memset(&template, 0, sizeof(template)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_A8R8G8B8_UNORM; + template.width0 = surface->drm.width; + template.height0 = surface->drm.height; + template.depth0 = 1; + template.last_level = 0; + template.bind = PIPE_BIND_RENDER_TARGET; + resource = device->screen->resource_create (device->screen, + &template); + + zsurface = device->screen->get_tex_surface(device->pipe->screen, + resource, + 0, 0, 0, + PIPE_BIND_DEPTH_STENCIL); + + } + + device->framebuffer.zsbuf = zsurface; + _gallium_set_states(abstract_surface); + + { + cso_save_blend(device->cso); + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.rt[0].colormask = PIPE_MASK_R; /*disable colorwrites*/ + + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + + cso_set_blend(device->cso, &blend); + } + memset(&sr, 0, sizeof(struct pipe_stencil_ref)); + cso_set_stencil_ref(device->cso, &sr); + + device->pipe->clear(device->pipe, PIPE_CLEAR_STENCIL, NULL, 0.0, 0); + // initialize stencil + st.depth.enabled = 1; st.stencil[0].enabled = 1; st.stencil[0].func = PIPE_FUNC_ALWAYS; st.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; st.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; st.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; st.stencil[0].valuemask = 1; + st.stencil[0].writemask = 1; cso_set_depth_stencil_alpha(device->cso, &st); - draw_path(device, gallium_path); + draw_path(abstract_surface, gallium_path); + st.depth.enabled = 0; st.stencil[0].func = PIPE_FUNC_EQUAL; st.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; st.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; st.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP; st.stencil[0].valuemask = 1; cso_set_depth_stencil_alpha(device->cso, &st); + cso_restore_blend(device->cso); _gallium_draw_quad(surface, gallium_path->minx, gallium_path->miny, gallium_path->maxx, gallium_path->maxy); _gallium_finish_path(gallium_path); + + gallium_surface_flush(abstract_surface); cso_restore_depth_stencil_alpha(device->cso); + printf("filling"); + + return status; } static cairo_int_status_t @@ -1209,7 +1291,7 @@ gallium_surface_create_internal (gallium_device_t *device, { { 1.0f, 0.0f, 0.0f, 1.0f }, { 0.0f, 0.0f, 0.0f, 1.0f } - } + } }; surface->vbuf = pipe_buffer_create(device->pipe->screen, PIPE_BIND_CONSTANT_BUFFER, sizeof(vertices)); @@ -1449,7 +1531,7 @@ _cairo_drm_gallium_device_create (int fd, dev_t dev, int vendor_id, int chip_id) //device->drm.surface.flink = gallium_surface_flink; device->drm.surface.flink = NULL; - device->drm.device.flush = NULL; + device->drm.device.flush = gallium_surface_flush; device->drm.device.throttle = NULL; device->drm.device.destroy = gallium_device_destroy; -- cgit v1.2.3