Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-gl-operand.c
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Eric Anholt
4  * Copyright © 2009 Chris Wilson
5  * Copyright © 2005,2010 Red Hat, Inc
6  * Copyright © 2011 Intel Corporation
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it either under the terms of the GNU Lesser General Public
10  * License version 2.1 as published by the Free Software Foundation
11  * (the "LGPL") or, at your option, under the terms of the Mozilla
12  * Public License Version 1.1 (the "MPL"). If you do not alter this
13  * notice, a recipient may use your version of this file under either
14  * the MPL or the LGPL.
15  *
16  * You should have received a copy of the LGPL along with this library
17  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19  * You should have received a copy of the MPL along with this library
20  * in the file COPYING-MPL-1.1
21  *
22  * The contents of this file are subject to the Mozilla Public License
23  * Version 1.1 (the "License"); you may not use this file except in
24  * compliance with the License. You may obtain a copy of the License at
25  * http://www.mozilla.org/MPL/
26  *
27  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29  * the specific language governing rights and limitations.
30  *
31  * The Original Code is the cairo graphics library.
32  *
33  * The Initial Developer of the Original Code is Red Hat, Inc.
34  *
35  * Contributor(s):
36  *      Benjamin Otte <otte@gnome.org>
37  *      Carl Worth <cworth@cworth.org>
38  *      Chris Wilson <chris@chris-wilson.co.uk>
39  *      Eric Anholt <eric@anholt.net>
40  */
41
42 #include "cairoint.h"
43
44 #include "cairo-gl-private.h"
45
46 #include "cairo-composite-rectangles-private.h"
47 #include "cairo-compositor-private.h"
48 #include "cairo-default-context-private.h"
49 #include "cairo-error-private.h"
50 #include "cairo-image-surface-private.h"
51 #include "cairo-surface-backend-private.h"
52 #include "cairo-surface-offset-private.h"
53 #include "cairo-surface-snapshot-inline.h"
54 #include "cairo-surface-subsurface-inline.h"
55 #include "cairo-rtree-private.h"
56
57 static cairo_int_status_t
58 _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
59                                    const cairo_gradient_pattern_t *pattern,
60                                    cairo_gl_gradient_t **gradient)
61 {
62     cairo_gl_context_t *ctx;
63     cairo_status_t status;
64
65     status = _cairo_gl_context_acquire (dst->base.device, &ctx);
66     if (unlikely (status))
67         return status;
68
69     status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient);
70
71     return _cairo_gl_context_release (ctx, status);
72 }
73
74 static cairo_int_status_t
75 _resolve_multisampling (cairo_gl_surface_t *surface)
76 {
77     cairo_gl_context_t *ctx;
78     cairo_int_status_t status;
79
80     if (! surface->msaa_active)
81         return CAIRO_INT_STATUS_SUCCESS;
82
83     if (surface->base.device == NULL)
84         return CAIRO_INT_STATUS_SUCCESS;
85
86     /* GLES surfaces do not need explicit resolution. */
87     if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES)
88         return CAIRO_INT_STATUS_SUCCESS;
89
90     if (! _cairo_gl_surface_is_texture (surface))
91         return CAIRO_INT_STATUS_SUCCESS;
92
93     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
94     if (unlikely (status))
95         return status;
96
97     ctx->current_target = surface;
98
99 #if CAIRO_HAS_GL_SURFACE
100     _cairo_gl_activate_surface_as_nonmultisampling (ctx, surface);
101 #endif
102
103     status = _cairo_gl_context_release (ctx, status);
104     return status;
105 }
106
107 static void
108 _cairo_gl_image_cache_lock (cairo_gl_context_t *ctx,
109                             cairo_gl_image_t *image_node)
110 {
111     _cairo_rtree_pin (&ctx->image_cache.rtree, &image_node->node);
112 }
113
114 void
115 _cairo_gl_image_cache_unlock (cairo_gl_context_t *ctx)
116 {
117     if (ctx->image_cache.surface)
118         _cairo_rtree_unpin (&(ctx->image_cache.rtree));
119 }
120
121 static cairo_int_status_t
122 _cairo_gl_copy_texture (cairo_gl_surface_t *dst,
123                         cairo_gl_surface_t *image,
124                         int x, int y,
125                         int width, int height,
126                         cairo_bool_t replace,
127                         cairo_gl_context_t **ctx)
128 {
129     cairo_int_status_t status;
130     cairo_gl_context_t *ctx_out;
131     cairo_gl_dispatch_t *dispatch;
132     cairo_gl_surface_t *cache_surface;
133     cairo_gl_surface_t *target;
134
135     if (! _cairo_gl_surface_is_texture (image))
136         return CAIRO_INT_STATUS_UNSUPPORTED;
137
138     status = _cairo_gl_context_acquire (dst->base.device, &ctx_out);
139     if(unlikely (status))
140         return status;
141
142     if (! ctx_out->image_cache.surface) {
143        status = _cairo_gl_image_cache_init (ctx_out);
144        if (unlikely (status))
145            return status;
146     }
147
148     if (replace)
149         _cairo_gl_composite_flush (ctx_out);
150
151     /* Bind framebuffer of source image. */
152     dispatch = &ctx_out->dispatch;
153     cache_surface = ctx_out->image_cache.surface;
154     target = ctx_out->current_target;
155
156     _cairo_gl_ensure_framebuffer (ctx_out, image);
157     dispatch->BindFramebuffer (GL_FRAMEBUFFER, image->fb);
158     glBindTexture (ctx_out->tex_target, cache_surface->tex);
159
160     glCopyTexSubImage2D (ctx_out->tex_target, 0, x, y, 0, 0, width, height);
161     dispatch->BindFramebuffer (GL_FRAMEBUFFER, target->fb);
162     ctx_out->current_target = target;
163     *ctx = ctx_out;
164
165     return CAIRO_INT_STATUS_SUCCESS;
166 }
167
168 static cairo_int_status_t
169 _cairo_gl_image_cache_replace_image (cairo_gl_image_t *image_node,
170                                      cairo_gl_surface_t *dst,
171                                      cairo_gl_surface_t *image,
172                                      cairo_gl_context_t **ctx)
173 {
174     cairo_int_status_t status;
175     /* Paint image to cache. */
176     status = _cairo_gl_copy_texture (dst, image, image_node->node.x,
177                                      image_node->node.y,
178                                      image->width, image->height,
179                                      TRUE,
180                                      ctx);
181     image->content_changed = FALSE;
182     return status;
183 }
184
185 static cairo_int_status_t
186 _cairo_gl_image_cache_add_image (cairo_gl_context_t *ctx,
187                                  cairo_gl_surface_t *dst,
188                                  cairo_gl_surface_t *image,
189                                  cairo_gl_image_t **image_node)
190 {
191     cairo_int_status_t status;
192     cairo_rtree_node_t *node = NULL;
193     int width, height;
194     cairo_bool_t replaced = FALSE;
195
196     if (! image->base.device ||
197         (image->width > IMAGE_CACHE_MAX_SIZE ||
198         image->height > IMAGE_CACHE_MAX_SIZE))
199         return CAIRO_INT_STATUS_UNSUPPORTED;
200
201     width = image->width;
202     height = image->height;
203
204     *image_node =
205         (cairo_gl_image_t *) cairo_surface_get_user_data (&image->base,
206                                                                (const cairo_user_data_key_t *) (&image->base));
207     if (*image_node) {
208         if (image->content_changed) {
209             status = _cairo_gl_image_cache_replace_image (*image_node,
210                                                           dst, image, &ctx);
211
212             if (unlikely (status))
213                 return status;
214
215             replaced = TRUE;
216         }
217
218         _cairo_gl_image_cache_lock (ctx, *image_node);
219
220         image->content_changed = FALSE;
221         if (replaced)
222             return _cairo_gl_context_release (ctx, status);
223         return CAIRO_INT_STATUS_SUCCESS;
224     }
225
226     status = _cairo_rtree_insert (&ctx->image_cache.rtree, width,
227                                   height, &node);
228     /* Search for an unlocked slot. */
229     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
230         _cairo_gl_composite_flush (ctx);
231         _cairo_gl_image_cache_unlock (ctx);
232
233         status = _cairo_rtree_evict_random (&ctx->image_cache.rtree,
234                                             width, height, &node);
235
236         if (status == CAIRO_INT_STATUS_SUCCESS)
237             status = _cairo_rtree_node_insert (&ctx->image_cache.rtree,
238                                                node, width, height, &node);
239     }
240
241     if (status)
242         return status;
243
244     /* Paint image to cache. */
245     status = _cairo_gl_copy_texture (dst, image, node->x, node->y,
246                                      image->width, image->height,
247                                      FALSE, &ctx);
248     if (unlikely (status))
249         return status;
250
251     *image_node = (cairo_gl_image_t *)node;
252     (*image_node)->ctx = ctx;
253     (*image_node)->original_surface = &image->base;
254     /* Coordinate. */
255     (*image_node)->p1.x = node->x;
256     (*image_node)->p1.y = node->y;
257     (*image_node)->p2.x = node->x + image->width;
258     (*image_node)->p2.y = node->y + image->height;
259     if (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base)) {
260         (*image_node)->p1.x /= IMAGE_CACHE_WIDTH;
261         (*image_node)->p2.x /= IMAGE_CACHE_WIDTH;
262         (*image_node)->p1.y /= IMAGE_CACHE_HEIGHT;
263         (*image_node)->p2.y /= IMAGE_CACHE_HEIGHT;
264     }
265     (*image_node)->user_data_removed = FALSE;
266     image->content_changed = FALSE;
267     /* Set user data. */
268     status = cairo_surface_set_user_data (&image->base,
269                                           (const cairo_user_data_key_t *) &image->base,
270                                           (void *) *image_node,
271                                           _cairo_gl_image_node_fini);
272
273     _cairo_gl_image_cache_lock (ctx, *image_node);
274     return _cairo_gl_context_release (ctx, status);
275 }
276
277 static cairo_status_t
278 _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t *operand,
279                                          const cairo_pattern_t *_src,
280                                          cairo_gl_surface_t *dst,
281                                          const cairo_rectangle_int_t *sample,
282                                          const cairo_rectangle_int_t *extents)
283 {
284     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
285     cairo_surface_pattern_t local_pattern;
286     cairo_surface_subsurface_t *sub;
287     cairo_gl_surface_t *surface;
288     cairo_gl_context_t *ctx;
289     cairo_surface_attributes_t *attributes;
290     cairo_status_t status;
291
292     sub = (cairo_surface_subsurface_t *) src->surface;
293
294     if (sub->snapshot &&
295         sub->snapshot->type == CAIRO_SURFACE_TYPE_GL &&
296         sub->snapshot->device == dst->base.device)
297     {
298         surface = (cairo_gl_surface_t *)
299             cairo_surface_reference (sub->snapshot);
300     }
301     else
302     {
303         status = _cairo_gl_context_acquire (dst->base.device, &ctx);
304         if (unlikely (status))
305             return status;
306
307         /* XXX Trim surface to the sample area within the subsurface? */
308         surface = (cairo_gl_surface_t *)
309             _cairo_gl_surface_create_scratch (ctx,
310                                               sub->target->content,
311                                               sub->extents.width,
312                                               sub->extents.height,
313                                               FALSE);
314
315         if (surface->base.status)
316             return _cairo_gl_context_release (ctx, surface->base.status);
317
318         _cairo_pattern_init_for_surface (&local_pattern, sub->target);
319         cairo_matrix_init_translate (&local_pattern.base.matrix,
320                                      sub->extents.x, sub->extents.y);
321         local_pattern.base.filter = CAIRO_FILTER_NEAREST;
322         status = _cairo_surface_paint (&surface->base,
323                                        CAIRO_OPERATOR_SOURCE,
324                                        &local_pattern.base,
325                                        NULL);
326         _cairo_pattern_fini (&local_pattern.base);
327
328         status = _cairo_gl_context_release (ctx, status);
329         if (unlikely (status)) {
330             cairo_surface_destroy (&surface->base);
331             return status;
332         }
333
334         _cairo_surface_subsurface_set_snapshot (&sub->base, &surface->base);
335     }
336
337     status = _resolve_multisampling (surface);
338     if (unlikely (status))
339         return status;
340
341     attributes = &operand->texture.attributes;
342
343     operand->type = CAIRO_GL_OPERAND_TEXTURE;
344     operand->texture.surface = surface;
345     operand->texture.owns_surface = surface;
346     operand->texture.tex = surface->tex;
347     operand->texture.use_atlas = FALSE;
348
349     if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
350         attributes->matrix = src->base.matrix;
351     } else {
352         cairo_matrix_t m;
353
354         cairo_matrix_init_scale (&m,
355                                  1.0 / surface->width,
356                                  1.0 / surface->height);
357         cairo_matrix_multiply (&attributes->matrix, &src->base.matrix, &m);
358     }
359
360     attributes->extend = src->base.extend;
361     attributes->filter = src->base.filter;
362     attributes->has_component_alpha = src->base.has_component_alpha;
363     return CAIRO_STATUS_SUCCESS;
364 }
365
366 static cairo_status_t
367 _cairo_gl_subsurface_operand_init (cairo_gl_operand_t *operand,
368                                    const cairo_pattern_t *_src,
369                                    cairo_gl_surface_t *dst,
370                                    const cairo_rectangle_int_t *sample,
371                                    const cairo_rectangle_int_t *extents)
372 {
373     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
374     cairo_surface_subsurface_t *sub;
375     cairo_gl_surface_t *surface;
376     cairo_surface_attributes_t *attributes;
377     cairo_int_status_t status;
378     cairo_gl_image_t *image_node = NULL;
379     cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
380
381     sub = (cairo_surface_subsurface_t *) src->surface;
382
383     if (sample->x < 0 || sample->y < 0 ||
384         sample->x + sample->width  > sub->extents.width ||
385         sample->y + sample->height > sub->extents.height)
386     {
387         return _cairo_gl_subsurface_clone_operand_init (operand, _src,
388                                                         dst, sample, extents);
389     }
390
391     surface = (cairo_gl_surface_t *) sub->target;
392     if (surface->base.device &&
393         (surface->base.device != dst->base.device ||
394          (! surface->tex && ! surface->bounded_tex)))
395         return CAIRO_INT_STATUS_UNSUPPORTED;
396
397     if (! _cairo_gl_surface_is_texture (surface))
398         return CAIRO_INT_STATUS_UNSUPPORTED;
399
400     status = _resolve_multisampling (surface);
401     if (unlikely (status))
402         return status;
403
404     _cairo_gl_operand_copy(operand, &surface->operand);
405     *operand = surface->operand;
406     operand->texture.use_atlas = FALSE;
407
408     attributes = &operand->texture.attributes;
409     attributes->extend = src->base.extend;
410     attributes->filter = src->base.filter;
411     attributes->has_component_alpha = src->base.has_component_alpha;
412
413     attributes->matrix = src->base.matrix;
414     attributes->matrix.x0 += sub->extents.x;
415     attributes->matrix.y0 += sub->extents.y;
416
417     if (surface->needs_to_cache)
418         status = _cairo_gl_image_cache_add_image (ctx, dst, surface,
419                                                   &image_node);
420
421     /* Translate the matrix from
422      * (unnormalized src -> unnormalized src) to
423      * (unnormalized dst -> unnormalized src)
424      */
425
426     if (unlikely (status) || ! image_node)
427         cairo_matrix_multiply (&attributes->matrix,
428                                &attributes->matrix,
429                                &surface->operand.texture.attributes.matrix);
430    else {
431         cairo_matrix_t matrix = src->base.matrix;
432         operand->texture.surface = ctx->image_cache.surface;
433         operand->texture.owns_surface = NULL;
434         operand->texture.tex = ctx->image_cache.surface->tex;
435         attributes->extend = CAIRO_EXTEND_NONE;
436         operand->texture.extend = src->base.extend;
437         attributes->matrix.x0 = image_node->node.x + sub->extents.x;
438         attributes->matrix.y0 = image_node->node.y + sub->extents.y;
439         operand->texture.use_atlas = TRUE;
440
441         operand->texture.p1.x = image_node->p1.x;
442         operand->texture.p1.y = image_node->p1.y;
443         operand->texture.p2.x = image_node->p2.x;
444         operand->texture.p2.y = image_node->p2.y;
445         if (src->base.extend == CAIRO_EXTEND_PAD) {
446             operand->texture.p1.x += 0.5 / IMAGE_CACHE_WIDTH;
447             operand->texture.p1.y += 0.5 / IMAGE_CACHE_HEIGHT;
448             operand->texture.p2.x -= 0.5 / IMAGE_CACHE_WIDTH;
449             operand->texture.p2.y -= 0.5 / IMAGE_CACHE_HEIGHT;
450         }
451
452         cairo_matrix_multiply (&attributes->matrix,
453                                &matrix,
454                                &ctx->image_cache.surface->operand.texture.attributes.matrix);
455     }
456
457     return CAIRO_STATUS_SUCCESS;
458 }
459
460 static cairo_status_t
461 _cairo_gl_surface_operand_init (cairo_gl_operand_t *operand,
462                                 const cairo_pattern_t *_src,
463                                 cairo_gl_surface_t *dst,
464                                 const cairo_rectangle_int_t *sample,
465                                 const cairo_rectangle_int_t *extents)
466 {
467     const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src;
468     cairo_gl_surface_t *surface;
469     cairo_surface_attributes_t *attributes;
470     cairo_int_status_t status;
471     cairo_gl_image_t *image_node = NULL;
472     cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
473
474     surface = (cairo_gl_surface_t *) src->surface;
475     if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
476         return CAIRO_INT_STATUS_UNSUPPORTED;
477
478     if (surface->base.backend->type != CAIRO_SURFACE_TYPE_GL) {
479         if (_cairo_surface_is_subsurface (&surface->base))
480             return _cairo_gl_subsurface_operand_init (operand, _src, dst,
481                                                       sample, extents);
482         else if (_cairo_surface_is_snapshot (src->surface)) {
483             cairo_surface_snapshot_t *surface_snapshot;
484             cairo_pattern_t *sub_pattern;
485
486             surface_snapshot = (cairo_surface_snapshot_t *)src->surface;
487             surface = (cairo_gl_surface_t *)surface_snapshot->target;
488             if (surface->base.type != CAIRO_SURFACE_TYPE_GL)
489                 return CAIRO_INT_STATUS_UNSUPPORTED;
490
491             if (_cairo_surface_is_subsurface (&surface->base)) {
492                 sub_pattern = cairo_pattern_create_for_surface (&surface->base);
493                 status = _cairo_gl_subsurface_operand_init (operand,
494                                                             sub_pattern,
495                                                             dst,
496                                                             sample,
497                                                             extents);
498                 cairo_pattern_destroy (sub_pattern);
499                 return status;
500             }
501         }
502         else
503             return CAIRO_INT_STATUS_UNSUPPORTED;
504     }
505
506     if (surface->base.device &&
507         (surface->base.device != dst->base.device ||
508          (! surface->tex && ! surface->bounded_tex)))
509         return CAIRO_INT_STATUS_UNSUPPORTED;
510
511     status = _resolve_multisampling (surface);
512     if (unlikely (status))
513         return status;
514
515     _cairo_gl_operand_copy(operand, &surface->operand);
516     operand->texture.use_atlas = FALSE;
517
518     attributes = &operand->texture.attributes;
519     attributes->extend = src->base.extend;
520     attributes->filter = src->base.filter;
521     attributes->has_component_alpha = src->base.has_component_alpha;
522
523     if (surface->needs_to_cache)
524         status = _cairo_gl_image_cache_add_image (ctx, dst, surface,
525                                                   &image_node);
526
527     if (unlikely (status) || ! image_node)
528         cairo_matrix_multiply (&attributes->matrix,
529                                &src->base.matrix,
530                                &attributes->matrix);
531     else {
532         cairo_matrix_t matrix = src->base.matrix;
533         operand->texture.use_atlas = TRUE;
534         attributes->extend = CAIRO_EXTEND_NONE;
535         operand->texture.extend = src->base.extend;
536
537         operand->texture.p1.x = image_node->p1.x;
538         operand->texture.p1.y = image_node->p1.y;
539         operand->texture.p2.x = image_node->p2.x;
540         operand->texture.p2.y = image_node->p2.y;
541         if (src->base.extend == CAIRO_EXTEND_PAD) {
542             operand->texture.p1.x += 0.5 / IMAGE_CACHE_WIDTH;
543             operand->texture.p1.y += 0.5 / IMAGE_CACHE_HEIGHT;
544             operand->texture.p2.x -= 0.5 / IMAGE_CACHE_WIDTH;
545             operand->texture.p2.y -= 0.5 / IMAGE_CACHE_HEIGHT;
546         }
547
548         operand->texture.surface = ctx->image_cache.surface;
549         operand->texture.owns_surface = NULL;
550         operand->texture.tex = ctx->image_cache.surface->tex;
551         matrix.x0 += image_node->node.x;
552         matrix.y0 += image_node->node.y;
553         cairo_matrix_multiply (&attributes->matrix,
554                                &matrix,
555                                &ctx->image_cache.surface->operand.texture.attributes.matrix);
556     }
557
558     return CAIRO_STATUS_SUCCESS;
559 }
560
561 static cairo_status_t
562 _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
563                                  const cairo_pattern_t *_src,
564                                  cairo_gl_surface_t *dst,
565                                  const cairo_rectangle_int_t *extents)
566 {
567     cairo_status_t status;
568     cairo_gl_surface_t *surface;
569     cairo_gl_context_t *ctx;
570     cairo_image_surface_t *image;
571     cairo_bool_t src_is_gl_surface = FALSE;
572     pixman_format_code_t pixman_format;
573
574     if (_src->type == CAIRO_PATTERN_TYPE_SURFACE) {
575         cairo_surface_t* src_surface = ((cairo_surface_pattern_t *) _src)->surface;
576         src_is_gl_surface = src_surface->type == CAIRO_SURFACE_TYPE_GL;
577     }
578
579     status = _cairo_gl_context_acquire (dst->base.device, &ctx);
580     if (unlikely (status))
581         return status;
582
583     surface = (cairo_gl_surface_t *)
584         _cairo_gl_surface_create_scratch (ctx,
585                                           CAIRO_CONTENT_COLOR_ALPHA,
586                                           extents->width, extents->height,
587                                           FALSE);
588
589     /* XXX: This is a hack for driver that does not support PBO, we
590        don't need an extra step of downloading newly created texture
591        to image, we can create image directly. */
592     if (! _cairo_is_little_endian ())
593         pixman_format = PIXMAN_r8g8b8a8;
594     else
595         pixman_format = PIXMAN_a8b8g8r8;
596     image = (cairo_image_surface_t*)
597         _cairo_image_surface_create_with_pixman_format (NULL,
598                                                         pixman_format,
599                                                         extents->width,
600                                                         extents->height,
601                                                         -1);
602     if (unlikely (image->base.status)) {
603         status = _cairo_gl_context_release (ctx, status);
604
605         /* The error status in the image is issue that caused the problem. */
606         status = image->base.status;
607
608         cairo_surface_destroy (&image->base);
609         goto fail;
610     }
611
612     /* If the pattern is a GL surface, it belongs to some other GL context,
613        so we need to release this device while we paint it to the image. */
614     if (src_is_gl_surface) {
615         status = _cairo_gl_context_release (ctx, status);
616         if (unlikely (status))
617             goto fail;
618     }
619
620     status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
621                                           CAIRO_OPERATOR_SOURCE, _src, NULL);
622
623     if (src_is_gl_surface) {
624         status = _cairo_gl_context_acquire (dst->base.device, &ctx);
625         if (unlikely (status))
626             goto fail;
627     }
628
629     status = _cairo_surface_unmap_image (&surface->base, image);
630     status = _cairo_gl_context_release (ctx, status);
631     if (unlikely (status))
632         goto fail;
633
634     *operand = surface->operand;
635     operand->texture.owns_surface = surface;
636     operand->texture.attributes.matrix.x0 -= extents->x * operand->texture.attributes.matrix.xx;
637     operand->texture.attributes.matrix.y0 -= extents->y * operand->texture.attributes.matrix.yy;
638     dst->needs_to_cache = TRUE;
639     operand->texture.use_atlas = FALSE;
640
641     return CAIRO_STATUS_SUCCESS;
642
643 fail:
644     cairo_surface_destroy (&surface->base);
645     return status;
646 }
647
648 void
649 _cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
650                               const cairo_color_t *color)
651 {
652     operand->type = CAIRO_GL_OPERAND_CONSTANT;
653     operand->constant.color[0] = color->red   * color->alpha;
654     operand->constant.color[1] = color->green * color->alpha;
655     operand->constant.color[2] = color->blue  * color->alpha;
656     operand->constant.color[3] = color->alpha;
657 }
658
659 void
660 _cairo_gl_operand_translate (cairo_gl_operand_t *operand,
661                              double tx, double ty)
662 {
663     switch (operand->type) {
664     case CAIRO_GL_OPERAND_TEXTURE:
665         operand->texture.attributes.matrix.x0 -= tx * operand->texture.attributes.matrix.xx;
666         operand->texture.attributes.matrix.y0 -= ty * operand->texture.attributes.matrix.yy;
667         break;
668
669     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
670     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
671     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
672     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
673         operand->gradient.m.x0 -= tx * operand->gradient.m.xx;
674         operand->gradient.m.y0 -= ty * operand->gradient.m.yy;
675         break;
676
677     case CAIRO_GL_OPERAND_NONE:
678     case CAIRO_GL_OPERAND_CONSTANT:
679     case CAIRO_GL_OPERAND_COUNT:
680     default:
681         break;
682     }
683 }
684
685 static cairo_status_t
686 _cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
687                                  const cairo_pattern_t *pattern,
688                                  cairo_gl_surface_t *dst)
689 {
690     const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern;
691     cairo_status_t status;
692
693     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
694             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
695
696     if (! _cairo_gl_device_has_glsl (dst->base.device))
697         return CAIRO_INT_STATUS_UNSUPPORTED;
698
699     status = _cairo_gl_create_gradient_texture (dst,
700                                                 gradient,
701                                                 &operand->gradient.gradient);
702     if (unlikely (status))
703         return status;
704
705     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
706         cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
707         double x0, y0, dx, dy, sf, offset;
708
709         dx = linear->pd2.x - linear->pd1.x;
710         dy = linear->pd2.y - linear->pd1.y;
711         sf = 1.0 / (dx * dx + dy * dy);
712         dx *= sf;
713         dy *= sf;
714
715         x0 = linear->pd1.x;
716         y0 = linear->pd1.y;
717         offset = dx * x0 + dy * y0;
718
719         operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
720
721         cairo_matrix_init (&operand->gradient.m, dx, 0, dy, 1, -offset, 0);
722         if (! _cairo_matrix_is_identity (&pattern->matrix)) {
723             cairo_matrix_multiply (&operand->gradient.m,
724                                    &pattern->matrix,
725                                    &operand->gradient.m);
726         }
727     } else {
728         cairo_matrix_t m;
729         cairo_circle_double_t circles[2];
730         double x0, y0, r0, dx, dy, dr;
731         double scale = 1.0;
732         cairo_radial_pattern_t *radial_pattern = (cairo_radial_pattern_t *)gradient;
733
734         /*
735          * Some fragment shader implementations use half-floats to
736          * represent numbers, so the maximum number they can represent
737          * is about 2^14. Some intermediate computations used in the
738          * radial gradient shaders can produce results of up to 2*k^4.
739          * Setting k=8 makes the maximum result about 8192 (assuming
740          * that the extreme circles are not much smaller than the
741          * destination image).
742          */
743         _cairo_gradient_pattern_fit_to_range (gradient, 8.,
744                                               &operand->gradient.m, circles);
745
746         /*
747          * Instead of using scaled data that might introducing rounding
748          * errors, we use original data directly
749          */
750         if (circles[0].center.x)
751                 scale = radial_pattern->cd1.center.x / circles[0].center.x;
752         else if (circles[0].center.y)
753                 scale = radial_pattern->cd1.center.y / circles[0].center.y;
754         else if (circles[0].radius)
755                 scale = radial_pattern->cd1.radius / circles[0].radius;
756         else if (circles[1].center.x)
757                 scale = radial_pattern->cd2.center.x / circles[1].center.x;
758         else if (circles[1].center.y)
759                 scale = radial_pattern->cd2.center.y / circles[1].center.y;
760         else if (circles[1].radius)
761                 scale = radial_pattern->cd2.radius / circles[1].radius;
762
763         x0 = circles[0].center.x;
764         y0 = circles[0].center.y;
765         r0 = circles[0].radius;
766         dx = radial_pattern->cd2.center.x - radial_pattern->cd1.center.x;
767         dy = radial_pattern->cd2.center.y - radial_pattern->cd1.center.y;
768         dr = radial_pattern->cd2.radius   - radial_pattern->cd1.radius;
769
770         operand->gradient.a = (dx * dx + dy * dy - dr * dr)/(scale * scale);
771         operand->gradient.radius_0 = r0;
772         operand->gradient.circle_d.center.x = dx / scale;
773         operand->gradient.circle_d.center.y = dy / scale;
774         operand->gradient.circle_d.radius       = dr / scale;
775
776         if (operand->gradient.a == 0)
777             operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0;
778         else if (pattern->extend == CAIRO_EXTEND_NONE)
779             operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE;
780         else
781             operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT;
782
783         cairo_matrix_init_translate (&m, -x0, -y0);
784         cairo_matrix_multiply (&operand->gradient.m,
785                                &operand->gradient.m,
786                                &m);
787     }
788
789     operand->gradient.extend = pattern->extend;
790
791     return CAIRO_STATUS_SUCCESS;
792 }
793
794 void
795 _cairo_gl_operand_copy (cairo_gl_operand_t *dst,
796                         const cairo_gl_operand_t *src)
797 {
798     *dst = *src;
799     switch (dst->type) {
800     case CAIRO_GL_OPERAND_CONSTANT:
801         break;
802     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
803     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
804     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
805     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
806         _cairo_gl_gradient_reference (dst->gradient.gradient);
807         break;
808     case CAIRO_GL_OPERAND_TEXTURE:
809         cairo_surface_reference (&dst->texture.owns_surface->base);
810         break;
811     default:
812     case CAIRO_GL_OPERAND_COUNT:
813         ASSERT_NOT_REACHED;
814     case CAIRO_GL_OPERAND_NONE:
815         break;
816     }
817 }
818
819 void
820 _cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
821 {
822     switch (operand->type) {
823     case CAIRO_GL_OPERAND_CONSTANT:
824         break;
825     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
826     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
827     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
828     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
829         _cairo_gl_gradient_destroy (operand->gradient.gradient);
830         break;
831     case CAIRO_GL_OPERAND_TEXTURE:
832         cairo_surface_destroy (&operand->texture.owns_surface->base);
833         break;
834     default:
835     case CAIRO_GL_OPERAND_COUNT:
836         ASSERT_NOT_REACHED;
837     case CAIRO_GL_OPERAND_NONE:
838         break;
839     }
840
841     operand->type = CAIRO_GL_OPERAND_NONE;
842 }
843
844 cairo_int_status_t
845 _cairo_gl_operand_init (cairo_gl_operand_t *operand,
846                         const cairo_pattern_t *pattern,
847                         cairo_gl_surface_t *dst,
848                         const cairo_rectangle_int_t *sample,
849                         const cairo_rectangle_int_t *extents,
850                         cairo_bool_t use_color_attribute)
851 {
852     cairo_int_status_t status;
853
854     TRACE ((stderr, "%s: type=%d\n", __FUNCTION__, pattern->type));
855     switch (pattern->type) {
856     case CAIRO_PATTERN_TYPE_SOLID:
857         _cairo_gl_solid_operand_init (operand,
858                                       &((cairo_solid_pattern_t *) pattern)->color);
859         operand->use_color_attribute = use_color_attribute;
860         return CAIRO_STATUS_SUCCESS;
861     case CAIRO_PATTERN_TYPE_SURFACE:
862         status = _cairo_gl_surface_operand_init (operand, pattern, dst,
863                                                  sample, extents);
864         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
865             break;
866
867         return status;
868
869     case CAIRO_PATTERN_TYPE_LINEAR:
870     case CAIRO_PATTERN_TYPE_RADIAL:
871         status = _cairo_gl_gradient_operand_init (operand, pattern, dst);
872         if (status == CAIRO_INT_STATUS_UNSUPPORTED)
873             break;
874
875         return status;
876
877     default:
878     case CAIRO_PATTERN_TYPE_MESH:
879     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
880         break;
881     }
882
883     return _cairo_gl_pattern_texture_setup (operand, pattern, dst, extents);
884 }
885
886 cairo_filter_t
887 _cairo_gl_operand_get_filter (cairo_gl_operand_t *operand)
888 {
889     cairo_filter_t filter;
890
891     switch ((int) operand->type) {
892     case CAIRO_GL_OPERAND_TEXTURE:
893         filter = operand->texture.attributes.filter;
894         break;
895     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
896     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
897     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
898     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
899         filter = CAIRO_FILTER_BILINEAR;
900         break;
901     default:
902         filter = CAIRO_FILTER_DEFAULT;
903         break;
904     }
905
906     return filter;
907 }
908
909 GLint
910 _cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand)
911 {
912     cairo_filter_t filter = _cairo_gl_operand_get_filter (operand);
913
914     return filter != CAIRO_FILTER_FAST && filter != CAIRO_FILTER_NEAREST ?
915            GL_LINEAR :
916            GL_NEAREST;
917 }
918
919 cairo_bool_t
920 _cairo_gl_operand_get_use_atlas (cairo_gl_operand_t *operand)
921 {
922     if (operand->type != CAIRO_GL_OPERAND_TEXTURE)
923         return FALSE;
924
925     return operand->texture.use_atlas;
926 }
927
928 cairo_extend_t
929 _cairo_gl_operand_get_extend (cairo_gl_operand_t *operand)
930 {
931     cairo_extend_t extend;
932
933     switch ((int) operand->type) {
934     case CAIRO_GL_OPERAND_TEXTURE:
935         if (! operand->texture.use_atlas)
936             extend = operand->texture.attributes.extend;
937         else
938             extend = operand->texture.extend;
939         break;
940     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
941     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
942     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
943     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
944         extend = operand->gradient.extend;
945         break;
946     default:
947         extend = CAIRO_EXTEND_NONE;
948         break;
949     }
950
951     return extend;
952 }
953
954 cairo_extend_t
955 _cairo_gl_operand_get_atlas_extend (cairo_gl_operand_t *operand)
956 {
957     cairo_extend_t extend;
958
959     switch ((int) operand->type) {
960     case CAIRO_GL_OPERAND_TEXTURE:
961         if (operand->texture.use_atlas)
962             extend = operand->texture.extend;
963         else
964             extend = CAIRO_EXTEND_NONE;
965         break;
966     default:
967         extend = CAIRO_EXTEND_NONE;
968         break;
969     }
970
971     return extend;
972 }
973
974 void
975 _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
976                                   cairo_gl_operand_t *operand,
977                                   cairo_gl_tex_t      tex_unit)
978 {
979     char uniform_name[50];
980     char *custom_part;
981     static const char *names[] = { "source", "mask" };
982
983     strcpy (uniform_name, names[tex_unit]);
984     custom_part = uniform_name + strlen (names[tex_unit]);
985
986     switch (operand->type) {
987     default:
988     case CAIRO_GL_OPERAND_COUNT:
989         ASSERT_NOT_REACHED;
990     case CAIRO_GL_OPERAND_NONE:
991         break;
992     case CAIRO_GL_OPERAND_CONSTANT:
993         if (!operand->use_color_attribute) {
994             strcpy (custom_part, "_constant");
995             _cairo_gl_shader_bind_vec4 (ctx,
996                                         uniform_name,
997                                         operand->constant.color[0],
998                                         operand->constant.color[1],
999                                         operand->constant.color[2],
1000                                         operand->constant.color[3]);
1001         }
1002         break;
1003     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1004     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1005         strcpy (custom_part, "_a");
1006         _cairo_gl_shader_bind_float  (ctx,
1007                                       uniform_name,
1008                                       operand->gradient.a);
1009         /* fall through */
1010     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1011         strcpy (custom_part, "_circle_d");
1012         _cairo_gl_shader_bind_vec3   (ctx,
1013                                       uniform_name,
1014                                       operand->gradient.circle_d.center.x,
1015                                       operand->gradient.circle_d.center.y,
1016                                       operand->gradient.circle_d.radius);
1017         strcpy (custom_part, "_radius_0");
1018         _cairo_gl_shader_bind_float  (ctx,
1019                                       uniform_name,
1020                                       operand->gradient.radius_0);
1021         /* fall through */
1022     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1023     case CAIRO_GL_OPERAND_TEXTURE:
1024         /*
1025          * For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used
1026          * with CAIRO_EXTEND_NONE). When bilinear filtering is enabled,
1027          * these shaders need the texture dimensions for their calculations.
1028          */
1029         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
1030             _cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE &&
1031             _cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR)
1032         {
1033             float width, height;
1034             if (operand->type == CAIRO_GL_OPERAND_TEXTURE) {
1035                 width = operand->texture.surface->width;
1036                 height = operand->texture.surface->height;
1037             }
1038             else {
1039                 width = operand->gradient.gradient->tex_width,
1040                 height = 1;
1041             }
1042             strcpy (custom_part, "_texdims");
1043             _cairo_gl_shader_bind_vec2 (ctx, uniform_name, width, height);
1044         }
1045         break;
1046     }
1047 }
1048
1049
1050 cairo_bool_t
1051 _cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
1052                                cairo_gl_operand_t *source,
1053                                unsigned int        vertex_offset,
1054                                cairo_bool_t        *needs_flush)
1055 {
1056     if (dest->type != source->type)
1057         return TRUE;
1058     if (dest->vertex_offset != vertex_offset)
1059         return TRUE;
1060
1061     switch (source->type) {
1062     case CAIRO_GL_OPERAND_NONE:
1063     case CAIRO_GL_OPERAND_CONSTANT:
1064         if (source->use_color_attribute) {
1065             *needs_flush = FALSE;
1066             return TRUE;
1067         } else {
1068             return dest->constant.color[0] != source->constant.color[0] ||
1069                 dest->constant.color[1] != source->constant.color[1] ||
1070                 dest->constant.color[2] != source->constant.color[2] ||
1071                 dest->constant.color[3] != source->constant.color[3];
1072         }
1073     case CAIRO_GL_OPERAND_TEXTURE:
1074         return dest->texture.surface != source->texture.surface ||
1075                dest->texture.attributes.extend != source->texture.attributes.extend ||
1076                dest->texture.attributes.filter != source->texture.attributes.filter ||
1077                dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha;
1078     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1079     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1080     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1081     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1082         /* XXX: improve this */
1083         return TRUE;
1084     default:
1085     case CAIRO_GL_OPERAND_COUNT:
1086         ASSERT_NOT_REACHED;
1087         break;
1088     }
1089     return TRUE;
1090 }
1091
1092 unsigned int
1093 _cairo_gl_operand_get_vertex_size (cairo_gl_operand_t *operand)
1094 {
1095     switch (operand->type) {
1096     default:
1097     case CAIRO_GL_OPERAND_COUNT:
1098         ASSERT_NOT_REACHED;
1099     case CAIRO_GL_OPERAND_NONE:
1100         return 0;
1101     case CAIRO_GL_OPERAND_CONSTANT:
1102         if (operand->use_color_attribute)
1103             return 4 * sizeof (GLubyte);
1104         else
1105             return 0;
1106     case CAIRO_GL_OPERAND_TEXTURE:
1107         if (operand->texture.use_atlas)
1108             return 6 * sizeof (GLfloat);
1109         else
1110             return 2 * sizeof (GLfloat);
1111     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1112     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1113     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1114     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1115         return 2 * sizeof (GLfloat);
1116     }
1117 }
1118
1119 static inline cairo_int_status_t
1120 _cairo_gl_context_get_image_cache (cairo_gl_context_t      *ctx,
1121                                    cairo_gl_image_cache_t  **cache_out)
1122 {
1123     if (! ctx->image_cache.surface)
1124         return CAIRO_INT_STATUS_UNSUPPORTED;
1125
1126     *cache_out = &(ctx->image_cache);
1127     return CAIRO_INT_STATUS_SUCCESS;
1128 }
1129
1130 /* Called from _cairo_rtree_node_remove. */
1131 void
1132 _cairo_gl_image_node_destroy (cairo_rtree_node_t *node)
1133 {
1134     cairo_surface_t *surface;
1135
1136     cairo_gl_image_t *image_node = cairo_container_of (node,
1137                                                        cairo_gl_image_t,
1138                                                        node);
1139
1140     surface = image_node->original_surface;
1141     image_node->node_removed = TRUE;
1142    /* Remove from original surface. */
1143    if (image_node->original_surface &&
1144        ! image_node->user_data_removed) {
1145         cairo_surface_set_user_data (image_node->original_surface,
1146                                      (const cairo_user_data_key_t *) surface,
1147                                      (void *) NULL, NULL);
1148     }
1149 }
1150
1151 void
1152 _cairo_gl_image_node_fini (void *data)
1153 {
1154     cairo_gl_image_t *image_node = (cairo_gl_image_t *)data;
1155
1156     image_node->user_data_removed = TRUE;
1157
1158     if (! image_node->node_removed && ! image_node->node.pinned)
1159         _cairo_rtree_node_remove (&image_node->ctx->image_cache.rtree,
1160                                   &image_node->node);
1161 }