1
/*
2
 * Copyright © 2006 Red Hat, Inc.
3
 * Copyright © 2009 Chris Wilson
4
 *
5
 * Permission to use, copy, modify, distribute, and sell this software
6
 * and its documentation for any purpose is hereby granted without
7
 * fee, provided that the above copyright notice appear in all copies
8
 * and that both that copyright notice and this permission notice
9
 * appear in supporting documentation, and that the name of
10
 * Red Hat, Inc. not be used in advertising or publicity pertaining to
11
 * distribution of the software without specific, written prior
12
 * permission. Red Hat, Inc. makes no representations about the
13
 * suitability of this software for any purpose.  It is provided "as
14
 * is" without express or implied warranty.
15
 *
16
 * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18
 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
19
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
22
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
 *
24
 * Author: Carl D. Worth <cworth@cworth.org>
25
 *         Chris Wilson <chris@chris-wilson.co.uk>
26
 */
27

            
28
#include "cairo-perf.h"
29

            
30
static cairo_time_t
31
do_mask_solid (cairo_t *cr, int width, int height, int loops)
32
{
33
    cairo_pattern_t *mask;
34

            
35
    mask = cairo_pattern_create_rgba (0, 0, 0, .5);
36

            
37
    cairo_perf_timer_start ();
38

            
39
    while (loops--)
40
	cairo_mask (cr, mask);
41

            
42
    cairo_perf_timer_stop ();
43

            
44
    cairo_pattern_destroy (mask);
45

            
46
    return cairo_perf_timer_elapsed ();
47
}
48

            
49
static cairo_surface_t *
50
init_surface (cairo_surface_t *surface, int width, int height)
51
{
52
    cairo_t *cr;
53

            
54
    cr = cairo_create (surface);
55
    cairo_surface_destroy (surface);
56

            
57
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
58
    cairo_set_source_rgb (cr, 0, 0, 0); /* back */
59
    cairo_paint (cr);
60

            
61
    cairo_set_source_rgba (cr, 1, 1, 1, 0.5); /* 50% */
62
    cairo_new_path (cr);
63
    cairo_rectangle (cr, 0, 0, width/2.0, height/2.0);
64
    cairo_rectangle (cr, width/2.0, height/2.0, width/2.0, height/2.0);
65
    cairo_fill (cr);
66

            
67
    surface = cairo_surface_reference (cairo_get_target (cr));
68
    cairo_destroy (cr);
69

            
70
    return surface;
71
}
72

            
73
static cairo_time_t
74
do_mask_image (cairo_t *cr, int width, int height, int loops)
75
{
76
    cairo_surface_t *surface;
77
    cairo_pattern_t *mask;
78

            
79
    surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
80
    mask = cairo_pattern_create_for_surface (init_surface (surface,
81
							   width,
82
							   height));
83
    cairo_surface_destroy (surface);
84

            
85
    cairo_perf_timer_start ();
86

            
87
    while (loops--)
88
	cairo_mask (cr, mask);
89

            
90
    cairo_perf_timer_stop ();
91

            
92
    cairo_pattern_destroy (mask);
93

            
94
    return cairo_perf_timer_elapsed ();
95
}
96

            
97
static cairo_time_t
98
do_mask_image_half (cairo_t *cr, int width, int height, int loops)
99
{
100
    cairo_surface_t *surface;
101
    cairo_pattern_t *mask;
102
    cairo_matrix_t matrix;
103

            
104
    surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
105
    mask = cairo_pattern_create_for_surface (init_surface (surface,
106
							   width,
107
							   height));
108
    cairo_surface_destroy (surface);
109
    cairo_matrix_init_scale (&matrix, .5, .5);
110
    cairo_pattern_set_matrix (mask, &matrix);
111

            
112
    cairo_perf_timer_start ();
113

            
114
    while (loops--)
115
	cairo_mask (cr, mask);
116

            
117
    cairo_perf_timer_stop ();
118

            
119
    cairo_pattern_destroy (mask);
120

            
121
    return cairo_perf_timer_elapsed ();
122
}
123

            
124
static cairo_time_t
125
do_mask_image_double (cairo_t *cr, int width, int height, int loops)
126
{
127
    cairo_surface_t *surface;
128
    cairo_pattern_t *mask;
129
    cairo_matrix_t matrix;
130

            
131
    surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
132
    mask = cairo_pattern_create_for_surface (init_surface (surface,
133
							   width,
134
							   height));
135
    cairo_surface_destroy (surface);
136
    cairo_matrix_init_scale (&matrix, 2., 2.);
137
    cairo_pattern_set_matrix (mask, &matrix);
138

            
139
    cairo_perf_timer_start ();
140

            
141
    while (loops--)
142
	cairo_mask (cr, mask);
143

            
144
    cairo_perf_timer_stop ();
145

            
146
    cairo_pattern_destroy (mask);
147

            
148
    return cairo_perf_timer_elapsed ();
149
}
150

            
151
static cairo_time_t
152
do_mask_similar (cairo_t *cr, int width, int height, int loops)
153
{
154
    cairo_surface_t *surface;
155
    cairo_pattern_t *mask;
156

            
157
    surface = cairo_surface_create_similar (cairo_get_group_target (cr),
158
					    CAIRO_CONTENT_ALPHA, width, height);
159
    mask = cairo_pattern_create_for_surface (init_surface (surface,
160
							   width,
161
							   height));
162
    cairo_surface_destroy (surface);
163

            
164
    cairo_perf_timer_start ();
165

            
166
    while (loops--)
167
	cairo_mask (cr, mask);
168

            
169
    cairo_perf_timer_stop ();
170

            
171
    cairo_pattern_destroy (mask);
172

            
173
    return cairo_perf_timer_elapsed ();
174
}
175

            
176
static cairo_time_t
177
do_mask_similar_half (cairo_t *cr, int width, int height, int loops)
178
{
179
    cairo_surface_t *surface;
180
    cairo_pattern_t *mask;
181
    cairo_matrix_t matrix;
182

            
183
    surface = cairo_surface_create_similar (cairo_get_group_target (cr),
184
					    CAIRO_CONTENT_ALPHA, width, height);
185
    mask = cairo_pattern_create_for_surface (init_surface (surface,
186
							   width,
187
							   height));
188
    cairo_surface_destroy (surface);
189
    cairo_matrix_init_scale (&matrix, .5, .5);
190
    cairo_pattern_set_matrix (mask, &matrix);
191

            
192
    cairo_perf_timer_start ();
193

            
194
    while (loops--)
195
	cairo_mask (cr, mask);
196

            
197
    cairo_perf_timer_stop ();
198

            
199
    cairo_pattern_destroy (mask);
200

            
201
    return cairo_perf_timer_elapsed ();
202
}
203

            
204
static cairo_time_t
205
do_mask_similar_double (cairo_t *cr, int width, int height, int loops)
206
{
207
    cairo_surface_t *surface;
208
    cairo_pattern_t *mask;
209
    cairo_matrix_t matrix;
210

            
211
    surface = cairo_surface_create_similar (cairo_get_group_target (cr),
212
					    CAIRO_CONTENT_ALPHA, width, height);
213
    mask = cairo_pattern_create_for_surface (init_surface (surface,
214
							   width,
215
							   height));
216
    cairo_surface_destroy (surface);
217
    cairo_matrix_init_scale (&matrix, 2., 2.);
218
    cairo_pattern_set_matrix (mask, &matrix);
219

            
220
    cairo_perf_timer_start ();
221

            
222
    while (loops--)
223
	cairo_mask (cr, mask);
224

            
225
    cairo_perf_timer_stop ();
226

            
227
    cairo_pattern_destroy (mask);
228

            
229
    return cairo_perf_timer_elapsed ();
230
}
231

            
232
static cairo_time_t
233
do_mask_linear (cairo_t *cr, int width, int height, int loops)
234
{
235
    cairo_pattern_t *mask;
236

            
237
    mask = cairo_pattern_create_linear (0.0, 0.0, width, height);
238
    cairo_pattern_add_color_stop_rgba (mask, 0.0, 0, 0, 0, 0.5); /*  50% */
239
    cairo_pattern_add_color_stop_rgba (mask, 0.0, 0, 0, 0, 1.0); /* 100% */
240

            
241
    cairo_perf_timer_start ();
242

            
243
    while (loops--)
244
	cairo_mask (cr, mask);
245

            
246
    cairo_perf_timer_stop ();
247

            
248
    cairo_pattern_destroy (mask);
249

            
250
    return cairo_perf_timer_elapsed ();
251
}
252

            
253
static cairo_time_t
254
do_mask_radial (cairo_t *cr, int width, int height, int loops)
255
{
256
    cairo_pattern_t *mask;
257

            
258
    mask = cairo_pattern_create_radial (width/2.0, height/2.0, 0.0,
259
					width/2.0, height/2.0, width/2.0);
260
    cairo_pattern_add_color_stop_rgba (mask, 0.0, 0, 0, 0, 0.5); /*  50% */
261
    cairo_pattern_add_color_stop_rgba (mask, 0.0, 0, 0, 0, 1.0); /* 100% */
262

            
263
    cairo_perf_timer_start ();
264

            
265
    while (loops--)
266
	cairo_mask (cr, mask);
267

            
268
    cairo_perf_timer_stop ();
269

            
270
    cairo_pattern_destroy (mask);
271

            
272
    return cairo_perf_timer_elapsed ();
273
}
274

            
275
cairo_bool_t
276
mask_enabled (cairo_perf_t *perf)
277
{
278
    return cairo_perf_can_run (perf, "mask", NULL);
279
}
280

            
281
void
282
mask (cairo_perf_t *perf, cairo_t *cr, int width, int height)
283
{
284
    if (! cairo_perf_can_run (perf, "mask", NULL))
285
	return;
286

            
287
    cairo_perf_cover_sources_and_operators (perf, "mask-solid",
288
					    do_mask_solid, NULL);
289
    cairo_perf_cover_sources_and_operators (perf, "mask-image",
290
					    do_mask_image, NULL);
291
    cairo_perf_cover_sources_and_operators (perf, "mask-image-half",
292
					    do_mask_image_half, NULL);
293
    cairo_perf_cover_sources_and_operators (perf, "mask-image-double",
294
					    do_mask_image_double, NULL);
295
    cairo_perf_cover_sources_and_operators (perf, "mask-similar",
296
					    do_mask_similar, NULL);
297
    cairo_perf_cover_sources_and_operators (perf, "mask-similar-half",
298
					    do_mask_similar_half, NULL);
299
    cairo_perf_cover_sources_and_operators (perf, "mask-similar-double",
300
					    do_mask_similar_double, NULL);
301
    cairo_perf_cover_sources_and_operators (perf, "mask-linear",
302
					    do_mask_linear, NULL);
303
    cairo_perf_cover_sources_and_operators (perf, "mask-radial",
304
					    do_mask_radial, NULL);
305
}