diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-31 12:40:21 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-31 14:26:27 +0000 |
commit | fff0686342f8ec3b3f3510340e073defdf2fb73f (patch) | |
tree | 6eeef2c780a2cbb1a962b76bdde619f256b62baf /src | |
parent | 839542d219bd919c99398d514c1d194d18b78eff (diff) |
sna/traps: Thread the fallback rectilinear compositor
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src')
-rw-r--r-- | src/sna/sna_trapezoids.c | 185 |
1 files changed, 147 insertions, 38 deletions
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c index 64c23d4c..547e4f53 100644 --- a/src/sna/sna_trapezoids.c +++ b/src/sna/sna_trapezoids.c @@ -69,6 +69,9 @@ #define FAST_SAMPLES_Y (1<<FAST_SAMPLES_shift) #define FAST_SAMPLES_mask ((1<<FAST_SAMPLES_shift)-1) +#define region_count(r) ((r)->data ? (r)->data->numRects : 1) +#define region_boxes(r) ((r)->data ? (BoxPtr)((r)->data + 1) : &(r)->extents) + typedef void (*span_func_t)(struct sna *sna, struct sna_composite_spans_op *op, pixman_region16_t *clip, @@ -3643,7 +3646,7 @@ pixmask_opacity(struct pixman_inplace *pi, static void pixmask_unaligned_box_row(struct pixman_inplace *pi, const BoxRec *extents, - xTrapezoid *trap, + const xTrapezoid *trap, int16_t y, int16_t h, uint8_t covered) { @@ -3674,6 +3677,72 @@ pixmask_unaligned_box_row(struct pixman_inplace *pi, } } +struct rectilinear_inplace_thread { + pixman_image_t *dst, *src; + const RegionRec *clip; + const xTrapezoid *trap; + int dx, dy, sx, sy; + int y1, y2; + CARD8 op; +}; + +static void rectilinear_inplace_thread(void *arg) +{ + struct rectilinear_inplace_thread *thread = arg; + const xTrapezoid *t = thread->trap; + struct pixman_inplace pi; + const BoxRec *extents; + int count; + + pi.image = thread->dst; + pi.dx = thread->dx; + pi.dy = thread->dy; + + pi.source = thread->src; + pi.sx = thread->sx; + pi.sy = thread->sy; + + pi.mask = pixman_image_create_bits(PIXMAN_a8, 1, 1, &pi.color, 4); + pixman_image_set_repeat(pi.mask, PIXMAN_REPEAT_NORMAL); + pi.bits = pixman_image_get_data(pi.mask); + pi.op = thread->op; + + count = region_count(thread->clip); + extents = region_boxes(thread->clip); + while (count--) { + int16_t y1 = pixman_fixed_to_int(t->top); + uint16_t fy1 = pixman_fixed_frac(t->top); + int16_t y2 = pixman_fixed_to_int(t->bottom); + uint16_t fy2 = pixman_fixed_frac(t->bottom); + + if (y1 < MAX(thread->y1, extents->y1)) + y1 = MAX(thread->y1, extents->y1), fy1 = 0; + if (y2 > MIN(thread->y2, extents->y2)) + y2 = MIN(thread->y2, extents->y2), fy2 = 0; + if (y1 < y2) { + if (fy1) { + pixmask_unaligned_box_row(&pi, extents, t, y1, 1, + SAMPLES_Y - grid_coverage(SAMPLES_Y, fy1)); + y1++; + } + + if (y2 > y1) + pixmask_unaligned_box_row(&pi, extents, t, y1, y2 - y1, + SAMPLES_Y); + + if (fy2) + pixmask_unaligned_box_row(&pi, extents, t, y2, 1, + grid_coverage(SAMPLES_Y, fy2)); + } else if (y1 == y2 && fy2 > fy1) { + pixmask_unaligned_box_row(&pi, extents, t, y1, 1, + grid_coverage(SAMPLES_Y, fy2) - grid_coverage(SAMPLES_Y, fy1)); + } + extents++; + } + + pixman_image_unref(pi.mask); +} + static bool composite_unaligned_boxes_inplace(CARD8 op, PicturePtr src, int16_t src_x, int16_t src_y, @@ -3691,10 +3760,10 @@ composite_unaligned_boxes_inplace(CARD8 op, src_x -= pixman_fixed_to_int(t[0].left.p1.x); src_y -= pixman_fixed_to_int(t[0].left.p1.y); do { - struct pixman_inplace pi; RegionRec clip; BoxPtr extents; int count; + int num_threads; clip.extents.x1 = pixman_fixed_to_int(t->left.p1.x); clip.extents.x2 = pixman_fixed_to_int(t->right.p1.x + pixman_fixed_1_minus_e); @@ -3733,52 +3802,92 @@ composite_unaligned_boxes_inplace(CARD8 op, } } - pi.image = image_from_pict(dst, false, &pi.dx, &pi.dy); - pi.source = image_from_pict(src, false, &pi.sx, &pi.sy); - pi.sx += src_x; - pi.sy += src_y; - pi.mask = pixman_image_create_bits(PIXMAN_a8, 1, 1, NULL, 0); - pixman_image_set_repeat(pi.mask, PIXMAN_REPEAT_NORMAL); - pi.bits = pixman_image_get_data(pi.mask); - pi.op = op; + num_threads = sna_use_threads(clip.extents.x2 - clip.extents.x1, + clip.extents.y2 - clip.extents.y1, + 32); + if (num_threads == 1) { + struct pixman_inplace pi; - count = REGION_NUM_RECTS(&clip); - extents = REGION_RECTS(&clip); - while (count--) { - int16_t y1 = pixman_fixed_to_int(t->top); - uint16_t fy1 = pixman_fixed_frac(t->top); - int16_t y2 = pixman_fixed_to_int(t->bottom); - uint16_t fy2 = pixman_fixed_frac(t->bottom); + pi.image = image_from_pict(dst, false, &pi.dx, &pi.dy); + pi.source = image_from_pict(src, false, &pi.sx, &pi.sy); + pi.sx += src_x; + pi.sy += src_y; + pi.mask = pixman_image_create_bits(PIXMAN_a8, 1, 1, &pi.color, 4); + pixman_image_set_repeat(pi.mask, PIXMAN_REPEAT_NORMAL); + pi.bits = pixman_image_get_data(pi.mask); + pi.op = op; - if (y1 < extents->y1) - y1 = extents->y1, fy1 = 0; - if (y2 > extents->y2) - y2 = extents->y2, fy2 = 0; - if (y1 < y2) { - if (fy1) { + count = REGION_NUM_RECTS(&clip); + extents = REGION_RECTS(&clip); + while (count--) { + int16_t y1 = pixman_fixed_to_int(t->top); + uint16_t fy1 = pixman_fixed_frac(t->top); + int16_t y2 = pixman_fixed_to_int(t->bottom); + uint16_t fy2 = pixman_fixed_frac(t->bottom); + + if (y1 < extents->y1) + y1 = extents->y1, fy1 = 0; + if (y2 > extents->y2) + y2 = extents->y2, fy2 = 0; + if (y1 < y2) { + if (fy1) { + pixmask_unaligned_box_row(&pi, extents, t, y1, 1, + SAMPLES_Y - grid_coverage(SAMPLES_Y, fy1)); + y1++; + } + + if (y2 > y1) + pixmask_unaligned_box_row(&pi, extents, t, y1, y2 - y1, + SAMPLES_Y); + + if (fy2) + pixmask_unaligned_box_row(&pi, extents, t, y2, 1, + grid_coverage(SAMPLES_Y, fy2)); + } else if (y1 == y2 && fy2 > fy1) { pixmask_unaligned_box_row(&pi, extents, t, y1, 1, - SAMPLES_Y - grid_coverage(SAMPLES_Y, fy1)); - y1++; + grid_coverage(SAMPLES_Y, fy2) - grid_coverage(SAMPLES_Y, fy1)); } + extents++; + } - if (y2 > y1) - pixmask_unaligned_box_row(&pi, extents, t, y1, y2 - y1, - SAMPLES_Y); + pixman_image_unref(pi.image); + pixman_image_unref(pi.source); + pixman_image_unref(pi.mask); + } else { + struct rectilinear_inplace_thread thread[num_threads]; + int i, y, dy; - if (fy2) - pixmask_unaligned_box_row(&pi, extents, t, y2, 1, - grid_coverage(SAMPLES_Y, fy2)); - } else if (y1 == y2 && fy2 > fy1) { - pixmask_unaligned_box_row(&pi, extents, t, y1, 1, - grid_coverage(SAMPLES_Y, fy2) - grid_coverage(SAMPLES_Y, fy1)); + + thread[0].trap = t; + thread[0].dst = image_from_pict(dst, false, &thread[0].dx, &thread[0].dy); + thread[0].src = image_from_pict(src, false, &thread[0].sx, &thread[0].sy); + thread[0].sx += src_x; + thread[0].sy += src_y; + + thread[0].clip = &clip; + thread[0].op = op; + + y = clip.extents.y1; + dy = (clip.extents.y2 - clip.extents.y1 + num_threads - 1) / num_threads; + + for (i = 1; i < num_threads; i++) { + thread[i] = thread[0]; + thread[i].y1 = y; + thread[i].y2 = y += dy; + sna_threads_run(rectilinear_inplace_thread, &thread[i]); } - extents++; + + thread[0].y1 = y; + thread[0].y2 = clip.extents.y2; + rectilinear_inplace_thread(&thread[0]); + + sna_threads_wait(); + + pixman_image_unref(thread[0].dst); + pixman_image_unref(thread[0].src); } RegionUninit(&clip); - pixman_image_unref(pi.image); - pixman_image_unref(pi.source); - pixman_image_unref(pi.mask); } while (--n && t++); return true; |