Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2002 University of Southern California
5
 * Copyright © 2005 Red Hat, Inc.
6
 * Copyright © 2011 Intel Corporation
7
 * Copyright © 2011 Samsung Electronics
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it either under the terms of the GNU Lesser General Public
11
 * License version 2.1 as published by the Free Software Foundation
12
 * (the "LGPL") or, at your option, under the terms of the Mozilla
13
 * Public License Version 1.1 (the "MPL"). If you do not alter this
14
 * notice, a recipient may use your version of this file under either
15
 * the MPL or the LGPL.
16
 *
17
 * You should have received a copy of the LGPL along with this library
18
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
20
 * You should have received a copy of the MPL along with this library
21
 * in the file COPYING-MPL-1.1
22
 *
23
 * The contents of this file are subject to the Mozilla Public License
24
 * Version 1.1 (the "License"); you may not use this file except in
25
 * compliance with the License. You may obtain a copy of the License at
26
 * http://www.mozilla.org/MPL/
27
 *
28
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
29
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
30
 * the specific language governing rights and limitations.
31
 *
32
 * The Original Code is the cairo graphics library.
33
 *
34
 * The Initial Developer of the Original Code is University of Southern
35
 * California.
36
 *
37
 * Contributor(s):
38
 *	Henry Song 
39
 *	Martin Robinson 
40
 */
41
 
42
#include "cairoint.h"
43
 
44
#include "cairo-clip-inline.h"
45
#include "cairo-composite-rectangles-private.h"
46
#include "cairo-compositor-private.h"
47
#include "cairo-gl-private.h"
48
#include "cairo-path-private.h"
49
#include "cairo-traps-private.h"
50
 
51
static cairo_bool_t
52
can_use_msaa_compositor (cairo_gl_surface_t *surface,
53
			 cairo_antialias_t antialias);
54
 
55
static void
56
query_surface_capabilities (cairo_gl_surface_t *surface);
57
 
58
struct _tristrip_composite_info {
59
    cairo_gl_composite_t	setup;
60
    cairo_gl_context_t		*ctx;
61
};
62
 
63
static cairo_int_status_t
64
_draw_trap (cairo_gl_context_t		*ctx,
65
	    cairo_gl_composite_t	*setup,
66
	    cairo_trapezoid_t		*trap)
67
{
68
    cairo_point_t quad[4];
69
 
70
    quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
71
							  &trap->left.p2,
72
							  trap->top);
73
    quad[0].y = trap->top;
74
 
75
    quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
76
						      &trap->left.p2,
77
						      trap->bottom);
78
    quad[1].y = trap->bottom;
79
 
80
    quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
81
						      &trap->right.p2,
82
						      trap->bottom);
83
    quad[2].y = trap->bottom;
84
 
85
    quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
86
						      &trap->right.p2,
87
						      trap->top);
88
    quad[3].y = trap->top;
89
    return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
90
}
91
 
92
static cairo_int_status_t
93
_draw_traps (cairo_gl_context_t		*ctx,
94
	     cairo_gl_composite_t	*setup,
95
	     cairo_traps_t		*traps)
96
{
97
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
98
    int i;
99
 
100
    for (i = 0; i < traps->num_traps; i++) {
101
	cairo_trapezoid_t *trap = traps->traps + i;
102
	if (unlikely ((status = _draw_trap (ctx, setup, trap))))
103
	    return status;
104
    }
105
 
106
   return status;
107
}
108
 
109
static cairo_int_status_t
110
_draw_int_rect (cairo_gl_context_t	*ctx,
111
		cairo_gl_composite_t	*setup,
112
		cairo_rectangle_int_t	*rect)
113
{
114
    cairo_box_t box;
115
    cairo_point_t quad[4];
116
 
117
    _cairo_box_from_rectangle (&box, rect);
118
    quad[0].x = box.p1.x;
119
    quad[0].y = box.p1.y;
120
    quad[1].x = box.p1.x;
121
    quad[1].y = box.p2.y;
122
    quad[2].x = box.p2.x;
123
    quad[2].y = box.p2.y;
124
    quad[3].x = box.p2.x;
125
    quad[3].y = box.p1.y;
126
 
127
    return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
128
}
129
 
130
static cairo_int_status_t
131
_draw_triangle_fan (cairo_gl_context_t		*ctx,
132
		    cairo_gl_composite_t	*setup,
133
		    const cairo_point_t		*midpt,
134
		    const cairo_point_t		*points,
135
		    int				 npoints)
136
{
137
    int i;
138
 
139
    /* Our strategy here is to not even try to build a triangle fan, but to
140
       draw each triangle as if it was an unconnected member of a triangle strip. */
141
    for (i = 1; i < npoints; i++) {
142
	cairo_int_status_t status;
143
	cairo_point_t triangle[3];
144
 
145
	triangle[0] = *midpt;
146
	triangle[1] = points[i - 1];
147
	triangle[2] = points[i];
148
 
149
	status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
150
	if (unlikely (status))
151
	    return status;
152
    }
153
 
154
    return CAIRO_STATUS_SUCCESS;
155
}
156
 
157
static cairo_int_status_t
158
_clip_to_traps (cairo_clip_t *clip,
159
		cairo_traps_t *traps)
160
{
161
    cairo_int_status_t status;
162
    cairo_polygon_t polygon;
163
    cairo_antialias_t antialias;
164
    cairo_fill_rule_t fill_rule;
165
 
166
    _cairo_traps_init (traps);
167
 
168
    if (clip->num_boxes == 1 && clip->path == NULL) {
169
	cairo_boxes_t boxes;
170
	_cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
171
	return _cairo_traps_init_boxes (traps, &boxes);
172
    }
173
 
174
    status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
175
    if (unlikely (status))
176
	return status;
177
 
178
    /* We ignore the antialias mode of the clip here, since the user requested
179
     * unantialiased rendering of their path and we expect that this stencil
180
     * based rendering of the clip to be a reasonable approximation to
181
     * the intersection between that clip and the path.
182
     *
183
     * In other words, what the user expects when they try to perform
184
     * a geometric intersection between an unantialiased polygon and an
185
     * antialiased polygon is open to interpretation. And we choose the fast
186
     * option.
187
     */
188
 
189
    _cairo_traps_init (traps);
190
    status = _cairo_bentley_ottmann_tessellate_polygon (traps,
191
							&polygon,
192
							fill_rule);
193
    _cairo_polygon_fini (&polygon);
194
 
195
    return status;
196
}
197
 
198
cairo_int_status_t
199
_cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
200
				     cairo_gl_composite_t *setup,
201
				     cairo_clip_t *clip)
202
{
203
    cairo_int_status_t status;
204
    cairo_traps_t traps;
205
 
206
    status = _clip_to_traps (clip, &traps);
207
    if (unlikely (status))
208
	return status;
209
    status = _draw_traps (ctx, setup, &traps);
210
 
211
    _cairo_traps_fini (&traps);
212
    return status;
213
}
214
 
215
static cairo_bool_t
216
_should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
217
{
218
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
219
    cairo_rectangle_int_t *source = &composite->source;
220
 
221
    if (composite->is_bounded)
222
	return FALSE;
223
 
224
    /* This isn't just an optimization. It also detects when painting is used
225
       to paint back the unbounded surface, preventing infinite recursion. */
226
    return ! (source->x <= 0 && source->y <= 0 &&
227
              source->height + source->y >= dst->height &&
228
              source->width + source->x >= dst->width);
229
}
230
 
231
static cairo_surface_t*
232
_prepare_unbounded_surface (cairo_gl_surface_t *dst)
233
{
234
 
235
    cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
236
							dst->base.content,
237
							dst->width,
238
							dst->height);
239
    if (surface == NULL)
240
        return NULL;
241
    if (unlikely (surface->status)) {
242
        cairo_surface_destroy (surface);
243
        return NULL;
244
    }
245
    return surface;
246
}
247
 
248
static cairo_int_status_t
249
_paint_back_unbounded_surface (const cairo_compositor_t		*compositor,
250
			       cairo_composite_rectangles_t	*composite,
251
			       cairo_surface_t			*surface)
252
{
253
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
254
    cairo_int_status_t status;
255
 
256
    cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
257
    if (unlikely (pattern->status)) {
258
	status = pattern->status;
259
	goto finish;
260
    }
261
 
262
    status = _cairo_compositor_paint (compositor, &dst->base,
263
				      composite->op, pattern,
264
				      composite->clip);
265
 
266
finish:
267
    cairo_pattern_destroy (pattern);
268
    cairo_surface_destroy (surface);
269
    return status;
270
}
271
 
272
static cairo_bool_t
273
can_use_msaa_compositor (cairo_gl_surface_t *surface,
274
			 cairo_antialias_t antialias)
275
{
276
    query_surface_capabilities (surface);
277
    if (! surface->supports_stencil)
278
	return FALSE;
279
 
280
    /* Multisampling OpenGL ES surfaces only maintain one multisampling
281
       framebuffer and thus must use the spans compositor to do non-antialiased
282
       rendering. */
283
    if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
284
	 && surface->supports_msaa
285
	 && antialias == CAIRO_ANTIALIAS_NONE)
286
	return FALSE;
287
 
288
    /* The MSAA compositor has a single-sample mode, so we can
289
       support non-antialiased rendering. */
290
    if (antialias == CAIRO_ANTIALIAS_NONE)
291
	return TRUE;
292
 
293
    if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT)
294
	return surface->supports_msaa;
295
    return FALSE;
296
}
297
 
298
static void
299
_cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
300
				    cairo_gl_composite_t *setup)
301
{
302
    if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
303
	return;
304
    _cairo_gl_composite_set_clip (setup, composite->clip);
305
}
306
 
307
/* Masking with the SOURCE operator requires two passes. In the first
308
 * pass we use the mask as the source to get:
309
 * result = (1 - ma) * dst
310
 * In the second pass we use the add operator to achieve:
311
 * result = (src * ma) + dst
312
 * Combined this produces:
313
 * result = (src * ma) + (1 - ma) * dst
314
 */
315
static cairo_int_status_t
316
_cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
317
						cairo_composite_rectangles_t *composite)
318
{
319
    cairo_gl_composite_t setup;
320
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
321
    cairo_gl_context_t *ctx = NULL;
322
    cairo_int_status_t status;
323
 
324
    cairo_clip_t *clip = composite->clip;
325
    cairo_traps_t traps;
326
 
327
    /* If we have a non-rectangular clip, we can avoid using the stencil buffer
328
     * for clipping and just draw the clip polygon. */
329
    if (clip) {
330
	status = _clip_to_traps (clip, &traps);
331
	if (unlikely (status)) {
332
	    _cairo_traps_fini (&traps);
333
	    return status;
334
	}
335
    }
336
 
337
    status = _cairo_gl_composite_init (&setup,
338
				       CAIRO_OPERATOR_DEST_OUT,
339
				       dst,
340
				       FALSE /* assume_component_alpha */);
341
    if (unlikely (status))
342
	return status;
343
    status = _cairo_gl_composite_set_source (&setup,
344
					     &composite->mask_pattern.base,
345
					     &composite->mask_sample_area,
346
					     &composite->bounded,
347
					     FALSE);
348
    if (unlikely (status))
349
	goto finish;
350
    _cairo_gl_composite_set_multisample (&setup);
351
    status = _cairo_gl_composite_begin (&setup, &ctx);
352
    if (unlikely (status))
353
	goto finish;
354
 
355
    if (! clip)
356
	status = _draw_int_rect (ctx, &setup, &composite->bounded);
357
    else
358
	status = _draw_traps (ctx, &setup, &traps);
359
    if (unlikely (status))
360
        goto finish;
361
 
362
    /* Now draw the second pass. */
363
    status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
364
					       FALSE /* assume_component_alpha */);
365
    if (unlikely (status))
366
        goto finish;
367
    status = _cairo_gl_composite_set_source (&setup,
368
					     &composite->source_pattern.base,
369
					     &composite->source_sample_area,
370
					     &composite->bounded,
371
					     FALSE);
372
    if (unlikely (status))
373
	goto finish;
374
    status = _cairo_gl_composite_set_mask (&setup,
375
				           &composite->mask_pattern.base,
376
					   &composite->source_sample_area,
377
					   &composite->bounded,
378
					   FALSE);
379
    if (unlikely (status))
380
	goto finish;
381
    status = _cairo_gl_set_operands_and_operator (&setup, ctx);
382
    if (unlikely (status))
383
	goto finish;
384
 
385
    if (! clip)
386
	status = _draw_int_rect (ctx, &setup, &composite->bounded);
387
    else
388
	status = _draw_traps (ctx, &setup, &traps);
389
 
390
finish:
391
    _cairo_gl_composite_fini (&setup);
392
    if (ctx)
393
	status = _cairo_gl_context_release (ctx, status);
394
    if (clip)
395
	_cairo_traps_fini (&traps);
396
 
397
    return status;
398
}
399
 
400
static cairo_int_status_t
401
_cairo_gl_msaa_compositor_mask (const cairo_compositor_t	*compositor,
402
				cairo_composite_rectangles_t	*composite)
403
{
404
    cairo_gl_composite_t setup;
405
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
406
    cairo_gl_context_t *ctx = NULL;
407
    cairo_int_status_t status;
408
    cairo_operator_t op = composite->op;
409
    cairo_clip_t *clip = composite->clip;
410
 
411
    if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
412
	return CAIRO_INT_STATUS_UNSUPPORTED;
413
 
414
    if (composite->op == CAIRO_OPERATOR_CLEAR &&
415
	composite->original_mask_pattern != NULL)
416
	return CAIRO_INT_STATUS_UNSUPPORTED;
417
 
418
    /* GL compositing operators cannot properly represent a mask operation
419
       using the SOURCE compositing operator in one pass. This only matters if
420
       there actually is a mask (there isn't in a paint operation) and if the
421
       mask isn't totally opaque. */
422
    if (op == CAIRO_OPERATOR_SOURCE &&
423
	 composite->original_mask_pattern != NULL &&
424
	! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
425
				    &composite->mask_sample_area)) {
426
 
427
	if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
428
				      &composite->source_sample_area)) {
429
	    return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
430
	}
431
 
432
	/* If the source is opaque the operation reduces to OVER. */
433
	op = CAIRO_OPERATOR_OVER;
434
    }
435
 
436
    if (_should_use_unbounded_surface (composite)) {
437
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);
438
 
439
	if (unlikely (surface == NULL))
440
	    return CAIRO_INT_STATUS_UNSUPPORTED;
441
 
442
	/* This may be a paint operation. */
443
	if (composite->original_mask_pattern == NULL) {
444
	    status = _cairo_compositor_paint (compositor, surface,
445
					      CAIRO_OPERATOR_SOURCE,
446
					      &composite->source_pattern.base,
447
					      NULL);
448
	} else {
449
	    status = _cairo_compositor_mask (compositor, surface,
450
					     CAIRO_OPERATOR_SOURCE,
451
					     &composite->source_pattern.base,
452
					     &composite->mask_pattern.base,
453
					     NULL);
454
	}
455
 
456
	if (unlikely (status)) {
457
	    cairo_surface_destroy (surface);
458
	    return status;
459
	}
460
 
461
	return _paint_back_unbounded_surface (compositor, composite, surface);
462
    }
463
 
464
    status = _cairo_gl_composite_init (&setup,
465
				       op,
466
				       dst,
467
				       FALSE /* assume_component_alpha */);
468
    if (unlikely (status))
469
	return status;
470
 
471
    status = _cairo_gl_composite_set_source (&setup,
472
					     &composite->source_pattern.base,
473
					     &composite->source_sample_area,
474
					     &composite->bounded,
475
					     FALSE);
476
    if (unlikely (status))
477
	goto finish;
478
 
479
    if (composite->original_mask_pattern != NULL) {
480
	status = _cairo_gl_composite_set_mask (&setup,
481
					       &composite->mask_pattern.base,
482
					       &composite->mask_sample_area,
483
					       &composite->bounded,
484
					       FALSE);
485
    }
486
    if (unlikely (status))
487
	goto finish;
488
 
489
    /* We always use multisampling here, because we do not yet have the smarts
490
       to calculate when the clip or the source requires it. */
491
     _cairo_gl_composite_set_multisample (&setup);
492
 
493
    status = _cairo_gl_composite_begin (&setup, &ctx);
494
    if (unlikely (status))
495
	goto finish;
496
 
497
    if (! clip)
498
	status = _draw_int_rect (ctx, &setup, &composite->bounded);
499
    else
500
	status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
501
 
502
finish:
503
    _cairo_gl_composite_fini (&setup);
504
 
505
    if (ctx)
506
	status = _cairo_gl_context_release (ctx, status);
507
 
508
    return status;
509
}
510
 
511
static cairo_int_status_t
512
_cairo_gl_msaa_compositor_paint (const cairo_compositor_t	*compositor,
513
				 cairo_composite_rectangles_t	*composite)
514
{
515
    return _cairo_gl_msaa_compositor_mask (compositor, composite);
516
}
517
 
518
static cairo_status_t
519
_stroke_shaper_add_triangle (void			*closure,
520
			     const cairo_point_t	 triangle[3])
521
{
522
    struct _tristrip_composite_info *info = closure;
523
    return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
524
							  &info->setup,
525
							  triangle);
526
}
527
 
528
static cairo_status_t
529
_stroke_shaper_add_triangle_fan (void			*closure,
530
				 const cairo_point_t	*midpoint,
531
				 const cairo_point_t	*points,
532
				 int			 npoints)
533
{
534
    struct _tristrip_composite_info *info = closure;
535
    return _draw_triangle_fan (info->ctx, &info->setup,
536
			       midpoint, points, npoints);
537
}
538
 
539
static cairo_status_t
540
_stroke_shaper_add_quad (void			*closure,
541
			 const cairo_point_t	 quad[4])
542
{
543
    struct _tristrip_composite_info *info = closure;
544
    return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
545
						      quad);
546
}
547
 
548
static cairo_int_status_t
549
_prevent_overlapping_strokes (cairo_gl_context_t 		*ctx,
550
			      cairo_gl_composite_t 		*setup,
551
			      cairo_composite_rectangles_t 	*composite,
552
			      const cairo_path_fixed_t		*path,
553
			      const cairo_stroke_style_t	*style,
554
			      const cairo_matrix_t		*ctm)
555
{
556
    cairo_rectangle_int_t stroke_extents;
557
 
558
    if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
559
	return CAIRO_INT_STATUS_UNSUPPORTED;
560
 
561
    if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
562
				  &composite->source_sample_area))
563
	return CAIRO_INT_STATUS_SUCCESS;
564
 
565
   if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
566
	cairo_bool_t scissor_was_enabled;
567
 
568
       /* In case we have pending operations we have to flush before
569
	  adding the stencil buffer. */
570
       _cairo_gl_composite_flush (ctx);
571
 
572
	/* Enable the stencil buffer, even if we are not using it for clipping,
573
	   so we can use it below to prevent overlapping shapes. We initialize
574
	   it all to one here which represents infinite clip. */
575
	glDepthMask (GL_TRUE);
576
	glEnable (GL_STENCIL_TEST);
577
 
578
	/* We scissor here so that we don't have to clear the entire stencil
579
	 * buffer. If the scissor test is already enabled, it was enabled
580
	 * for clipping. In that case, instead of calculating an intersection,
581
	 * we just reuse it, and risk clearing too much. */
582
	scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
583
	if (! scissor_was_enabled) {
584
	    _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
585
							  &stroke_extents);
586
	    _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
587
	}
588
	glClearStencil (1);
589
	glClear (GL_STENCIL_BUFFER_BIT);
590
	if (! scissor_was_enabled)
591
	    glDisable (GL_SCISSOR_TEST);
592
 
593
	glStencilFunc (GL_EQUAL, 1, 1);
594
    }
595
 
596
    /* This means that once we draw to a particular pixel nothing else can
597
       be drawn there until the stencil buffer is reset or the stencil test
598
       is disabled. */
599
    glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
600
 
601
    _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
602
    setup->dst->clip_on_stencil_buffer = NULL;
603
 
604
    return CAIRO_INT_STATUS_SUCCESS;
605
}
606
 
607
static void
608
query_surface_capabilities (cairo_gl_surface_t *surface)
609
{
610
    GLint samples, stencil_bits;
611
    cairo_gl_context_t *ctx;
612
    cairo_int_status_t status;
613
 
614
    /* Texture surfaces are create in such a way that they always
615
       have stencil and multisample bits if possible, so we don't
616
       need to query their capabilities lazily. */
617
    if (_cairo_gl_surface_is_texture (surface))
618
	return;
619
    if (surface->stencil_and_msaa_caps_initialized)
620
	return;
621
 
622
    surface->stencil_and_msaa_caps_initialized = TRUE;
623
    surface->supports_stencil = FALSE;
624
    surface->supports_msaa = FALSE;
625
 
626
    status = _cairo_gl_context_acquire (surface->base.device, &ctx);
627
    if (unlikely (status))
628
	return;
629
 
630
    _cairo_gl_context_set_destination (ctx, surface, FALSE);
631
 
632
    glGetIntegerv(GL_SAMPLES, &samples);
633
    glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
634
    surface->supports_stencil = stencil_bits > 0;
635
    surface->supports_msaa = samples > 1;
636
 
637
    status = _cairo_gl_context_release (ctx, status);
638
}
639
 
640
static cairo_int_status_t
641
_cairo_gl_msaa_compositor_stroke (const cairo_compositor_t	*compositor,
642
				  cairo_composite_rectangles_t	*composite,
643
				  const cairo_path_fixed_t	*path,
644
				  const cairo_stroke_style_t	*style,
645
				  const cairo_matrix_t		*ctm,
646
				  const cairo_matrix_t		*ctm_inverse,
647
				  double			 tolerance,
648
				  cairo_antialias_t		 antialias)
649
{
650
    cairo_int_status_t status;
651
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
652
    struct _tristrip_composite_info info;
653
 
654
    if (! can_use_msaa_compositor (dst, antialias))
655
	return CAIRO_INT_STATUS_UNSUPPORTED;
656
 
657
    if (composite->is_bounded == FALSE) {
658
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);
659
 
660
	if (unlikely (surface == NULL))
661
	    return CAIRO_INT_STATUS_UNSUPPORTED;
662
 
663
	status = _cairo_compositor_stroke (compositor, surface,
664
					   CAIRO_OPERATOR_SOURCE,
665
					   &composite->source_pattern.base,
666
					   path, style, ctm, ctm_inverse,
667
					   tolerance, antialias, NULL);
668
	if (unlikely (status)) {
669
	    cairo_surface_destroy (surface);
670
	    return status;
671
	}
672
 
673
	return _paint_back_unbounded_surface (compositor, composite, surface);
674
    }
675
 
676
    status = _cairo_gl_composite_init (&info.setup,
677
				       composite->op,
678
				       dst,
679
				       FALSE /* assume_component_alpha */);
680
    if (unlikely (status))
681
	return status;
682
 
683
    info.ctx = NULL;
684
 
685
    status = _cairo_gl_composite_set_source (&info.setup,
686
					     &composite->source_pattern.base,
687
					     &composite->source_sample_area,
688
					     &composite->bounded,
689
					     FALSE);
690
    if (unlikely (status))
691
	goto finish;
692
 
693
    _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
694
    if (antialias != CAIRO_ANTIALIAS_NONE)
695
	_cairo_gl_composite_set_multisample (&info.setup);
696
 
697
    status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
698
    if (unlikely (status))
699
	goto finish;
700
 
701
    status = _prevent_overlapping_strokes (info.ctx, &info.setup,
702
					   composite, path, style, ctm);
703
    if (unlikely (status))
704
	goto finish;
705
 
706
    status = _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
707
						 style,
708
						 ctm,
709
						 ctm_inverse,
710
						 tolerance,
711
						 _stroke_shaper_add_triangle,
712
						 _stroke_shaper_add_triangle_fan,
713
						 _stroke_shaper_add_quad,
714
						 &info);
715
    if (unlikely (status))
716
	goto finish;
717
 
718
finish:
719
    _cairo_gl_composite_fini (&info.setup);
720
 
721
    if (info.ctx)
722
	status = _cairo_gl_context_release (info.ctx, status);
723
 
724
    return status;
725
}
726
 
727
static cairo_int_status_t
728
_draw_simple_quad_path (cairo_gl_context_t *ctx,
729
			cairo_gl_composite_t *setup,
730
			const cairo_path_fixed_t *path)
731
{
732
    cairo_point_t triangle[3];
733
    cairo_int_status_t status;
734
    const cairo_point_t *points;
735
 
736
    points = cairo_path_head (path)->points;
737
    triangle[0] = points[0];
738
    triangle[1] = points[1];
739
    triangle[2] = points[2];
740
    status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
741
    if (status)
742
	return status;
743
 
744
    triangle[0] = points[2];
745
    triangle[1] = points[3];
746
    triangle[2] = points[0];
747
    return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
748
}
749
 
750
static cairo_int_status_t
751
_cairo_gl_msaa_compositor_fill (const cairo_compositor_t	*compositor,
752
				cairo_composite_rectangles_t	*composite,
753
				const cairo_path_fixed_t	*path,
754
				cairo_fill_rule_t		 fill_rule,
755
				double				 tolerance,
756
				cairo_antialias_t		 antialias)
757
{
758
    cairo_gl_composite_t setup;
759
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
760
    cairo_gl_context_t *ctx = NULL;
761
    cairo_int_status_t status;
762
    cairo_traps_t traps;
763
    cairo_bool_t draw_path_with_traps;
764
 
765
    if (! can_use_msaa_compositor (dst, antialias))
766
	return CAIRO_INT_STATUS_UNSUPPORTED;
767
 
768
    if (composite->is_bounded == FALSE) {
769
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);
770
 
771
	if (unlikely (surface == NULL))
772
	    return CAIRO_INT_STATUS_UNSUPPORTED;
773
 
774
 
775
	status = _cairo_compositor_fill (compositor, surface,
776
					 CAIRO_OPERATOR_SOURCE,
777
					 &composite->source_pattern.base,
778
					 path, fill_rule, tolerance,
779
					 antialias, NULL);
780
 
781
	if (unlikely (status)) {
782
	    cairo_surface_destroy (surface);
783
	    return status;
784
	}
785
 
786
	return _paint_back_unbounded_surface (compositor, composite, surface);
787
    }
788
 
789
    draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
790
 
791
    if (draw_path_with_traps) {
792
	_cairo_traps_init (&traps);
793
	status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
794
	if (unlikely (status))
795
	    goto cleanup_traps;
796
    }
797
 
798
    status = _cairo_gl_composite_init (&setup,
799
				       composite->op,
800
				       dst,
801
				       FALSE /* assume_component_alpha */);
802
    if (unlikely (status))
803
	goto cleanup_traps;
804
 
805
    status = _cairo_gl_composite_set_source (&setup,
806
					     &composite->source_pattern.base,
807
					     &composite->source_sample_area,
808
					     &composite->bounded,
809
					     FALSE);
810
    if (unlikely (status))
811
	goto cleanup_setup;
812
 
813
    _cairo_gl_msaa_compositor_set_clip (composite, &setup);
814
    if (antialias != CAIRO_ANTIALIAS_NONE)
815
	_cairo_gl_composite_set_multisample (&setup);
816
 
817
    status = _cairo_gl_composite_begin (&setup, &ctx);
818
    if (unlikely (status))
819
	goto cleanup_setup;
820
 
821
    if (! draw_path_with_traps)
822
	status = _draw_simple_quad_path (ctx, &setup, path);
823
    else
824
	status = _draw_traps (ctx, &setup, &traps);
825
    if (unlikely (status))
826
        goto cleanup_setup;
827
 
828
cleanup_setup:
829
    _cairo_gl_composite_fini (&setup);
830
 
831
    if (ctx)
832
	status = _cairo_gl_context_release (ctx, status);
833
 
834
cleanup_traps:
835
    if (draw_path_with_traps)
836
	_cairo_traps_fini (&traps);
837
 
838
    return status;
839
}
840
 
841
static cairo_int_status_t
842
_cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t	*compositor,
843
				  cairo_composite_rectangles_t	*composite,
844
				  cairo_scaled_font_t		*scaled_font,
845
				  cairo_glyph_t			*glyphs,
846
				  int				 num_glyphs,
847
				  cairo_bool_t			 overlap)
848
{
849
    cairo_int_status_t status;
850
    cairo_surface_t *src = NULL;
851
    int src_x, src_y;
852
    cairo_composite_glyphs_info_t info;
853
 
854
    cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
855
 
856
    query_surface_capabilities (dst);
857
    if (! dst->supports_stencil)
858
	return CAIRO_INT_STATUS_UNSUPPORTED;
859
 
860
    if (composite->op == CAIRO_OPERATOR_CLEAR)
861
	return CAIRO_INT_STATUS_UNSUPPORTED;
862
 
863
    if (composite->is_bounded == FALSE) {
864
	cairo_surface_t* surface = _prepare_unbounded_surface (dst);
865
 
866
	if (unlikely (surface == NULL))
867
	    return CAIRO_INT_STATUS_UNSUPPORTED;
868
 
869
	status = _cairo_compositor_glyphs (compositor, surface,
870
					   CAIRO_OPERATOR_SOURCE,
871
					   &composite->source_pattern.base,
872
					   glyphs, num_glyphs,
873
					   scaled_font, composite->clip);
874
 
875
	if (unlikely (status)) {
876
	    cairo_surface_destroy (surface);
877
	    return status;
878
	}
879
 
880
	return _paint_back_unbounded_surface (compositor, composite, surface);
881
    }
882
 
883
    src = _cairo_gl_pattern_to_source (&dst->base,
884
				       &composite->source_pattern.base,
885
				       FALSE,
886
				       &composite->bounded,
887
				       &composite->source_sample_area,
888
				       &src_x, &src_y);
889
    if (unlikely (src->status)) {
890
	status = src->status;
891
	goto finish;
892
    }
893
 
894
    status = _cairo_gl_check_composite_glyphs (composite,
895
					       scaled_font, glyphs,
896
					       &num_glyphs);
897
    if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
898
	goto finish;
899
 
900
    info.font = scaled_font;
901
    info.glyphs = glyphs;
902
    info.num_glyphs = num_glyphs;
903
    info.use_mask = overlap || ! composite->is_bounded ||
904
		    composite->op == CAIRO_OPERATOR_SOURCE;
905
    info.extents = composite->bounded;
906
 
907
    _cairo_scaled_font_freeze_cache (scaled_font);
908
    status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
909
						   src, src_x, src_y,
910
						   0, 0, &info,
911
						   composite->clip);
912
 
913
    _cairo_scaled_font_thaw_cache (scaled_font);
914
 
915
finish:
916
    if (src)
917
	cairo_surface_destroy (src);
918
 
919
    return status;
920
}
921
 
922
static void
923
_cairo_gl_msaa_compositor_init (cairo_compositor_t	 *compositor,
924
				const cairo_compositor_t *delegate)
925
{
926
    compositor->delegate = delegate;
927
 
928
    compositor->paint = _cairo_gl_msaa_compositor_paint;
929
    compositor->mask = _cairo_gl_msaa_compositor_mask;
930
    compositor->fill = _cairo_gl_msaa_compositor_fill;
931
    compositor->stroke = _cairo_gl_msaa_compositor_stroke;
932
    compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
933
}
934
 
935
const cairo_compositor_t *
936
_cairo_gl_msaa_compositor_get (void)
937
{
938
    static cairo_compositor_t compositor;
939
    if (compositor.delegate == NULL)
940
	_cairo_gl_msaa_compositor_init (&compositor,
941
					_cairo_gl_span_compositor_get ());
942
 
943
    return &compositor;
944
}