diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-20 19:24:33 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-21 14:25:01 +0100 |
commit | cae4f4af2a0174ef36b9292eef7b9cf57afbfe83 (patch) | |
tree | 71789681604a04074c87095e1d51bd2a98070361 | |
parent | 12fc6687949c299d8c13751663217e7b37be7e43 (diff) |
sna/trapezoids: Thread tristrip rasterisation
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_trapezoids_imprecise.c | 193 |
1 files changed, 156 insertions, 37 deletions
diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c index 47adf5ab..b670ca55 100644 --- a/src/sna/sna_trapezoids_imprecise.c +++ b/src/sna/sna_trapezoids_imprecise.c @@ -600,6 +600,8 @@ polygon_add_line(struct polygon *polygon, if (e->height_left <= 0) return; + __DBG(("%s: edge height=%d\n", __FUNCTION__, e->dir * e->height_left)); + if (dx == 0) { e->x.quo = p1->x; e->x.rem = -dy; @@ -740,7 +742,7 @@ static struct edge *filter(struct edge *edges) struct edge *e; e = edges; - do { + while (e->next) { struct edge *n = e->next; if (e->dir == -n->dir && e->height_left == n->height_left && @@ -754,11 +756,10 @@ static struct edge *filter(struct edge *edges) n->next->prev = e->prev; else break; - e = n->next; } else - e = e->next; - } while (e->next); + e = n; + } return edges; } @@ -809,6 +810,7 @@ fill_buckets(struct active_list *active, while (edge) { struct edge *next = edge->next; struct edge **b = &buckets[edge->ytop & (FAST_SAMPLES_Y-1)]; + __DBG(("%s: ytop %d -> bucket %d\n", __FUNCTION__, edge->ytop, edge->ytop & (FAST_SAMPLES_Y-1))); if (*b) (*b)->prev = edge; edge->next = *b; @@ -1097,9 +1099,9 @@ tor_blt(struct sna *sna, assert(x >= converter->extents.x1); assert(x < converter->extents.x2); - __DBG(("%s: cell=(%d, %d, %d), cover=%d, max=%d\n", __FUNCTION__, + __DBG(("%s: cell=(%d, %d, %d), cover=%d\n", __FUNCTION__, cell->x, cell->covered_height, cell->uncovered_area, - cover, xmax)); + cover)); if (cell->covered_height || cell->uncovered_area) { box.x2 = x; @@ -1192,9 +1194,9 @@ tor_render(struct sna *sna, do_full_step = can_full_step(active); } - __DBG(("%s: y=%d [%d], do_full_step=%d, new edges=%d, min_height=%d, vertical=%d\n", + __DBG(("%s: y=%d-%d, do_full_step=%d, new edges=%d\n", __FUNCTION__, - i, i+ymin, do_full_step, + i, j, do_full_step, polygon->y_buckets[i] != NULL)); if (do_full_step) { nonzero_row(active, coverages); @@ -3541,6 +3543,11 @@ project_point_onto_grid(const xPointFixed *in, { out->x = dx + pixman_fixed_to_fast(in->x); out->y = dy + pixman_fixed_to_fast(in->y); + __DBG(("%s: (%f, %f) -> (%d, %d)\n", + __FUNCTION__, + pixman_fixed_to_double(in->x), + pixman_fixed_to_double(in->y), + out->x, out->y)); } #if HAS_PIXMAN_TRIANGLES @@ -3805,6 +3812,68 @@ triangles_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst, return true; } +struct tristrip_thread { + struct sna *sna; + const struct sna_composite_spans_op *op; + const xPointFixed *points; + RegionPtr clip; + span_func_t span; + BoxRec extents; + int dx, dy, draw_y; + int count; + bool unbounded; +}; + +static void +tristrip_thread(void *arg) +{ + struct tristrip_thread *thread = arg; + struct span_thread_boxes boxes; + struct tor tor; + xPointFixed p[4]; + int n, cw, ccw; + + if (!tor_init(&tor, &thread->extents, 2*thread->count)) + return; + + boxes.op = thread->op; + boxes.num_boxes = 0; + + cw = ccw = 0; + project_point_onto_grid(&thread->points[0], thread->dx, thread->dy, &p[cw]); + project_point_onto_grid(&thread->points[1], thread->dx, thread->dy, &p[2+ccw]); + polygon_add_line(tor.polygon, &p[2+ccw], &p[cw]); + n = 2; + do { + cw = !cw; + project_point_onto_grid(&thread->points[n], thread->dx, thread->dy, &p[cw]); + polygon_add_line(tor.polygon, &p[!cw], &p[cw]); + if (++n == thread->count) + break; + + ccw = !ccw; + project_point_onto_grid(&thread->points[n], thread->dx, thread->dy, &p[2+ccw]); + polygon_add_line(tor.polygon, &p[2+ccw], &p[2+!ccw]); + if (++n == thread->count) + break; + } while (1); + polygon_add_line(tor.polygon, &p[cw], &p[2+ccw]); + assert(tor.polygon->num_edges <= 2*thread->count); + + tor_render(thread->sna, &tor, + (struct sna_composite_spans_op *)&boxes, thread->clip, + thread->span, thread->unbounded); + + tor_fini(&tor); + + if (boxes.num_boxes) { + DBG(("%s: flushing %d boxes\n", __FUNCTION__, boxes.num_boxes)); + assert(boxes.num_boxes <= SPAN_THREAD_MAX_BOXES); + thread->op->thread_boxes(thread->sna, thread->op, + boxes.boxes, boxes.num_boxes); + } +} + bool tristrip_span_converter(struct sna *sna, CARD8 op, PicturePtr src, PicturePtr dst, @@ -3812,13 +3881,10 @@ tristrip_span_converter(struct sna *sna, int count, xPointFixed *points) { struct sna_composite_spans_op tmp; - struct tor tor; BoxRec extents; pixman_region16_t clip; - xPointFixed p[4]; int16_t dst_x, dst_y; - int dx, dy; - int cw, ccw, n; + int dx, dy, num_threads; bool was_clear; if (NO_SCAN_CONVERTER) @@ -3907,35 +3973,88 @@ tristrip_span_converter(struct sna *sna, dx *= FAST_SAMPLES_X; dy *= FAST_SAMPLES_Y; - if (!tor_init(&tor, &extents, 2*count)) - goto skip; - cw = ccw = 0; - project_point_onto_grid(&points[0], dx, dy, &p[cw]); - project_point_onto_grid(&points[1], dx, dy, &p[2+ccw]); - polygon_add_line(tor.polygon, &p[cw], &p[2+ccw]); - n = 2; - do { - cw = !cw; - project_point_onto_grid(&points[n], dx, dy, &p[cw]); - polygon_add_line(tor.polygon, &p[!cw], &p[cw]); - if (++n == count) - break; + num_threads = 1; + if (!NO_GPU_THREADS && + tmp.thread_boxes && + thread_choose_span(&tmp, dst, maskFormat, &clip)) + num_threads = sna_use_threads(extents.x2 - extents.x1, + extents.y2 - extents.y1, + 16); + if (num_threads == 1) { + struct tor tor; + xPointFixed p[4]; + int cw, ccw, n; - ccw = !ccw; - project_point_onto_grid(&points[n], dx, dy, &p[2+ccw]); - polygon_add_line(tor.polygon, &p[2+ccw], &p[2+!ccw]); - if (++n == count) - break; - } while (1); - polygon_add_line(tor.polygon, &p[2+ccw], &p[cw]); - assert(tor.polygon->num_edges <= 2*count); + if (!tor_init(&tor, &extents, 2*count)) + goto skip; - tor_render(sna, &tor, &tmp, &clip, - choose_span(&tmp, dst, maskFormat, &clip), - !was_clear && maskFormat && !operator_is_bounded(op)); + cw = ccw = 0; + project_point_onto_grid(&points[0], dx, dy, &p[cw]); + project_point_onto_grid(&points[1], dx, dy, &p[2+ccw]); + polygon_add_line(tor.polygon, &p[2+ccw], &p[cw]); + n = 2; + do { + cw = !cw; + project_point_onto_grid(&points[n], dx, dy, &p[cw]); + polygon_add_line(tor.polygon, &p[!cw], &p[cw]); + if (++n == count) + break; - tor_fini(&tor); + ccw = !ccw; + project_point_onto_grid(&points[n], dx, dy, &p[2+ccw]); + polygon_add_line(tor.polygon, &p[2+ccw], &p[2+!ccw]); + if (++n == count) + break; + } while (1); + polygon_add_line(tor.polygon, &p[cw], &p[2+ccw]); + assert(tor.polygon->num_edges <= 2*count); + + tor_render(sna, &tor, &tmp, &clip, + choose_span(&tmp, dst, maskFormat, &clip), + !was_clear && maskFormat && !operator_is_bounded(op)); + + tor_fini(&tor); + } else { + struct tristrip_thread threads[num_threads]; + int y, h, n; + + DBG(("%s: using %d threads for tristrip compositing %dx%d\n", + __FUNCTION__, num_threads, + clip.extents.x2 - clip.extents.x1, + clip.extents.y2 - clip.extents.y1)); + + threads[0].sna = sna; + threads[0].op = &tmp; + threads[0].points = points; + threads[0].count = count; + threads[0].extents = clip.extents; + threads[0].clip = &clip; + threads[0].dx = dx; + threads[0].dy = dy; + threads[0].draw_y = dst->pDrawable->y; + threads[0].unbounded = !was_clear && maskFormat && !operator_is_bounded(op); + threads[0].span = thread_choose_span(&tmp, dst, maskFormat, &clip); + + y = clip.extents.y1; + h = clip.extents.y2 - clip.extents.y1; + h = (h + num_threads - 1) / num_threads; + num_threads -= (num_threads-1) * h >= clip.extents.y2 - clip.extents.y1; + + for (n = 1; n < num_threads; n++) { + threads[n] = threads[0]; + threads[n].extents.y1 = y; + threads[n].extents.y2 = y += h; + + sna_threads_run(n, tristrip_thread, &threads[n]); + } + + assert(y < threads[0].extents.y2); + threads[0].extents.y1 = y; + tristrip_thread(&threads[0]); + + sna_threads_wait(); + } skip: tmp.done(sna, &tmp); |