Upload Tizen2.0 source
[framework/graphics/cairo.git] / perf / micro / dragon.c
1 /*
2  * Copyright © 2007 Chris Wilson
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of
9  * Chris Wilson not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior
11  * permission. Chris Wilson makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
18  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author: Chris Wilson <chris@chris-wilson.co.uk>
24  *
25  * Inspiration (and path!) taken from
26  * http://labs.trolltech.com/blogs/2007/08/31/rasterizing-dragons/
27  */
28
29 #include "cairo-perf.h"
30
31 #ifndef MIN
32 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
33 #endif
34
35 #ifndef MAX
36 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
37 #endif
38
39 static inline int
40 next_pot (int v)
41 {
42     v--;
43     v |= v >> 1;
44     v |= v >> 2;
45     v |= v >> 4;
46     v |= v >> 8;
47     v |= v >> 16;
48     v++;
49     return v;
50 }
51
52 static cairo_bool_t
53 direction (int i)
54 {
55     int pivot, np2;
56
57     if (i < 2)
58         return TRUE;
59
60     np2 = next_pot (i + 1);
61     if (np2 == i + 1)
62         return TRUE;
63
64     pivot = np2 / 2 - 1;
65     return ! direction (2 * pivot - i);
66 }
67
68 static void
69 path (cairo_t *cr, int step, int dir, int iterations)
70 {
71     double dx, dy;
72     int i;
73
74     switch (dir) {
75         default:
76         case 0: dx =  step; dy =  0; break;
77         case 1: dx = -step; dy =  0; break;
78         case 2: dx =  0; dy =  step; break;
79         case 3: dx =  0; dy = -step; break;
80     }
81
82     for (i = 0; i < iterations; i++) {
83         cairo_rel_line_to (cr, dx, dy);
84
85         if (direction (i)) {
86             double t = dx;
87             dx = dy;
88             dy = -t;
89         } else {
90             double t = dx;
91             dx = -dy;
92             dy = t;
93         }
94     }
95 }
96
97 static cairo_time_t
98 do_dragon (cairo_t *cr, int width, int height, int loops)
99 {
100     cairo_pattern_t *pattern;
101     double cx, cy, r;
102
103     cx = cy = .5 * MAX (width, height);
104     r = .5 * MIN (width, height);
105
106     cairo_perf_timer_start ();
107     cairo_perf_set_thread_aware (cr, FALSE);
108
109     while (loops--) {
110         if (loops == 0)
111                 cairo_perf_set_thread_aware (cr, TRUE);
112         pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
113         cairo_pattern_add_color_stop_rgb (pattern, 0., .0, .0, .0);
114         cairo_pattern_add_color_stop_rgb (pattern, 0.25, .5, .4, .4);
115         cairo_pattern_add_color_stop_rgb (pattern, .5, .8, .8, .9);
116         cairo_pattern_add_color_stop_rgb (pattern, 1., .9, .9, 1.);
117         cairo_set_source (cr, pattern);
118         cairo_pattern_destroy (pattern);
119         cairo_paint (cr);
120
121         cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
122         cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
123         cairo_set_line_width (cr, 4.);
124
125         cairo_move_to (cr, cx, cy);
126         path (cr, 12, 0, 2048);
127         pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
128         cairo_pattern_add_color_stop_rgb (pattern, 0., 1., 1., 1.);
129         cairo_pattern_add_color_stop_rgb (pattern, 1., 0., 0., 0.);
130         cairo_set_source (cr, pattern);
131         cairo_pattern_destroy (pattern);
132         cairo_stroke(cr);
133
134         cairo_move_to (cr, cx, cy);
135         path (cr, 12, 1, 2048);
136         pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
137         cairo_pattern_add_color_stop_rgb (pattern, 1., 1., 1., 0.);
138         cairo_pattern_add_color_stop_rgb (pattern, 0., 1., 0., 0.);
139         cairo_set_source (cr, pattern);
140         cairo_pattern_destroy (pattern);
141         cairo_stroke(cr);
142
143         cairo_move_to (cr, cx, cy);
144         path (cr, 12, 2, 2048);
145         pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
146         cairo_pattern_add_color_stop_rgb (pattern, 1., 0., 1., 1.);
147         cairo_pattern_add_color_stop_rgb (pattern, 0., 0., 1., 0.);
148         cairo_set_source (cr, pattern);
149         cairo_pattern_destroy (pattern);
150         cairo_stroke(cr);
151
152         cairo_move_to (cr, cx, cy);
153         path (cr, 12, 3, 2048);
154         pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
155         cairo_pattern_add_color_stop_rgb (pattern, 1., 1., 0., 1.);
156         cairo_pattern_add_color_stop_rgb (pattern, 0., 0., 0., 1.);
157         cairo_set_source (cr, pattern);
158         cairo_pattern_destroy (pattern);
159         cairo_stroke(cr);
160     }
161
162     cairo_perf_timer_stop ();
163
164     return cairo_perf_timer_elapsed ();
165 }
166
167 static cairo_time_t
168 do_dragon_solid (cairo_t *cr, int width, int height, int loops)
169 {
170     double cx, cy;
171
172     cx = cy = .5 * MAX (width, height);
173
174     cairo_perf_timer_start ();
175     cairo_perf_set_thread_aware (cr, FALSE);
176
177     while (loops--) {
178         if (loops == 0)
179                 cairo_perf_set_thread_aware (cr, TRUE);
180         cairo_set_source_rgb (cr, 0, 0, 0);
181         cairo_paint (cr);
182
183         cairo_set_line_width (cr, 4.);
184
185         cairo_move_to (cr, cx, cy);
186         path (cr, 12, 0, 2048);
187         cairo_set_source_rgb (cr, 1, 0, 0);
188         cairo_stroke(cr);
189
190         cairo_move_to (cr, cx, cy);
191         path (cr, 12, 1, 2048);
192         cairo_set_source_rgb (cr, 0, 1, 0);
193         cairo_stroke(cr);
194
195         cairo_move_to (cr, cx, cy);
196         path (cr, 12, 2, 2048);
197         cairo_set_source_rgb (cr, 0, 0, 1);
198         cairo_stroke(cr);
199
200         cairo_move_to (cr, cx, cy);
201         path (cr, 12, 3, 2048);
202         cairo_set_source_rgb (cr, 1, 1, 1);
203         cairo_stroke(cr);
204     }
205
206     cairo_perf_timer_stop ();
207
208     return cairo_perf_timer_elapsed ();
209 }
210
211 static cairo_time_t
212 do_dragon_solid_unaligned (cairo_t *cr, int width, int height, int loops)
213 {
214     cairo_translate (cr, 0.01, 0.01);
215     return do_dragon_solid (cr, width, height, loops);
216 }
217
218 static cairo_time_t
219 do_dragon_solid_aligned_clip (cairo_t *cr, int width, int height, int loops)
220 {
221     cairo_reset_clip (cr);
222     cairo_rectangle (cr, 10, 10, width/2 + 10, height/2 + 10);
223     cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 10, height/2 + 10);
224     cairo_clip (cr);
225
226     return do_dragon_solid (cr, width, height, loops);
227 }
228
229 static cairo_time_t
230 do_dragon_unaligned_solid_aligned_clip (cairo_t *cr, int width, int height, int loops)
231 {
232     cairo_translate (cr, 0.01, 0.01);
233     cairo_reset_clip (cr);
234     cairo_rectangle (cr, 10, 10, width/2 + 10, height/2 + 10);
235     cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 10, height/2 + 10);
236     cairo_clip (cr);
237
238     return do_dragon_solid (cr, width, height, loops);
239 }
240
241 static cairo_time_t
242 do_dragon_solid_unaligned_clip (cairo_t *cr, int width, int height, int loops)
243 {
244     cairo_reset_clip (cr);
245     cairo_rectangle (cr, 10.5, 10.5, width/2 + 10, height/2 + 10);
246     cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 9.5, height/2 + 9.5);
247     cairo_clip (cr);
248
249     return do_dragon_solid (cr, width, height, loops);
250 }
251
252 static cairo_time_t
253 do_dragon_unaligned_solid_unaligned_clip (cairo_t *cr, int width, int height, int loops)
254 {
255     cairo_translate (cr, 0.01, 0.01);
256     cairo_reset_clip (cr);
257     cairo_rectangle (cr, 10.5, 10.5, width/2 + 10, height/2 + 10);
258     cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 9.5, height/2 + 9.5);
259     cairo_clip (cr);
260
261     return do_dragon_solid (cr, width, height, loops);
262 }
263
264 static cairo_time_t
265 do_dragon_solid_circle_clip (cairo_t *cr, int width, int height, int loops)
266 {
267     cairo_reset_clip (cr);
268     cairo_arc (cr, width/2., height/2., MIN (width, height)/2. - 10, 0, 2 * M_PI);
269     cairo_clip (cr);
270
271     return do_dragon_solid (cr, width, height, loops);
272 }
273
274 cairo_bool_t
275 dragon_enabled (cairo_perf_t *perf)
276 {
277     return cairo_perf_can_run (perf, "dragon", NULL);
278 }
279
280 void
281 dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
282 {
283     cairo_perf_run (perf, "dragon-solid", do_dragon_solid, NULL);
284     cairo_perf_run (perf, "dragon-unaligned-solid", do_dragon_solid_unaligned, NULL);
285     cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip, NULL);
286     cairo_perf_run (perf, "dragon-unaligned-solid-aligned-clip", do_dragon_unaligned_solid_aligned_clip, NULL);
287     cairo_perf_run (perf, "dragon-solid-unaligned-clip", do_dragon_solid_unaligned_clip, NULL);
288     cairo_perf_run (perf, "dragon-unaligned-solid-unaligned-clip", do_dragon_unaligned_solid_unaligned_clip, NULL);
289     cairo_perf_run (perf, "dragon-solid-circle-clip", do_dragon_solid_circle_clip, NULL);
290     cairo_perf_run (perf, "dragon", do_dragon, NULL);
291 }