b9a0f7ded807f82180191d376d6f9590bb5b966b
[framework/graphics/cairo.git] / src / cairo-gl-shaders.c
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 T. Zachary Laine
4  * Copyright © 2010 Eric Anholt
5  * Copyright © 2010 Red Hat, Inc
6  * Copyright © 2010 Linaro Limited
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 T. Zachary Laine.
34  *
35  * Contributor(s):
36  *      Benjamin Otte <otte@gnome.org>
37  *      Eric Anholt <eric@anholt.net>
38  *      T. Zachary Laine <whatwasthataddress@gmail.com>
39  *      Alexandros Frantzis <alexandros.frantzis@linaro.org>
40  */
41
42 #include "cairoint.h"
43 #include "cairo-gl-private.h"
44 #include "cairo-error-private.h"
45 #include "cairo-output-stream-private.h"
46
47 typedef struct cairo_gl_shader_impl {
48     void
49     (*compile_shader) (cairo_gl_context_t *ctx, GLuint *shader, GLenum type,
50                        const char *text);
51
52     void
53     (*link_shader) (cairo_gl_context_t *ctx, GLuint *program, GLuint vert, GLuint frag);
54
55     void
56     (*destroy_shader) (cairo_gl_context_t *ctx, GLuint shader);
57
58     void
59     (*destroy_program) (cairo_gl_context_t *ctx, GLuint program);
60
61     void
62     (*bind_float) (cairo_gl_context_t *ctx,
63                    cairo_gl_shader_t *shader,
64                    const char *name,
65                    float value);
66
67     void
68     (*bind_vec2) (cairo_gl_context_t *ctx,
69                   cairo_gl_shader_t *shader,
70                   const char *name,
71                   float value0,
72                   float value1);
73
74     void
75     (*bind_vec3) (cairo_gl_context_t *ctx,
76                   cairo_gl_shader_t *shader,
77                   const char *name,
78                   float value0,
79                   float value1,
80                   float value2);
81
82     void
83     (*bind_vec4) (cairo_gl_context_t *ctx,
84                   cairo_gl_shader_t *shader,
85                   const char *name,
86                   float value0, float value1,
87                   float value2, float value3);
88
89     void
90     (*bind_matrix) (cairo_gl_context_t *ctx,
91                     cairo_gl_shader_t *shader,
92                     const char *name,
93                     cairo_matrix_t* m);
94
95     void
96     (*bind_matrix4f) (cairo_gl_context_t *ctx,
97                       cairo_gl_shader_t *shader,
98                       const char *name,
99                       GLfloat* gl_m);
100
101     void
102     (*use) (cairo_gl_context_t *ctx,
103             cairo_gl_shader_t *shader);
104 } shader_impl_t;
105
106 static cairo_status_t
107 _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
108                           cairo_gl_shader_t *shader,
109                           cairo_gl_operand_t *src,
110                           cairo_gl_operand_t *mask,
111                           cairo_bool_t use_coverage,
112                           const char *fragment_text);
113
114 /* OpenGL Core 2.0 API. */
115 static void
116 compile_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint *shader,
117                          GLenum type, const char *text)
118 {
119     const char* strings[1] = { text };
120     GLint gl_status;
121     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
122
123     *shader = dispatch->CreateShader (type);
124     dispatch->ShaderSource (*shader, 1, strings, 0);
125     dispatch->CompileShader (*shader);
126     dispatch->GetShaderiv (*shader, GL_COMPILE_STATUS, &gl_status);
127     if (gl_status == GL_FALSE) {
128         GLint log_size;
129         dispatch->GetShaderiv (*shader, GL_INFO_LOG_LENGTH, &log_size);
130         if (0 < log_size) {
131             char *log = _cairo_malloc (log_size);
132             GLint chars;
133
134             log[log_size - 1] = '\0';
135             dispatch->GetShaderInfoLog (*shader, log_size, &chars, log);
136             printf ("OpenGL shader compilation failed.  Shader:\n"
137                     "%s\n"
138                     "OpenGL compilation log:\n"
139                     "%s\n",
140                     text, log);
141
142             free (log);
143         } else {
144             printf ("OpenGL shader compilation failed.\n");
145         }
146
147         ASSERT_NOT_REACHED;
148     }
149 }
150
151 static void
152 link_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint *program,
153                       GLuint vert, GLuint frag)
154 {
155     GLint gl_status;
156     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
157
158     *program = dispatch->CreateProgram ();
159     dispatch->AttachShader (*program, vert);
160     dispatch->AttachShader (*program, frag);
161
162     dispatch->BindAttribLocation (*program, CAIRO_GL_VERTEX_ATTRIB_INDEX,
163                                   "Vertex");
164     dispatch->BindAttribLocation (*program, CAIRO_GL_COLOR_ATTRIB_INDEX,
165                                   "Color");
166     dispatch->BindAttribLocation (*program, CAIRO_GL_COVERAGE_ATTRIB_INDEX,
167                                   "Coverage");
168     dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD0_ATTRIB_INDEX,
169                                   "MultiTexCoord0");
170     dispatch->BindAttribLocation (*program, CAIRO_GL_TEXCOORD1_ATTRIB_INDEX,
171                                   "MultiTexCoord1");
172     dispatch->BindAttribLocation (*program, CAIRO_GL_START_COORD0_ATTRIB_INDEX,
173                                   "StartCoords0");
174     dispatch->BindAttribLocation (*program, CAIRO_GL_START_COORD1_ATTRIB_INDEX,
175                                   "StartCoords1");
176     dispatch->BindAttribLocation (*program, CAIRO_GL_STOP_COORD0_ATTRIB_INDEX,
177                                   "StopCoords0");
178     dispatch->BindAttribLocation (*program, CAIRO_GL_STOP_COORD1_ATTRIB_INDEX,
179                                   "StopCoords1");
180
181     dispatch->LinkProgram (*program);
182     dispatch->GetProgramiv (*program, GL_LINK_STATUS, &gl_status);
183     if (gl_status == GL_FALSE) {
184         GLint log_size;
185         dispatch->GetProgramiv (*program, GL_INFO_LOG_LENGTH, &log_size);
186         if (0 < log_size) {
187             char *log = _cairo_malloc (log_size);
188             GLint chars;
189
190             log[log_size - 1] = '\0';
191             dispatch->GetProgramInfoLog (*program, log_size, &chars, log);
192             printf ("OpenGL shader link failed:\n%s\n", log);
193
194             free (log);
195         } else {
196             printf ("OpenGL shader link failed.\n");
197         }
198
199         ASSERT_NOT_REACHED;
200     }
201 }
202
203 static void
204 destroy_shader_core_2_0 (cairo_gl_context_t *ctx, GLuint shader)
205 {
206     ctx->dispatch.DeleteShader (shader);
207 }
208
209 static void
210 destroy_program_core_2_0 (cairo_gl_context_t *ctx, GLuint shader)
211 {
212     ctx->dispatch.DeleteProgram (shader);
213 }
214
215 typedef struct _cairo_gl_uniform_entry {
216     cairo_hash_entry_t base;
217     char *name;
218     GLint location;
219 } cairo_gl_uniform_entry_t;
220
221 static void
222 _cairo_gl_uniform_init_key (cairo_gl_uniform_entry_t *key,
223                             const char *name)
224 {
225     unsigned long sum = 0;
226     unsigned int i;
227
228     for (i = 0; i < strlen(name); i++)
229         sum += name[i];
230     key->base.hash = sum;
231     key->name = strdup(name);
232     key->location = -1;
233 }
234
235 static cairo_status_t
236 create_gl_uniform_entry (const char *name,
237                          cairo_gl_uniform_entry_t **entry)
238 {
239     *entry = malloc (sizeof (cairo_gl_uniform_entry_t));
240     if (unlikely (*entry == NULL))
241         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
242
243     _cairo_gl_uniform_init_key (*entry, name);
244     return CAIRO_STATUS_SUCCESS;
245 }
246
247
248 static cairo_bool_t
249 _cairo_gl_uniform_equal (const void *key_a,
250                          const void *key_b)
251 {
252     const cairo_gl_uniform_entry_t *a = key_a;
253     const cairo_gl_uniform_entry_t *b = key_b;
254
255     return strcmp (a->name, b->name) == 0;
256 }
257
258 static cairo_int_status_t
259 get_uniform_location (cairo_gl_context_t *ctx,
260                       cairo_gl_shader_t *shader,
261                       const char *name,
262                       GLint *location)
263 {
264     cairo_gl_uniform_entry_t *key, *uniform_entry;
265     cairo_int_status_t status;
266
267     status = create_gl_uniform_entry (name, &key);
268     if (status)
269         return status;
270
271     //_cairo_gl_uniform_init_key (key, name);
272     uniform_entry = _cairo_hash_table_lookup (shader->uniform_cache,
273                                               &key->base);
274     if (uniform_entry) {
275         *location = uniform_entry->location;
276         free (key->name);
277         free (key);
278         return CAIRO_INT_STATUS_SUCCESS;
279     }
280
281     key->location = ctx->dispatch.GetUniformLocation (shader->program, name);
282     status = _cairo_hash_table_insert (shader->uniform_cache, &key->base);
283     *location = key->location;
284
285     return status;
286 }
287
288 static cairo_int_status_t
289 bind_float_core_2_0 (cairo_gl_context_t *ctx,
290                      cairo_gl_shader_t *shader,
291                      const char *name,
292                      float value)
293 {
294     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
295     GLint location;
296     cairo_int_status_t status;
297
298     status = get_uniform_location (ctx, shader, name, &location);
299     if (status)
300         return status;
301
302     assert(location != -1);
303     dispatch->Uniform1f (location, value);
304     return CAIRO_INT_STATUS_SUCCESS;
305 }
306
307 static cairo_int_status_t
308 bind_vec2_core_2_0 (cairo_gl_context_t *ctx,
309                     cairo_gl_shader_t *shader,
310                     const char *name,
311                     float value0,
312                     float value1)
313 {
314     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
315     GLint location;
316     cairo_int_status_t status;
317
318     status = get_uniform_location (ctx, shader, name, &location);
319     if (status)
320         return status;
321
322     assert(location != -1);
323     dispatch->Uniform2f (location, value0, value1);
324     return CAIRO_INT_STATUS_SUCCESS;
325 }
326
327 static cairo_int_status_t
328 bind_vec3_core_2_0 (cairo_gl_context_t *ctx,
329                     cairo_gl_shader_t *shader,
330                     const char *name,
331                     float value0,
332                     float value1,
333                     float value2)
334 {
335     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
336     GLint location;
337     cairo_int_status_t status;
338
339     status = get_uniform_location (ctx, shader, name, &location);
340     if (status)
341         return status;
342
343     assert(location != -1);
344     dispatch->Uniform3f (location, value0, value1, value2);
345     return CAIRO_INT_STATUS_SUCCESS;
346 }
347
348 static cairo_int_status_t
349 bind_vec4_core_2_0 (cairo_gl_context_t *ctx,
350                     cairo_gl_shader_t *shader,
351                     const char *name,
352                     float value0,
353                     float value1,
354                     float value2,
355                     float value3)
356 {
357     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
358     GLint location;
359     cairo_int_status_t status;
360
361     status = get_uniform_location (ctx, shader, name, &location);
362     if (status)
363         return status;
364
365     assert(location != -1);
366     dispatch->Uniform4f (location, value0, value1, value2, value3);
367     return CAIRO_INT_STATUS_SUCCESS;
368 }
369
370 static cairo_int_status_t
371 bind_matrix_core_2_0 (cairo_gl_context_t *ctx,
372                       cairo_gl_shader_t *shader,
373                       const char *name,
374                       cairo_matrix_t* m)
375 {
376     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
377     GLint location;
378     cairo_int_status_t status;
379     float gl_m[16] = {
380         m->xx, m->xy, m->x0,
381         m->yx, m->yy, m->y0,
382         0,     0,     1
383     };
384
385     status = get_uniform_location (ctx, shader, name, &location);
386     if (status)
387         return status;
388
389     assert(location != -1);
390     dispatch->UniformMatrix3fv (location, 1, GL_TRUE, gl_m);
391     return CAIRO_INT_STATUS_SUCCESS;
392 }
393
394 static cairo_int_status_t
395 bind_matrix4f_core_2_0 (cairo_gl_context_t *ctx,
396                         cairo_gl_shader_t *shader,
397                         const char *name,
398                         GLfloat* gl_m)
399 {
400     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
401     GLint location;
402     cairo_int_status_t status;
403
404     status = get_uniform_location (ctx, shader, name, &location);
405     if (status)
406         return status;
407
408     assert(location != -1);
409     dispatch->UniformMatrix4fv (location, 1, GL_FALSE, gl_m);
410     return CAIRO_INT_STATUS_SUCCESS;
411 }
412
413 static void
414 use_program_core_2_0 (cairo_gl_context_t *ctx,
415                       cairo_gl_shader_t *shader)
416 {
417     if (shader)
418         ctx->dispatch.UseProgram (shader->program);
419     else
420         ctx->dispatch.UseProgram (0);
421 }
422
423 static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
424     compile_shader_core_2_0,
425     link_shader_core_2_0,
426     destroy_shader_core_2_0,
427     destroy_program_core_2_0,
428     bind_float_core_2_0,
429     bind_vec2_core_2_0,
430     bind_vec3_core_2_0,
431     bind_vec4_core_2_0,
432     bind_matrix_core_2_0,
433     bind_matrix4f_core_2_0,
434     use_program_core_2_0,
435 };
436
437 typedef struct _cairo_shader_cache_entry {
438     cairo_cache_entry_t base;
439
440     cairo_gl_operand_type_t src;
441     cairo_gl_operand_type_t mask;
442     cairo_gl_operand_type_t dest;
443     cairo_bool_t use_coverage;
444     cairo_bool_t use_color_attribute;
445     cairo_gl_shader_in_t in;
446     GLint src_gl_filter;
447     cairo_bool_t src_border_fade;
448     cairo_extend_t src_extend;
449     GLint mask_gl_filter;
450     cairo_bool_t mask_border_fade;
451     cairo_extend_t mask_extend;
452
453     cairo_bool_t src_use_atlas;
454     cairo_bool_t mask_use_atlas;
455
456     cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */
457     cairo_gl_shader_t shader;
458 } cairo_shader_cache_entry_t;
459
460 static cairo_bool_t
461 _cairo_gl_shader_cache_equal_desktop (const void *key_a, const void *key_b)
462 {
463     const cairo_shader_cache_entry_t *a = key_a;
464     const cairo_shader_cache_entry_t *b = key_b;
465     cairo_bool_t both_have_npot_repeat =
466         a->ctx->has_npot_repeat && b->ctx->has_npot_repeat;
467
468     return a->src  == b->src  &&
469            a->mask == b->mask &&
470            a->dest == b->dest &&
471            a->use_coverage == b->use_coverage &&
472            a->in   == b->in &&
473            (both_have_npot_repeat || a->src_extend == b->src_extend) &&
474            (both_have_npot_repeat || a->mask_extend == b->mask_extend);
475 }
476
477 /*
478  * For GLES2 we use more complicated shaders to implement missing GL
479  * features. In this case we need more parameters to uniquely identify
480  * a shader (vs _cairo_gl_shader_cache_equal_desktop()).
481  */
482 static cairo_bool_t
483 _cairo_gl_shader_cache_equal_gles2 (const void *key_a, const void *key_b)
484 {
485     const cairo_shader_cache_entry_t *a = key_a;
486     const cairo_shader_cache_entry_t *b = key_b;
487     cairo_bool_t both_have_npot_repeat =
488         a->ctx->has_npot_repeat && b->ctx->has_npot_repeat;
489
490     return a->src  == b->src  &&
491            a->mask == b->mask &&
492            a->dest == b->dest &&
493            a->use_coverage == b->use_coverage &&
494            a->in   == b->in   &&
495            a->src_gl_filter == b->src_gl_filter &&
496            a->src_border_fade == b->src_border_fade &&
497            (both_have_npot_repeat || a->src_extend == b->src_extend) &&
498            a->mask_gl_filter == b->mask_gl_filter &&
499            a->mask_border_fade == b->mask_border_fade &&
500            (both_have_npot_repeat || a->mask_extend == b->mask_extend);
501 }
502
503 static unsigned long
504 _cairo_gl_shader_cache_hash (const cairo_shader_cache_entry_t *entry)
505 {
506     return (entry->src << 16) | (entry->mask << 13) | (entry->dest << 10) | (entry->in << 8) | (entry->mask_extend << 6) | (entry->src_extend << 4) |(entry->mask_use_atlas << 3) | (entry->src_use_atlas << 2) |(entry->use_color_attribute << 1) | entry->use_coverage;
507 }
508
509 static void
510 _cairo_gl_shader_cache_destroy (void *data)
511 {
512     cairo_shader_cache_entry_t *entry = data;
513
514     _cairo_gl_shader_fini (entry->ctx, &entry->shader);
515     if (entry->ctx->current_shader == &entry->shader)
516         entry->ctx->current_shader = NULL;
517     free (entry);
518 }
519
520 static void
521 _cairo_gl_shader_init (cairo_gl_shader_t *shader)
522 {
523     shader->fragment_shader = 0;
524     shader->program = 0;
525     shader->uniform_cache = _cairo_hash_table_create (_cairo_gl_uniform_equal);
526 }
527
528 cairo_status_t
529 _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
530 {
531     static const char *fill_fs_source =
532         "#ifdef GL_ES\n"
533         "precision mediump float;\n"
534         "#endif\n"
535         "uniform vec4 color;\n"
536         "void main()\n"
537         "{\n"
538         "       gl_FragColor = color;\n"
539         "}\n";
540     cairo_status_t status;
541
542     if (_cairo_gl_get_version () >= CAIRO_GL_VERSION_ENCODE (2, 0) ||
543         (_cairo_gl_has_extension ("GL_ARB_shader_objects") &&
544          _cairo_gl_has_extension ("GL_ARB_fragment_shader") &&
545          _cairo_gl_has_extension ("GL_ARB_vertex_shader")))
546     {
547         ctx->shader_impl = &shader_impl_core_2_0;
548     }
549     else
550     {
551         ctx->shader_impl = NULL;
552         fprintf (stderr, "Error: The cairo gl backend requires shader support!\n");
553         return CAIRO_STATUS_DEVICE_ERROR;
554     }
555
556     memset (ctx->vertex_shaders, 0, sizeof (ctx->vertex_shaders));
557
558     status = _cairo_cache_init (&ctx->shaders,
559                                 ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ?
560                                     _cairo_gl_shader_cache_equal_desktop :
561                                     _cairo_gl_shader_cache_equal_gles2,
562                                 NULL,
563                                 _cairo_gl_shader_cache_destroy,
564                                 CAIRO_GL_MAX_SHADERS_PER_CONTEXT);
565     if (unlikely (status))
566         return status;
567
568     _cairo_gl_shader_init (&ctx->fill_rectangles_shader);
569     status = _cairo_gl_shader_compile (ctx,
570                                        &ctx->fill_rectangles_shader,
571                                        NULL,
572                                        NULL,
573                                        FALSE,
574                                        fill_fs_source);
575     if (unlikely (status))
576         return status;
577
578     return CAIRO_STATUS_SUCCESS;
579 }
580
581 void
582 _cairo_gl_context_fini_shaders (cairo_gl_context_t *ctx)
583 {
584     int i;
585
586     for (i = 0; i <= CAIRO_GL_VAR_TYPE_MAX; i++) {
587         if (ctx->vertex_shaders[i])
588             ctx->shader_impl->destroy_shader (ctx, ctx->vertex_shaders[i]);
589     }
590
591     _cairo_cache_fini (&ctx->shaders);
592     _cairo_gl_shader_fini (ctx, &ctx->fill_rectangles_shader);
593 }
594
595 static void
596 destroy_uniform_callback (void *entry, void *closure)
597 {
598     cairo_gl_uniform_entry_t *key = entry;
599     _cairo_hash_table_remove ((cairo_hash_table_t *) closure, &key->base);
600     free (key->name);
601     free (key);
602 }
603
604 void
605 _cairo_gl_shader_fini (cairo_gl_context_t *ctx,
606                        cairo_gl_shader_t *shader)
607 {
608     if (shader->fragment_shader)
609         ctx->shader_impl->destroy_shader (ctx, shader->fragment_shader);
610
611     if (shader->program)
612         ctx->shader_impl->destroy_program (ctx, shader->program);
613
614     if (shader->uniform_cache) {
615         _cairo_hash_table_foreach (shader->uniform_cache,
616                                    destroy_uniform_callback,
617                                    shader->uniform_cache);
618         _cairo_hash_table_destroy (shader->uniform_cache);
619     }
620 }
621
622 static const char *operand_names[] = { "source", "mask", "dest" };
623
624 static cairo_gl_var_type_t
625 cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type,
626                                cairo_bool_t use_color_attribute)
627 {
628     switch (type) {
629     default:
630     case CAIRO_GL_OPERAND_COUNT:
631         ASSERT_NOT_REACHED;
632     case CAIRO_GL_OPERAND_NONE:
633         return CAIRO_GL_VAR_NONE;
634     case CAIRO_GL_OPERAND_CONSTANT:
635         if (use_color_attribute)
636             return CAIRO_GL_VAR_COLOR;
637         else
638             return CAIRO_GL_VAR_NONE;
639     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
640     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
641     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
642     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
643     case CAIRO_GL_OPERAND_TEXTURE:
644         return CAIRO_GL_VAR_TEXCOORDS;
645     }
646 }
647
648 static void
649 cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
650                                cairo_gl_var_type_t type,
651                                cairo_gl_tex_t name,
652                                cairo_bool_t use_atlas)
653 {
654     switch (type) {
655     default:
656         ASSERT_NOT_REACHED;
657     case CAIRO_GL_VAR_NONE:
658         break;
659     case CAIRO_GL_VAR_COLOR:
660         _cairo_output_stream_printf (stream,
661                                      "varying vec4 fragment_color;\n");
662         break;
663     case CAIRO_GL_VAR_TEXCOORDS:
664         _cairo_output_stream_printf (stream,
665                                      "varying vec2 %s_texcoords;\n",
666                                      operand_names[name]);
667         if (use_atlas)
668             _cairo_output_stream_printf (stream,
669                                          "varying vec2 %s_start_coords;\n"
670                                          "varying vec2 %s_stop_coords;\n",
671                                          operand_names[name], operand_names[name]);
672         break;
673     }
674 }
675
676 static void
677 cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
678                              cairo_gl_var_type_t type,
679                              cairo_gl_tex_t name)
680 {
681     switch (type) {
682     default:
683         ASSERT_NOT_REACHED;
684     case CAIRO_GL_VAR_NONE:
685         break;
686     case CAIRO_GL_VAR_COLOR:
687         _cairo_output_stream_printf (stream,
688                                      "    fragment_color = Color;\n");
689         break;
690     case CAIRO_GL_VAR_TEXCOORDS:
691         _cairo_output_stream_printf (stream,
692                                      "    %s_texcoords = MultiTexCoord%d.xy;\n",
693                                      operand_names[name], name);
694         break;
695     }
696 }
697
698 static void
699 cairo_gl_shader_dcl_coverage (cairo_output_stream_t *stream)
700 {
701     _cairo_output_stream_printf (stream, "varying float coverage;\n");
702 }
703
704 static void
705 cairo_gl_shader_def_coverage (cairo_output_stream_t *stream)
706 {
707     _cairo_output_stream_printf (stream, "    coverage = Coverage.a;\n");
708 }
709
710 static void
711 cairo_gl_shader_def_use_atlas (cairo_output_stream_t *stream,
712                                cairo_gl_var_type_t type,
713                                cairo_gl_tex_t name)
714 {
715     if (type == CAIRO_GL_VAR_TEXCOORDS) {
716             _cairo_output_stream_printf (stream,
717                                          "    %s_start_coords = StartCoords%d.xy;\n"
718                                          "    %s_stop_coords = StopCoords%d.xy;\n",
719                                          operand_names[name], name,
720                                          operand_names[name], name);
721     }
722 }
723
724 static cairo_status_t
725 cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src_type,
726                                    cairo_gl_var_type_t mask_type,
727                                    cairo_bool_t src_use_atlas,
728                                    cairo_bool_t mask_use_atlas,
729                                    cairo_bool_t use_coverage,
730                                    cairo_gl_var_type_t dest,
731                                    char **out)
732 {
733     cairo_output_stream_t *stream = _cairo_memory_stream_create ();
734     unsigned char *source;
735     unsigned long length;
736     cairo_status_t status;
737
738     cairo_gl_shader_emit_variable (stream, src_type, CAIRO_GL_TEX_SOURCE,
739                                    src_use_atlas);
740     cairo_gl_shader_emit_variable (stream, mask_type, CAIRO_GL_TEX_MASK,
741                                    mask_use_atlas);
742     if (use_coverage)
743         cairo_gl_shader_dcl_coverage (stream);
744
745     _cairo_output_stream_printf (stream,
746                                  "attribute vec4 Vertex;\n"
747                                  "attribute vec4 Color;\n"
748                                  "attribute vec4 Coverage;\n"
749                                  "attribute vec4 MultiTexCoord0;\n"
750                                  "attribute vec4 MultiTexCoord1;\n"
751                                  "attribute vec2 StartCoords0;\n"
752                                  "attribute vec2 StartCoords1;\n"
753                                  "attribute vec2 StopCoords0;\n"
754                                  "attribute vec2 StopCoords1;\n"
755                                  "uniform mat4 ModelViewProjectionMatrix;\n"
756                                  "void main()\n"
757                                  "{\n"
758                                  "    gl_Position = ModelViewProjectionMatrix * Vertex;\n");
759
760     cairo_gl_shader_emit_vertex (stream, src_type, CAIRO_GL_TEX_SOURCE);
761     cairo_gl_shader_emit_vertex (stream, mask_type, CAIRO_GL_TEX_MASK);
762
763     if (use_coverage)
764         cairo_gl_shader_def_coverage (stream);
765
766     if (src_use_atlas)
767         cairo_gl_shader_def_use_atlas (stream, src_type, CAIRO_GL_TEX_SOURCE);
768     if (mask_use_atlas)
769         cairo_gl_shader_def_use_atlas (stream, mask_type, CAIRO_GL_TEX_MASK);
770
771     _cairo_output_stream_write (stream,
772                                 "}\n\0", 3);
773
774     status = _cairo_memory_stream_destroy (stream, &source, &length);
775     if (unlikely (status))
776         return status;
777
778     *out = (char *) source;
779     return CAIRO_STATUS_SUCCESS;
780 }
781
782 /*
783  * Returns whether an operand needs a special border fade fragment shader
784  * to simulate the GL_CLAMP_TO_BORDER wrapping method that is missing in GLES2.
785  */
786 static cairo_bool_t
787 _cairo_gl_shader_needs_border_fade (cairo_gl_operand_t *operand)
788 {
789     cairo_extend_t extend =_cairo_gl_operand_get_extend (operand);
790
791     return extend == CAIRO_EXTEND_NONE &&
792            (operand->type == CAIRO_GL_OPERAND_TEXTURE ||
793             operand->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT ||
794             operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE ||
795             operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0);
796 }
797
798 static void
799 cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
800                             cairo_gl_context_t *ctx,
801                             cairo_gl_operand_t *op,
802                             cairo_gl_tex_t name)
803 {
804     const char *namestr = operand_names[name];
805     const char *rectstr = (ctx->tex_target == GL_TEXTURE_RECTANGLE ? "Rect" : "");
806     cairo_bool_t use_atlas = _cairo_gl_operand_get_use_atlas (op);
807
808     switch (op->type) {
809     case CAIRO_GL_OPERAND_COUNT:
810     default:
811         ASSERT_NOT_REACHED;
812         break;
813     case CAIRO_GL_OPERAND_NONE:
814         _cairo_output_stream_printf (stream, 
815             "vec4 get_%s()\n"
816             "{\n"
817             "    return vec4 (0, 0, 0, 1);\n"
818             "}\n",
819             namestr);
820         break;
821     case CAIRO_GL_OPERAND_CONSTANT:
822         if (op->use_color_attribute)
823           _cairo_output_stream_printf (stream,
824                                        "varying vec4 fragment_color;\n"
825                                        "vec4 get_%s()\n"
826                                        "{\n"
827                                        "    return fragment_color;\n"
828                                        "}\n",
829                                        namestr);
830         else
831           _cairo_output_stream_printf (stream,
832                                        "uniform vec4 %s_constant;\n"
833                                        "vec4 get_%s()\n"
834                                        "{\n"
835                                        "    return %s_constant;\n"
836                                        "}\n",
837                                        namestr, namestr, namestr);
838         break;
839     case CAIRO_GL_OPERAND_TEXTURE:
840         if (! use_atlas) {
841             _cairo_output_stream_printf (stream,
842                 "uniform sampler2D%s %s_sampler;\n"
843                 "uniform vec2 %s_texdims;\n"
844                 "varying vec2 %s_texcoords;\n"
845                 "vec4 get_%s()\n"
846                 "{\n",
847                 rectstr, namestr, namestr, namestr, namestr);
848         } else {
849             _cairo_output_stream_printf (stream,
850                 "uniform sampler2D%s %s_sampler;\n"
851                 "uniform vec2 %s_texdims;\n"
852                 "varying vec2 %s_texcoords;\n"
853                 "varying vec2 %s_start_coords;\n"
854                 "varying vec2 %s_stop_coords;\n"
855                 "vec4 get_%s()\n"
856                 "{\n",
857                 rectstr, namestr, namestr, namestr, namestr, namestr, namestr);
858         }
859
860         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
861             _cairo_gl_shader_needs_border_fade (op))
862         {
863             _cairo_output_stream_printf (stream,
864                 "    vec2 border_fade = %s_border_fade (%s_texcoords, %s_texdims);\n"
865                 "    vec4 texel = texture2D%s (%s_sampler, %s_texcoords);\n"
866                 "    return texel * border_fade.x * border_fade.y;\n"
867                 "}\n",
868                 namestr, namestr, namestr, rectstr, namestr, namestr);
869         }
870         else
871         {
872             if (! use_atlas) {
873                 _cairo_output_stream_printf (stream,
874                     "    return texture2D%s (%s_sampler, %s_wrap (%s_texcoords));\n"
875                     "}\n",
876                     rectstr, namestr, namestr, namestr);
877             } else {
878                 _cairo_output_stream_printf (stream,
879                     "    return texture2D%s (%s_sampler, %s_wrap (%s_texcoords, %s_start_coords, %s_stop_coords));\n"
880                     "}\n",
881                     rectstr, namestr, namestr, namestr, namestr, namestr);
882             }
883         }
884         break;
885     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
886         _cairo_output_stream_printf (stream,
887             "varying vec2 %s_texcoords;\n"
888             "uniform vec2 %s_texdims;\n"
889             "uniform sampler2D%s %s_sampler;\n"
890             "\n"
891             "vec4 get_%s()\n"
892             "{\n",
893             namestr, namestr, rectstr, namestr, namestr);
894         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
895             _cairo_gl_shader_needs_border_fade (op))
896         {
897             _cairo_output_stream_printf (stream,
898                 "    float border_fade = %s_border_fade (%s_texcoords.x, %s_texdims.x);\n"
899                 "    vec4 texel = texture2D%s (%s_sampler, vec2 (%s_texcoords.x, 0.5));\n"
900                 "    return texel * border_fade;\n"
901                 "}\n",
902                 namestr, namestr, namestr, rectstr, namestr, namestr);
903         }
904         else
905         {
906             _cairo_output_stream_printf (stream,
907                 "    return texture2D%s (%s_sampler, %s_wrap (vec2 (%s_texcoords.x, 0.5)));\n"
908                 "}\n",
909                 rectstr, namestr, namestr, namestr);
910         }
911         break;
912     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
913         _cairo_output_stream_printf (stream,
914             "varying vec2 %s_texcoords;\n"
915             "uniform vec2 %s_texdims;\n"
916             "uniform sampler2D%s %s_sampler;\n"
917             "uniform vec3 %s_circle_d;\n"
918             "uniform float %s_radius_0;\n"
919             "\n"
920             "vec4 get_%s()\n"
921             "{\n"
922             "    vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
923             "    \n"
924             "    float B = dot (pos, %s_circle_d);\n"
925             "    float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
926             "    \n"
927             "    float t = 0.5 * C / B;\n"
928             "    float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n",
929             namestr, namestr, rectstr, namestr, namestr, namestr, namestr,
930             namestr, namestr, namestr, namestr, namestr);
931         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
932             _cairo_gl_shader_needs_border_fade (op))
933         {
934             _cairo_output_stream_printf (stream,
935                 "    float border_fade = %s_border_fade (t, %s_texdims.x);\n"
936                 "    vec4 texel = texture2D%s (%s_sampler, vec2 (t, 0.5));\n"
937                 "    return mix (vec4 (0.0), texel * border_fade, is_valid);\n"
938                 "}\n",
939                 namestr, namestr, rectstr, namestr);
940         }
941         else
942         {
943             _cairo_output_stream_printf (stream,
944                 "    vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n"
945                 "    return mix (vec4 (0.0), texel, is_valid);\n"
946                 "}\n",
947                 rectstr, namestr, namestr);
948         }
949         break;
950     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
951         _cairo_output_stream_printf (stream,
952             "varying vec2 %s_texcoords;\n"
953             "uniform vec2 %s_texdims;\n"
954             "uniform sampler2D%s %s_sampler;\n"
955             "uniform vec3 %s_circle_d;\n"
956             "uniform float %s_a;\n"
957             "uniform float %s_radius_0;\n"
958             "\n"
959             "vec4 get_%s()\n"
960             "{\n"
961             "    vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
962             "    \n"
963             "    float B = dot (pos, %s_circle_d);\n"
964             "    float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
965             "    \n"
966             "    float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
967             "    float sqrtdet = sqrt (abs (det));\n"
968             "    vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
969             "    \n"
970             "    vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n"
971             "    float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
972             "    \n"
973             "    float upper_t = mix (t.y, t.x, is_valid.x);\n",
974             namestr, namestr, rectstr, namestr, namestr, namestr, namestr,
975             namestr, namestr, namestr, namestr, namestr, namestr);
976         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
977             _cairo_gl_shader_needs_border_fade (op))
978         {
979             _cairo_output_stream_printf (stream,
980                 "    float border_fade = %s_border_fade (upper_t, %s_texdims.x);\n"
981                 "    vec4 texel = texture2D%s (%s_sampler, vec2 (upper_t, 0.5));\n"
982                 "    return mix (vec4 (0.0), texel * border_fade, has_color);\n"
983                 "}\n",
984                 namestr, namestr, rectstr, namestr);
985         }
986         else
987         {
988             _cairo_output_stream_printf (stream,
989                 "    vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
990                 "    return mix (vec4 (0.0), texel, has_color);\n"
991                 "}\n",
992                 rectstr, namestr, namestr);
993         }
994         break;
995     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
996         _cairo_output_stream_printf (stream,
997             "varying vec2 %s_texcoords;\n"
998             "uniform sampler2D%s %s_sampler;\n"
999             "uniform vec3 %s_circle_d;\n"
1000             "uniform float %s_a;\n"
1001             "uniform float %s_radius_0;\n"
1002             "\n"
1003             "vec4 get_%s()\n"
1004             "{\n"
1005             "    vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n"
1006             "    \n"
1007             "    float B = dot (pos, %s_circle_d);\n"
1008             "    float C = dot (pos, vec3 (pos.xy, -pos.z));\n"
1009             "    \n"
1010             "    float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n"
1011             "    float sqrtdet = sqrt (abs (det));\n"
1012             "    vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n"
1013             "    \n"
1014             "    vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n"
1015             "    float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n"
1016             "    \n"
1017             "    float upper_t = mix (t.y, t.x, is_valid.x);\n"
1018             "    vec4 texel = texture2D%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
1019             "    return mix (vec4 (0.0), texel, has_color);\n"
1020             "}\n",
1021             namestr, rectstr, namestr, namestr, namestr, namestr,
1022             namestr, namestr, namestr, namestr, namestr,
1023             namestr, namestr, namestr, rectstr, namestr, namestr);
1024         break;
1025     }
1026 }
1027
1028 /*
1029  * Emits the border fade functions used by an operand.
1030  *
1031  * If bilinear filtering is used, the emitted function performs a linear
1032  * fade to transparency effect in the intervals [-1/2n, 1/2n] and
1033  * [1 - 1/2n, 1 + 1/2n] (n: texture size).
1034  *
1035  * If nearest filtering is used, the emitted function just returns
1036  * 0.0 for all values outside [0, 1).
1037  */
1038 static void
1039 _cairo_gl_shader_emit_border_fade (cairo_output_stream_t *stream,
1040                                    cairo_gl_operand_t *operand,
1041                                    cairo_gl_tex_t name)
1042 {
1043     const char *namestr = operand_names[name];
1044     GLint gl_filter = _cairo_gl_operand_get_gl_filter (operand);
1045
1046     /* 2D version */
1047     _cairo_output_stream_printf (stream,
1048         "vec2 %s_border_fade (vec2 coords, vec2 dims)\n"
1049         "{\n",
1050         namestr);
1051
1052     if (gl_filter == GL_LINEAR)
1053         _cairo_output_stream_printf (stream,
1054             "    return clamp(-abs(dims * (coords - 0.5)) + (dims + vec2(1.0)) * 0.5, 0.0, 1.0);\n");
1055     else
1056         _cairo_output_stream_printf (stream,
1057             "    bvec2 in_tex1 = greaterThanEqual (coords, vec2 (0.0));\n"
1058             "    bvec2 in_tex2 = lessThan (coords, vec2 (1.0));\n"
1059             "    return vec2 (float (all (in_tex1) && all (in_tex2)));\n");
1060
1061     _cairo_output_stream_printf (stream, "}\n");
1062
1063     /* 1D version */
1064     _cairo_output_stream_printf (stream,
1065         "float %s_border_fade (float x, float dim)\n"
1066         "{\n",
1067         namestr);
1068     if (gl_filter == GL_LINEAR)
1069         _cairo_output_stream_printf (stream,
1070             "    return clamp(-abs(dim * (x - 0.5)) + (dim + 1.0) * 0.5, 0.0, 1.0);\n");
1071     else
1072         _cairo_output_stream_printf (stream,
1073             "    bool in_tex = x >= 0.0 && x < 1.0;\n"
1074             "    return float (in_tex);\n");
1075
1076     _cairo_output_stream_printf (stream, "}\n");
1077 }
1078
1079 /*
1080  * Emits the wrap function used by an operand.
1081  *
1082  * In OpenGL ES 2.0, repeat wrap modes (GL_REPEAT and GL_MIRRORED REPEAT) are
1083  * only available for NPOT textures if the GL_OES_texture_npot is supported.
1084  * If GL_OES_texture_npot is not supported, we need to implement the wrapping
1085  * functionality in the shader.
1086  */
1087 static void
1088 _cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx,
1089                             cairo_output_stream_t *stream,
1090                             cairo_gl_operand_t *operand,
1091                             cairo_gl_tex_t name)
1092 {
1093     const char *namestr = operand_names[name];
1094     cairo_extend_t extend = _cairo_gl_operand_get_extend (operand);
1095     cairo_bool_t use_atlas = _cairo_gl_operand_get_use_atlas (operand);
1096
1097     if (use_atlas)
1098         _cairo_output_stream_printf (stream,
1099             "vec2 %s_wrap (vec2 coords, vec2 start_coords, vec2 stop_coords)\n"
1100             "{\n",
1101             namestr);
1102     else
1103         _cairo_output_stream_printf (stream,
1104             "vec2 %s_wrap(vec2 coords)\n"
1105             "{\n",
1106             namestr);
1107
1108     if (use_atlas) {
1109         if (extend == CAIRO_EXTEND_REPEAT) {
1110             _cairo_output_stream_printf (stream,
1111                 "    vec2 range = stop_coords - start_coords;\n"
1112                 "    return mod (coords - start_coords, range) + start_coords;\n");
1113         } else if (extend == CAIRO_EXTEND_REFLECT){
1114             _cairo_output_stream_printf (stream,
1115                 "    vec2 range = stop_coords - start_coords;\n"
1116                 "    vec2 frac = mod (coords - start_coords, range);\n"
1117                 "    return mix(frac + start_coords, range - frac + start_coords,  mod(floor((coords - start_coords) / range), 2.0));\n");
1118         }
1119         else if (extend == CAIRO_EXTEND_PAD) {
1120             _cairo_output_stream_printf (stream,
1121                 "    bvec2 compare_to_start = lessThan (coords, start_coords);\n"
1122                 "    bvec2 compare_to_stop = greaterThan (coords, stop_coords);\n"
1123                 "    if (all (compare_to_start))\n"
1124                 "        return start_coords;\n"
1125                 "    else if (all (compare_to_stop))\n"
1126                 "        return stop_coords;\n"
1127                 "    else if (compare_to_start.x && compare_to_stop.y)\n"
1128                 "        return vec2 (start_coords.x, stop_coords.y);\n"
1129                 "    else if (compare_to_start.x && ! compare_to_stop.y)\n"
1130                 "        return vec2 (start_coords.x, coords.y);\n"
1131                 "    else if (compare_to_stop.x && compare_to_start.y)\n"
1132                 "        return vec2 (stop_coords.x, start_coords.y);\n"
1133                 "    else if (compare_to_stop.x && ! compare_to_stop.y)\n"
1134                 "        return vec2 (stop_coords.x, coords.y);\n"
1135                 "    else if (compare_to_start.y && ! compare_to_start.x)\n"
1136                 "        return vec2 (coords.x, start_coords.y);\n"
1137                 "    else if (compare_to_stop.y && ! compare_to_start.x)\n"
1138                 "        return vec2 (coords.x, stop_coords.y);\n"
1139                 "    else\n"
1140                 "        return coords;\n");
1141         }
1142         else {
1143             _cairo_output_stream_printf (stream,
1144                 "    if (any (lessThan (coords, start_coords)))\n"
1145                 "        return vec2 (-1.0);\n"
1146                 "    if (any (greaterThan (coords, stop_coords)))\n"
1147                 "        return vec2 (-1.0);\n"
1148                 "    else\n"
1149                 "        return coords;\n");
1150         }
1151     }
1152     else {
1153         if (! ctx->has_npot_repeat &&
1154             (extend == CAIRO_EXTEND_REPEAT ||
1155              extend == CAIRO_EXTEND_REFLECT)) {
1156             if (extend == CAIRO_EXTEND_REPEAT) {
1157                 _cairo_output_stream_printf (stream,
1158                     "    return fract(coords);\n");
1159             } else { /* CAIRO_EXTEND_REFLECT */
1160                 _cairo_output_stream_printf (stream,
1161                     "    return mix(fract(coords), 1.0 - fract(coords), floor(mod(coords, 2.0)));\n");
1162             }
1163         }
1164         else
1165         {
1166             _cairo_output_stream_printf (stream, "    return coords;\n");
1167         }
1168     }
1169
1170     _cairo_output_stream_printf (stream, "}\n");
1171 }
1172
1173 static cairo_status_t
1174 cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
1175                                      cairo_gl_shader_in_t in,
1176                                      cairo_gl_operand_t *src,
1177                                      cairo_gl_operand_t *mask,
1178                                      cairo_bool_t use_coverage,
1179                                      cairo_gl_operand_type_t dest_type,
1180                                      char **out)
1181 {
1182     cairo_output_stream_t *stream = _cairo_memory_stream_create ();
1183     unsigned char *source;
1184     unsigned long length;
1185     cairo_status_t status;
1186     const char *coverage_str;
1187
1188     _cairo_output_stream_printf (stream,
1189         "#ifdef GL_ES\n"
1190         "precision mediump float;\n"
1191         "#endif\n");
1192
1193     _cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE);
1194     _cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK);
1195
1196     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) {
1197         if (_cairo_gl_shader_needs_border_fade (src))
1198             _cairo_gl_shader_emit_border_fade (stream, src, CAIRO_GL_TEX_SOURCE);
1199         if (_cairo_gl_shader_needs_border_fade (mask))
1200             _cairo_gl_shader_emit_border_fade (stream, mask, CAIRO_GL_TEX_MASK);
1201     }
1202
1203     cairo_gl_shader_emit_color (stream, ctx, src, CAIRO_GL_TEX_SOURCE);
1204     cairo_gl_shader_emit_color (stream, ctx, mask, CAIRO_GL_TEX_MASK);
1205
1206     coverage_str = "";
1207     if (use_coverage) {
1208         _cairo_output_stream_printf (stream, "varying float coverage;\n");
1209         coverage_str = " * coverage";
1210     }
1211
1212     _cairo_output_stream_printf (stream,
1213         "void main()\n"
1214         "{\n");
1215     switch (in) {
1216     case CAIRO_GL_SHADER_IN_COUNT:
1217     default:
1218         ASSERT_NOT_REACHED;
1219     case CAIRO_GL_SHADER_IN_NORMAL:
1220         _cairo_output_stream_printf (stream,
1221             "    gl_FragColor = get_source() * get_mask().a%s;\n",
1222             coverage_str);
1223         break;
1224     case CAIRO_GL_SHADER_IN_CA_SOURCE:
1225         _cairo_output_stream_printf (stream,
1226             "    gl_FragColor = get_source() * get_mask()%s;\n",
1227             coverage_str);
1228         break;
1229     case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
1230         _cairo_output_stream_printf (stream,
1231             "    gl_FragColor = get_source().a * get_mask()%s;\n",
1232             coverage_str);
1233         break;
1234     }
1235
1236     _cairo_output_stream_write (stream,
1237                                 "}\n\0", 3);
1238
1239     status = _cairo_memory_stream_destroy (stream, &source, &length);
1240     if (unlikely (status))
1241         return status;
1242
1243     *out = (char *) source;
1244     return CAIRO_STATUS_SUCCESS;
1245 }
1246
1247 static cairo_status_t
1248 _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
1249                           cairo_gl_shader_t *shader,
1250                           cairo_gl_operand_t *src,
1251                           cairo_gl_operand_t *mask,
1252                           cairo_bool_t use_coverage,
1253                           const char *fragment_text)
1254 {
1255     unsigned int vertex_shader;
1256     cairo_status_t status;
1257     cairo_gl_var_type_t src_type;
1258     cairo_gl_var_type_t mask_type;
1259     cairo_extend_t src_atlas_extend = CAIRO_EXTEND_NONE;
1260     cairo_extend_t mask_atlas_extend = CAIRO_EXTEND_NONE;
1261     cairo_bool_t src_use_atlas = FALSE;
1262     cairo_bool_t mask_use_atlas = FALSE;
1263
1264     assert (shader->program == 0);
1265
1266     if (src != NULL) {
1267       src_type = cairo_gl_operand_get_var_type (src->type,
1268                                                 src->use_color_attribute);
1269       src_atlas_extend = _cairo_gl_operand_get_atlas_extend (src);
1270       src_use_atlas = _cairo_gl_operand_get_use_atlas (src);
1271     }
1272     else
1273       src_type = CAIRO_GL_VAR_NONE;
1274
1275     if (mask != NULL) {
1276       mask_type = cairo_gl_operand_get_var_type (mask->type,
1277                                                  mask->use_color_attribute);
1278       mask_atlas_extend = _cairo_gl_operand_get_atlas_extend (mask);
1279       mask_use_atlas = _cairo_gl_operand_get_use_atlas (mask);
1280     }
1281     else
1282       mask_type = CAIRO_GL_VAR_NONE;
1283
1284     vertex_shader = cairo_gl_var_type_hash (src_type, mask_type,
1285                                             src_atlas_extend,
1286                                             mask_atlas_extend,
1287                                             src_use_atlas,
1288                                             mask_use_atlas,
1289                                             use_coverage,
1290                                             CAIRO_GL_VAR_NONE);
1291     if (ctx->vertex_shaders[vertex_shader] == 0) {
1292         char *source;
1293
1294         status = cairo_gl_shader_get_vertex_source (src_type,
1295                                                     mask_type,
1296                                                     src_use_atlas,
1297                                                     mask_use_atlas,
1298                                                     use_coverage,
1299                                                     CAIRO_GL_VAR_NONE,
1300                                                     &source);
1301         if (unlikely (status))
1302             goto FAILURE;
1303
1304         ctx->shader_impl->compile_shader (ctx, &ctx->vertex_shaders[vertex_shader],
1305                                           GL_VERTEX_SHADER,
1306                                           source);
1307         free (source);
1308     }
1309
1310     ctx->shader_impl->compile_shader (ctx, &shader->fragment_shader,
1311                                       GL_FRAGMENT_SHADER,
1312                                       fragment_text);
1313
1314     ctx->shader_impl->link_shader (ctx, &shader->program,
1315                                    ctx->vertex_shaders[vertex_shader],
1316                                    shader->fragment_shader);
1317
1318     return CAIRO_STATUS_SUCCESS;
1319
1320  FAILURE:
1321     _cairo_gl_shader_fini (ctx, shader);
1322     shader->fragment_shader = 0;
1323     shader->program = 0;
1324
1325     return status;
1326 }
1327
1328 /* We always bind the source to texture unit 0 if present, and mask to
1329  * texture unit 1 if present, so we can just initialize these once at
1330  * compile time.
1331  */
1332 static cairo_int_status_t
1333 _cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx,
1334                                cairo_gl_shader_t *shader)
1335 {
1336     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
1337     GLint location;
1338     GLint saved_program;
1339     cairo_int_status_t status;
1340
1341     /* We have to save/restore the current program because we might be
1342      * asked for a different program while a shader is bound.  This shouldn't
1343      * be a performance issue, since this is only called once per compile.
1344      */
1345     glGetIntegerv (GL_CURRENT_PROGRAM, &saved_program);
1346     dispatch->UseProgram (shader->program);
1347
1348     status = get_uniform_location (ctx, shader, "source_sampler", &location);
1349     if (status)
1350         return status;
1351     if (location != -1) {
1352         dispatch->Uniform1i (location, CAIRO_GL_TEX_SOURCE);
1353     }
1354
1355     get_uniform_location (ctx, shader, "mask_sampler", &location);
1356     if (status)
1357         return status;
1358     if (location != -1) {
1359         dispatch->Uniform1i (location, CAIRO_GL_TEX_MASK);
1360     }
1361
1362     dispatch->UseProgram (saved_program);
1363     return CAIRO_INT_STATUS_SUCCESS;
1364 }
1365
1366 void
1367 _cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
1368                              const char *name,
1369                              float value)
1370 {
1371     ctx->shader_impl->bind_float (ctx, ctx->current_shader, name, value);
1372 }
1373
1374 void
1375 _cairo_gl_shader_bind_vec2 (cairo_gl_context_t *ctx,
1376                             const char *name,
1377                             float value0,
1378                             float value1)
1379 {
1380     ctx->shader_impl->bind_vec2 (ctx, ctx->current_shader, name, value0, value1);
1381 }
1382
1383 void
1384 _cairo_gl_shader_bind_vec3 (cairo_gl_context_t *ctx,
1385                             const char *name,
1386                             float value0,
1387                             float value1,
1388                             float value2)
1389 {
1390     ctx->shader_impl->bind_vec3 (ctx, ctx->current_shader, name, value0, value1, value2);
1391 }
1392
1393 void
1394 _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx,
1395                             const char *name,
1396                             float value0, float value1,
1397                             float value2, float value3)
1398 {
1399     ctx->shader_impl->bind_vec4 (ctx, ctx->current_shader, name, value0, value1, value2, value3);
1400 }
1401
1402 void
1403 _cairo_gl_shader_bind_matrix (cairo_gl_context_t *ctx,
1404                               const char *name, cairo_matrix_t* m)
1405 {
1406     ctx->shader_impl->bind_matrix (ctx, ctx->current_shader, name, m);
1407 }
1408
1409 void
1410 _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
1411                                 const char *name, GLfloat* gl_m)
1412 {
1413     ctx->shader_impl->bind_matrix4f (ctx, ctx->current_shader, name, gl_m);
1414 }
1415
1416 void
1417 _cairo_gl_set_shader (cairo_gl_context_t *ctx,
1418                       cairo_gl_shader_t *shader)
1419 {
1420     if (ctx->current_shader == shader)
1421         return;
1422
1423     ctx->shader_impl->use (ctx, shader);
1424
1425     ctx->current_shader = shader;
1426 }
1427
1428 cairo_status_t
1429 _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
1430                               cairo_gl_operand_t *source,
1431                               cairo_gl_operand_t *mask,
1432                               cairo_bool_t use_coverage,
1433                               cairo_gl_shader_in_t in,
1434                               cairo_gl_shader_t **shader)
1435 {
1436     cairo_shader_cache_entry_t lookup, *entry;
1437     char *fs_source;
1438     cairo_status_t status;
1439
1440     lookup.ctx = ctx;
1441     lookup.src = source->type;
1442     lookup.mask = mask->type;
1443     lookup.dest = CAIRO_GL_OPERAND_NONE;
1444     lookup.use_coverage = use_coverage;
1445     lookup.use_color_attribute = source->use_color_attribute;
1446     lookup.in = in;
1447     lookup.src_gl_filter = _cairo_gl_operand_get_gl_filter (source);
1448     lookup.src_border_fade = _cairo_gl_shader_needs_border_fade (source);
1449     lookup.src_extend = _cairo_gl_operand_get_atlas_extend (source);
1450     lookup.mask_gl_filter = _cairo_gl_operand_get_gl_filter (mask);
1451     lookup.mask_border_fade = _cairo_gl_shader_needs_border_fade (mask);
1452     lookup.mask_extend = _cairo_gl_operand_get_atlas_extend (mask);
1453     lookup.src_use_atlas = _cairo_gl_operand_get_use_atlas (source);
1454     lookup.mask_use_atlas = _cairo_gl_operand_get_use_atlas (mask);
1455     lookup.base.hash = _cairo_gl_shader_cache_hash (&lookup);
1456     lookup.base.size = 1;
1457
1458     entry = _cairo_cache_lookup (&ctx->shaders, &lookup.base);
1459     if (entry) {
1460         assert (entry->shader.program);
1461         *shader = &entry->shader;
1462         return CAIRO_STATUS_SUCCESS;
1463     }
1464
1465     status = cairo_gl_shader_get_fragment_source (ctx,
1466                                                   in,
1467                                                   source,
1468                                                   mask,
1469                                                   use_coverage,
1470                                                   CAIRO_GL_OPERAND_NONE,
1471                                                   &fs_source);
1472     if (unlikely (status))
1473         return status;
1474
1475     entry = malloc (sizeof (cairo_shader_cache_entry_t));
1476     if (unlikely (entry == NULL)) {
1477         free (fs_source);
1478         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1479     }
1480
1481     memcpy (entry, &lookup, sizeof (cairo_shader_cache_entry_t));
1482
1483     entry->ctx = ctx;
1484     _cairo_gl_shader_init (&entry->shader);
1485     status = _cairo_gl_shader_compile (ctx,
1486                                        &entry->shader,
1487                                        source,
1488                                        mask,
1489                                        use_coverage,
1490                                        fs_source);
1491     free (fs_source);
1492
1493     if (unlikely (status))
1494         goto error;
1495
1496     status = _cairo_gl_shader_set_samplers (ctx, &entry->shader);
1497     if (unlikely (status))
1498         goto error;
1499
1500     status = _cairo_cache_insert (&ctx->shaders, &entry->base);
1501     if (unlikely (status))
1502         goto error;
1503
1504     *shader = &entry->shader;
1505
1506     return CAIRO_STATUS_SUCCESS;
1507
1508 error:
1509     _cairo_gl_shader_fini (ctx, &entry->shader);
1510     free (entry);
1511     return status;
1512 }