Bug 977880 - Handle ReleaseFence on tiled thebes layer r=cwiiis,nical,BenWa
[gecko.git] / gfx / cairo / clip-invariant.patch
blob08ba4d4deaf640fb45f9597fd340fa08453463fe
1 diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
2 index 2acc8b5..019249e 100644
3 --- a/src/cairo-gl-surface.c
4 +++ b/src/cairo-gl-surface.c
5 @@ -2012,13 +2012,14 @@ typedef struct _cairo_gl_surface_span_renderer {
7 cairo_gl_composite_setup_t setup;
9 + int xmin, xmax;
11 cairo_operator_t op;
12 cairo_antialias_t antialias;
14 cairo_gl_surface_t *dst;
15 cairo_region_t *clip;
17 - cairo_composite_rectangles_t composite_rectangles;
18 GLuint vbo;
19 void *vbo_base;
20 unsigned int vbo_size;
21 @@ -2049,11 +2050,11 @@ _cairo_gl_span_renderer_flush (cairo_gl_surface_span_renderer_t *renderer)
22 cairo_region_get_rectangle (renderer->clip, i, &rect);
24 glScissor (rect.x, rect.y, rect.width, rect.height);
25 - glDrawArrays (GL_LINES, 0, count);
26 + glDrawArrays (GL_QUADS, 0, count);
28 glDisable (GL_SCISSOR_TEST);
29 } else {
30 - glDrawArrays (GL_LINES, 0, count);
31 + glDrawArrays (GL_QUADS, 0, count);
35 @@ -2134,72 +2135,87 @@ _cairo_gl_emit_span_vertex (cairo_gl_surface_span_renderer_t *renderer,
37 static void
38 _cairo_gl_emit_span (cairo_gl_surface_span_renderer_t *renderer,
39 - int x1, int x2, int y, uint8_t alpha)
40 + int x, int y1, int y2,
41 + uint8_t alpha)
43 float *vertices = _cairo_gl_span_renderer_get_vbo (renderer, 2);
45 - _cairo_gl_emit_span_vertex (renderer, x1, y, alpha, vertices);
46 - _cairo_gl_emit_span_vertex (renderer, x2, y, alpha,
47 + _cairo_gl_emit_span_vertex (renderer, x, y1, alpha, vertices);
48 + _cairo_gl_emit_span_vertex (renderer, x, y2, alpha,
49 vertices + renderer->vertex_size / 4);
52 -/* Emits the contents of the span renderer rows as GL_LINES with the span's
53 - * alpha.
54 - *
55 - * Unlike the image surface, which is compositing into a temporary, we emit
56 - * coverage even for alpha == 0, in case we're using an unbounded operator.
57 - * But it means we avoid having to do the fixup.
58 - */
59 +static void
60 +_cairo_gl_emit_rectangle (cairo_gl_surface_span_renderer_t *renderer,
61 + int x1, int y1,
62 + int x2, int y2,
63 + int coverage)
65 + _cairo_gl_emit_span (renderer, x1, y1, y2, coverage);
66 + _cairo_gl_emit_span (renderer, x2, y2, y1, coverage);
69 static cairo_status_t
70 -_cairo_gl_surface_span_renderer_render_row (
71 - void *abstract_renderer,
72 - int y,
73 - const cairo_half_open_span_t *spans,
74 - unsigned num_spans)
75 +_cairo_gl_render_bounded_spans (void *abstract_renderer,
76 + int y, int height,
77 + const cairo_half_open_span_t *spans,
78 + unsigned num_spans)
80 cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
81 - int xmin = renderer->composite_rectangles.mask.x;
82 - int xmax = xmin + renderer->composite_rectangles.width;
83 - int prev_x = xmin;
84 - int prev_alpha = 0;
85 - unsigned i;
86 - int x_translate;
88 - /* Make sure we're within y-range. */
89 - if (y < renderer->composite_rectangles.mask.y ||
90 - y >= renderer->composite_rectangles.mask.y +
91 - renderer->composite_rectangles.height)
93 + if (num_spans == 0)
94 return CAIRO_STATUS_SUCCESS;
96 - x_translate = renderer->composite_rectangles.dst.x -
97 - renderer->composite_rectangles.mask.x;
98 - y += renderer->composite_rectangles.dst.y -
99 - renderer->composite_rectangles.mask.y;
100 + do {
101 + if (spans[0].coverage) {
102 + _cairo_gl_emit_rectangle (renderer,
103 + spans[0].x, y,
104 + spans[1].x, y + height,
105 + spans[0].coverage);
108 - /* Find the first span within x-range. */
109 - for (i=0; i < num_spans && spans[i].x < xmin; i++) {}
110 - if (i>0)
111 - prev_alpha = spans[i-1].coverage;
112 + spans++;
113 + } while (--num_spans > 1);
115 - /* Set the intermediate spans. */
116 - for (; i < num_spans; i++) {
117 - int x = spans[i].x;
118 + return CAIRO_STATUS_SUCCESS;
121 - if (x >= xmax)
122 - break;
123 +static cairo_status_t
124 +_cairo_gl_render_unbounded_spans (void *abstract_renderer,
125 + int y, int height,
126 + const cairo_half_open_span_t *spans,
127 + unsigned num_spans)
129 + cairo_gl_surface_span_renderer_t *renderer = abstract_renderer;
131 - _cairo_gl_emit_span (renderer,
132 - prev_x + x_translate, x + x_translate, y,
133 - prev_alpha);
134 + if (num_spans == 0) {
135 + _cairo_gl_emit_rectangle (renderer,
136 + renderer->xmin, y,
137 + renderer->xmax, y + height,
138 + 0);
139 + return CAIRO_STATUS_SUCCESS;
142 - prev_x = x;
143 - prev_alpha = spans[i].coverage;
144 + if (spans[0].x != renderer->xmin) {
145 + _cairo_gl_emit_rectangle (renderer,
146 + renderer->xmin, y,
147 + spans[0].x, y + height,
148 + 0);
151 - if (prev_x < xmax) {
152 - _cairo_gl_emit_span (renderer,
153 - prev_x + x_translate, xmax + x_translate, y,
154 - prev_alpha);
155 + do {
156 + _cairo_gl_emit_rectangle (renderer,
157 + spans[0].x, y,
158 + spans[1].x, y + height,
159 + spans[0].coverage);
160 + spans++;
161 + } while (--num_spans > 1);
163 + if (spans[0].x != renderer->xmax) {
164 + _cairo_gl_emit_rectangle (renderer,
165 + spans[0].x, y,
166 + renderer->xmax, y + height,
167 + 0);
170 return CAIRO_STATUS_SUCCESS;
171 @@ -2274,8 +2290,6 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
172 cairo_gl_surface_t *dst = abstract_dst;
173 cairo_gl_surface_span_renderer_t *renderer;
174 cairo_status_t status;
175 - int width = rects->width;
176 - int height = rects->height;
177 cairo_surface_attributes_t *src_attributes;
178 GLenum err;
180 diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
181 index 48d8013..d52979d 100644
182 --- a/src/cairo-image-surface.c
183 +++ b/src/cairo-image-surface.c
184 @@ -1390,11 +1390,13 @@ typedef struct _cairo_image_surface_span_renderer {
185 const cairo_pattern_t *pattern;
186 cairo_antialias_t antialias;
188 + uint8_t *mask_data;
189 + uint32_t mask_stride;
191 cairo_image_surface_t *src;
192 cairo_surface_attributes_t src_attributes;
193 cairo_image_surface_t *mask;
194 cairo_image_surface_t *dst;
196 cairo_composite_rectangles_t composite_rectangles;
197 } cairo_image_surface_span_renderer_t;
199 @@ -1403,66 +1405,46 @@ _cairo_image_surface_span_render_row (
200 int y,
201 const cairo_half_open_span_t *spans,
202 unsigned num_spans,
203 - cairo_image_surface_t *mask,
204 - const cairo_composite_rectangles_t *rects)
205 + uint8_t *data,
206 + uint32_t stride)
208 - int xmin = rects->mask.x;
209 - int xmax = xmin + rects->width;
210 uint8_t *row;
211 - int prev_x = xmin;
212 - int prev_alpha = 0;
213 unsigned i;
215 - /* Make sure we're within y-range. */
216 - y -= rects->mask.y;
217 - if (y < 0 || y >= rects->height)
218 + if (num_spans == 0)
219 return;
221 - row = (uint8_t*)(mask->data) + y*(size_t)mask->stride - xmin;
223 - /* Find the first span within x-range. */
224 - for (i=0; i < num_spans && spans[i].x < xmin; i++) {}
225 - if (i>0)
226 - prev_alpha = spans[i-1].coverage;
228 - /* Set the intermediate spans. */
229 - for (; i < num_spans; i++) {
230 - int x = spans[i].x;
232 - if (x >= xmax)
233 - break;
235 - if (prev_alpha != 0) {
236 - /* We implement setting rendering the most common single
237 - * pixel wide span case to avoid the overhead of a memset
238 - * call. Open coding setting longer spans didn't show a
239 - * noticeable improvement over memset. */
240 - if (x == prev_x + 1) {
241 - row[prev_x] = prev_alpha;
243 - else {
244 - memset(row + prev_x, prev_alpha, x - prev_x);
246 + row = data + y * stride;
247 + for (i = 0; i < num_spans - 1; i++) {
248 + if (! spans[i].coverage)
249 + continue;
251 + /* We implement setting the most common single pixel wide
252 + * span case to avoid the overhead of a memset call.
253 + * Open coding setting longer spans didn't show a
254 + * noticeable improvement over memset.
255 + */
256 + if (spans[i+1].x == spans[i].x + 1) {
257 + row[spans[i].x] = spans[i].coverage;
258 + } else {
259 + memset (row + spans[i].x,
260 + spans[i].coverage,
261 + spans[i+1].x - spans[i].x);
264 - prev_x = x;
265 - prev_alpha = spans[i].coverage;
268 - if (prev_alpha != 0 && prev_x < xmax) {
269 - memset(row + prev_x, prev_alpha, xmax - prev_x);
273 static cairo_status_t
274 -_cairo_image_surface_span_renderer_render_row (
275 +_cairo_image_surface_span_renderer_render_rows (
276 void *abstract_renderer,
277 int y,
278 + int height,
279 const cairo_half_open_span_t *spans,
280 unsigned num_spans)
282 cairo_image_surface_span_renderer_t *renderer = abstract_renderer;
283 - _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles);
284 + while (height--)
285 + _cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride);
286 return CAIRO_STATUS_SUCCESS;
289 @@ -1517,11 +1499,11 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
290 &dst->base,
291 src_attributes,
292 src->width, src->height,
293 - rects->width, rects->height,
294 + width, height,
295 rects->src.x, rects->src.y,
296 0, 0, /* mask.x, mask.y */
297 rects->dst.x, rects->dst.y,
298 - rects->width, rects->height,
299 + width, height,
300 dst->clip_region);
303 @@ -1567,7 +1549,7 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
305 renderer->base.destroy = _cairo_image_surface_span_renderer_destroy;
306 renderer->base.finish = _cairo_image_surface_span_renderer_finish;
307 - renderer->base.render_row = _cairo_image_surface_span_renderer_render_row;
308 + renderer->base.render_rows = _cairo_image_surface_span_renderer_render_rows;
309 renderer->op = op;
310 renderer->pattern = pattern;
311 renderer->antialias = antialias;
312 @@ -1604,6 +1586,9 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
313 _cairo_image_surface_span_renderer_destroy (renderer);
314 return _cairo_span_renderer_create_in_error (status);
317 + renderer->mask_data = renderer->mask->data - rects->mask.x - rects->mask.y * renderer->mask->stride;
318 + renderer->mask_stride = renderer->mask->stride;
319 return &renderer->base;
322 diff --git a/src/cairo-spans-private.h b/src/cairo-spans-private.h
323 index e29a567..af3b38c 100644
324 --- a/src/cairo-spans-private.h
325 +++ b/src/cairo-spans-private.h
326 @@ -47,26 +47,24 @@ typedef struct _cairo_half_open_span {
327 * surfaces if they want to composite spans instead of trapezoids. */
328 typedef struct _cairo_span_renderer cairo_span_renderer_t;
329 struct _cairo_span_renderer {
330 + /* Private status variable. */
331 + cairo_status_t status;
333 /* Called to destroy the renderer. */
334 cairo_destroy_func_t destroy;
336 - /* Render the spans on row y of the source by whatever compositing
337 - * method is required. The function should ignore spans outside
338 - * the bounding box set by the init() function. */
339 - cairo_status_t (*render_row)(
340 - void *abstract_renderer,
341 - int y,
342 - const cairo_half_open_span_t *coverages,
343 - unsigned num_coverages);
344 + /* Render the spans on row y of the destination by whatever compositing
345 + * method is required. */
346 + cairo_warn cairo_status_t
347 + (*render_rows) (void *abstract_renderer,
348 + int y, int height,
349 + const cairo_half_open_span_t *coverages,
350 + unsigned num_coverages);
352 /* Called after all rows have been rendered to perform whatever
353 * final rendering step is required. This function is called just
354 * once before the renderer is destroyed. */
355 - cairo_status_t (*finish)(
356 - void *abstract_renderer);
358 - /* Private status variable. */
359 - cairo_status_t status;
360 + cairo_status_t (*finish) (void *abstract_renderer);
363 /* Scan converter interface. */
364 diff --git a/src/cairo-spans.c b/src/cairo-spans.c
365 index af3b85f..69894c1 100644
366 --- a/src/cairo-spans.c
367 +++ b/src/cairo-spans.c
368 @@ -275,13 +275,15 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
371 static cairo_status_t
372 -_cairo_nil_span_renderer_render_row (
373 +_cairo_nil_span_renderer_render_rows (
374 void *abstract_renderer,
375 int y,
376 + int height,
377 const cairo_half_open_span_t *coverages,
378 unsigned num_coverages)
380 (void) y;
381 + (void) height;
382 (void) coverages;
383 (void) num_coverages;
384 return _cairo_span_renderer_status (abstract_renderer);
385 @@ -310,7 +312,7 @@ _cairo_span_renderer_set_error (
386 ASSERT_NOT_REACHED;
388 if (renderer->status == CAIRO_STATUS_SUCCESS) {
389 - renderer->render_row = _cairo_nil_span_renderer_render_row;
390 + renderer->render_rows = _cairo_nil_span_renderer_render_rows;
391 renderer->finish = _cairo_nil_span_renderer_finish;
392 renderer->status = error;
394 diff --git a/src/cairo-tor-scan-converter.c b/src/cairo-tor-scan-converter.c
395 index 29262c2..2b9fb1b 100644
396 --- a/src/cairo-tor-scan-converter.c
397 +++ b/src/cairo-tor-scan-converter.c
398 @@ -128,27 +128,29 @@ blit_with_span_renderer(
399 cairo_span_renderer_t *span_renderer,
400 struct pool *span_pool,
401 int y,
402 + int height,
403 int xmin,
404 int xmax);
406 static glitter_status_t
407 -blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y);
408 +blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height);
410 #define GLITTER_BLIT_COVERAGES_ARGS \
411 cairo_span_renderer_t *span_renderer, \
412 struct pool *span_pool
414 -#define GLITTER_BLIT_COVERAGES(cells, y, xmin, xmax) do { \
415 +#define GLITTER_BLIT_COVERAGES(cells, y, height,xmin, xmax) do { \
416 cairo_status_t status = blit_with_span_renderer (cells, \
417 span_renderer, \
418 span_pool, \
419 - y, xmin, xmax); \
420 + y, height, \
421 + xmin, xmax); \
422 if (unlikely (status)) \
423 return status; \
424 } while (0)
426 -#define GLITTER_BLIT_COVERAGES_EMPTY(y, xmin, xmax) do { \
427 - cairo_status_t status = blit_empty_with_span_renderer (span_renderer, y); \
428 +#define GLITTER_BLIT_COVERAGES_EMPTY(y, height, xmin, xmax) do { \
429 + cairo_status_t status = blit_empty_with_span_renderer (span_renderer, y, height); \
430 if (unlikely (status)) \
431 return status; \
432 } while (0)
433 @@ -309,8 +311,8 @@ typedef int grid_area_t;
434 #define UNROLL3(x) x x x
436 struct quorem {
437 - int quo;
438 - int rem;
439 + int32_t quo;
440 + int32_t rem;
443 /* Header for a chunk of memory in a memory pool. */
444 @@ -382,6 +384,7 @@ struct edge {
445 /* Original sign of the edge: +1 for downwards, -1 for upwards
446 * edges. */
447 int dir;
448 + int vertical;
451 /* Number of subsample rows per y-bucket. Must be GRID_Y. */
452 @@ -389,18 +392,28 @@ struct edge {
454 #define EDGE_Y_BUCKET_INDEX(y, ymin) (((y) - (ymin))/EDGE_Y_BUCKET_HEIGHT)
456 +struct bucket {
457 + /* Unsorted list of edges starting within this bucket. */
458 + struct edge *edges;
460 + /* Set to non-zero if there are edges starting strictly within the
461 + * bucket. */
462 + unsigned have_inside_edges;
465 /* A collection of sorted and vertically clipped edges of the polygon.
466 * Edges are moved from the polygon to an active list while scan
467 * converting. */
468 struct polygon {
469 - /* The vertical clip extents. */
470 + /* The clip extents. */
471 + grid_scaled_x_t xmin, xmax;
472 grid_scaled_y_t ymin, ymax;
474 /* Array of edges all starting in the same bucket. An edge is put
475 * into bucket EDGE_BUCKET_INDEX(edge->ytop, polygon->ymin) when
476 * it is added to the polygon. */
477 - struct edge **y_buckets;
478 - struct edge *y_buckets_embedded[64];
479 + struct bucket *y_buckets;
480 + struct bucket y_buckets_embedded[64];
482 struct {
483 struct pool base[1];
484 @@ -702,7 +715,6 @@ static void
485 cell_list_fini(struct cell_list *cells)
487 pool_fini (cells->cell_pool.base);
488 - cell_list_init (cells);
491 /* Empty the cell list. This is called at the start of every pixel
492 @@ -715,6 +727,26 @@ cell_list_reset (struct cell_list *cells)
493 pool_reset (cells->cell_pool.base);
496 +static struct cell *
497 +cell_list_alloc (struct cell_list *cells,
498 + struct cell **cursor,
499 + struct cell *tail,
500 + int x)
502 + struct cell *cell;
504 + cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell));
505 + if (unlikely (NULL == cell))
506 + return NULL;
508 + *cursor = cell;
509 + cell->next = tail;
510 + cell->x = x;
511 + cell->uncovered_area = 0;
512 + cell->covered_height = 0;
513 + return cell;
516 /* Find a cell at the given x-coordinate. Returns %NULL if a new cell
517 * needed to be allocated but couldn't be. Cells must be found with
518 * non-decreasing x-coordinate until the cell list is rewound using
519 @@ -737,22 +769,10 @@ cell_list_find (struct cell_list *cells, int x)
521 cells->cursor = cursor;
523 - if (tail->x == x) {
524 + if (tail->x == x)
525 return tail;
526 - } else {
527 - struct cell *cell;
529 - cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell));
530 - if (unlikely (NULL == cell))
531 - return NULL;
533 - *cursor = cell;
534 - cell->next = tail;
535 - cell->x = x;
536 - cell->uncovered_area = 0;
537 - cell->covered_height = 0;
538 - return cell;
540 + return cell_list_alloc (cells, cursor, tail, x);
543 /* Find two cells at x1 and x2. This is exactly equivalent
544 @@ -832,9 +852,8 @@ cell_list_find_pair(struct cell_list *cells, int x1, int x2)
545 /* Add an unbounded subpixel span covering subpixels >= x to the
546 * coverage cells. */
547 static glitter_status_t
548 -cell_list_add_unbounded_subspan(
549 - struct cell_list *cells,
550 - grid_scaled_x_t x)
551 +cell_list_add_unbounded_subspan (struct cell_list *cells,
552 + grid_scaled_x_t x)
554 struct cell *cell;
555 int ix, fx;
556 @@ -907,20 +926,24 @@ cell_list_render_edge(
557 struct edge *edge,
558 int sign)
560 - struct quorem x1 = edge->x;
561 - struct quorem x2 = x1;
562 grid_scaled_y_t y1, y2, dy;
563 grid_scaled_x_t dx;
564 int ix1, ix2;
565 grid_scaled_x_t fx1, fx2;
567 - x2.quo += edge->dxdy_full.quo;
568 - x2.rem += edge->dxdy_full.rem;
569 - if (x2.rem >= 0) {
570 - ++x2.quo;
571 - x2.rem -= edge->dy;
572 + struct quorem x1 = edge->x;
573 + struct quorem x2 = x1;
575 + if (! edge->vertical) {
576 + x2.quo += edge->dxdy_full.quo;
577 + x2.rem += edge->dxdy_full.rem;
578 + if (x2.rem >= 0) {
579 + ++x2.quo;
580 + x2.rem -= edge->dy;
583 + edge->x = x2;
585 - edge->x = x2;
587 GRID_X_TO_INT_FRAC(x1.quo, ix1, fx1);
588 GRID_X_TO_INT_FRAC(x2.quo, ix2, fx2);
589 @@ -1026,6 +1049,7 @@ static void
590 polygon_init (struct polygon *polygon)
592 polygon->ymin = polygon->ymax = 0;
593 + polygon->xmin = polygon->xmax = 0;
594 polygon->y_buckets = polygon->y_buckets_embedded;
595 pool_init (polygon->edge_pool.base,
596 8192 - sizeof (struct _pool_chunk),
597 @@ -1045,10 +1069,11 @@ polygon_fini (struct polygon *polygon)
598 * receive new edges and clip them to the vertical range
599 * [ymin,ymax). */
600 static glitter_status_t
601 -polygon_reset(
602 - struct polygon *polygon,
603 - grid_scaled_y_t ymin,
604 - grid_scaled_y_t ymax)
605 +polygon_reset (struct polygon *polygon,
606 + grid_scaled_x_t xmin,
607 + grid_scaled_x_t xmax,
608 + grid_scaled_y_t ymin,
609 + grid_scaled_y_t ymax)
611 unsigned h = ymax - ymin;
612 unsigned num_buckets = EDGE_Y_BUCKET_INDEX(ymax + EDGE_Y_BUCKET_HEIGHT-1,
613 @@ -1065,14 +1090,16 @@ polygon_reset(
614 polygon->y_buckets = polygon->y_buckets_embedded;
615 if (num_buckets > ARRAY_LENGTH (polygon->y_buckets_embedded)) {
616 polygon->y_buckets = _cairo_malloc_ab (num_buckets,
617 - sizeof (struct edge *));
618 + sizeof (struct bucket));
619 if (unlikely (NULL == polygon->y_buckets))
620 goto bail_no_mem;
622 - memset (polygon->y_buckets, 0, num_buckets * sizeof (struct edge *));
623 + memset (polygon->y_buckets, 0, num_buckets * sizeof (struct bucket));
625 polygon->ymin = ymin;
626 polygon->ymax = ymax;
627 + polygon->xmin = xmin;
628 + polygon->xmax = xmax;
629 return GLITTER_STATUS_SUCCESS;
631 bail_no_mem:
632 @@ -1086,10 +1113,13 @@ _polygon_insert_edge_into_its_y_bucket(
633 struct polygon *polygon,
634 struct edge *e)
636 - unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop, polygon->ymin);
637 - struct edge **ptail = &polygon->y_buckets[ix];
638 + unsigned j = e->ytop - polygon->ymin;
639 + unsigned ix = j / EDGE_Y_BUCKET_HEIGHT;
640 + unsigned offset = j % EDGE_Y_BUCKET_HEIGHT;
641 + struct edge **ptail = &polygon->y_buckets[ix].edges;
642 e->next = *ptail;
643 *ptail = e;
644 + polygon->y_buckets[ix].have_inside_edges |= offset;
647 inline static glitter_status_t
648 @@ -1115,30 +1145,53 @@ polygon_add_edge (struct polygon *polygon,
649 dx = edge->line.p2.x - edge->line.p1.x;
650 dy = edge->line.p2.y - edge->line.p1.y;
651 e->dy = dy;
652 - e->dxdy = floored_divrem (dx, dy);
654 - if (ymin <= edge->top)
655 - ytop = edge->top;
656 - else
657 - ytop = ymin;
658 - if (ytop == edge->line.p1.y) {
659 - e->x.quo = edge->line.p1.x;
660 - e->x.rem = 0;
661 - } else {
662 - e->x = floored_muldivrem (ytop - edge->line.p1.y, dx, dy);
663 - e->x.quo += edge->line.p1.x;
666 e->dir = edge->dir;
668 + ytop = edge->top >= ymin ? edge->top : ymin;
669 + ybot = edge->bottom <= ymax ? edge->bottom : ymax;
670 e->ytop = ytop;
671 - ybot = edge->bottom < ymax ? edge->bottom : ymax;
672 e->height_left = ybot - ytop;
674 - if (e->height_left >= GRID_Y) {
675 - e->dxdy_full = floored_muldivrem (GRID_Y, dx, dy);
676 - } else {
677 + if (dx == 0) {
678 + e->vertical = TRUE;
679 + e->x.quo = edge->line.p1.x;
680 + e->x.rem = 0;
681 + e->dxdy.quo = 0;
682 + e->dxdy.rem = 0;
683 e->dxdy_full.quo = 0;
684 e->dxdy_full.rem = 0;
686 + /* Drop edges to the right of the clip extents. */
687 + if (e->x.quo >= polygon->xmax)
688 + return GLITTER_STATUS_SUCCESS;
690 + /* Offset vertical edges at the left side of the clip extents
691 + * to just shy of the left side. We depend on this when
692 + * checking for possible intersections within the clip
693 + * rectangle. */
694 + if (e->x.quo <= polygon->xmin) {
695 + e->x.quo = polygon->xmin - 1;
697 + } else {
698 + e->vertical = FALSE;
699 + e->dxdy = floored_divrem (dx, dy);
700 + if (ytop == edge->line.p1.y) {
701 + e->x.quo = edge->line.p1.x;
702 + e->x.rem = 0;
703 + } else {
704 + e->x = floored_muldivrem (ytop - edge->line.p1.y, dx, dy);
705 + e->x.quo += edge->line.p1.x;
708 + if (e->x.quo >= polygon->xmax && e->dxdy.quo >= 0)
709 + return GLITTER_STATUS_SUCCESS;
711 + if (e->height_left >= GRID_Y) {
712 + e->dxdy_full = floored_muldivrem (GRID_Y, dx, dy);
713 + } else {
714 + e->dxdy_full.quo = 0;
715 + e->dxdy_full.rem = 0;
719 _polygon_insert_edge_into_its_y_bucket (polygon, e);
720 @@ -1161,31 +1214,30 @@ active_list_init(struct active_list *active)
721 active_list_reset(active);
724 -static void
725 -active_list_fini(
726 - struct active_list *active)
728 - active_list_reset(active);
731 /* Merge the edges in an unsorted list of edges into a sorted
732 * list. The sort order is edges ascending by edge->x.quo. Returns
733 * the new head of the sorted list. */
734 static struct edge *
735 merge_unsorted_edges(struct edge *sorted_head, struct edge *unsorted_head)
737 - struct edge *head = unsorted_head;
738 struct edge **cursor = &sorted_head;
739 int x;
741 - while (NULL != head) {
742 + if (sorted_head == NULL) {
743 + sorted_head = unsorted_head;
744 + unsorted_head = unsorted_head->next;
745 + sorted_head->next = NULL;
746 + if (unsorted_head == NULL)
747 + return sorted_head;
750 + do {
751 + struct edge *next = unsorted_head->next;
752 struct edge *prev = *cursor;
753 - struct edge *next = head->next;
754 - x = head->x.quo;
756 - if (NULL == prev || x < prev->x.quo) {
757 + x = unsorted_head->x.quo;
758 + if (x < prev->x.quo)
759 cursor = &sorted_head;
762 while (1) {
763 UNROLL3({
764 @@ -1196,26 +1248,29 @@ merge_unsorted_edges(struct edge *sorted_head, struct edge *unsorted_head)
768 - head->next = *cursor;
769 - *cursor = head;
770 + unsorted_head->next = *cursor;
771 + *cursor = unsorted_head;
772 + unsorted_head = next;
773 + } while (unsorted_head != NULL);
775 - head = next;
777 return sorted_head;
780 /* Test if the edges on the active list can be safely advanced by a
781 * full row without intersections or any edges ending. */
782 inline static int
783 -active_list_can_step_full_row(
784 - struct active_list *active)
785 +active_list_can_step_full_row (struct active_list *active,
786 + grid_scaled_x_t xmin)
788 + const struct edge *e;
789 + grid_scaled_x_t prev_x = INT_MIN;
791 /* Recomputes the minimum height of all edges on the active
792 * list if we have been dropping edges. */
793 if (active->min_height <= 0) {
794 - struct edge *e = active->head;
795 int min_height = INT_MAX;
797 + e = active->head;
798 while (NULL != e) {
799 if (e->height_left < min_height)
800 min_height = e->height_left;
801 @@ -1225,27 +1280,38 @@ active_list_can_step_full_row(
802 active->min_height = min_height;
805 - /* Check for intersections only if no edges end during the next
806 - * row. */
807 - if (active->min_height >= GRID_Y) {
808 - grid_scaled_x_t prev_x = INT_MIN;
809 - struct edge *e = active->head;
810 - while (NULL != e) {
811 - struct quorem x = e->x;
812 + if (active->min_height < GRID_Y)
813 + return 0;
815 + /* Check for intersections as no edges end during the next row. */
816 + e = active->head;
817 + while (NULL != e) {
818 + struct quorem x = e->x;
820 + if (! e->vertical) {
821 x.quo += e->dxdy_full.quo;
822 x.rem += e->dxdy_full.rem;
823 if (x.rem >= 0)
824 ++x.quo;
827 - if (x.quo <= prev_x)
828 + /* There's may be an intersection if the edge sort order might
829 + * change. */
830 + if (x.quo <= prev_x) {
831 + /* Ignore intersections to the left of the clip extents.
832 + * This assumes that all vertical edges on or at the left
833 + * side of the clip rectangle have been shifted slightly
834 + * to the left in polygon_add_edge(). */
835 + if (prev_x >= xmin || x.quo >= xmin || e->x.quo >= xmin)
836 return 0;
838 + else {
839 prev_x = x.quo;
840 - e = e->next;
842 - return 1;
843 + e = e->next;
845 - return 0;
847 + return 1;
850 /* Merges edges on the given subpixel row from the polygon to the
851 @@ -1261,7 +1327,7 @@ active_list_merge_edges_from_polygon(
852 unsigned ix = EDGE_Y_BUCKET_INDEX(y, polygon->ymin);
853 int min_height = active->min_height;
854 struct edge *subrow_edges = NULL;
855 - struct edge **ptail = &polygon->y_buckets[ix];
856 + struct edge **ptail = &polygon->y_buckets[ix].edges;
858 while (1) {
859 struct edge *tail = *ptail;
860 @@ -1277,8 +1343,10 @@ active_list_merge_edges_from_polygon(
861 ptail = &tail->next;
864 - active->head = merge_unsorted_edges(active->head, subrow_edges);
865 - active->min_height = min_height;
866 + if (subrow_edges) {
867 + active->head = merge_unsorted_edges(active->head, subrow_edges);
868 + active->min_height = min_height;
872 /* Advance the edges on the active list by one subsample row by
873 @@ -1439,11 +1507,13 @@ apply_nonzero_fill_rule_and_step_edges (struct active_list *active,
877 - right_edge->x.quo += right_edge->dxdy_full.quo;
878 - right_edge->x.rem += right_edge->dxdy_full.rem;
879 - if (right_edge->x.rem >= 0) {
880 - ++right_edge->x.quo;
881 - right_edge->x.rem -= right_edge->dy;
882 + if (! right_edge->vertical) {
883 + right_edge->x.quo += right_edge->dxdy_full.quo;
884 + right_edge->x.rem += right_edge->dxdy_full.rem;
885 + if (right_edge->x.rem >= 0) {
886 + ++right_edge->x.quo;
887 + right_edge->x.rem -= right_edge->dy;
892 @@ -1472,6 +1542,7 @@ apply_evenodd_fill_rule_and_step_edges (struct active_list *active,
893 left_edge = *cursor;
894 while (NULL != left_edge) {
895 struct edge *right_edge;
896 + int winding = left_edge->dir;
898 left_edge->height_left -= GRID_Y;
899 if (left_edge->height_left)
900 @@ -1490,17 +1561,22 @@ apply_evenodd_fill_rule_and_step_edges (struct active_list *active,
901 else
902 *cursor = right_edge->next;
904 + winding += right_edge->dir;
905 + if ((winding & 1) == 0) {
906 if (right_edge->next == NULL ||
907 right_edge->next->x.quo != right_edge->x.quo)
909 break;
913 - right_edge->x.quo += right_edge->dxdy_full.quo;
914 - right_edge->x.rem += right_edge->dxdy_full.rem;
915 - if (right_edge->x.rem >= 0) {
916 - ++right_edge->x.quo;
917 - right_edge->x.rem -= right_edge->dy;
918 + if (! right_edge->vertical) {
919 + right_edge->x.quo += right_edge->dxdy_full.quo;
920 + right_edge->x.rem += right_edge->dxdy_full.rem;
921 + if (right_edge->x.rem >= 0) {
922 + ++right_edge->x.quo;
923 + right_edge->x.rem -= right_edge->dy;
928 @@ -1537,8 +1613,14 @@ blit_span(
932 -#define GLITTER_BLIT_COVERAGES(coverages, y, xmin, xmax) \
933 - blit_cells(coverages, raster_pixels + (y)*raster_stride, xmin, xmax)
934 +#define GLITTER_BLIT_COVERAGES(coverages, y, height, xmin, xmax) \
935 + do { \
936 + int __y = y; \
937 + int __h = height; \
938 + do { \
939 + blit_cells(coverages, raster_pixels + (__y)*raster_stride, xmin, xmax); \
940 + } while (--__h); \
941 + } while (0)
943 static void
944 blit_cells(
945 @@ -1597,7 +1679,6 @@ static void
946 _glitter_scan_converter_fini(glitter_scan_converter_t *converter)
948 polygon_fini(converter->polygon);
949 - active_list_fini(converter->active);
950 cell_list_fini(converter->coverages);
951 converter->xmin=0;
952 converter->ymin=0;
953 @@ -1641,7 +1722,7 @@ glitter_scan_converter_reset(
955 active_list_reset(converter->active);
956 cell_list_reset(converter->coverages);
957 - status = polygon_reset(converter->polygon, ymin, ymax);
958 + status = polygon_reset(converter->polygon, xmin, xmax, ymin, ymax);
959 if (status)
960 return status;
962 @@ -1711,19 +1792,48 @@ glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
963 #endif
965 #ifndef GLITTER_BLIT_COVERAGES_EMPTY
966 -# define GLITTER_BLIT_COVERAGES_EMPTY(y, xmin, xmax)
967 +# define GLITTER_BLIT_COVERAGES_EMPTY(y0, y1, xmin, xmax)
968 #endif
970 +static cairo_bool_t
971 +active_list_is_vertical (struct active_list *active)
973 + struct edge *e;
975 + for (e = active->head; e != NULL; e = e->next) {
976 + if (! e->vertical)
977 + return FALSE;
980 + return TRUE;
983 +static void
984 +step_edges (struct active_list *active, int count)
986 + struct edge **cursor = &active->head;
987 + struct edge *edge;
989 + for (edge = *cursor; edge != NULL; edge = *cursor) {
990 + edge->height_left -= GRID_Y * count;
991 + if (edge->height_left)
992 + cursor = &edge->next;
993 + else
994 + *cursor = edge->next;
998 I glitter_status_t
999 glitter_scan_converter_render(
1000 glitter_scan_converter_t *converter,
1001 int nonzero_fill,
1002 GLITTER_BLIT_COVERAGES_ARGS)
1004 - int i;
1005 + int i, j;
1006 int ymax_i = converter->ymax / GRID_Y;
1007 int ymin_i = converter->ymin / GRID_Y;
1008 int xmin_i, xmax_i;
1009 + grid_scaled_x_t xmin = converter->xmin;
1010 int h = ymax_i - ymin_i;
1011 struct polygon *polygon = converter->polygon;
1012 struct cell_list *coverages = converter->coverages;
1013 @@ -1738,22 +1848,28 @@ glitter_scan_converter_render(
1014 GLITTER_BLIT_COVERAGES_BEGIN;
1016 /* Render each pixel row. */
1017 - for (i=0; i<h; i++) {
1018 + for (i = 0; i < h; i = j) {
1019 int do_full_step = 0;
1020 glitter_status_t status = 0;
1022 + j = i + 1;
1024 /* Determine if we can ignore this row or use the full pixel
1025 * stepper. */
1026 - if (GRID_Y == EDGE_Y_BUCKET_HEIGHT && ! polygon->y_buckets[i]) {
1027 + if (polygon->y_buckets[i].edges == NULL) {
1028 if (! active->head) {
1029 - GLITTER_BLIT_COVERAGES_EMPTY (i+ymin_i, xmin_i, xmax_i);
1030 + for (; j < h && ! polygon->y_buckets[j].edges; j++)
1032 + GLITTER_BLIT_COVERAGES_EMPTY (i+ymin_i, j-i, xmin_i, xmax_i);
1033 continue;
1036 - do_full_step = active_list_can_step_full_row (active);
1037 + do_full_step = active_list_can_step_full_row (active, xmin);
1039 + else if (! polygon->y_buckets[i].have_inside_edges) {
1040 + grid_scaled_y_t y = (i+ymin_i)*GRID_Y;
1041 + active_list_merge_edges_from_polygon (active, y, polygon);
1042 + do_full_step = active_list_can_step_full_row (active, xmin);
1045 - cell_list_reset (coverages);
1047 if (do_full_step) {
1048 /* Step by a full pixel row's worth. */
1049 @@ -1764,8 +1880,20 @@ glitter_scan_converter_render(
1050 status = apply_evenodd_fill_rule_and_step_edges (active,
1051 coverages);
1054 + if (active_list_is_vertical (active)) {
1055 + while (j < h &&
1056 + polygon->y_buckets[j].edges == NULL &&
1057 + active->min_height >= 2*GRID_Y)
1059 + active->min_height -= GRID_Y;
1060 + j++;
1062 + if (j != i + 1)
1063 + step_edges (active, j - (i + 1));
1065 } else {
1066 - /* Subsample this row. */
1067 + /* Supersample this row. */
1068 grid_scaled_y_t suby;
1069 for (suby = 0; suby < GRID_Y; suby++) {
1070 grid_scaled_y_t y = (i+ymin_i)*GRID_Y + suby;
1071 @@ -1787,13 +1915,13 @@ glitter_scan_converter_render(
1072 if (unlikely (status))
1073 return status;
1075 - GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, xmin_i, xmax_i);
1076 + GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, j-i, xmin_i, xmax_i);
1077 + cell_list_reset (coverages);
1079 - if (! active->head) {
1080 + if (! active->head)
1081 active->min_height = INT_MAX;
1082 - } else {
1083 + else
1084 active->min_height -= GRID_Y;
1088 /* Clean up the coverage blitter. */
1089 @@ -1807,21 +1935,20 @@ glitter_scan_converter_render(
1090 * scan converter subclass. */
1092 static glitter_status_t
1093 -blit_with_span_renderer(
1094 - struct cell_list *cells,
1095 - cairo_span_renderer_t *renderer,
1096 - struct pool *span_pool,
1097 - int y,
1098 - int xmin,
1099 - int xmax)
1100 +blit_with_span_renderer (struct cell_list *cells,
1101 + cairo_span_renderer_t *renderer,
1102 + struct pool *span_pool,
1103 + int y, int height,
1104 + int xmin, int xmax)
1106 struct cell *cell = cells->head;
1107 int prev_x = xmin;
1108 int cover = 0;
1109 cairo_half_open_span_t *spans;
1110 unsigned num_spans;
1112 if (cell == NULL)
1113 - return CAIRO_STATUS_SUCCESS;
1114 + return blit_empty_with_span_renderer (renderer, y, height);
1116 /* Skip cells to the left of the clip region. */
1117 while (cell != NULL && cell->x < xmin) {
1118 @@ -1833,12 +1960,12 @@ blit_with_span_renderer(
1119 /* Count number of cells remaining. */
1121 struct cell *next = cell;
1122 - num_spans = 0;
1123 - while (next) {
1124 + num_spans = 1;
1125 + while (next != NULL) {
1126 next = next->next;
1127 ++num_spans;
1129 - num_spans = 2*num_spans + 1;
1130 + num_spans = 2*num_spans;
1133 /* Allocate enough spans for the row. */
1134 @@ -1853,6 +1980,7 @@ blit_with_span_renderer(
1135 for (; cell != NULL; cell = cell->next) {
1136 int x = cell->x;
1137 int area;
1139 if (x >= xmax)
1140 break;
1142 @@ -1872,20 +2000,26 @@ blit_with_span_renderer(
1143 prev_x = x+1;
1146 - if (prev_x < xmax) {
1147 + if (prev_x <= xmax) {
1148 spans[num_spans].x = prev_x;
1149 spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
1150 ++num_spans;
1153 + if (prev_x < xmax && cover) {
1154 + spans[num_spans].x = xmax;
1155 + spans[num_spans].coverage = 0;
1156 + ++num_spans;
1159 /* Dump them into the renderer. */
1160 - return renderer->render_row (renderer, y, spans, num_spans);
1161 + return renderer->render_rows (renderer, y, height, spans, num_spans);
1164 static glitter_status_t
1165 -blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y)
1166 +blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height)
1168 - return renderer->render_row (renderer, y, NULL, 0);
1169 + return renderer->render_rows (renderer, y, height, NULL, 0);
1172 struct _cairo_tor_scan_converter {
1173 diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
1174 index 82d1cf5..d4575a3 100644
1175 --- a/src/cairo-win32-surface.c
1176 +++ b/src/cairo-win32-surface.c
1177 @@ -1954,6 +1954,9 @@ typedef struct _cairo_win32_surface_span_renderer {
1178 const cairo_pattern_t *pattern;
1179 cairo_antialias_t antialias;
1181 + uint8_t *mask_data;
1182 + uint32_t mask_stride;
1184 cairo_image_surface_t *mask;
1185 cairo_win32_surface_t *dst;
1186 cairo_region_t *clip_region;
1187 @@ -1962,14 +1965,16 @@ typedef struct _cairo_win32_surface_span_renderer {
1188 } cairo_win32_surface_span_renderer_t;
1190 static cairo_status_t
1191 -_cairo_win32_surface_span_renderer_render_row (
1192 +_cairo_win32_surface_span_renderer_render_rows (
1193 void *abstract_renderer,
1194 int y,
1195 + int height,
1196 const cairo_half_open_span_t *spans,
1197 unsigned num_spans)
1199 cairo_win32_surface_span_renderer_t *renderer = abstract_renderer;
1200 - _cairo_image_surface_span_render_row (y, spans, num_spans, renderer->mask, &renderer->composite_rectangles);
1201 + while (height--)
1202 + _cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride);
1203 return CAIRO_STATUS_SUCCESS;
1206 @@ -2066,8 +2071,7 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
1208 renderer->base.destroy = _cairo_win32_surface_span_renderer_destroy;
1209 renderer->base.finish = _cairo_win32_surface_span_renderer_finish;
1210 - renderer->base.render_row =
1211 - _cairo_win32_surface_span_renderer_render_row;
1212 + renderer->base.render_rows = _cairo_win32_surface_span_renderer_render_rows;
1213 renderer->op = op;
1214 renderer->pattern = pattern;
1215 renderer->antialias = antialias;
1216 @@ -2088,6 +2092,9 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
1217 _cairo_win32_surface_span_renderer_destroy (renderer);
1218 return _cairo_span_renderer_create_in_error (status);
1221 + renderer->mask_data = renderer->mask->data - rects->mask.x - rects->mask.y * renderer->mask->stride;
1222 + renderer->mask_stride = renderer->mask->stride;
1223 return &renderer->base;
1226 diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
1227 index a7a40b8..566d9fb 100644
1228 --- a/src/cairo-xlib-display.c
1229 +++ b/src/cairo-xlib-display.c
1230 @@ -407,6 +407,10 @@ _cairo_xlib_display_get (Display *dpy,
1231 display->buggy_pad_reflect = TRUE;
1234 + /* gradients don't seem to work */
1235 + display->buggy_gradients = TRUE;
1238 /* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */
1239 /* If buggy_repeat_force == -1, then initialize.
1240 * - set to -2, meaning "nothing was specified", and we trust the above detection.
1241 diff --git a/src/cairoint.h b/src/cairoint.h
1242 index 58850ab..1cdf6ff 100644
1243 --- a/src/cairoint.h
1244 +++ b/src/cairoint.h
1245 @@ -2257,8 +2257,8 @@ cairo_private void
1246 _cairo_image_surface_span_render_row (int y,
1247 const cairo_half_open_span_t *spans,
1248 unsigned num_spans,
1249 - cairo_image_surface_t *mask,
1250 - const cairo_composite_rectangles_t *rects);
1251 + uint8_t *data,
1252 + uint32_t stride);
1254 cairo_private cairo_image_transparency_t
1255 _cairo_image_analyze_transparency (cairo_image_surface_t *image);