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