1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Eric Anholt
4 * Copyright © 2009 Chris Wilson
5 * Copyright © 2005,2010 Red Hat, Inc
6 * Copyright © 2011 Intel Corporation
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.
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
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/
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.
31 * The Original Code is the cairo graphics library.
33 * The Initial Developer of the Original Code is Red Hat, Inc.
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>
44 #include "cairo-gl-private.h"
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-subsurface-inline.h"
55 static cairo_int_status_t
56 _cairo_gl_create_gradient_texture (cairo_gl_surface_t
*dst
,
57 const cairo_gradient_pattern_t
*pattern
,
58 cairo_gl_gradient_t
**gradient
)
60 cairo_gl_context_t
*ctx
;
61 cairo_status_t status
;
63 status
= _cairo_gl_context_acquire (dst
->base
.device
, &ctx
);
64 if (unlikely (status
))
67 status
= _cairo_gl_gradient_create (ctx
, pattern
->n_stops
, pattern
->stops
, gradient
);
69 return _cairo_gl_context_release (ctx
, status
);
73 _cairo_gl_subsurface_clone_operand_init (cairo_gl_operand_t
*operand
,
74 const cairo_pattern_t
*_src
,
75 cairo_gl_surface_t
*dst
,
76 const cairo_rectangle_int_t
*sample
,
77 const cairo_rectangle_int_t
*extents
,
78 cairo_bool_t use_texgen
)
80 const cairo_surface_pattern_t
*src
= (cairo_surface_pattern_t
*)_src
;
81 cairo_surface_pattern_t local_pattern
;
82 cairo_surface_subsurface_t
*sub
;
83 cairo_gl_surface_t
*surface
;
84 cairo_gl_context_t
*ctx
;
85 cairo_surface_attributes_t
*attributes
;
86 cairo_status_t status
;
88 sub
= (cairo_surface_subsurface_t
*) src
->surface
;
91 sub
->snapshot
->type
== CAIRO_SURFACE_TYPE_GL
&&
92 sub
->snapshot
->device
== dst
->base
.device
)
94 surface
= (cairo_gl_surface_t
*)
95 cairo_surface_reference (sub
->snapshot
);
99 status
= _cairo_gl_context_acquire (dst
->base
.device
, &ctx
);
100 if (unlikely (status
))
103 /* XXX Trim surface to the sample area within the subsurface? */
104 surface
= (cairo_gl_surface_t
*)
105 _cairo_gl_surface_create_scratch (ctx
,
106 sub
->target
->content
,
108 sub
->extents
.height
);
109 if (surface
->base
.status
)
110 return _cairo_gl_context_release (ctx
, surface
->base
.status
);
112 _cairo_pattern_init_for_surface (&local_pattern
, sub
->target
);
113 cairo_matrix_init_translate (&local_pattern
.base
.matrix
,
114 sub
->extents
.x
, sub
->extents
.y
);
115 local_pattern
.base
.filter
= CAIRO_FILTER_NEAREST
;
116 status
= _cairo_surface_paint (&surface
->base
,
117 CAIRO_OPERATOR_SOURCE
,
120 _cairo_pattern_fini (&local_pattern
.base
);
122 status
= _cairo_gl_context_release (ctx
, status
);
123 if (unlikely (status
)) {
124 cairo_surface_destroy (&surface
->base
);
128 _cairo_surface_subsurface_set_snapshot (&sub
->base
, &surface
->base
);
131 status
= _cairo_gl_surface_resolve_multisampling (surface
);
132 if (unlikely (status
))
135 attributes
= &operand
->texture
.attributes
;
137 operand
->type
= CAIRO_GL_OPERAND_TEXTURE
;
138 operand
->texture
.surface
= surface
;
139 operand
->texture
.owns_surface
= surface
;
140 operand
->texture
.tex
= surface
->tex
;
142 if (_cairo_gl_device_requires_power_of_two_textures (dst
->base
.device
)) {
143 attributes
->matrix
= src
->base
.matrix
;
147 cairo_matrix_init_scale (&m
,
148 1.0 / surface
->width
,
149 1.0 / surface
->height
);
150 cairo_matrix_multiply (&attributes
->matrix
, &src
->base
.matrix
, &m
);
153 attributes
->extend
= src
->base
.extend
;
154 attributes
->filter
= src
->base
.filter
;
155 attributes
->has_component_alpha
= src
->base
.has_component_alpha
;
157 operand
->texture
.texgen
= use_texgen
;
158 return CAIRO_STATUS_SUCCESS
;
161 static cairo_status_t
162 _cairo_gl_subsurface_operand_init (cairo_gl_operand_t
*operand
,
163 const cairo_pattern_t
*_src
,
164 cairo_gl_surface_t
*dst
,
165 const cairo_rectangle_int_t
*sample
,
166 const cairo_rectangle_int_t
*extents
,
167 cairo_bool_t use_texgen
)
169 const cairo_surface_pattern_t
*src
= (cairo_surface_pattern_t
*)_src
;
170 cairo_surface_subsurface_t
*sub
;
171 cairo_gl_surface_t
*surface
;
172 cairo_surface_attributes_t
*attributes
;
173 cairo_int_status_t status
;
175 sub
= (cairo_surface_subsurface_t
*) src
->surface
;
177 if (sample
->x
< 0 || sample
->y
< 0 ||
178 sample
->x
+ sample
->width
> sub
->extents
.width
||
179 sample
->y
+ sample
->height
> sub
->extents
.height
)
181 return _cairo_gl_subsurface_clone_operand_init (operand
, _src
,
182 dst
, sample
, extents
,
186 surface
= (cairo_gl_surface_t
*) sub
->target
;
187 if (surface
->base
.device
&& surface
->base
.device
!= dst
->base
.device
)
188 return CAIRO_INT_STATUS_UNSUPPORTED
;
190 if (! _cairo_gl_surface_is_texture (surface
))
191 return CAIRO_INT_STATUS_UNSUPPORTED
;
193 status
= _cairo_gl_surface_resolve_multisampling (surface
);
194 if (unlikely (status
))
197 /* Translate the matrix from
198 * (unnormalized src -> unnormalized src) to
199 * (unnormalized dst -> unnormalized src)
201 _cairo_gl_operand_copy(operand
, &surface
->operand
);
203 attributes
= &operand
->texture
.attributes
;
204 attributes
->matrix
= src
->base
.matrix
;
205 attributes
->matrix
.x0
+= sub
->extents
.x
;
206 attributes
->matrix
.y0
+= sub
->extents
.y
;
207 cairo_matrix_multiply (&attributes
->matrix
,
209 &surface
->operand
.texture
.attributes
.matrix
);
211 attributes
->extend
= src
->base
.extend
;
212 attributes
->filter
= src
->base
.filter
;
213 attributes
->has_component_alpha
= src
->base
.has_component_alpha
;
215 operand
->texture
.texgen
= use_texgen
;
216 return CAIRO_STATUS_SUCCESS
;
219 static cairo_status_t
220 _cairo_gl_surface_operand_init (cairo_gl_operand_t
*operand
,
221 const cairo_pattern_t
*_src
,
222 cairo_gl_surface_t
*dst
,
223 const cairo_rectangle_int_t
*sample
,
224 const cairo_rectangle_int_t
*extents
,
225 cairo_bool_t use_texgen
)
227 const cairo_surface_pattern_t
*src
= (cairo_surface_pattern_t
*)_src
;
228 cairo_gl_surface_t
*surface
;
229 cairo_surface_attributes_t
*attributes
;
230 cairo_int_status_t status
;
232 surface
= (cairo_gl_surface_t
*) src
->surface
;
233 if (surface
->base
.type
!= CAIRO_SURFACE_TYPE_GL
)
234 return CAIRO_INT_STATUS_UNSUPPORTED
;
236 if (surface
->base
.backend
->type
!= CAIRO_SURFACE_TYPE_GL
) {
237 if (_cairo_surface_is_subsurface (&surface
->base
))
238 return _cairo_gl_subsurface_operand_init (operand
, _src
, dst
,
242 return CAIRO_INT_STATUS_UNSUPPORTED
;
245 if (surface
->base
.device
&& surface
->base
.device
!= dst
->base
.device
)
246 return CAIRO_INT_STATUS_UNSUPPORTED
;
248 if (surface
->base
.device
&& ! _cairo_gl_surface_is_texture (surface
))
249 return CAIRO_INT_STATUS_UNSUPPORTED
;
251 status
= _cairo_gl_surface_resolve_multisampling (surface
);
252 if (unlikely (status
))
255 _cairo_gl_operand_copy(operand
, &surface
->operand
);
257 attributes
= &operand
->texture
.attributes
;
258 cairo_matrix_multiply (&attributes
->matrix
,
260 &attributes
->matrix
);
262 attributes
->extend
= src
->base
.extend
;
263 attributes
->filter
= src
->base
.filter
;
264 attributes
->has_component_alpha
= src
->base
.has_component_alpha
;
266 operand
->texture
.texgen
= use_texgen
;
267 return CAIRO_STATUS_SUCCESS
;
270 static cairo_status_t
271 _cairo_gl_pattern_texture_setup (cairo_gl_operand_t
*operand
,
272 const cairo_pattern_t
*_src
,
273 cairo_gl_surface_t
*dst
,
274 const cairo_rectangle_int_t
*extents
)
276 cairo_status_t status
;
277 cairo_gl_surface_t
*surface
;
278 cairo_gl_context_t
*ctx
;
279 cairo_image_surface_t
*image
;
280 cairo_bool_t src_is_gl_surface
= FALSE
;
281 cairo_rectangle_int_t map_extents
;
283 if (_src
->type
== CAIRO_PATTERN_TYPE_SURFACE
) {
284 cairo_surface_t
* src_surface
= ((cairo_surface_pattern_t
*) _src
)->surface
;
285 src_is_gl_surface
= src_surface
->type
== CAIRO_SURFACE_TYPE_GL
;
288 status
= _cairo_gl_context_acquire (dst
->base
.device
, &ctx
);
289 if (unlikely (status
))
292 surface
= (cairo_gl_surface_t
*)
293 _cairo_gl_surface_create_scratch (ctx
,
294 CAIRO_CONTENT_COLOR_ALPHA
,
295 extents
->width
, extents
->height
);
296 map_extents
= *extents
;
297 map_extents
.x
= map_extents
.y
= 0;
298 image
= _cairo_surface_map_to_image (&surface
->base
, &map_extents
);
300 /* If the pattern is a GL surface, it belongs to some other GL context,
301 so we need to release this device while we paint it to the image. */
302 if (src_is_gl_surface
) {
303 status
= _cairo_gl_context_release (ctx
, status
);
304 if (unlikely (status
)) {
305 _cairo_surface_unmap_image (&surface
->base
, image
);
310 status
= _cairo_surface_offset_paint (&image
->base
, extents
->x
, extents
->y
,
311 CAIRO_OPERATOR_SOURCE
, _src
, NULL
);
313 if (src_is_gl_surface
) {
314 status
= _cairo_gl_context_acquire (dst
->base
.device
, &ctx
);
315 if (unlikely (status
)) {
316 _cairo_surface_unmap_image (&surface
->base
, image
);
321 status
= _cairo_surface_unmap_image (&surface
->base
, image
);
322 status
= _cairo_gl_context_release (ctx
, status
);
323 if (unlikely (status
))
326 *operand
= surface
->operand
;
327 operand
->texture
.owns_surface
= surface
;
328 operand
->texture
.attributes
.matrix
.x0
-= extents
->x
* operand
->texture
.attributes
.matrix
.xx
;
329 operand
->texture
.attributes
.matrix
.y0
-= extents
->y
* operand
->texture
.attributes
.matrix
.yy
;
330 return CAIRO_STATUS_SUCCESS
;
333 cairo_surface_destroy (&surface
->base
);
338 _cairo_gl_solid_operand_init (cairo_gl_operand_t
*operand
,
339 const cairo_color_t
*color
)
341 operand
->type
= CAIRO_GL_OPERAND_CONSTANT
;
342 operand
->constant
.color
[0] = color
->red
* color
->alpha
;
343 operand
->constant
.color
[1] = color
->green
* color
->alpha
;
344 operand
->constant
.color
[2] = color
->blue
* color
->alpha
;
345 operand
->constant
.color
[3] = color
->alpha
;
349 _cairo_gl_operand_translate (cairo_gl_operand_t
*operand
,
350 double tx
, double ty
)
352 switch (operand
->type
) {
353 case CAIRO_GL_OPERAND_TEXTURE
:
354 operand
->texture
.attributes
.matrix
.x0
-= tx
* operand
->texture
.attributes
.matrix
.xx
;
355 operand
->texture
.attributes
.matrix
.y0
-= ty
* operand
->texture
.attributes
.matrix
.yy
;
358 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
359 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
360 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
361 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
362 operand
->gradient
.m
.x0
-= tx
* operand
->gradient
.m
.xx
;
363 operand
->gradient
.m
.y0
-= ty
* operand
->gradient
.m
.yy
;
366 case CAIRO_GL_OPERAND_NONE
:
367 case CAIRO_GL_OPERAND_CONSTANT
:
368 case CAIRO_GL_OPERAND_COUNT
:
374 static cairo_status_t
375 _cairo_gl_gradient_operand_init (cairo_gl_operand_t
*operand
,
376 const cairo_pattern_t
*pattern
,
377 cairo_gl_surface_t
*dst
,
378 cairo_bool_t use_texgen
)
380 const cairo_gradient_pattern_t
*gradient
= (const cairo_gradient_pattern_t
*)pattern
;
381 cairo_status_t status
;
383 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
384 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
386 if (! _cairo_gl_device_has_glsl (dst
->base
.device
))
387 return CAIRO_INT_STATUS_UNSUPPORTED
;
389 status
= _cairo_gl_create_gradient_texture (dst
,
391 &operand
->gradient
.gradient
);
392 if (unlikely (status
))
395 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
396 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) gradient
;
397 double x0
, y0
, dx
, dy
, sf
, offset
;
399 dx
= linear
->pd2
.x
- linear
->pd1
.x
;
400 dy
= linear
->pd2
.y
- linear
->pd1
.y
;
401 sf
= 1.0 / (dx
* dx
+ dy
* dy
);
407 offset
= dx
* x0
+ dy
* y0
;
409 operand
->type
= CAIRO_GL_OPERAND_LINEAR_GRADIENT
;
411 cairo_matrix_init (&operand
->gradient
.m
, dx
, 0, dy
, 1, -offset
, 0);
412 if (! _cairo_matrix_is_identity (&pattern
->matrix
)) {
413 cairo_matrix_multiply (&operand
->gradient
.m
,
415 &operand
->gradient
.m
);
419 cairo_circle_double_t circles
[2];
420 double x0
, y0
, r0
, dx
, dy
, dr
;
423 * Some fragment shader implementations use half-floats to
424 * represent numbers, so the maximum number they can represent
425 * is about 2^14. Some intermediate computations used in the
426 * radial gradient shaders can produce results of up to 2*k^4.
427 * Setting k=8 makes the maximum result about 8192 (assuming
428 * that the extreme circles are not much smaller than the
429 * destination image).
431 _cairo_gradient_pattern_fit_to_range (gradient
, 8.,
432 &operand
->gradient
.m
, circles
);
434 x0
= circles
[0].center
.x
;
435 y0
= circles
[0].center
.y
;
436 r0
= circles
[0].radius
;
437 dx
= circles
[1].center
.x
- x0
;
438 dy
= circles
[1].center
.y
- y0
;
439 dr
= circles
[1].radius
- r0
;
441 operand
->gradient
.a
= dx
* dx
+ dy
* dy
- dr
* dr
;
442 operand
->gradient
.radius_0
= r0
;
443 operand
->gradient
.circle_d
.center
.x
= dx
;
444 operand
->gradient
.circle_d
.center
.y
= dy
;
445 operand
->gradient
.circle_d
.radius
= dr
;
447 if (operand
->gradient
.a
== 0)
448 operand
->type
= CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
;
449 else if (pattern
->extend
== CAIRO_EXTEND_NONE
)
450 operand
->type
= CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
;
452 operand
->type
= CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
;
454 cairo_matrix_init_translate (&m
, -x0
, -y0
);
455 cairo_matrix_multiply (&operand
->gradient
.m
,
456 &operand
->gradient
.m
,
460 operand
->gradient
.extend
= pattern
->extend
;
461 operand
->gradient
.texgen
= use_texgen
;
463 return CAIRO_STATUS_SUCCESS
;
467 _cairo_gl_operand_copy (cairo_gl_operand_t
*dst
,
468 const cairo_gl_operand_t
*src
)
472 case CAIRO_GL_OPERAND_CONSTANT
:
474 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
475 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
476 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
477 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
478 _cairo_gl_gradient_reference (dst
->gradient
.gradient
);
480 case CAIRO_GL_OPERAND_TEXTURE
:
481 cairo_surface_reference (&dst
->texture
.owns_surface
->base
);
484 case CAIRO_GL_OPERAND_COUNT
:
486 case CAIRO_GL_OPERAND_NONE
:
492 _cairo_gl_operand_destroy (cairo_gl_operand_t
*operand
)
494 switch (operand
->type
) {
495 case CAIRO_GL_OPERAND_CONSTANT
:
497 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
498 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
499 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
500 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
501 _cairo_gl_gradient_destroy (operand
->gradient
.gradient
);
503 case CAIRO_GL_OPERAND_TEXTURE
:
504 cairo_surface_destroy (&operand
->texture
.owns_surface
->base
);
507 case CAIRO_GL_OPERAND_COUNT
:
509 case CAIRO_GL_OPERAND_NONE
:
513 operand
->type
= CAIRO_GL_OPERAND_NONE
;
517 _cairo_gl_operand_init (cairo_gl_operand_t
*operand
,
518 const cairo_pattern_t
*pattern
,
519 cairo_gl_surface_t
*dst
,
520 const cairo_rectangle_int_t
*sample
,
521 const cairo_rectangle_int_t
*extents
,
522 cairo_bool_t use_texgen
)
524 cairo_int_status_t status
;
526 TRACE ((stderr
, "%s: type=%d\n", __FUNCTION__
, pattern
->type
));
527 switch (pattern
->type
) {
528 case CAIRO_PATTERN_TYPE_SOLID
:
529 _cairo_gl_solid_operand_init (operand
,
530 &((cairo_solid_pattern_t
*) pattern
)->color
);
531 return CAIRO_STATUS_SUCCESS
;
532 case CAIRO_PATTERN_TYPE_SURFACE
:
533 status
= _cairo_gl_surface_operand_init (operand
, pattern
, dst
,
534 sample
, extents
, use_texgen
);
535 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
)
540 case CAIRO_PATTERN_TYPE_LINEAR
:
541 case CAIRO_PATTERN_TYPE_RADIAL
:
542 status
= _cairo_gl_gradient_operand_init (operand
, pattern
, dst
,
544 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
)
550 case CAIRO_PATTERN_TYPE_MESH
:
551 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
555 return _cairo_gl_pattern_texture_setup (operand
, pattern
, dst
, extents
);
559 _cairo_gl_operand_get_filter (cairo_gl_operand_t
*operand
)
561 cairo_filter_t filter
;
563 switch ((int) operand
->type
) {
564 case CAIRO_GL_OPERAND_TEXTURE
:
565 filter
= operand
->texture
.attributes
.filter
;
567 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
568 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
569 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
570 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
571 filter
= CAIRO_FILTER_BILINEAR
;
574 filter
= CAIRO_FILTER_DEFAULT
;
582 _cairo_gl_operand_get_gl_filter (cairo_gl_operand_t
*operand
)
584 cairo_filter_t filter
= _cairo_gl_operand_get_filter (operand
);
586 return filter
!= CAIRO_FILTER_FAST
&& filter
!= CAIRO_FILTER_NEAREST
?
592 _cairo_gl_operand_get_extend (cairo_gl_operand_t
*operand
)
594 cairo_extend_t extend
;
596 switch ((int) operand
->type
) {
597 case CAIRO_GL_OPERAND_TEXTURE
:
598 extend
= operand
->texture
.attributes
.extend
;
600 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
601 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
602 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
603 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
604 extend
= operand
->gradient
.extend
;
607 extend
= CAIRO_EXTEND_NONE
;
616 _cairo_gl_operand_bind_to_shader (cairo_gl_context_t
*ctx
,
617 cairo_gl_operand_t
*operand
,
618 cairo_gl_tex_t tex_unit
)
620 const cairo_matrix_t
*texgen
= NULL
;
622 switch (operand
->type
) {
624 case CAIRO_GL_OPERAND_COUNT
:
626 case CAIRO_GL_OPERAND_NONE
:
629 case CAIRO_GL_OPERAND_CONSTANT
:
630 _cairo_gl_shader_bind_vec4 (ctx
,
631 ctx
->current_shader
->constant_location
[tex_unit
],
632 operand
->constant
.color
[0],
633 operand
->constant
.color
[1],
634 operand
->constant
.color
[2],
635 operand
->constant
.color
[3]);
638 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
639 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
640 _cairo_gl_shader_bind_float (ctx
,
641 ctx
->current_shader
->a_location
[tex_unit
],
642 operand
->gradient
.a
);
644 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
645 _cairo_gl_shader_bind_vec3 (ctx
,
646 ctx
->current_shader
->circle_d_location
[tex_unit
],
647 operand
->gradient
.circle_d
.center
.x
,
648 operand
->gradient
.circle_d
.center
.y
,
649 operand
->gradient
.circle_d
.radius
);
650 _cairo_gl_shader_bind_float (ctx
,
651 ctx
->current_shader
->radius_0_location
[tex_unit
],
652 operand
->gradient
.radius_0
);
654 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
655 case CAIRO_GL_OPERAND_TEXTURE
:
657 * For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used
658 * with CAIRO_EXTEND_NONE). When bilinear filtering is enabled,
659 * these shaders need the texture dimensions for their calculations.
661 if (ctx
->gl_flavor
== CAIRO_GL_FLAVOR_ES
&&
662 _cairo_gl_operand_get_extend (operand
) == CAIRO_EXTEND_NONE
&&
663 _cairo_gl_operand_get_gl_filter (operand
) == GL_LINEAR
)
666 if (operand
->type
== CAIRO_GL_OPERAND_TEXTURE
) {
667 width
= operand
->texture
.surface
->width
;
668 height
= operand
->texture
.surface
->height
;
671 width
= operand
->gradient
.gradient
->cache_entry
.size
,
674 _cairo_gl_shader_bind_vec2 (ctx
,
675 ctx
->current_shader
->texdims_location
[tex_unit
],
681 if (operand
->type
== CAIRO_GL_OPERAND_TEXTURE
) {
682 if (operand
->texture
.texgen
)
683 texgen
= &operand
->texture
.attributes
.matrix
;
685 if (operand
->gradient
.texgen
)
686 texgen
= &operand
->gradient
.m
;
689 _cairo_gl_shader_bind_matrix(ctx
,
690 ctx
->current_shader
->texgen_location
[tex_unit
],
697 _cairo_gl_operand_needs_setup (cairo_gl_operand_t
*dest
,
698 cairo_gl_operand_t
*source
,
699 unsigned int vertex_offset
)
701 if (dest
->type
!= source
->type
)
703 if (dest
->vertex_offset
!= vertex_offset
)
706 switch (source
->type
) {
707 case CAIRO_GL_OPERAND_NONE
:
709 case CAIRO_GL_OPERAND_CONSTANT
:
710 return dest
->constant
.color
[0] != source
->constant
.color
[0] ||
711 dest
->constant
.color
[1] != source
->constant
.color
[1] ||
712 dest
->constant
.color
[2] != source
->constant
.color
[2] ||
713 dest
->constant
.color
[3] != source
->constant
.color
[3];
714 case CAIRO_GL_OPERAND_TEXTURE
:
715 return dest
->texture
.surface
!= source
->texture
.surface
||
716 dest
->texture
.attributes
.extend
!= source
->texture
.attributes
.extend
||
717 dest
->texture
.attributes
.filter
!= source
->texture
.attributes
.filter
||
718 dest
->texture
.attributes
.has_component_alpha
!= source
->texture
.attributes
.has_component_alpha
;
719 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
720 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
721 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
722 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
723 /* XXX: improve this */
726 case CAIRO_GL_OPERAND_COUNT
:
734 _cairo_gl_operand_get_vertex_size (const cairo_gl_operand_t
*operand
)
736 switch (operand
->type
) {
738 case CAIRO_GL_OPERAND_COUNT
:
740 case CAIRO_GL_OPERAND_NONE
:
741 case CAIRO_GL_OPERAND_CONSTANT
:
743 case CAIRO_GL_OPERAND_TEXTURE
:
744 return operand
->texture
.texgen
? 0 : 2 * sizeof (GLfloat
);
745 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
746 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
747 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
748 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
749 return operand
->gradient
.texgen
? 0 : 2 * sizeof (GLfloat
);
754 _cairo_gl_operand_emit (cairo_gl_operand_t
*operand
,
759 switch (operand
->type
) {
761 case CAIRO_GL_OPERAND_COUNT
:
763 case CAIRO_GL_OPERAND_NONE
:
764 case CAIRO_GL_OPERAND_CONSTANT
:
766 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
767 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
768 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
769 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
770 if (! operand
->gradient
.texgen
) {
774 cairo_matrix_transform_point (&operand
->gradient
.m
, &s
, &t
);
780 case CAIRO_GL_OPERAND_TEXTURE
:
781 if (! operand
->texture
.texgen
) {
782 cairo_surface_attributes_t
*src_attributes
= &operand
->texture
.attributes
;
786 cairo_matrix_transform_point (&src_attributes
->matrix
, &s
, &t
);