tizen 2.3.1 release
[framework/graphics/cairo.git] / src / cairo-tg-surface.c
1 /*
2  * Copyright © 2012 SCore Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it either under the terms of the GNU Lesser General Public
6  * License version 2.1 as published by the Free Software Foundation
7  * (the "LGPL") or, at your option, under the terms of the Mozilla
8  * Public License Version 1.1 (the "MPL"). If you do not alter this
9  * notice, a recipient may use your version of this file under either
10  * the MPL or the LGPL.
11  *
12  * You should have received a copy of the LGPL along with this library
13  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
15  * You should have received a copy of the MPL along with this library
16  * in the file COPYING-MPL-1.1
17  *
18  * The contents of this file are subject to the Mozilla Public License
19  * Version 1.1 (the "License"); you may not use this file except in
20  * compliance with the License. You may obtain a copy of the License at
21  * http://www.mozilla.org/MPL/
22  *
23  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
24  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
25  * the specific language governing rights and limitations.
26  *
27  * Author: Taekyun Kim (podain77@gmail.com)
28  */
29
30 #include "cairoint.h"
31 #include "cairo-surface-fallback-private.h"
32 #include "cairo-tg.h"
33 #include "cairo-tg-private.h"
34 #include "cairo-image-surface-inline.h"
35 #include "cairo-surface-subsurface-inline.h"
36 #include "cairo-compositor-private.h"
37 #include "cairo-clip-inline.h"
38 #include "cairo-recording-surface-inline.h"
39
40 #if CAIRO_HAS_OPENMP
41 #include <omp.h>
42 #endif
43
44 #define CAIRO_TG_THREAD_POOL_BUSY_WAIT
45 #define CAIRO_TG_NUM_MIN_ENTRIES_FOR_PARALLEL_FLUSH 2
46
47 static inline int
48 get_num_cpu_cores (void)
49 {
50     static int num_cpu_cores = 0;
51
52     if (num_cpu_cores == 0)
53     {
54 #if CAIRO_HAS_OPENMP
55         num_cpu_cores = omp_get_num_procs ();
56 #elif defined (__WIN32)
57         SYSTEM_INFO sysinfo;
58
59         GetSystemInfo (&sysinfo);
60         num_cpu_cores = sysinfo.dwNumberOfProcessors;
61 #elif defined (__linux__)
62         cpu_set_t   cs;
63         int         i;
64
65         CPU_ZERO (&cs);
66
67         if (sched_getaffinity (0, sizeof (cs), &cs) != 0)
68             num_cpu_cores = 1;
69
70         for (i = 0; i < 8; i++)
71         {
72             if (CPU_ISSET (i, &cs))
73                 num_cpu_cores++;
74         }
75 #else
76         num_cpu_cores = 1;
77 #endif
78     }
79
80     return num_cpu_cores;
81 }
82
83 static inline int
84 get_bpp_for_format (cairo_format_t format)
85 {
86     switch (format)
87     {
88     case CAIRO_FORMAT_ARGB32:
89     case CAIRO_FORMAT_RGB24:
90     case CAIRO_FORMAT_RGB30:
91         return 32;
92     case CAIRO_FORMAT_RGB16_565:
93         return 16;
94     case CAIRO_FORMAT_A8:
95         return 8;
96     case CAIRO_FORMAT_A1:
97         return 1;
98     case CAIRO_FORMAT_INVALID:
99     default:
100         ASSERT_NOT_REACHED;
101         return 0;
102     }
103 }
104
105 static inline cairo_bool_t
106 _cairo_surface_is_tg(const cairo_surface_t *surface)
107 {
108     return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_TG;
109 }
110
111 static inline cairo_bool_t
112 _cairo_tg_surface_is_size_valid (int width, int height)
113 {
114     if (width < 0 || height < 0)
115         return FALSE;
116
117     /* TODO: Check for upper limit of surface size. */
118
119     return TRUE;
120 }
121
122 static inline cairo_bool_t
123 _cairo_pattern_is_self_copy (cairo_surface_t        *surface,
124                              const cairo_pattern_t  *pattern)
125 {
126     if (unlikely (surface == NULL))
127         return FALSE;
128
129     if (unlikely (pattern == NULL))
130         return FALSE;
131
132     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE )
133     {
134         cairo_surface_t *pattern_surface =
135             ((cairo_surface_pattern_t *) pattern)->surface;
136
137         while (_cairo_surface_is_subsurface (pattern_surface))
138         {
139             pattern_surface =
140                 _cairo_surface_subsurface_get_target (pattern_surface);
141         }
142
143         return pattern_surface == surface;
144     }
145
146     return FALSE;
147 }
148
149 static inline cairo_bool_t
150 _cairo_pattern_is_recording (const cairo_pattern_t *pattern)
151 {
152     cairo_surface_t *surface;
153
154     if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
155         return FALSE;
156
157     surface = ((const cairo_surface_pattern_t *) pattern)->surface;
158     return _cairo_surface_is_recording (surface);
159 }
160
161 static inline cairo_bool_t
162 _cairo_tg_surface_owns_data (cairo_tg_surface_t *surface)
163 {
164     return ((cairo_image_surface_t *) surface->image_surface)->owns_data;
165 }
166
167 static inline cairo_int_status_t
168 _cairo_tg_image_surface_paint (void                     *closure,
169                                cairo_operator_t         op,
170                                const cairo_pattern_t    *source,
171                                const cairo_clip_t       *clip)
172 {
173     cairo_image_surface_t   *surface = (cairo_image_surface_t *) closure;
174     cairo_int_status_t status;
175
176     status = _cairo_surface_begin_modification (&surface->base);
177
178     if (unlikely (status))
179         return status;
180
181     status = _cairo_compositor_paint (surface->compositor, &surface->base,
182                                       op, source, clip);
183
184     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
185     {
186         surface->base.is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
187         surface->base.serial++;
188     }
189
190     return status;
191 }
192
193 static inline cairo_int_status_t
194 _cairo_tg_image_surface_mask (void                      *closure,
195                               cairo_operator_t          op,
196                               const cairo_pattern_t     *source,
197                               const cairo_pattern_t     *mask,
198                               const cairo_clip_t        *clip)
199 {
200     cairo_image_surface_t   *surface = (cairo_image_surface_t *) closure;
201     cairo_int_status_t status;
202
203     status = _cairo_surface_begin_modification (&surface->base);
204
205     if (unlikely (status))
206         return status;
207
208     status = _cairo_compositor_mask (surface->compositor, &surface->base,
209                                      op, source, mask, clip);
210
211     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
212     {
213         surface->base.is_clear = FALSE;
214         surface->base.serial++;
215     }
216
217     return status;
218 }
219
220 static inline cairo_int_status_t
221 _cairo_tg_image_surface_stroke (void                        *closure,
222                                 cairo_operator_t            op,
223                                 const cairo_pattern_t       *source,
224                                 const cairo_path_fixed_t    *path,
225                                 const cairo_stroke_style_t  *style,
226                                 const cairo_matrix_t        *ctm,
227                                 const cairo_matrix_t        *ctm_inverse,
228                                 double                      tolerance,
229                                 cairo_antialias_t           antialias,
230                                 const cairo_clip_t          *clip)
231 {
232     cairo_image_surface_t   *surface = (cairo_image_surface_t *) closure;
233     cairo_int_status_t status;
234
235     status = _cairo_surface_begin_modification (&surface->base);
236
237     if (unlikely (status))
238         return status;
239
240     status =  _cairo_compositor_stroke (surface->compositor, &surface->base,
241                                         op, source, path,
242                                         style, ctm, ctm_inverse,
243                                         tolerance, antialias, clip);
244
245     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
246     {
247         surface->base.is_clear = FALSE;
248         surface->base.serial++;
249     }
250
251     return status;
252 }
253
254
255 static inline cairo_int_status_t
256 _cairo_tg_image_surface_fill (void                      *closure,
257                               cairo_operator_t          op,
258                               const cairo_pattern_t     *source,
259                               const cairo_path_fixed_t  *path,
260                               cairo_fill_rule_t         fill_rule,
261                               double                    tolerance,
262                               cairo_antialias_t         antialias,
263                               const cairo_clip_t        *clip)
264 {
265     cairo_image_surface_t   *surface = (cairo_image_surface_t *) closure;
266     cairo_int_status_t status;
267
268     status = _cairo_surface_begin_modification (&surface->base);
269
270     if (unlikely (status))
271         return status;
272
273     status = _cairo_compositor_fill (surface->compositor, &surface->base,
274                                      op, source, path,
275                                      fill_rule, tolerance, antialias, clip);
276
277     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
278     {
279         surface->base.is_clear = FALSE;
280         surface->base.serial++;
281     }
282
283     return status;
284 }
285
286 static inline cairo_int_status_t
287 _cairo_tg_image_surface_glyphs (void                    *closure,
288                                 cairo_operator_t        op,
289                                 const cairo_pattern_t   *source,
290                                 cairo_glyph_t           *glyphs,
291                                 int                     num_glyphs,
292                                 cairo_scaled_font_t     *scaled_font,
293                                 const cairo_clip_t      *clip)
294 {
295     cairo_image_surface_t   *surface = (cairo_image_surface_t *) closure;
296     cairo_int_status_t status;
297
298     status = _cairo_surface_begin_modification (&surface->base);
299
300     if (unlikely (status))
301         return status;
302
303     status = _cairo_compositor_glyphs (surface->compositor, &surface->base,
304                                        op, source,
305                                        glyphs, num_glyphs, scaled_font,
306                                        clip);
307
308     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO)
309     {
310         surface->base.is_clear = FALSE;
311         surface->base.serial++;
312     }
313
314     return status;
315 }
316
317 const cairo_tg_journal_replay_funcs_t replay_funcs_image_fallback =
318 {
319     _cairo_tg_image_surface_paint,
320     _cairo_tg_image_surface_mask,
321     _cairo_tg_image_surface_stroke,
322     _cairo_tg_image_surface_fill,
323     _cairo_tg_image_surface_glyphs,
324 };
325
326 typedef struct _cairo_tg_surface_tile
327 {
328     cairo_surface_t         *surface;
329     cairo_rectangle_int_t   tile_rect;
330 } cairo_tg_surface_tile_t;
331
332 static inline int
333 _cairo_tg_surface_tiles_init (cairo_tg_surface_t            *surface,
334                               const cairo_rectangle_int_t   *extents,
335                               int                           num_tiles,
336                               cairo_tg_surface_tile_t       *tiles)
337 {
338     int tile_height;
339     int i;
340
341     if (extents->height <= 0)
342         return 0;
343
344     if (extents->height <= num_tiles)
345         num_tiles = extents->height;
346
347     tile_height = extents->height / num_tiles;
348
349     for (i = 0; i < num_tiles; i++)
350     {
351         tiles[i].surface = surface->tile_surfaces[i];
352         tiles[i].tile_rect.x = extents->x;
353         tiles[i].tile_rect.y = extents->y + i * tile_height;
354         tiles[i].tile_rect.width = extents->width;
355         tiles[i].tile_rect.height = tile_height;
356     }
357
358     tiles[num_tiles - 1].tile_rect.height = extents->height - i * (num_tiles - 1);
359
360     return num_tiles;
361 }
362
363 static cairo_int_status_t
364 _cairo_tg_surface_tile_paint (void                  *closure,
365                               cairo_operator_t      op,
366                               const cairo_pattern_t *source,
367                               const cairo_clip_t    *clip)
368 {
369     cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
370     cairo_clip_t            *tile_clip;
371     cairo_int_status_t      status = CAIRO_INT_STATUS_SUCCESS;
372
373     tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
374
375     if (! _cairo_clip_is_all_clipped (tile_clip))
376         status = _cairo_tg_image_surface_paint (tile->surface, op, source, tile_clip);
377
378     _cairo_clip_destroy (tile_clip);
379
380     return status;
381 }
382
383 static cairo_int_status_t
384 _cairo_tg_surface_tile_mask (void                   *closure,
385                              cairo_operator_t       op,
386                              const cairo_pattern_t  *source,
387                              const cairo_pattern_t  *mask,
388                              const cairo_clip_t     *clip)
389 {
390     cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
391     cairo_clip_t            *tile_clip;
392     cairo_int_status_t      status = CAIRO_INT_STATUS_SUCCESS;
393
394     tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
395
396     if (! _cairo_clip_is_all_clipped (tile_clip))
397     {
398         status = _cairo_tg_image_surface_mask (tile->surface, op, source,
399                                                mask, tile_clip);
400     }
401
402     _cairo_clip_destroy (tile_clip);
403
404     return status;
405 }
406
407 static cairo_int_status_t
408 _cairo_tg_surface_tile_stroke (void                         *closure,
409                                cairo_operator_t             op,
410                                const cairo_pattern_t        *source,
411                                const cairo_path_fixed_t     *path,
412                                const cairo_stroke_style_t   *style,
413                                const cairo_matrix_t         *ctm,
414                                const cairo_matrix_t         *ctm_inverse,
415                                double                       tolerance,
416                                cairo_antialias_t            antialias,
417                                const cairo_clip_t           *clip)
418 {
419     cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
420     cairo_clip_t            *tile_clip;
421     cairo_int_status_t      status = CAIRO_INT_STATUS_SUCCESS;
422
423     tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
424
425     if (! _cairo_clip_is_all_clipped (tile_clip))
426     {
427         status = _cairo_tg_image_surface_stroke (tile->surface, op, source,
428                                                  path, style, ctm, ctm_inverse,
429                                                  tolerance, antialias, tile_clip);
430     }
431
432     _cairo_clip_destroy (tile_clip);
433
434     return status;
435 }
436
437 static cairo_int_status_t
438 _cairo_tg_surface_tile_fill (void                       *closure,
439                              cairo_operator_t           op,
440                              const cairo_pattern_t      *source,
441                              const cairo_path_fixed_t   *path,
442                              cairo_fill_rule_t          fill_rule,
443                              double                     tolerance,
444                              cairo_antialias_t          antialias,
445                              const cairo_clip_t         *clip)
446 {
447     cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
448     cairo_clip_t            *tile_clip;
449     cairo_int_status_t      status = CAIRO_INT_STATUS_SUCCESS;
450
451     tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
452
453     if (! _cairo_clip_is_all_clipped (tile_clip))
454     {
455         status = _cairo_tg_image_surface_fill (tile->surface, op, source,
456                                                path, fill_rule, tolerance,
457                                                antialias, tile_clip);
458     }
459
460     _cairo_clip_destroy (tile_clip);
461
462     return status;
463 }
464
465 static cairo_int_status_t
466 _cairo_tg_surface_tile_glyphs (void                     *closure,
467                                cairo_operator_t         op,
468                                const cairo_pattern_t    *source,
469                                cairo_glyph_t            *glyphs,
470                                int                      num_glyphs,
471                                cairo_scaled_font_t      *scaled_font,
472                                const cairo_clip_t       *clip)
473 {
474     cairo_tg_surface_tile_t *tile = (cairo_tg_surface_tile_t *) closure;
475     cairo_clip_t            *tile_clip;
476     cairo_int_status_t      status = CAIRO_INT_STATUS_SUCCESS;
477
478     tile_clip = _cairo_clip_copy_intersect_rectangle (clip, &tile->tile_rect);
479
480     if (! _cairo_clip_is_all_clipped (tile_clip))
481     {
482         status = _cairo_tg_image_surface_glyphs (tile->surface, op, source,
483                                                  glyphs, num_glyphs, scaled_font,
484                                                  tile_clip);
485     }
486
487     _cairo_clip_destroy (tile_clip);
488
489     return status;
490 }
491
492 const cairo_tg_journal_replay_funcs_t replay_funcs_tile =
493 {
494     _cairo_tg_surface_tile_paint,
495     _cairo_tg_surface_tile_mask,
496     _cairo_tg_surface_tile_stroke,
497     _cairo_tg_surface_tile_fill,
498     _cairo_tg_surface_tile_glyphs,
499 };
500
501 #if ! CAIRO_HAS_OPENMP
502 #define CAIRO_TG_NUM_MAX_WORKERS    CAIRO_TG_NUM_MAX_TILES
503
504 typedef enum _cairo_tg_worker_status
505 {
506     CAIRO_TG_WORKER_STATUS_IDLE,        /* can transit to either OCCUPIED or KILLED */
507     CAIRO_TG_WORKER_STATUS_TO_DO,       /* only can transit to IDLE state */
508     CAIRO_TG_WORKER_STATUS_KILLED,      /* worker will be no longer valid */
509 } cairo_tg_worker_status_t;
510
511 typedef struct _cairo_tg_worker
512 {
513     cairo_tg_journal_t          *journal;
514     cairo_tg_surface_tile_t     *tile;
515
516     pthread_t                   thread;
517     pthread_mutex_t             lock;
518     pthread_cond_t              cond_wake_up;
519     cairo_tg_worker_status_t    status;
520
521 #ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
522     pthread_spinlock_t          spinlock;
523 #else
524     pthread_cond_t              cond_done;
525 #endif
526 } cairo_tg_worker_t;
527
528 cairo_tg_worker_t   workers[CAIRO_TG_NUM_MAX_WORKERS];
529
530 pthread_mutex_t workers_lock;
531 cairo_bool_t    workers_occupied;
532
533 static void *
534 _cairo_tg_worker_mainloop (void *arg)
535 {
536     cairo_tg_worker_t   *worker = (cairo_tg_worker_t *) arg;
537
538     while (1)
539     {
540         pthread_mutex_lock (&worker->lock);
541
542         while (worker->status == CAIRO_TG_WORKER_STATUS_IDLE)
543             pthread_cond_wait (&worker->cond_wake_up, &worker->lock);
544
545         /* Here, worker is kicked off to do some action. */
546
547         if (worker->status == CAIRO_TG_WORKER_STATUS_KILLED)
548         {
549             /* Worker is killed, so release mutex and exit. */
550             pthread_mutex_unlock (&worker->lock);
551             pthread_exit (NULL);
552         }
553
554         assert (worker->status == CAIRO_TG_WORKER_STATUS_TO_DO);
555
556         _cairo_tg_journal_replay (worker->journal, (void *)worker->tile,
557                                   &worker->tile->tile_rect, &replay_funcs_tile);
558
559         worker->status = CAIRO_TG_WORKER_STATUS_IDLE;
560
561 #ifndef CAIRO_TG_THREAD_POOL_BUSY_WAIT
562         pthread_cond_signal (&worker->cond_done);
563 #endif
564
565         pthread_mutex_unlock (&worker->lock);
566     }
567
568     return NULL;
569 }
570
571 static void
572 _cairo_tg_workers_init (void)
573 {
574     int i;
575
576     for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
577     {
578         workers[i].status = CAIRO_TG_WORKER_STATUS_IDLE;
579
580         pthread_mutex_init (&workers[i].lock, NULL);
581         pthread_cond_init (&workers[i].cond_wake_up, NULL);
582
583 #ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
584         pthread_spin_init (&workers[i].spinlock, 0);
585 #else
586         pthread_cond_init (&workers[i].cond_done, NULL);
587 #endif
588
589         pthread_create (&workers[i].thread, NULL, _cairo_tg_worker_mainloop, (void *) &workers[i]);
590     }
591
592     pthread_mutex_init (&workers_lock, NULL);
593     workers_occupied = FALSE;
594 }
595
596 static void
597 _cairo_tg_workers_fini (void)
598 {
599     int i;
600
601     for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
602     {
603         pthread_mutex_lock (&workers[i].lock);
604
605         workers[i].status = CAIRO_TG_WORKER_STATUS_KILLED;
606         pthread_cond_signal (&workers[i].cond_wake_up);
607         pthread_mutex_unlock (&workers[i].lock);
608     }
609
610     for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
611         pthread_join (workers[i].thread, NULL);
612
613     for (i = 0; i < CAIRO_TG_NUM_MAX_WORKERS; i++)
614     {
615         pthread_mutex_destroy (&workers[i].lock);
616         pthread_cond_destroy (&workers[i].cond_wake_up);
617
618 #ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
619         pthread_spin_destroy (&workers[i].spinlock);
620 #else
621         pthread_cond_destroy (&workers[i].cond_done);
622 #endif
623     }
624 }
625
626 static void __attribute__((constructor))
627 _cairo_tg_constructor (void)
628 {
629     pthread_atfork (NULL, NULL, _cairo_tg_workers_init);
630     _cairo_tg_workers_init ();
631 }
632
633 static void __attribute__((destructor))
634 _cairo_tg_destructor (void)
635 {
636     _cairo_tg_workers_fini ();
637 }
638
639 #endif /* ! CAIRO_HAS_OPENMP */
640
641 static void
642 _cairo_tg_surface_prepare_flush_parallel (cairo_tg_surface_t *surface)
643 {
644     const cairo_tg_journal_entry_t  *entry;
645     const cairo_tg_journal_entry_t  *next;
646
647     cairo_list_foreach_entry_safe (entry, next, cairo_tg_journal_entry_t,
648                                    &surface->journal.entry_list, link)
649     {
650         if (entry->source.base.type == CAIRO_PATTERN_TYPE_SURFACE)
651         {
652             cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) (&entry->source.base);
653             cairo_surface_flush (pattern->surface);
654         }
655
656         if (entry->type == CAIRO_TG_JOURNAL_ENTRY_MASK)
657         {
658             cairo_tg_journal_entry_mask_t *e =
659                 (cairo_tg_journal_entry_mask_t *) entry;
660
661             if (e->mask.base.type == CAIRO_PATTERN_TYPE_SURFACE)
662             {
663                 cairo_surface_pattern_t *pattern = (cairo_surface_pattern_t *) (&e->mask.base);
664                 cairo_surface_flush (pattern->surface);
665             }
666         }
667     }
668 }
669
670 static cairo_int_status_t
671 _cairo_tg_surface_flush_parallel (cairo_tg_surface_t *surface)
672 {
673     int                         num_tiles, i;
674     cairo_tg_surface_tile_t     tiles[CAIRO_TG_NUM_MAX_TILES];
675     cairo_rectangle_int_t       extents;
676
677     if (surface->journal.num_entries < CAIRO_TG_NUM_MIN_ENTRIES_FOR_PARALLEL_FLUSH)
678         return CAIRO_INT_STATUS_UNSUPPORTED;
679
680     _cairo_tg_surface_prepare_flush_parallel (surface);
681
682     extents.x = 0;
683     extents.y = 0;
684     extents.width = surface->width;
685     extents.height = surface->height;
686
687     _cairo_rectangle_intersect (&extents, &surface->journal.extents);
688
689     num_tiles = get_num_cpu_cores ();
690
691 #if ! CAIRO_HAS_OPENMP
692     if (num_tiles > CAIRO_TG_NUM_MAX_WORKERS)
693         num_tiles = CAIRO_TG_NUM_MAX_WORKERS;
694 #endif
695
696     num_tiles = _cairo_tg_surface_tiles_init (surface, &extents, num_tiles, &tiles[0]);
697
698 #if CAIRO_HAS_OPENMP
699     #pragma omp parallel for
700     for (i = 0; i < num_tiles; i++)
701     {
702         _cairo_tg_journal_replay (&surface->journal, (void *) &tiles[i],
703                                   &tiles[i].tile_rect, &replay_funcs_tile);
704     }
705 #else
706     pthread_mutex_lock (&workers_lock);
707
708     if (workers_occupied)
709     {
710         pthread_mutex_unlock (&workers_lock);
711         return CAIRO_INT_STATUS_UNSUPPORTED;
712     }
713
714     workers_occupied = TRUE;
715     pthread_mutex_unlock (&workers_lock);
716
717     /* Kick workers to start. */
718     for (i = 0; i < num_tiles - 1; i++)
719     {
720         pthread_mutex_lock (&workers[i].lock);
721
722         workers[i].status = CAIRO_TG_WORKER_STATUS_TO_DO;
723         workers[i].journal = &surface->journal;
724         workers[i].tile = &tiles[i];
725
726         pthread_cond_signal (&workers[i].cond_wake_up);
727         pthread_mutex_unlock (&workers[i].lock);
728     }
729
730     _cairo_tg_journal_replay (&surface->journal, &tiles[num_tiles - 1],
731                               &tiles[num_tiles - 1].tile_rect, &replay_funcs_tile);
732
733     /* Wait for workers to finish. */
734     for (i = 0; i < num_tiles - 1; i++)
735     {
736 #ifdef CAIRO_TG_THREAD_POOL_BUSY_WAIT
737         pthread_spin_lock (&workers[i].spinlock);
738
739         while (workers[i].status == CAIRO_TG_WORKER_STATUS_TO_DO)
740         {
741             pthread_spin_unlock (&workers[i].spinlock);
742             pthread_spin_lock (&workers[i].spinlock);
743         }
744
745         pthread_spin_unlock (&workers[i].spinlock);
746 #else
747         pthread_mutex_lock (&workers[i].lock);
748
749         while (workers[i].status == CAIRO_TG_WORKER_STATUS_TO_DO)
750             pthread_cond_wait (&workers[i].cond_done, &workers[i].lock);
751
752         pthread_mutex_unlock (&workers[i].lock);
753 #endif
754     }
755
756     /* Release thread pool. */
757     pthread_mutex_lock (&workers_lock);
758     workers_occupied = FALSE;
759     pthread_mutex_unlock (&workers_lock);
760 #endif
761
762     return CAIRO_INT_STATUS_SUCCESS;
763 }
764
765 static cairo_status_t
766 _cairo_tg_surface_flush (void       *abstract_surface,
767                          unsigned   flags)
768 {
769     cairo_tg_surface_t  *surface = abstract_surface;
770     cairo_int_status_t  status = CAIRO_INT_STATUS_SUCCESS;
771
772     if (flags)
773         return CAIRO_STATUS_SUCCESS;
774
775     _cairo_tg_journal_lock (&surface->journal);
776
777     if (surface->journal.num_entries)
778     {
779         status = _cairo_tg_surface_flush_parallel (surface);
780
781         if (status)
782         {
783             status = _cairo_tg_journal_replay (&surface->journal,
784                                                (void *) surface->image_surface,
785                                                NULL, &replay_funcs_image_fallback);
786         }
787
788         _cairo_tg_journal_clear (&surface->journal);
789     }
790
791     _cairo_tg_journal_unlock (&surface->journal);
792
793     return status;
794 }
795
796 static cairo_image_surface_t *
797 _cairo_tg_surface_map_to_image (void                        *abstract_surface,
798                                 const cairo_rectangle_int_t *extents)
799 {
800     cairo_tg_surface_t  *other = abstract_surface;
801     cairo_surface_t     *surface;
802     uint8_t             *buffer;
803
804     _cairo_tg_surface_flush (other, 0);
805
806     buffer = other->data;
807     buffer += extents->y * other->stride;
808     buffer += extents->x * other->bpp / 8;
809
810     surface =
811         _cairo_image_surface_create_with_pixman_format (buffer,
812                                                         other->pixman_format,
813                                                         extents->width,
814                                                         extents->height,
815                                                         other->stride);
816
817     if (unlikely (surface == NULL))
818         return NULL;
819
820     cairo_surface_set_device_offset (surface, -extents->x, extents->y);
821
822     return (cairo_image_surface_t *) surface;
823 }
824
825 static cairo_int_status_t
826 _cairo_tg_surface_unmap_image (void                     *abstract_surface,
827                                cairo_image_surface_t    *image)
828 {
829     cairo_surface_finish (&image->base);
830     cairo_surface_destroy (&image->base);
831
832     return CAIRO_INT_STATUS_SUCCESS;
833 }
834
835 static cairo_bool_t
836 _cairo_tg_surface_get_extents (void                     *abstract_surface,
837                                cairo_rectangle_int_t    *extents)
838 {
839     cairo_tg_surface_t *surface = abstract_surface;
840
841     extents->x = 0;
842     extents->y = 0;
843     extents->width = surface->width;
844     extents->height = surface->height;
845
846     return TRUE;
847 }
848
849 static cairo_int_status_t
850 _cairo_tg_surface_paint (void                   *abstract_surface,
851                          cairo_operator_t       op,
852                          const cairo_pattern_t  *source,
853                          const cairo_clip_t     *clip)
854 {
855     cairo_tg_surface_t  *surface = abstract_surface;
856     cairo_int_status_t  status = CAIRO_INT_STATUS_UNSUPPORTED;
857
858     if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
859         ! _cairo_pattern_is_recording (source))
860         status = _cairo_tg_journal_log_paint (&surface->journal, op, source, clip);
861
862     if (status)
863     {
864         status = _cairo_tg_surface_flush (surface, 0);
865
866         if (unlikely (status))
867             return status;
868
869         status =  _cairo_tg_image_surface_paint (surface->image_surface, op, source, clip);
870     }
871
872     return status;
873 }
874
875 static cairo_int_status_t
876 _cairo_tg_surface_mask (void                    *abstract_surface,
877                         cairo_operator_t        op,
878                         const cairo_pattern_t   *source,
879                         const cairo_pattern_t   *mask,
880                         const cairo_clip_t      *clip)
881 {
882     cairo_tg_surface_t  *surface = abstract_surface;
883     cairo_int_status_t  status = CAIRO_INT_STATUS_UNSUPPORTED;
884
885     if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
886         ! _cairo_pattern_is_self_copy (&surface->base, mask) &&
887         ! _cairo_pattern_is_recording (source))
888         status = _cairo_tg_journal_log_mask (&surface->journal, op, source, mask, clip);
889
890     if (status)
891     {
892         status = _cairo_tg_surface_flush (surface, 0);
893
894         if (unlikely (status))
895             return status;
896
897         status =  _cairo_tg_image_surface_mask (surface->image_surface, op, source,
898                                                 mask, clip);
899     }
900
901     return status;
902 }
903
904 static cairo_int_status_t
905 _cairo_tg_surface_stroke (void                          *abstract_surface,
906                           cairo_operator_t              op,
907                           const cairo_pattern_t         *source,
908                           const cairo_path_fixed_t      *path,
909                           const cairo_stroke_style_t    *style,
910                           const cairo_matrix_t          *ctm,
911                           const cairo_matrix_t          *ctm_inverse,
912                           double                        tolerance,
913                           cairo_antialias_t             antialias,
914                           const cairo_clip_t            *clip)
915 {
916     cairo_tg_surface_t  *surface = abstract_surface;
917     cairo_int_status_t  status = CAIRO_INT_STATUS_UNSUPPORTED;
918
919     if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
920         ! _cairo_pattern_is_recording (source))
921     {
922         status = _cairo_tg_journal_log_stroke (&surface->journal, op, source,
923                                                path, style, ctm, ctm_inverse,
924                                                tolerance, antialias, clip);
925     }
926
927     if (status)
928     {
929         status = _cairo_tg_surface_flush (surface, 0);
930
931         if (unlikely (status))
932             return status;
933
934         status = _cairo_tg_image_surface_stroke (surface->image_surface, op, source,
935                                                  path, style, ctm, ctm_inverse,
936                                                  tolerance, antialias, clip);
937     }
938
939     return status;
940 }
941
942 static cairo_int_status_t
943 _cairo_tg_surface_fill (void                        *abstract_surface,
944                         cairo_operator_t            op,
945                         const cairo_pattern_t       *source,
946                         const cairo_path_fixed_t    *path,
947                         cairo_fill_rule_t           fill_rule,
948                         double                      tolerance,
949                         cairo_antialias_t           antialias,
950                         const cairo_clip_t          *clip)
951 {
952     cairo_tg_surface_t  *surface = abstract_surface;
953     cairo_int_status_t  status = CAIRO_INT_STATUS_UNSUPPORTED;
954
955     if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
956         ! _cairo_pattern_is_recording (source))
957     {
958         status = _cairo_tg_journal_log_fill (&surface->journal, op, source,
959                                              path, fill_rule, tolerance, antialias, clip);
960     }
961
962     if (status)
963     {
964         status = _cairo_tg_surface_flush (surface, 0);
965
966         if (unlikely (status))
967             return status;
968
969         status =  _cairo_tg_image_surface_fill (surface->image_surface, op, source,
970                                                 path, fill_rule, tolerance, antialias, clip);
971     }
972
973     return status;
974 }
975
976 static cairo_int_status_t
977 _cairo_tg_surface_glyphs (void                  *abstract_surface,
978                           cairo_operator_t      op,
979                           const cairo_pattern_t *source,
980                           cairo_glyph_t         *glyphs,
981                           int                   num_glyphs,
982                           cairo_scaled_font_t   *scaled_font,
983                           const cairo_clip_t    *clip)
984 {
985     cairo_tg_surface_t  *surface = abstract_surface;
986     cairo_int_status_t  status = CAIRO_INT_STATUS_UNSUPPORTED;
987
988     if (! _cairo_pattern_is_self_copy (&surface->base, source) &&
989         ! _cairo_pattern_is_recording (source))
990     {
991         status = _cairo_tg_journal_log_glyphs (&surface->journal, op, source,
992                                                glyphs, num_glyphs, scaled_font, clip);
993     }
994
995     if (status)
996     {
997         status = _cairo_tg_surface_flush (surface, 0);
998
999         if (unlikely (status))
1000             return status;
1001
1002         status = _cairo_tg_image_surface_glyphs (surface->image_surface, op, source,
1003                                                  glyphs, num_glyphs, scaled_font, clip);
1004     }
1005
1006     return status;
1007 }
1008
1009 static cairo_surface_t *
1010 _cairo_tg_surface_create_similar (void              *abstract_other,
1011                                   cairo_content_t   content,
1012                                   int               width,
1013                                   int               height)
1014 {
1015     cairo_tg_surface_t *other = abstract_other;
1016
1017     if (! _cairo_tg_surface_is_size_valid (width, height))
1018         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1019
1020     if (content == other->base.content)
1021         return cairo_tg_surface_create (other->format, width, height);
1022
1023     return cairo_tg_surface_create (_cairo_format_from_content (content), width, height);
1024 }
1025
1026 static cairo_surface_t *
1027 _cairo_tg_surface_source (void                  *abstract_surface,
1028                           cairo_rectangle_int_t *extents)
1029 {
1030     cairo_tg_surface_t *surface = abstract_surface;
1031
1032     if (extents)
1033     {
1034         extents->x = extents->y = 0;
1035         extents->width = surface->width;
1036         extents->height = surface->height;
1037     }
1038
1039     return &surface->base;
1040 }
1041
1042 static cairo_status_t
1043 _cairo_tg_surface_acquire_source_image (void                    *abstract_surface,
1044                                         cairo_image_surface_t   **image_out,
1045                                         void                    **image_extra)
1046 {
1047     cairo_tg_surface_t *surface = abstract_surface;
1048
1049     _cairo_tg_surface_flush (surface, 0);
1050
1051     *image_out = (cairo_image_surface_t *) surface->image_surface;
1052     *image_extra = NULL;
1053
1054     return CAIRO_STATUS_SUCCESS;
1055 }
1056
1057 static void
1058 _cairo_tg_surface_release_source_image (void                    *abstract_surface,
1059                                         cairo_image_surface_t   *image,
1060                                         void                    *image_extra)
1061 {
1062     /* Do nothing */
1063 }
1064
1065 static cairo_surface_t *
1066 _cairo_tg_surface_snapshot (void *abstract_surface)
1067 {
1068     cairo_tg_surface_t *surface = abstract_surface;
1069     cairo_tg_surface_t *clone;
1070
1071     _cairo_tg_surface_flush (surface, 0);
1072
1073     if (_cairo_tg_surface_owns_data (surface) && surface->base._finishing)
1074     {
1075         return cairo_tg_surface_create_for_data (surface->data, surface->format,
1076                                                  surface->width, surface->height,
1077                                                  surface->stride);
1078     }
1079
1080     clone = (cairo_tg_surface_t *)
1081         cairo_tg_surface_create (surface->format, surface->width, surface->height);
1082
1083     if (unlikely (clone->base.status))
1084         return &clone->base;
1085
1086     if (surface->stride == clone->stride)
1087     {
1088         memcpy (clone->data, surface->data, clone->stride * clone->height);
1089     }
1090     else
1091     {
1092         unsigned char *dst = clone->data;
1093         unsigned char *src = surface->data;
1094         int i;
1095         int stride = clone->stride < surface->stride ? clone->stride : surface->stride;
1096
1097         for (i = 0; i < clone->height; i++)
1098         {
1099             memcpy (dst, src, stride);
1100             dst += clone->stride;
1101             src += surface->stride;
1102         }
1103     }
1104
1105     clone->base.is_clear = FALSE;
1106
1107     return &clone->base;
1108 }
1109
1110 static cairo_int_status_t
1111 _cairo_tg_surface_init_tile_surfaces (cairo_tg_surface_t *surface)
1112 {
1113     int                 i;
1114     cairo_int_status_t  status = CAIRO_INT_STATUS_SUCCESS;
1115
1116     memset (&surface->tile_surfaces[0], 0x00,
1117             sizeof (cairo_surface_t *) * CAIRO_TG_NUM_MAX_TILES);
1118
1119     for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
1120     {
1121         surface->tile_surfaces[i] = cairo_image_surface_create_for_data (surface->data,
1122                                                                          surface->format,
1123                                                                          surface->width,
1124                                                                          surface->height,
1125                                                                          surface->stride);
1126
1127         if (surface->tile_surfaces[i] == NULL)
1128         {
1129             status = CAIRO_INT_STATUS_NO_MEMORY;
1130             break;
1131         }
1132     }
1133
1134     if (unlikely (status))
1135     {
1136         for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
1137         {
1138             if (surface->tile_surfaces[i])
1139                 cairo_surface_destroy (surface->tile_surfaces[i]);
1140             else
1141                 break;
1142         }
1143     }
1144
1145     return status;
1146 }
1147
1148 static void
1149 _cairo_tg_surface_fini_tile_surfaces (cairo_tg_surface_t *surface)
1150 {
1151     int i;
1152
1153     for (i = 0; i < CAIRO_TG_NUM_MAX_TILES; i++)
1154     {
1155         if (surface->tile_surfaces[i])
1156             cairo_surface_destroy (surface->tile_surfaces[i]);
1157         else
1158             break;
1159     }
1160 }
1161
1162 static cairo_status_t
1163 _cairo_tg_surface_finish (void *abstract_surface)
1164 {
1165     cairo_tg_surface_t *surface = abstract_surface;
1166
1167     _cairo_tg_surface_flush (surface, 0);
1168     _cairo_tg_journal_fini (&surface->journal);
1169     _cairo_tg_surface_fini_tile_surfaces (surface);
1170     cairo_surface_destroy (surface->image_surface);
1171
1172     return CAIRO_STATUS_SUCCESS;
1173 }
1174
1175 static const cairo_surface_backend_t _cairo_tg_surface_backend =
1176 {
1177     CAIRO_SURFACE_TYPE_TG,
1178     _cairo_tg_surface_finish,
1179
1180     _cairo_default_context_create,
1181
1182     _cairo_tg_surface_create_similar,
1183     NULL, /* create_similar image */
1184     _cairo_tg_surface_map_to_image,
1185     _cairo_tg_surface_unmap_image,
1186
1187     _cairo_tg_surface_source,
1188     _cairo_tg_surface_acquire_source_image,
1189     _cairo_tg_surface_release_source_image,
1190     _cairo_tg_surface_snapshot,
1191
1192     NULL, /* copy_page */
1193     NULL, /* show_page */
1194
1195     _cairo_tg_surface_get_extents,
1196     NULL, /* get_font_options */
1197
1198     _cairo_tg_surface_flush,
1199     NULL, /* mark_dirty_rectangle */
1200
1201     _cairo_tg_surface_paint,
1202     _cairo_tg_surface_mask,
1203     _cairo_tg_surface_stroke,
1204     _cairo_tg_surface_fill,
1205     NULL, /* fill_stroke */
1206     _cairo_tg_surface_glyphs,
1207 };
1208
1209 cairo_surface_t *
1210 cairo_tg_surface_create (cairo_format_t format,
1211                          int            width,
1212                          int            height)
1213 {
1214     cairo_tg_surface_t  *surface;
1215     cairo_surface_t     *image_surface;
1216
1217     image_surface = cairo_image_surface_create (format, width, height);
1218
1219     if (unlikely (image_surface == NULL))
1220         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1221
1222     surface = malloc (sizeof (cairo_tg_surface_t));
1223
1224     if (unlikely (surface == NULL))
1225     {
1226         cairo_surface_destroy (image_surface);
1227
1228         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1229     }
1230
1231     _cairo_surface_init (&surface->base,
1232                          &_cairo_tg_surface_backend,
1233                          NULL, image_surface->content);
1234
1235     surface->format = format;
1236     surface->pixman_format = ((cairo_image_surface_t *) image_surface)->pixman_format;
1237     surface->data = (unsigned char *) cairo_image_surface_get_data (image_surface);
1238     surface->width = width;
1239     surface->height = height;
1240     surface->stride = cairo_image_surface_get_stride (image_surface);
1241     surface->bpp = get_bpp_for_format (format);
1242     surface->image_surface = image_surface;
1243     surface->base.is_clear = image_surface->is_clear;
1244
1245     _cairo_tg_journal_init (&surface->journal);
1246
1247     if (_cairo_tg_surface_init_tile_surfaces (surface))
1248     {
1249         cairo_surface_destroy (image_surface);
1250         _cairo_tg_journal_fini (&surface->journal);
1251
1252         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1253     }
1254
1255     return &surface->base;
1256 }
1257
1258 cairo_surface_t *
1259 cairo_tg_surface_create_for_data (unsigned char     *data,
1260                                   cairo_format_t    format,
1261                                   int               width,
1262                                   int               height,
1263                                   int               stride)
1264 {
1265     cairo_tg_surface_t  *surface;
1266     cairo_surface_t     *image_surface;
1267
1268     image_surface = cairo_image_surface_create_for_data (data, format, width, height, stride);
1269
1270     if (unlikely (image_surface == NULL))
1271         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1272
1273     surface = malloc (sizeof (cairo_tg_surface_t));
1274
1275     if (unlikely (surface == NULL))
1276     {
1277         cairo_surface_destroy (image_surface);
1278
1279         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1280     }
1281
1282     _cairo_surface_init (&surface->base,
1283                          &_cairo_tg_surface_backend,
1284                          NULL, image_surface->content);
1285
1286     surface->format = format;
1287     surface->pixman_format = ((cairo_image_surface_t *) image_surface)->pixman_format;
1288     surface->data = (unsigned char *) cairo_image_surface_get_data (image_surface);
1289     surface->width = width;
1290     surface->height = height;
1291     surface->stride = cairo_image_surface_get_stride (image_surface);
1292     surface->bpp = get_bpp_for_format (format);
1293     surface->image_surface = image_surface;
1294     surface->base.is_clear = image_surface->is_clear;
1295
1296     _cairo_tg_journal_init (&surface->journal);
1297
1298     if (_cairo_tg_surface_init_tile_surfaces (surface))
1299     {
1300         cairo_surface_destroy (image_surface);
1301         _cairo_tg_journal_fini (&surface->journal);
1302
1303         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1304     }
1305
1306     return &surface->base;
1307 }
1308
1309 unsigned char *
1310 cairo_tg_surface_get_data (cairo_surface_t *surface)
1311 {
1312     cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
1313
1314     if (! _cairo_surface_is_tg (surface)) {
1315         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1316         return NULL;
1317     }
1318
1319     return tg_surface->data;
1320 }
1321
1322 cairo_format_t
1323 cairo_tg_surface_get_format (cairo_surface_t *surface)
1324 {
1325     cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
1326
1327     if (! _cairo_surface_is_tg (surface)) {
1328         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1329         return CAIRO_FORMAT_INVALID;
1330     }
1331
1332     return tg_surface->format;
1333 }
1334
1335 int
1336 cairo_tg_surface_get_width (cairo_surface_t *surface)
1337 {
1338     cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
1339
1340     if (! _cairo_surface_is_tg (surface)) {
1341         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1342         return 0;
1343     }
1344
1345     return tg_surface->width;
1346 }
1347
1348 int
1349 cairo_tg_surface_get_height (cairo_surface_t *surface)
1350 {
1351     cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
1352
1353     if (! _cairo_surface_is_tg (surface)) {
1354         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1355         return 0;
1356     }
1357
1358     return tg_surface->height;
1359 }
1360
1361 int
1362 cairo_tg_surface_get_stride (cairo_surface_t *surface)
1363 {
1364     cairo_tg_surface_t *tg_surface = (cairo_tg_surface_t *) surface;
1365
1366     if (! _cairo_surface_is_tg (surface)) {
1367         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1368         return 0;
1369     }
1370
1371     return tg_surface->stride;
1372 }