Initialize Tizen 2.3
[framework/graphics/cairo.git] / src / cairo-gl-device.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 © 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 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  *      Alexandros Frantzis <alexandros.frantzis@linaro.org>
41  */
42
43 #include "cairoint.h"
44
45 #include "cairo-error-private.h"
46 #include "cairo-gl-private.h"
47 #include "cairo-rtree-private.h"
48
49 #define MAX_MSAA_SAMPLES 4
50
51 cairo_int_status_t
52 _cairo_gl_image_cache_init (cairo_gl_context_t *ctx, int width, int height,
53                             cairo_gl_image_cache_t **image_cache)
54 {
55     cairo_surface_t *cache_surface = _cairo_gl_surface_create_scratch (ctx,
56                                                 CAIRO_CONTENT_COLOR_ALPHA,
57                                                 width, height);
58     if (unlikely (cache_surface->status)) {
59         cairo_surface_destroy (cache_surface);
60         return CAIRO_INT_STATUS_UNSUPPORTED;
61     }
62
63     _cairo_surface_release_device_reference (cache_surface);
64     *image_cache = _cairo_malloc (sizeof (cairo_gl_image_cache_t));
65     (*image_cache)->surface = (cairo_gl_surface_t *)cache_surface;
66     (*image_cache)->surface->supports_msaa = FALSE;
67
68     _cairo_rtree_init (&((*image_cache)->rtree), width, height,
69                        IMAGE_CACHE_MIN_SIZE,
70                        sizeof (cairo_gl_image_t),
71                        _cairo_gl_image_node_destroy);
72
73     (*image_cache)->copy_success = TRUE;
74     return CAIRO_INT_STATUS_SUCCESS;
75 }
76
77 void
78 _cairo_gl_image_cache_fini (cairo_gl_context_t *ctx)
79 {
80     if (ctx->image_cache) {
81         _cairo_rtree_fini (&ctx->image_cache->rtree);
82         cairo_surface_destroy (&ctx->image_cache->surface->base);
83     }
84     free (ctx->image_cache);
85 }
86
87 static void
88 _gl_lock (void *device)
89 {
90     cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
91
92     ctx->acquire (ctx);
93 }
94
95 static void
96 _gl_unlock (void *device)
97 {
98     cairo_gl_context_t *ctx = (cairo_gl_context_t *) device;
99
100     ctx->release (ctx);
101 }
102
103 static cairo_status_t
104 _gl_flush (void *device)
105 {
106     cairo_gl_context_t *ctx;
107     cairo_status_t status;
108
109     status = _cairo_gl_context_acquire (device, &ctx);
110     if (unlikely (status))
111         return status;
112
113     _cairo_gl_composite_flush (ctx);
114
115     _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
116     _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);
117
118     if (ctx->clip_region) {
119         cairo_region_destroy (ctx->clip_region);
120         ctx->clip_region = NULL;
121     }
122
123     ctx->current_target = NULL;
124     ctx->current_operator = -1;
125     ctx->vertex_size = 0;
126     ctx->pre_shader = NULL;
127     _cairo_gl_set_shader (ctx, NULL);
128
129     ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, 0);
130
131     _cairo_gl_context_reset (ctx);
132
133     _disable_scissor_buffer (ctx);
134
135     if (ctx->states_cache.blend_enabled == TRUE ) {
136         glDisable (GL_BLEND);
137         ctx->states_cache.blend_enabled = FALSE;
138     }
139
140     return _cairo_gl_context_release (ctx, status);
141 }
142
143 static void
144 _gl_finish (void *device)
145 {
146     cairo_gl_context_t *ctx = device;
147     int n;
148
149     _gl_lock (device);
150
151     _cairo_cache_fini (&ctx->gradients);
152
153     _cairo_gl_context_fini_shaders (ctx);
154
155     for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
156         _cairo_gl_glyph_cache_fini (ctx, &ctx->glyph_cache[n]);
157
158
159     _cairo_gl_image_cache_fini (ctx);
160
161     _gl_unlock (device);
162 }
163
164 static void
165 _gl_destroy (void *device)
166 {
167     int n;
168
169     cairo_gl_context_t *ctx = device;
170
171     ctx->acquire (ctx);
172
173     if(ctx->glyph_mask) {
174         cairo_surface_destroy (&ctx->glyph_mask->base);
175         ctx->glyph_mask = NULL;
176     }
177
178     for (n = 0; n < 2; n++) {
179         if (ctx->source_scratch_surfaces[n])
180             cairo_surface_destroy (&ctx->source_scratch_surfaces[n]->base);
181         if (ctx->mask_scratch_surfaces[n])
182             cairo_surface_destroy (&ctx->mask_scratch_surfaces[n]->base);
183         if (ctx->shadow_scratch_surfaces[n])
184             cairo_surface_destroy (&ctx->shadow_scratch_surfaces[n]->base);
185     }
186     if (ctx->shadow_scratch_surfaces[2])
187         cairo_surface_destroy (&ctx->shadow_scratch_surfaces[2]->base);
188
189     for (n = 0; n < 4; n++) {
190         if (ctx->shadow_masks[n])
191             cairo_surface_destroy (&ctx->shadow_masks[n]->base);
192     }
193
194     while (! cairo_list_is_empty (&ctx->fonts)) {
195         cairo_gl_font_t *font;
196
197         font = cairo_list_first_entry (&ctx->fonts,
198                                        cairo_gl_font_t,
199                                        link);
200
201         cairo_list_del (&font->base.link);
202         cairo_list_del (&font->link);
203         free (font);
204     }
205
206     _cairo_array_fini (&ctx->tristrip_indices);
207
208     cairo_region_destroy (ctx->clip_region);
209
210     free (ctx->vb);
211
212     ctx->destroy (ctx);
213
214     free (ctx);
215 }
216
217 static const cairo_device_backend_t _cairo_gl_device_backend = {
218     CAIRO_DEVICE_TYPE_GL,
219
220     _gl_lock,
221     _gl_unlock,
222
223     _gl_flush, /* flush */
224     _gl_finish,
225     _gl_destroy,
226 };
227
228 static cairo_bool_t
229 _cairo_gl_msaa_compositor_enabled (void)
230 {
231     const char *env = getenv ("CAIRO_GL_COMPOSITOR");
232     return env && strcmp(env, "msaa") == 0;
233 }
234
235 static cairo_bool_t
236 test_can_read_bgra (cairo_gl_flavor_t gl_flavor)
237 {
238     /* Desktop GL always supports BGRA formats. */
239     if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
240         return TRUE;
241
242     assert (gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
243             gl_flavor == CAIRO_GL_FLAVOR_ES3);
244
245    /* For OpenGL ES we have to look for the specific extension and BGRA only
246     * matches cairo's integer packed bytes on little-endian machines. */
247     if (!_cairo_is_little_endian())
248         return FALSE;
249     return _cairo_gl_has_extension ("EXT_read_format_bgra");
250 }
251
252 cairo_status_t
253 _cairo_gl_context_init (cairo_gl_context_t *ctx)
254 {
255     cairo_status_t status;
256     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
257     int gl_version = _cairo_gl_get_version ();
258     cairo_gl_flavor_t gl_flavor = _cairo_gl_get_flavor ();
259     int n;
260
261     cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP;
262     cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
263                             gl_flavor == CAIRO_GL_FLAVOR_ES3);
264
265     _cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
266
267     /* XXX The choice of compositor should be made automatically at runtime.
268      * However, it is useful to force one particular compositor whilst
269      * testing.
270      */
271      if (_cairo_gl_msaa_compositor_enabled ())
272         ctx->compositor = _cairo_gl_msaa_compositor_get ();
273     else
274         ctx->compositor = _cairo_gl_span_compositor_get ();
275
276
277     ctx->thread_aware = TRUE;
278     ctx->has_angle_multisampling = FALSE;
279
280     memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
281     cairo_list_init (&ctx->fonts);
282
283     /* Support only GL version >= 1.3 */
284     if (gl_version < CAIRO_GL_VERSION_ENCODE (1, 3))
285         return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
286
287     /* Check for required extensions */
288     if (is_desktop) {
289         if (_cairo_gl_has_extension ("GL_ARB_texture_non_power_of_two")) {
290             ctx->tex_target = GL_TEXTURE_2D;
291             ctx->has_npot_repeat = TRUE;
292         } else if (_cairo_gl_has_extension ("GL_ARB_texture_rectangle")) {
293             ctx->tex_target = GL_TEXTURE_RECTANGLE;
294             ctx->has_npot_repeat = FALSE;
295         } else
296             return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
297     } else {
298         ctx->tex_target = GL_TEXTURE_2D;
299         if (_cairo_gl_has_extension ("GL_OES_texture_npot") ||
300             _cairo_gl_has_extension ("GL_IMG_texture_npot"))
301             ctx->has_npot_repeat = TRUE;
302         else
303             ctx->has_npot_repeat = FALSE;
304     }
305
306     if (is_desktop && gl_version < CAIRO_GL_VERSION_ENCODE (2, 1) &&
307         ! _cairo_gl_has_extension ("GL_ARB_pixel_buffer_object"))
308         return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
309
310     if (is_gles && ! _cairo_gl_has_extension ("GL_EXT_texture_format_BGRA8888"))
311         return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
312
313     ctx->has_map_buffer =
314         is_desktop || (is_gles && _cairo_gl_has_extension ("GL_OES_mapbuffer"));
315
316     ctx->can_read_bgra = test_can_read_bgra (gl_flavor);
317
318     ctx->has_mesa_pack_invert =
319         _cairo_gl_has_extension ("GL_MESA_pack_invert");
320
321     ctx->has_packed_depth_stencil =
322         (is_desktop && _cairo_gl_has_extension ("GL_EXT_packed_depth_stencil")) ||
323         (is_gles && _cairo_gl_has_extension ("GL_OES_packed_depth_stencil"));
324
325     ctx->num_samples = 1;
326
327 #if CAIRO_HAS_GL_SURFACE
328     if (is_desktop && ctx->has_packed_depth_stencil &&
329         (gl_version >= CAIRO_GL_VERSION_ENCODE (3, 0) ||
330          _cairo_gl_has_extension ("GL_ARB_framebuffer_object") ||
331          (_cairo_gl_has_extension ("GL_EXT_framebuffer_blit") &&
332           _cairo_gl_has_extension ("GL_EXT_framebuffer_multisample")))) {
333         glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
334     }
335 #endif
336
337 #if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT)
338     if (is_gles && ctx->has_packed_depth_stencil &&
339         _cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) {
340         glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
341     }
342 #endif
343
344 #if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_IMG)
345     if (is_gles && ctx->has_packed_depth_stencil &&
346         _cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) {
347         glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples);
348     }
349 #endif
350
351 #if CAIRO_HAS_GLESV2_SURFACE && defined (GL_MAX_SAMPLES_ANGLE)
352     if (is_gles && ctx->has_packed_depth_stencil &&
353         _cairo_gl_has_extension ("GL_ANGLE_framebuffer_blit") &&
354         _cairo_gl_has_extension ("GL_ANGLE_framebuffer_multisample")) {
355         glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &ctx->num_samples);
356         ctx->has_angle_multisampling = TRUE;
357     }
358 #endif
359
360 #if CAIRO_HAS_GLESV3_SURFACE
361     if (is_gles && ctx->has_packed_depth_stencil) {
362         glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples);
363     }
364 #endif
365
366     /* we always use renderbuffer for rendering in glesv3 */
367     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
368         (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
369          ctx->has_angle_multisampling))
370         ctx->supports_msaa = TRUE;
371     else
372         ctx->supports_msaa = ctx->num_samples > 1;
373     if (ctx->num_samples > MAX_MSAA_SAMPLES)
374         ctx->num_samples = MAX_MSAA_SAMPLES;
375
376
377     ctx->current_operator = -1;
378     ctx->gl_flavor = gl_flavor;
379
380     status = _cairo_gl_context_init_shaders (ctx);
381     if (unlikely (status))
382         return status;
383
384     status = _cairo_cache_init (&ctx->gradients,
385                                 _cairo_gl_gradient_equal,
386                                 NULL,
387                                 (cairo_destroy_func_t) _cairo_gl_gradient_destroy,
388                                 CAIRO_GL_GRADIENT_CACHE_SIZE);
389     if (unlikely (status))
390         return status;
391
392     ctx->vb = malloc (CAIRO_GL_VBO_SIZE);
393     if (unlikely (ctx->vb == NULL)) {
394             _cairo_cache_fini (&ctx->gradients);
395             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
396     }
397
398     ctx->primitive_type = CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES;
399     _cairo_array_init (&ctx->tristrip_indices, sizeof (unsigned short));
400
401     /* PBO for any sort of texture upload */
402     dispatch->GenBuffers (1, &ctx->texture_load_pbo);
403
404     ctx->max_framebuffer_size = 0;
405     glGetIntegerv (GL_MAX_RENDERBUFFER_SIZE, &ctx->max_framebuffer_size);
406     ctx->max_texture_size = 0;
407     glGetIntegerv (GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size);
408     ctx->max_textures = 0;
409     glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &ctx->max_textures);
410
411     for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
412         _cairo_gl_glyph_cache_init (&ctx->glyph_cache[n]);
413
414     ctx->image_cache = NULL;
415
416     for (n = 0; n < 2; n++) {
417         ctx->source_scratch_surfaces[n] = NULL;
418         ctx->mask_scratch_surfaces[n] = NULL;
419         ctx->shadow_scratch_surfaces[n] = NULL;
420     }
421
422     for (n = 0; n < 4; n++)
423     ctx->shadow_masks[n] = NULL;
424
425     ctx->source_scratch_in_use = FALSE;
426
427     _cairo_gl_context_reset (ctx);
428
429     return CAIRO_STATUS_SUCCESS;
430 }
431
432 void
433 _cairo_gl_context_activate (cairo_gl_context_t *ctx,
434                             cairo_gl_tex_t      tex_unit)
435 {
436     if (ctx->max_textures <= (GLint) tex_unit) {
437         if (tex_unit < 2) {
438             _cairo_gl_composite_flush (ctx);
439             _cairo_gl_context_destroy_operand (ctx, ctx->max_textures - 1);
440         }
441         if (ctx->states_cache.active_texture != ctx->max_textures - 1) {
442             glActiveTexture (ctx->max_textures - 1);
443             ctx->states_cache.active_texture = ctx->max_textures - 1;
444         }
445     } else {
446         if (ctx->states_cache.active_texture != GL_TEXTURE0 + tex_unit) {
447             glActiveTexture (GL_TEXTURE0 + tex_unit);
448             ctx->states_cache.active_texture = GL_TEXTURE0 + tex_unit;
449         }
450     }
451 }
452
453 static GLenum
454 _get_depth_stencil_format (cairo_gl_context_t *ctx)
455 {
456     /* This is necessary to properly handle the situation where both
457        OpenGL and OpenGLES are active and returning a sane default. */
458 #if CAIRO_HAS_GL_SURFACE
459     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
460         return GL_DEPTH_STENCIL;
461 #endif
462
463 #if CAIRO_HAS_GLESV2_SURFACE
464     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
465         return GL_DEPTH24_STENCIL8_OES;
466 #endif
467
468 #if CAIRO_HAS_GL_SURFACE
469     return GL_DEPTH_STENCIL;
470 #elif CAIRO_HAS_GLESV2_SURFACE
471     return GL_DEPTH24_STENCIL8_OES;
472 #elif CAIRO_HAS_GLESV3_SURFACE
473     return GL_DEPTH24_STENCIL8;
474 #endif
475 }
476
477 static void
478 _cairo_gl_clear_framebuffer (cairo_gl_context_t *ctx,
479                              cairo_gl_surface_t *surface)
480 {
481     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
482         return;
483
484     if (_cairo_gl_surface_is_scratch (ctx, surface)) {
485         _disable_scissor_buffer (ctx);
486         _disable_stencil_buffer (ctx);
487         glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
488     }
489 }
490
491 #if CAIRO_HAS_GLESV2_SURFACE
492 static void
493 _cairo_gl_ensure_msaa_gles_framebuffer (cairo_gl_context_t *ctx,
494                                         cairo_gl_surface_t *surface)
495 {
496     if (ctx->has_angle_multisampling)
497         return;
498
499     if (surface->msaa_active)
500         return;
501
502     ctx->dispatch.FramebufferTexture2DMultisample(GL_FRAMEBUFFER,
503                                                   GL_COLOR_ATTACHMENT0,
504                                                   ctx->tex_target,
505                                                   surface->tex,
506                                                   0,
507                                                   ctx->num_samples);
508
509     /* From now on MSAA will always be active on this surface. */
510     surface->msaa_active = TRUE;
511 }
512 #endif
513
514 void
515 _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
516                               cairo_gl_surface_t *surface)
517 {
518     GLenum status;
519     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
520
521     if (likely (surface->fb))
522         return;
523
524     /* Create a framebuffer object wrapping the texture so that we can render
525      * to it.
526      */
527     dispatch->GenFramebuffers (1, &surface->fb);
528     dispatch->BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
529
530     /* Unlike for desktop GL we only maintain one multisampling framebuffer
531        for OpenGLES since the EXT_multisampled_render_to_texture extension
532        does not require an explicit multisample resolution. */
533 #if CAIRO_HAS_GLESV2_SURFACE
534     if (surface->supports_msaa && _cairo_gl_msaa_compositor_enabled () &&
535         ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
536         ! ctx->has_angle_multisampling) {
537         _cairo_gl_ensure_msaa_gles_framebuffer (ctx, surface);
538     } else
539 #endif
540         dispatch->FramebufferTexture2D (GL_FRAMEBUFFER,
541                                         GL_COLOR_ATTACHMENT0,
542                                         ctx->tex_target,
543                                         surface->tex,
544                                         0);
545
546 #if CAIRO_HAS_GL_SURFACE
547     glDrawBuffer (GL_COLOR_ATTACHMENT0);
548     glReadBuffer (GL_COLOR_ATTACHMENT0);
549 #endif
550
551     status = dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER);
552     if (status != GL_FRAMEBUFFER_COMPLETE) {
553         const char *str;
554         switch (status) {
555         //case GL_FRAMEBUFFER_UNDEFINED: str= "undefined"; break;
556         case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: str= "incomplete attachment"; break;
557         case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: str= "incomplete/missing attachment"; break;
558         case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: str= "incomplete draw buffer"; break;
559         case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: str= "incomplete read buffer"; break;
560         case GL_FRAMEBUFFER_UNSUPPORTED: str= "unsupported"; break;
561         case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: str= "incomplete multiple"; break;
562         default: str = "unknown error"; break;
563         }
564
565         fprintf (stderr,
566                  "destination is framebuffer incomplete: %s [%#x]\n",
567                  str, status);
568     }
569 }
570
571 static void
572 _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
573                                 cairo_gl_surface_t *surface)
574 {
575     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
576         ! ctx->has_angle_multisampling)
577         return;
578
579     assert (surface->supports_msaa);
580
581     if (surface->msaa_fb)
582         return;
583
584     /* We maintain a separate framebuffer for multisampling operations.
585        This allows us to do a fast paint to the non-multisampling framebuffer
586        when mulitsampling is disabled. */
587     ctx->dispatch.GenFramebuffers (1, &surface->msaa_fb);
588     ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
589     ctx->dispatch.GenRenderbuffers (1, &surface->msaa_rb);
590     ctx->dispatch.BindRenderbuffer (GL_RENDERBUFFER, surface->msaa_rb);
591
592     /* FIXME: For now we assume that textures passed from the outside have GL_RGBA
593        format, but eventually we need to expose a way for the API consumer to pass
594        this information. */
595     ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER,
596                                                   ctx->num_samples,
597 #if CAIRO_HAS_GLESV3_SURFACE || CAIRO_HAS_GLESV2_SURFACE
598                                                   GL_RGBA8,
599 #else
600                                                   GL_RGBA,
601 #endif
602                                                   surface->width,
603                                                   surface->height);
604
605     ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER,
606                                            GL_COLOR_ATTACHMENT0,
607                                            GL_RENDERBUFFER,
608                                            surface->msaa_rb);
609
610     if (ctx->dispatch.CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
611         ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb);
612         surface->msaa_rb = 0;
613         ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_fb);
614         surface->msaa_fb = 0;
615         return;
616     }
617
618     /* Cairo surfaces start out initialized to transparent (black) */
619     _disable_scissor_buffer (ctx);
620     glClearColor (0, 0, 0, 0);
621     // reset cached clear colors
622     memset (&ctx->states_cache.clear_red, 0, sizeof (GLclampf) * 4);
623     glClear (GL_COLOR_BUFFER_BIT);
624 }
625
626 static cairo_bool_t
627 _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
628                                             cairo_gl_surface_t *surface)
629 {
630     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
631     if (surface->msaa_depth_stencil)
632         return TRUE;
633
634     _cairo_gl_ensure_multisampling (ctx, surface);
635
636     dispatch->GenRenderbuffers (1, &surface->msaa_depth_stencil);
637     dispatch->BindRenderbuffer (GL_RENDERBUFFER,
638                                 surface->msaa_depth_stencil);
639
640     dispatch->RenderbufferStorageMultisample (GL_RENDERBUFFER,
641                                               ctx->num_samples,
642                                               _get_depth_stencil_format (ctx),
643                                               surface->width,
644                                               surface->height);
645
646 #if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
647     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
648         ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) {
649         dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
650                                            GL_DEPTH_STENCIL_ATTACHMENT,
651                                            GL_RENDERBUFFER,
652                                            surface->msaa_depth_stencil);
653     }
654 #endif
655
656 #if CAIRO_HAS_GLESV2_SURFACE
657     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
658         dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
659                                            GL_DEPTH_ATTACHMENT,
660                                            GL_RENDERBUFFER,
661                                            surface->msaa_depth_stencil);
662         dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
663                                            GL_STENCIL_ATTACHMENT,
664                                            GL_RENDERBUFFER,
665                                            surface->msaa_depth_stencil);
666     }
667 #endif
668
669     if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
670         dispatch->DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
671         surface->msaa_depth_stencil = 0;
672         return FALSE;
673     }
674
675     return TRUE;
676 }
677
678 static cairo_bool_t
679 _cairo_gl_ensure_depth_stencil_buffer (cairo_gl_context_t *ctx,
680                                        cairo_gl_surface_t *surface)
681 {
682     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
683
684     if (surface->depth_stencil)
685         return TRUE;
686
687     _cairo_gl_ensure_framebuffer (ctx, surface);
688
689     dispatch->GenRenderbuffers (1, &surface->depth_stencil);
690     dispatch->BindRenderbuffer (GL_RENDERBUFFER, surface->depth_stencil);
691     dispatch->RenderbufferStorage (GL_RENDERBUFFER,
692                                    _get_depth_stencil_format (ctx),
693                                    surface->width, surface->height);
694
695     dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
696                                        GL_RENDERBUFFER, surface->depth_stencil);
697     dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
698                                        GL_RENDERBUFFER, surface->depth_stencil);
699     if (dispatch->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
700         dispatch->DeleteRenderbuffers (1, &surface->depth_stencil);
701         surface->depth_stencil = 0;
702         return FALSE;
703     }
704
705     return TRUE;
706 }
707
708 cairo_bool_t
709 _cairo_gl_ensure_stencil (cairo_gl_context_t *ctx,
710                           cairo_gl_surface_t *surface)
711 {
712     if (! _cairo_gl_surface_is_texture (surface))
713         return TRUE; /* best guess for now, will check later */
714     if (! ctx->has_packed_depth_stencil)
715         return FALSE;
716
717     if (surface->msaa_active)
718         return _cairo_gl_ensure_msaa_depth_stencil_buffer (ctx, surface);
719     else
720         return _cairo_gl_ensure_depth_stencil_buffer (ctx, surface);
721 }
722
723 /*
724  * Stores a parallel projection transformation in matrix 'm',
725  * using column-major order.
726  *
727  * This is equivalent to:
728  *
729  * glLoadIdentity()
730  * gluOrtho2D()
731  *
732  * The calculation for the ortho tranformation was taken from the
733  * mesa source code.
734  */
735 static void
736 _gl_identity_ortho (GLfloat *m,
737                     GLfloat left, GLfloat right,
738                     GLfloat bottom, GLfloat top)
739 {
740 #define M(row,col)  m[col*4+row]
741     M(0,0) = 2.f / (right - left);
742     M(0,1) = 0.f;
743     M(0,2) = 0.f;
744     M(0,3) = -(right + left) / (right - left);
745
746     M(1,0) = 0.f;
747     M(1,1) = 2.f / (top - bottom);
748     M(1,2) = 0.f;
749     M(1,3) = -(top + bottom) / (top - bottom);
750
751     M(2,0) = 0.f;
752     M(2,1) = 0.f;
753     M(2,2) = -1.f;
754     M(2,3) = 0.f;
755
756     M(3,0) = 0.f;
757     M(3,1) = 0.f;
758     M(3,2) = 0.f;
759     M(3,3) = 1.f;
760 #undef M
761 }
762
763 static void
764 bind_multisample_framebuffer (cairo_gl_context_t *ctx,
765                                cairo_gl_surface_t *surface)
766 {
767 #if CAIRO_HAS_GL_SURFACE
768     cairo_bool_t stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
769     cairo_bool_t scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
770
771     cairo_bool_t has_stencil_cache = surface->clip_on_stencil_buffer ? TRUE : FALSE;
772     GLbitfield mask = GL_COLOR_BUFFER_BIT;
773 #endif
774     assert (surface->supports_msaa);
775
776     _cairo_gl_ensure_framebuffer (ctx, surface);
777     _cairo_gl_ensure_multisampling (ctx, surface);
778
779     if (surface->msaa_active) {
780 #if CAIRO_HAS_GL_SURFACE
781         glEnable (GL_MULTISAMPLE);
782
783 #endif
784         ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
785         return;
786     }
787
788     _cairo_gl_composite_flush (ctx);
789
790 #if CAIRO_HAS_GL_SURFACE
791     /* we must disable scissor and stencil test */
792     _disable_stencil_buffer (ctx);
793     _disable_scissor_buffer (ctx);
794
795     glEnable (GL_MULTISAMPLE);
796
797     if (has_stencil_cache)
798         mask |= GL_STENCIL_BUFFER_BIT;
799
800     /* The last time we drew to the surface, we were not using multisampling,
801        so we need to blit from the non-multisampling framebuffer into the
802        multisampling framebuffer. */
803     ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->msaa_fb);
804     ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
805     ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
806                                    0, 0, surface->width, surface->height,
807                                    mask, GL_NEAREST);
808     surface->content_synced = TRUE;
809 #endif
810     ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
811
812 #if CAIRO_HAS_GL_SURFACE
813     /* re-enable stencil and scissor test */
814     if (scissor_test_enabled)
815         _enable_scissor_buffer (ctx);
816     if (stencil_test_enabled)
817         _enable_stencil_buffer (ctx);
818 #endif
819 }
820
821 static void
822 bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
823                                cairo_gl_surface_t *surface)
824 {
825     cairo_bool_t has_stencil_cache = surface->clip_on_stencil_buffer ? TRUE : FALSE;
826     cairo_bool_t stencil_test_enabled = ctx->states_cache.stencil_test_enabled;
827     cairo_bool_t scissor_test_enabled = ctx->states_cache.scissor_test_enabled;
828     GLbitfield mask = GL_COLOR_BUFFER_BIT;
829
830     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
831         ! ctx->has_angle_multisampling)
832         return;
833
834     _cairo_gl_ensure_framebuffer (ctx, surface);
835
836     if (! surface->msaa_active) {
837 #if CAIRO_HAS_GL_SURFACE
838         glDisable (GL_MULTISAMPLE);
839 #endif
840         ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
841         return;
842     }
843
844     _cairo_gl_composite_flush (ctx);
845
846     /* we must disable scissor and stencil test */
847     _disable_stencil_buffer (ctx);
848     _disable_scissor_buffer (ctx);
849 #if CAIRO_HAS_GL_SURFACE
850     glDisable (GL_MULTISAMPLE);
851 #endif
852
853     if (has_stencil_cache)
854         mask |= GL_STENCIL_BUFFER_BIT;
855
856     /* The last time we drew to the surface, we were using multisampling,
857        so we need to blit from the multisampling framebuffer into the
858        non-multisampling framebuffer. */
859 #if CAIRO_HAS_GLESV2_SURFACE
860     ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER_ANGLE, surface->fb);
861     ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER_ANGLE, surface->msaa_fb);
862 #else
863     ctx->dispatch.BindFramebuffer (GL_DRAW_FRAMEBUFFER, surface->fb);
864     ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->msaa_fb);
865 #endif
866     ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
867                                    0, 0, surface->width, surface->height,
868                                    mask, GL_NEAREST);
869     ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
870
871     surface->content_synced = TRUE;
872     /* re-enable stencil and scissor test */
873     if (scissor_test_enabled)
874         _enable_scissor_buffer (ctx);
875     if (stencil_test_enabled)
876         _enable_stencil_buffer (ctx);
877 }
878
879 void
880 _cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
881                                     cairo_gl_surface_t *surface,
882                                     cairo_bool_t multisampling)
883 {
884     if (_cairo_gl_surface_is_texture (surface)) {
885         /* OpenGL ES surfaces only have either a multisample framebuffer or a
886          * singlesample framebuffer, so we cannot switch back and forth. */
887         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
888             ! ctx->has_angle_multisampling) {
889             _cairo_gl_ensure_framebuffer (ctx, surface);
890             ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
891             _cairo_gl_clear_framebuffer (ctx, surface);
892             return;
893         }
894
895         if (multisampling)
896             bind_multisample_framebuffer (ctx, surface);
897         else
898             bind_singlesample_framebuffer (ctx, surface);
899     } else {
900         ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);
901
902 #if CAIRO_HAS_GL_SURFACE
903         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
904             if (multisampling)
905                 glEnable (GL_MULTISAMPLE);
906             else
907                 glDisable (GL_MULTISAMPLE);
908         }
909 #endif
910     }
911
912     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
913         ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
914         (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
915          ctx->has_angle_multisampling))
916         surface->msaa_active = multisampling;
917
918     if (ctx->gl_flavor != CAIRO_GL_FLAVOR_DESKTOP && multisampling)
919         _cairo_gl_clear_framebuffer (ctx, surface);
920 }
921
922 void
923 _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
924                                    cairo_gl_surface_t *surface,
925                                    cairo_bool_t multisampling)
926 {
927     cairo_bool_t changing_surface, changing_sampling;
928
929     /* The decision whether or not to use multisampling happens when
930      * we create an OpenGL ES surface, so we can never switch modes. */
931     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
932         ! ctx->has_angle_multisampling)
933         multisampling = surface->msaa_active;
934
935     changing_surface = ctx->current_target != surface || surface->size_changed;
936     changing_sampling = surface->msaa_active != multisampling;
937
938     if (! changing_surface && ! changing_sampling) {
939         if (surface->needs_update)
940             _cairo_gl_composite_flush (ctx);
941         return;
942     }
943     if (! changing_surface) {
944         _cairo_gl_composite_flush (ctx);
945         _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
946         return;
947     }
948
949     _cairo_gl_composite_flush (ctx);
950
951     ctx->current_target = surface;
952     surface->needs_update = FALSE;
953
954     if (! _cairo_gl_surface_is_texture (surface)) {
955         ctx->make_current (ctx, surface);
956     }
957
958     _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
959
960     if (! _cairo_gl_surface_is_texture (surface)) {
961 #if CAIRO_HAS_GL_SURFACE
962         glDrawBuffer (GL_BACK_LEFT);
963         glReadBuffer (GL_BACK_LEFT);
964 #endif
965     }
966
967     glDisable (GL_DITHER);
968     if (ctx->states_cache.viewport_box.width != surface->width ||
969         ctx->states_cache.viewport_box.height != surface->height) {
970         glViewport (0, 0, surface->width, surface->height);
971         ctx->states_cache.viewport_box.width = surface->width;
972         ctx->states_cache.viewport_box.height = surface->height;
973     }
974
975     if (_cairo_gl_surface_is_texture (surface))
976         _gl_identity_ortho (ctx->modelviewprojection_matrix,
977                             0, surface->width, 0, surface->height);
978     else
979         _gl_identity_ortho (ctx->modelviewprojection_matrix,
980                             0, surface->width, surface->height, 0);
981 }
982
983 void
984 cairo_gl_device_set_thread_aware (cairo_device_t        *device,
985                                   cairo_bool_t           thread_aware)
986 {
987     if (device->backend->type != CAIRO_DEVICE_TYPE_GL) {
988         _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
989         return;
990     }
991     ((cairo_gl_context_t *) device)->thread_aware = thread_aware;
992 }
993
994 void _cairo_gl_context_reset (cairo_gl_context_t *ctx)
995 {
996     ctx->states_cache.viewport_box.width = 0;
997     ctx->states_cache.viewport_box.height = 0;
998
999     ctx->states_cache.clear_red = -1;
1000     ctx->states_cache.clear_green = -1;
1001     ctx->states_cache.clear_blue = -1;
1002     ctx->states_cache.clear_alpha = -1;
1003
1004     ctx->states_cache.blend_enabled = FALSE;
1005
1006     ctx->states_cache.src_color_factor = CAIRO_GL_ENUM_UNINITIALIZED;
1007     ctx->states_cache.dst_color_factor = CAIRO_GL_ENUM_UNINITIALIZED;
1008     ctx->states_cache.src_alpha_factor = CAIRO_GL_ENUM_UNINITIALIZED;
1009     ctx->states_cache.dst_alpha_factor = CAIRO_GL_ENUM_UNINITIALIZED;
1010
1011     ctx->states_cache.active_texture = CAIRO_GL_ENUM_UNINITIALIZED;
1012
1013     ctx->states_cache.depth_mask = FALSE;
1014 }