Fix bug in _cairo_gl_has_extension
[platform/core/graphics/cairo.git] / src / cairo-compositor.c
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 © 2011 Intel Corporation
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it either under the terms of the GNU Lesser General Public
8  * License version 2.1 as published by the Free Software Foundation
9  * (the "LGPL") or, at your option, under the terms of the Mozilla
10  * Public License Version 1.1 (the "MPL"). If you do not alter this
11  * notice, a recipient may use your version of this file under either
12  * the MPL or the LGPL.
13  *
14  * You should have received a copy of the LGPL along with this library
15  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17  * You should have received a copy of the MPL along with this library
18  * in the file COPYING-MPL-1.1
19  *
20  * The contents of this file are subject to the Mozilla Public License
21  * Version 1.1 (the "License"); you may not use this file except in
22  * compliance with the License. You may obtain a copy of the License at
23  * http://www.mozilla.org/MPL/
24  *
25  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27  * the specific language governing rights and limitations.
28  *
29  * The Original Code is the cairo graphics library.
30  *
31  * The Initial Developer of the Original Code is University of Southern
32  * California.
33  *
34  * Contributor(s):
35  *      Chris Wilson <chris@chris-wilson.co.uk>
36  */
37
38 #include "cairoint.h"
39
40 #include "cairo-compositor-private.h"
41 #include "cairo-damage-private.h"
42 #include "cairo-error-private.h"
43 #include "cairo-ttrace.h"
44
45 cairo_int_status_t
46 _cairo_compositor_paint (const cairo_compositor_t       *compositor,
47                          cairo_surface_t                *surface,
48                          cairo_operator_t                op,
49                          const cairo_pattern_t          *source,
50                          const cairo_clip_t             *clip)
51 {
52     CAIRO_TRACE_BEGIN (__func__);
53     cairo_composite_rectangles_t extents;
54     cairo_int_status_t status;
55     cairo_bool_t initialized = TRUE;
56
57     TRACE ((stderr, "%s\n", __FUNCTION__));
58
59     if (compositor->lazy_init) {
60         status = _cairo_composite_rectangles_lazy_init_for_paint (&extents,
61                                                                   surface,
62                                                                   op, source,
63                                                                   clip);
64         initialized = FALSE;
65     }
66     else
67         status = _cairo_composite_rectangles_init_for_paint (&extents,
68                                                              surface,
69                                                              op, source,
70                                                              clip);
71     if (unlikely (status)) {
72         CAIRO_TRACE_END (__func__);
73                 return status;
74     }
75
76     do {
77         while (compositor->paint == NULL)
78             compositor = compositor->delegate;
79
80         if (! compositor->lazy_init && ! initialized) {
81             /* XXX: we should do better instead of re-init */
82             _cairo_composite_rectangles_fini (&extents);
83             status = _cairo_composite_rectangles_init_for_paint (&extents,
84                                                                  surface,
85                                                                  op, source,
86                                                                  clip);
87             initialized = TRUE;
88
89             if (unlikely (status)) {
90                 CAIRO_TRACE_END (__func__);
91                         return status;
92             }
93         }
94
95         status = compositor->paint (compositor, &extents);
96
97         compositor = compositor->delegate;
98     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
99
100     if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
101         TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
102                 __FUNCTION__,
103                 extents.unbounded.x, extents.unbounded.y,
104                 extents.unbounded.width, extents.unbounded.height));
105         surface->damage = _cairo_damage_add_rectangle (surface->damage,
106                                                        &extents.unbounded);
107     }
108
109     _cairo_composite_rectangles_fini (&extents);
110
111     CAIRO_TRACE_END (__func__);
112     return status;
113 }
114
115 cairo_int_status_t
116 _cairo_compositor_mask (const cairo_compositor_t        *compositor,
117                         cairo_surface_t                 *surface,
118                         cairo_operator_t                 op,
119                         const cairo_pattern_t           *source,
120                         const cairo_pattern_t           *mask,
121                         const cairo_clip_t              *clip)
122 {
123     CAIRO_TRACE_BEGIN (__func__);
124     cairo_composite_rectangles_t extents;
125     cairo_int_status_t status;
126     cairo_bool_t initialized = TRUE;
127
128     TRACE ((stderr, "%s\n", __FUNCTION__));
129
130     if (compositor->lazy_init) {
131         status = _cairo_composite_rectangles_lazy_init_for_mask (&extents,
132                                                                  surface,
133                                                                  op, source,
134                                                                  mask, clip);
135         initialized = FALSE;
136     } else
137         status = _cairo_composite_rectangles_init_for_mask (&extents,
138                                                             surface,
139                                                             op, source,
140                                                             mask, clip);
141     if (unlikely (status)) {
142                 CAIRO_TRACE_END (__func__);
143                 return status;
144     }
145
146     do {
147         while (compositor->mask == NULL)
148             compositor = compositor->delegate;
149
150         if (! compositor->lazy_init && ! initialized) {
151             /* XXX: we should do better instead of re-init */
152             _cairo_composite_rectangles_fini (&extents);
153             status = _cairo_composite_rectangles_init_for_mask (&extents,
154                                                                 surface,
155                                                                 op, source,
156                                                                 mask, clip);
157             initialized = TRUE;
158
159             if (unlikely (status)) {
160                         CAIRO_TRACE_END (__func__);
161                         return status;
162             }
163         }
164
165         status = compositor->mask (compositor, &extents);
166
167         compositor = compositor->delegate;
168     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
169
170     if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
171         TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
172                 __FUNCTION__,
173                 extents.unbounded.x, extents.unbounded.y,
174                 extents.unbounded.width, extents.unbounded.height));
175         surface->damage = _cairo_damage_add_rectangle (surface->damage,
176                                                        &extents.unbounded);
177     }
178
179     _cairo_composite_rectangles_fini (&extents);
180
181     CAIRO_TRACE_END (__func__);
182     return status;
183 }
184
185 cairo_int_status_t
186 _cairo_compositor_stroke (const cairo_compositor_t      *compositor,
187                           cairo_surface_t               *surface,
188                           cairo_operator_t               op,
189                           const cairo_pattern_t         *source,
190                           const cairo_path_fixed_t      *path,
191                           const cairo_stroke_style_t    *style,
192                           const cairo_matrix_t          *ctm,
193                           const cairo_matrix_t          *ctm_inverse,
194                           double                         tolerance,
195                           cairo_antialias_t              antialias,
196                           const cairo_clip_t            *clip)
197 {
198     CAIRO_TRACE_BEGIN (__func__);
199     cairo_composite_rectangles_t extents;
200     cairo_int_status_t status;
201     cairo_bool_t initialized = TRUE;
202
203     TRACE ((stderr, "%s\n", __FUNCTION__));
204
205     if (_cairo_pen_vertices_needed (tolerance, style->line_width/2, ctm) <= 1) {
206                 CAIRO_TRACE_END (__func__);
207                 return CAIRO_INT_STATUS_NOTHING_TO_DO;
208     }
209
210     if (compositor->lazy_init) {
211         status = _cairo_composite_rectangles_lazy_init_for_stroke (&extents,
212                                                                    surface,
213                                                                    op, source,
214                                                                    path, style,
215                                                                    ctm, clip);
216         initialized = FALSE;
217     }
218     else
219         status = _cairo_composite_rectangles_init_for_stroke (&extents,
220                                                               surface,
221                                                               op, source,
222                                                               path, style,
223                                                               ctm, clip);
224     if (unlikely (status)) {
225                 CAIRO_TRACE_END (__func__);
226                 return status;
227     }
228
229     do {
230         while (compositor->stroke == NULL)
231             compositor = compositor->delegate;
232
233         if (! compositor->lazy_init && ! initialized) {
234             /* XXX: we should do better instead of re-init */
235             _cairo_composite_rectangles_fini (&extents);
236             status = _cairo_composite_rectangles_init_for_stroke (&extents,
237                                                                   surface,
238                                                                   op,
239                                                                   source,
240                                                                   path,
241                                                                   style,
242                                                                   ctm,
243                                                                   clip);
244             initialized = TRUE;
245
246             if (unlikely (status)) {
247                         CAIRO_TRACE_END (__func__);
248                         return status;
249             }
250         }
251
252         status = compositor->stroke (compositor, &extents,
253                                      path, style, ctm, ctm_inverse,
254                                      tolerance, antialias);
255
256         compositor = compositor->delegate;
257     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
258
259     if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
260         TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
261                 __FUNCTION__,
262                 extents.unbounded.x, extents.unbounded.y,
263                 extents.unbounded.width, extents.unbounded.height));
264         surface->damage = _cairo_damage_add_rectangle (surface->damage,
265                                                        &extents.unbounded);
266     }
267
268     _cairo_composite_rectangles_fini (&extents);
269
270     CAIRO_TRACE_END (__func__);
271     return status;
272 }
273
274 cairo_int_status_t
275 _cairo_compositor_fill (const cairo_compositor_t        *compositor,
276                         cairo_surface_t                 *surface,
277                         cairo_operator_t                 op,
278                         const cairo_pattern_t           *source,
279                         const cairo_path_fixed_t        *path,
280                         cairo_fill_rule_t                fill_rule,
281                         double                           tolerance,
282                         cairo_antialias_t                antialias,
283                         const cairo_clip_t              *clip)
284 {
285     CAIRO_TRACE_BEGIN (__func__);
286     cairo_composite_rectangles_t extents;
287     cairo_int_status_t status;
288     cairo_bool_t initialized = TRUE;
289
290     TRACE ((stderr, "%s\n", __FUNCTION__));
291
292     if (compositor->lazy_init) {
293         status = _cairo_composite_rectangles_lazy_init_for_fill (&extents,
294                                                                  surface,
295                                                                  op, source,
296                                                                  path, clip);
297         initialized = FALSE;
298     }
299     else
300         status = _cairo_composite_rectangles_init_for_fill (&extents,
301                                                             surface,
302                                                             op, source,
303                                                             path, clip);
304     if (unlikely (status)) {
305                 CAIRO_TRACE_END (__func__);
306                 return status;
307     }
308
309     do {
310         while (compositor->fill == NULL)
311             compositor = compositor->delegate;
312
313         if (! compositor->lazy_init && ! initialized) {
314             /* XXX: we should do better instead of re-init */
315             _cairo_composite_rectangles_fini (&extents);
316             status = _cairo_composite_rectangles_init_for_fill (&extents,
317                                                                 surface,
318                                                                 op, source,
319                                                                 path, clip);
320             initialized = TRUE;
321
322             if (unlikely (status)) {
323                         CAIRO_TRACE_END (__func__);
324                         return status;
325             }
326         }
327
328         status = compositor->fill (compositor, &extents,
329                                    path, fill_rule, tolerance, antialias);
330
331         compositor = compositor->delegate;
332     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
333
334     if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
335         TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
336                 __FUNCTION__,
337                 extents.unbounded.x, extents.unbounded.y,
338                 extents.unbounded.width, extents.unbounded.height));
339         surface->damage = _cairo_damage_add_rectangle (surface->damage,
340                                                        &extents.unbounded);
341     }
342
343     _cairo_composite_rectangles_fini (&extents);
344
345     CAIRO_TRACE_END (__func__);
346     return status;
347 }
348
349 cairo_int_status_t
350 _cairo_compositor_glyphs (const cairo_compositor_t              *compositor,
351                           cairo_surface_t                       *surface,
352                           cairo_operator_t                       op,
353                           const cairo_pattern_t                 *source,
354                           cairo_glyph_t                         *glyphs,
355                           int                                    num_glyphs,
356                           cairo_scaled_font_t                   *scaled_font,
357                           const cairo_clip_t                    *clip)
358 {
359     CAIRO_TRACE_BEGIN (__func__);
360     cairo_composite_rectangles_t extents;
361     cairo_bool_t overlap;
362     cairo_int_status_t status;
363     cairo_bool_t initialized = TRUE;
364
365     TRACE ((stderr, "%s\n", __FUNCTION__));
366
367     if (compositor->lazy_init) {
368         status = _cairo_composite_rectangles_lazy_init_for_glyphs (&extents, surface,
369                                                                   op, source,
370                                                                   scaled_font,
371                                                                   glyphs, num_glyphs,
372                                                                   clip, &overlap);
373         initialized = FALSE;
374     } else
375         status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
376                                                              op, source,
377                                                              scaled_font,
378                                                              glyphs, num_glyphs,
379                                                              clip, &overlap);
380     if (unlikely (status)) {
381                 CAIRO_TRACE_END (__func__);
382                 return status;
383     }
384
385     do {
386         while (compositor->glyphs == NULL)
387             compositor = compositor->delegate;
388
389         if (! compositor->lazy_init && ! initialized) {
390             /* XXX: we should do better instead of re-init */
391             _cairo_composite_rectangles_fini (&extents);
392             status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
393                                                                  op, source,
394                                                                  scaled_font,
395                                                                  glyphs, num_glyphs,
396                                                                  clip, &overlap);
397             initialized = TRUE;
398
399             if (unlikely (status)) {
400                         CAIRO_TRACE_END (__func__);
401                         return status;
402             }
403         }
404
405         status = compositor->glyphs (compositor, &extents,
406                                      scaled_font, glyphs, num_glyphs, overlap);
407
408         compositor = compositor->delegate;
409     } while (status == CAIRO_INT_STATUS_UNSUPPORTED);
410
411     if (status == CAIRO_INT_STATUS_SUCCESS && surface->damage) {
412         TRACE ((stderr, "%s: applying damage (%d,%d)x(%d, %d)\n",
413                 __FUNCTION__,
414                 extents.unbounded.x, extents.unbounded.y,
415                 extents.unbounded.width, extents.unbounded.height));
416         surface->damage = _cairo_damage_add_rectangle (surface->damage,
417                                                        &extents.unbounded);
418     }
419
420     _cairo_composite_rectangles_fini (&extents);
421
422     CAIRO_TRACE_END (__func__);
423     return status;
424 }