1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Eric Anholt
4 * Copyright © 2009 Chris Wilson
5 * Copyright © 2005,2010 Red Hat, Inc
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is Red Hat, Inc.
35 * Benjamin Otte <otte@gnome.org>
36 * Carl Worth <cworth@cworth.org>
37 * Chris Wilson <chris@chris-wilson.co.uk>
38 * Eric Anholt <eric@anholt.net>
43 #include "cairo-gl-private.h"
45 #include "cairo-composite-rectangles-private.h"
46 #include "cairo-compositor-private.h"
47 #include "cairo-default-context-private.h"
48 #include "cairo-error-private.h"
49 #include "cairo-image-surface-inline.h"
50 #include "cairo-surface-backend-private.h"
51 #include "cairo-surface-shadow-private.h"
52 #include "cairo-surface-scale-translate-private.h"
54 static const cairo_surface_backend_t _cairo_gl_surface_backend;
57 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags);
59 static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
61 return surface->backend == &_cairo_gl_surface_backend;
64 static cairo_surface_t *
65 _cairo_gl_surface_shadow_surface (void *surface,
66 const cairo_bool_t has_blur,
67 int width, int height,
68 int *width_out, int *height_out)
70 int shadow_width, shadow_height;
71 cairo_gl_surface_t *shadow_surface = NULL;
73 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
74 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
78 shadow_surface = ctx->shadow_scratch_surfaces[0];
81 shadow_width = shadow_surface->width;
82 shadow_height = shadow_surface->height;
85 if(shadow_width >= width &&
86 shadow_height >= height) {
89 return cairo_surface_reference (&shadow_surface->base);
92 cairo_surface_destroy (&shadow_surface->base);
93 shadow_surface = NULL;
97 if (shadow_width * 2 < width &&
98 shadow_height * 2 < height) {
99 if (shadow_width < MAX_SCRATCH_SIZE ||
100 shadow_height < MAX_SCRATCH_SIZE) {
101 cairo_surface_destroy (&shadow_surface->base);
102 shadow_surface = NULL;
105 else if (shadow_width > 4 * width &&
106 shadow_height > 4 * height) {
107 cairo_surface_destroy (&shadow_surface->base);
108 shadow_surface = NULL;
113 if (! shadow_surface) {
114 shadow_width = shadow_height = MIN_SCRATCH_SIZE;
116 while (shadow_width * 2 < width) {
118 if (shadow_width == MAX_SCRATCH_SIZE)
120 else if (shadow_width > MAX_SCRATCH_SIZE) {
125 while (shadow_height * 2 < height) {
127 if (shadow_height == MAX_SCRATCH_SIZE)
129 else if (shadow_height > MAX_SCRATCH_SIZE) {
130 shadow_height *= 0.5;
136 while (shadow_width < width) {
138 if (shadow_width == MAX_SCRATCH_SIZE)
140 else if (shadow_width > MAX_SCRATCH_SIZE) {
145 while (shadow_height < height) {
147 if (shadow_height == MAX_SCRATCH_SIZE)
149 else if (shadow_height > MAX_SCRATCH_SIZE) {
150 shadow_height *= 0.5;
157 shadow_surface = (cairo_gl_surface_t *)
158 _cairo_gl_surface_create_scratch (ctx,
159 CAIRO_CONTENT_COLOR_ALPHA,
162 if (unlikely (shadow_surface->base.status)) {
163 cairo_surface_destroy (&shadow_surface->base);
167 _cairo_surface_release_device_reference (&shadow_surface->base);
170 ctx->shadow_scratch_surfaces[0] = shadow_surface;
172 shadow_surface->needs_to_cache = FALSE;
173 shadow_surface->force_no_cache = TRUE;
176 *height_out = height;
179 while (*width_out > shadow_width) {
183 while (*height_out > shadow_height) {
188 if (*width_out > MAX_SCRATCH_SIZE)
190 if (*height_out > MAX_SCRATCH_SIZE)
194 return cairo_surface_reference (&shadow_surface->base);
197 static cairo_surface_t *
198 _cairo_gl_surface_shadow_mask_surface (void *surface,
199 int width, int height,
202 cairo_gl_surface_t *mask_surface = NULL;
204 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
205 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
212 mask_surface = ctx->shadow_masks[index];
215 if (mask_surface->width != width ||
216 mask_surface->height != height) {
217 cairo_surface_destroy (&mask_surface->base);
219 ctx->shadow_masks[index] = NULL;
223 if (! mask_surface) {
224 mask_surface = (cairo_gl_surface_t *)
225 _cairo_gl_surface_create_scratch (ctx,
226 CAIRO_CONTENT_COLOR_ALPHA,
229 if (unlikely (mask_surface->base.status)) {
230 cairo_surface_destroy (&mask_surface->base);
233 _cairo_surface_release_device_reference (&mask_surface->base);
236 ctx->shadow_masks[index] = mask_surface;
238 mask_surface->needs_to_cache = FALSE;
239 mask_surface->force_no_cache = TRUE;
241 return cairo_surface_reference (&mask_surface->base);
244 static cairo_surface_t *
245 _cairo_gl_surface_glyph_shadow_surface (void *surface,
246 int width, int height,
247 cairo_bool_t for_source)
249 int shadow_width, shadow_height;
250 cairo_gl_surface_t *shadow_surface = NULL;
252 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
253 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
258 shadow_surface = ctx->shadow_scratch_surfaces[1];
260 shadow_surface = ctx->shadow_scratch_surfaces[2];
262 if (shadow_surface) {
263 shadow_width = shadow_surface->width;
264 shadow_height = shadow_surface->height;
266 if (shadow_width < width ||
267 shadow_height < height) {
268 cairo_surface_destroy (&shadow_surface->base);
269 shadow_surface = NULL;
273 if (! shadow_surface) {
274 shadow_surface = (cairo_gl_surface_t *)
275 _cairo_gl_surface_create_scratch (ctx,
276 CAIRO_CONTENT_COLOR_ALPHA,
278 if (unlikely (shadow_surface->base.status)) {
279 cairo_surface_destroy (&shadow_surface->base);
282 _cairo_surface_release_device_reference (&shadow_surface->base);
286 ctx->shadow_scratch_surfaces[1] = shadow_surface;
288 ctx->shadow_scratch_surfaces[2] = shadow_surface;
290 shadow_surface->needs_to_cache = FALSE;
291 shadow_surface->force_no_cache = TRUE;
293 return cairo_surface_reference (&shadow_surface->base);
296 static cairo_surface_t *
297 _cairo_gl_surface_glyph_shadow_mask_surface (void *surface,
298 int width, int height,
301 cairo_gl_surface_t *mask_surface = NULL;
303 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
304 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
311 mask_surface = ctx->shadow_masks[index + 2];
314 if (mask_surface->width != width ||
315 mask_surface->height != height) {
316 cairo_surface_destroy (&mask_surface->base);
318 ctx->shadow_masks[index + 2] = NULL;
322 if (! mask_surface) {
323 mask_surface = (cairo_gl_surface_t *)
324 _cairo_gl_surface_create_scratch (ctx,
328 if (unlikely (mask_surface->base.status)) {
329 cairo_surface_destroy (&mask_surface->base);
332 _cairo_surface_release_device_reference (&mask_surface->base);
335 ctx->shadow_masks[index + 2] = mask_surface;
337 mask_surface->needs_to_cache = FALSE;
338 mask_surface->force_no_cache = TRUE;
340 return cairo_surface_reference (&mask_surface->base);
344 _cairo_gl_get_image_format_and_type_gles2 (pixman_format_code_t pixman_format,
345 GLenum *internal_format, GLenum *format,
346 GLenum *type, cairo_bool_t *has_alpha,
347 cairo_bool_t *needs_swap)
349 cairo_bool_t is_little_endian = _cairo_is_little_endian ();
353 switch ((int) pixman_format) {
354 case PIXMAN_a8r8g8b8:
355 *internal_format = GL_BGRA;
357 *type = GL_UNSIGNED_BYTE;
358 *needs_swap = !is_little_endian;
361 case PIXMAN_x8r8g8b8:
362 *internal_format = GL_BGRA;
364 *type = GL_UNSIGNED_BYTE;
366 *needs_swap = !is_little_endian;
369 case PIXMAN_a8b8g8r8:
370 *internal_format = GL_RGBA;
372 *type = GL_UNSIGNED_BYTE;
373 *needs_swap = !is_little_endian;
376 case PIXMAN_x8b8g8r8:
377 *internal_format = GL_RGBA;
379 *type = GL_UNSIGNED_BYTE;
381 *needs_swap = !is_little_endian;
384 case PIXMAN_b8g8r8a8:
385 *internal_format = GL_BGRA;
387 *type = GL_UNSIGNED_BYTE;
388 *needs_swap = is_little_endian;
391 case PIXMAN_b8g8r8x8:
392 *internal_format = GL_BGRA;
394 *type = GL_UNSIGNED_BYTE;
396 *needs_swap = is_little_endian;
400 *internal_format = GL_RGB;
402 *type = GL_UNSIGNED_BYTE;
403 *needs_swap = is_little_endian;
407 *internal_format = GL_RGB;
409 *type = GL_UNSIGNED_BYTE;
410 *needs_swap = !is_little_endian;
414 *internal_format = GL_RGB;
416 *type = GL_UNSIGNED_SHORT_5_6_5;
421 *internal_format = GL_RGB;
423 *type = GL_UNSIGNED_SHORT_5_6_5;
427 case PIXMAN_a1b5g5r5:
428 *internal_format = GL_RGBA;
430 *type = GL_UNSIGNED_SHORT_5_5_5_1;
434 case PIXMAN_x1b5g5r5:
435 *internal_format = GL_RGBA;
437 *type = GL_UNSIGNED_SHORT_5_5_5_1;
443 *internal_format = GL_ALPHA;
445 *type = GL_UNSIGNED_BYTE;
455 _cairo_gl_get_image_format_and_type_gl (pixman_format_code_t pixman_format,
456 GLenum *internal_format, GLenum *format,
457 GLenum *type, cairo_bool_t *has_alpha,
458 cairo_bool_t *needs_swap)
463 switch (pixman_format) {
464 case PIXMAN_a8r8g8b8:
465 *internal_format = GL_RGBA;
467 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
469 case PIXMAN_x8r8g8b8:
470 *internal_format = GL_RGB;
472 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
475 case PIXMAN_a8b8g8r8:
476 *internal_format = GL_RGBA;
478 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
480 case PIXMAN_x8b8g8r8:
481 *internal_format = GL_RGB;
483 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
486 case PIXMAN_b8g8r8a8:
487 *internal_format = GL_RGBA;
489 *type = GL_UNSIGNED_INT_8_8_8_8;
491 case PIXMAN_b8g8r8x8:
492 *internal_format = GL_RGB;
494 *type = GL_UNSIGNED_INT_8_8_8_8;
498 *internal_format = GL_RGB;
500 *type = GL_UNSIGNED_BYTE;
503 *internal_format = GL_RGB;
505 *type = GL_UNSIGNED_BYTE;
508 *internal_format = GL_RGB;
510 *type = GL_UNSIGNED_SHORT_5_6_5;
513 *internal_format = GL_RGB;
515 *type = GL_UNSIGNED_SHORT_5_6_5_REV;
517 case PIXMAN_a1r5g5b5:
518 *internal_format = GL_RGBA;
520 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
522 case PIXMAN_x1r5g5b5:
523 *internal_format = GL_RGB;
525 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
528 case PIXMAN_a1b5g5r5:
529 *internal_format = GL_RGBA;
531 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
533 case PIXMAN_x1b5g5r5:
534 *internal_format = GL_RGB;
536 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
540 *internal_format = GL_ALPHA;
542 *type = GL_UNSIGNED_BYTE;
545 case PIXMAN_a2b10g10r10:
546 case PIXMAN_x2b10g10r10:
547 case PIXMAN_a4r4g4b4:
548 case PIXMAN_x4r4g4b4:
549 case PIXMAN_a4b4g4r4:
550 case PIXMAN_x4b4g4r4:
553 case PIXMAN_a2r2g2b2:
554 case PIXMAN_a2b2g2r2:
557 /* case PIXMAN_x4c4: */
562 case PIXMAN_a1r1g1b1:
563 case PIXMAN_a1b1g1r1:
570 case PIXMAN_x2r10g10b10:
571 case PIXMAN_a2r10g10b10:
572 case PIXMAN_r8g8b8x8:
573 case PIXMAN_r8g8b8a8:
574 case PIXMAN_x14r6g6b6:
581 * Extracts pixel data from an image surface.
583 static cairo_status_t
584 _cairo_gl_surface_extract_image_data (cairo_image_surface_t *image,
586 int width, int height,
589 int cpp = PIXMAN_FORMAT_BPP (image->pixman_format) / 8;
590 char *data = _cairo_malloc_ab (width * height, cpp);
592 unsigned char *src = image->data + y * image->stride + x * cpp;
595 if (unlikely (data == NULL))
596 return CAIRO_STATUS_NO_MEMORY;
598 for (i = 0; i < height; i++) {
599 memcpy (dst, src, width * cpp);
600 src += image->stride;
606 return CAIRO_STATUS_SUCCESS;
610 _cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor,
611 pixman_format_code_t pixman_format,
612 GLenum *internal_format, GLenum *format,
613 GLenum *type, cairo_bool_t *has_alpha,
614 cairo_bool_t *needs_swap)
616 if (flavor == CAIRO_GL_FLAVOR_DESKTOP)
617 return _cairo_gl_get_image_format_and_type_gl (pixman_format,
618 internal_format, format,
622 return _cairo_gl_get_image_format_and_type_gles2 (pixman_format,
623 internal_format, format,
630 _cairo_gl_operator_is_supported (cairo_operator_t op)
632 return op < CAIRO_OPERATOR_SATURATE;
636 _cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
638 cairo_gl_operand_t *operand = &surface->operand;
639 cairo_surface_attributes_t *attributes = &operand->texture.attributes;
641 memset (operand, 0, sizeof (cairo_gl_operand_t));
643 operand->type = CAIRO_GL_OPERAND_TEXTURE;
644 operand->texture.surface = surface;
645 operand->texture.tex = surface->tex;
648 if (_cairo_gl_device_requires_power_of_two_textures (surface->base.device)) {
649 cairo_matrix_init_identity (&attributes->matrix);
651 cairo_matrix_init_scale (&attributes->matrix,
652 1.0 / surface->width,
653 1.0 / surface->height);
656 attributes->extend = CAIRO_EXTEND_NONE;
657 attributes->filter = CAIRO_FILTER_NEAREST;
661 _cairo_gl_surface_init (cairo_device_t *device,
662 cairo_gl_surface_t *surface,
663 cairo_content_t content,
664 int width, int height)
666 assert (width > 0 && height > 0);
668 _cairo_surface_init (&surface->base,
669 &_cairo_gl_surface_backend,
673 surface->width = width;
674 surface->height = height;
675 surface->needs_update = FALSE;
676 surface->size_changed = FALSE;
677 surface->needs_to_cache = FALSE;
678 surface->image_node = NULL;
679 surface->force_no_cache = FALSE;
681 surface->image_content_scale_x = 1.0;
682 surface->image_content_scale_y = 1.0;
683 surface->blur_stage = CAIRO_GL_BLUR_STAGE_NONE;
685 surface->clip_on_stencil_buffer = NULL;
687 surface->content_synced = TRUE;
688 surface->content_cleared = FALSE;
690 _cairo_gl_surface_embedded_operand_init (surface);
693 static cairo_surface_t *
694 _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
695 cairo_content_t content,
699 cairo_bool_t set_tex_param)
701 cairo_gl_surface_t *surface;
703 assert (width <= ctx->max_framebuffer_size && height <= ctx->max_framebuffer_size);
704 surface = calloc (1, sizeof (cairo_gl_surface_t));
705 if (unlikely (surface == NULL))
706 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
709 _cairo_gl_surface_init (&ctx->base, surface, content, width, height);
711 surface->supports_msaa = ctx->supports_msaa;
712 surface->num_samples = ctx->num_samples;
713 surface->supports_stencil = TRUE;
715 /* Create the texture used to store the surface's data. */
716 if (!set_tex_param) {
717 _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
718 ctx->dispatch.BindTexture (ctx->tex_target, surface->tex);
719 ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
720 ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
723 return &surface->base;
726 static cairo_surface_t *
727 _create_scratch_internal (cairo_gl_context_t *ctx,
728 cairo_content_t content,
731 cairo_bool_t for_caching)
733 cairo_gl_surface_t *surface;
737 ctx->dispatch.GenTextures (1, &tex);
738 surface = (cairo_gl_surface_t *)
739 _cairo_gl_surface_create_scratch_for_texture (ctx, content,
740 tex, width, height, FALSE);
741 if (unlikely (surface->base.status))
742 return &surface->base;
744 surface->owns_tex = TRUE;
746 /* adjust the texture size after setting our real extents */
755 case CAIRO_CONTENT_COLOR_ALPHA:
756 if (ctx->can_read_bgra)
761 case CAIRO_CONTENT_ALPHA:
762 /* When using GL_ALPHA, compositing doesn't work properly, but for
763 * caching surfaces, we are just uploading pixel data, so it isn't
770 case CAIRO_CONTENT_COLOR:
771 /* GL_RGB is almost what we want here -- sampling 1 alpha when
772 * texturing, using 1 as destination alpha factor in blending,
773 * etc. However, when filtering with GL_CLAMP_TO_BORDER, the
774 * alpha channel of the border color will also be clamped to
775 * 1, when we actually want the border color we explicitly
776 * specified. So, we have to store RGBA, and fill the alpha
777 * channel with 1 when blending.
779 if (ctx->can_read_bgra)
786 ctx->dispatch.TexImage2D (ctx->tex_target, 0, format,
788 format, GL_UNSIGNED_BYTE, NULL);
790 return &surface->base;
794 _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
795 cairo_content_t content,
799 return _create_scratch_internal (ctx, content, width, height, FALSE);
803 _cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx,
804 cairo_content_t content,
808 return _create_scratch_internal (ctx, content, width, height, TRUE);
811 static cairo_status_t
812 _cairo_gl_surface_clear (cairo_gl_surface_t *surface,
813 const cairo_color_t *color)
815 cairo_gl_context_t *ctx;
816 cairo_status_t status;
819 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
820 if (unlikely (status))
823 if (ctx->current_target == surface)
824 _cairo_gl_composite_flush (ctx);
826 /* FIXME: for glesv3 and glesv2 with ANGLE extension of multisample
827 supports, it is much more expensive to paint texture back to
828 multisample renderbuffer. Therefore, instead of clear
829 texture, we clear the renderbuffer.
830 In case, the next draw render target is texture, it will
831 blit renderbuffer back to texture */
832 if (ctx->gl_flavor != CAIRO_GL_FLAVOR_DESKTOP)
833 _cairo_gl_context_set_destination (ctx, surface, TRUE);
835 _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active);
836 if (surface->base.content & CAIRO_CONTENT_COLOR) {
837 r = color->red * color->alpha;
838 g = color->green * color->alpha;
839 b = color->blue * color->alpha;
843 if (surface->base.content & CAIRO_CONTENT_ALPHA) {
849 _disable_scissor_buffer (ctx);
850 if (ctx->states_cache.clear_red != r ||
851 ctx->states_cache.clear_green != g ||
852 ctx->states_cache.clear_blue != b ||
853 ctx->states_cache.clear_alpha != a) {
855 ctx->states_cache.clear_red = r;
856 ctx->states_cache.clear_green = g;
857 ctx->states_cache.clear_blue = b;
858 ctx->states_cache.clear_alpha = a;
860 ctx->dispatch.ClearColor (r, g, b, a);
863 /* optimize for mobile gl driver with deferred rendering */
864 if (surface->clip_on_stencil_buffer ||
865 ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
866 ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT);
868 if (surface->clip_on_stencil_buffer) {
869 _cairo_clip_destroy(surface->clip_on_stencil_buffer);
870 surface->clip_on_stencil_buffer = NULL;
872 ctx->dispatch.Clear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
876 surface->base.is_clear = TRUE;
878 surface->content_changed = TRUE;
879 surface->content_synced = FALSE;
880 surface->content_cleared = TRUE;
881 return _cairo_gl_context_release (ctx, status);
884 static cairo_surface_t *
885 _cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx,
886 cairo_content_t content,
890 cairo_gl_surface_t *surface;
891 cairo_int_status_t status;
893 surface = (cairo_gl_surface_t *)
894 _cairo_gl_surface_create_scratch (ctx, content, width, height);
895 if (unlikely (surface->base.status))
896 return &surface->base;
898 /* Cairo surfaces start out initialized to transparent (black) */
899 status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
900 if (unlikely (status)) {
901 cairo_surface_destroy (&surface->base);
902 return _cairo_surface_create_in_error (status);
905 return &surface->base;
909 cairo_gl_surface_create (cairo_device_t *abstract_device,
910 cairo_content_t content,
914 cairo_gl_context_t *ctx;
915 cairo_gl_surface_t *surface;
916 cairo_status_t status;
918 if (! CAIRO_CONTENT_VALID (content))
919 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
921 if (abstract_device == NULL)
922 return _cairo_image_surface_create_with_content (content, width, height);
924 if (abstract_device->status)
925 return _cairo_surface_create_in_error (abstract_device->status);
927 if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
928 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
930 status = _cairo_gl_context_acquire (abstract_device, &ctx);
931 if (unlikely (status))
932 return _cairo_surface_create_in_error (status);
934 surface = (cairo_gl_surface_t *)
935 _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
936 if (unlikely (surface->base.status)) {
937 status = _cairo_gl_context_release (ctx, surface->base.status);
938 cairo_surface_destroy (&surface->base);
939 return _cairo_surface_create_in_error (status);
942 status = _cairo_gl_context_release (ctx, status);
943 if (unlikely (status)) {
944 cairo_surface_destroy (&surface->base);
945 return _cairo_surface_create_in_error (status);
948 return &surface->base;
950 slim_hidden_def (cairo_gl_surface_create);
953 * cairo_gl_surface_create_for_texture:
954 * @content: type of content in the surface
955 * @tex: name of texture to use for storage of surface pixels
956 * @width: width of the surface, in pixels
957 * @height: height of the surface, in pixels
959 * Creates a GL surface for the specified texture with the specified
960 * content and dimensions. The texture must be kept around until the
961 * #cairo_surface_t is destroyed or cairo_surface_finish() is called
962 * on the surface. The initial contents of @tex will be used as the
963 * initial image contents; you must explicitly clear the buffer,
964 * using, for example, cairo_rectangle() and cairo_fill() if you want
965 * it cleared. The format of @tex should be compatible with @content,
966 * in the sense that it must have the color components required by
969 * Return value: a pointer to the newly created surface. The caller
970 * owns the surface and should call cairo_surface_destroy() when done
973 * This function always returns a valid pointer, but it will return a
974 * pointer to a "nil" surface if an error such as out of memory
975 * occurs. You can use cairo_surface_status() to check for this.
980 cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device,
981 cairo_content_t content,
986 cairo_gl_context_t *ctx;
987 cairo_gl_surface_t *surface;
988 cairo_status_t status;
990 if (! CAIRO_CONTENT_VALID (content))
991 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
993 if (abstract_device == NULL)
994 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
996 if (abstract_device->status)
997 return _cairo_surface_create_in_error (abstract_device->status);
999 if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
1000 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH));
1002 status = _cairo_gl_context_acquire (abstract_device, &ctx);
1003 if (unlikely (status))
1004 return _cairo_surface_create_in_error (status);
1006 surface = (cairo_gl_surface_t *)
1007 _cairo_gl_surface_create_scratch_for_texture (ctx, content,
1008 tex, width, height, TRUE);
1009 status = _cairo_gl_context_release (ctx, status);
1011 return &surface->base;
1013 slim_hidden_def (cairo_gl_surface_create_for_texture);
1017 cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
1021 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
1023 if (unlikely (abstract_surface->status))
1025 if (unlikely (abstract_surface->finished)) {
1026 _cairo_surface_set_error (abstract_surface,
1027 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1031 if (! _cairo_surface_is_gl (abstract_surface) ||
1032 _cairo_gl_surface_is_texture (surface)) {
1033 _cairo_surface_set_error (abstract_surface,
1034 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1038 if (surface->width != width || surface->height != height) {
1039 surface->size_changed = TRUE;
1040 surface->width = width;
1041 surface->height = height;
1046 cairo_gl_surface_get_width (cairo_surface_t *abstract_surface)
1048 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
1050 if (! _cairo_surface_is_gl (abstract_surface))
1053 return surface->width;
1057 cairo_gl_surface_get_height (cairo_surface_t *abstract_surface)
1059 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
1061 if (! _cairo_surface_is_gl (abstract_surface))
1064 return surface->height;
1068 cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
1070 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
1072 if (unlikely (abstract_surface->status))
1074 if (unlikely (abstract_surface->finished)) {
1075 _cairo_surface_set_error (abstract_surface,
1076 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1080 if (! _cairo_surface_is_gl (abstract_surface)) {
1081 _cairo_surface_set_error (abstract_surface,
1082 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1086 if (! _cairo_gl_surface_is_texture (surface)) {
1087 cairo_gl_context_t *ctx;
1088 cairo_status_t status;
1090 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1091 if (unlikely (status))
1094 /* And in any case we should flush any pending operations. */
1095 _cairo_gl_composite_flush (ctx);
1097 /* For swapping on EGL, at least, we need a valid context/target. */
1098 _cairo_gl_context_set_destination (ctx, surface, FALSE);
1100 ctx->swap_buffers (ctx, surface);
1102 /* according to khronos specs on egl 1.4, stencil buffer is
1103 * not preserved after eglSwapBuffers */
1104 if (surface->clip_on_stencil_buffer) {
1105 _cairo_clip_destroy (surface->clip_on_stencil_buffer);
1106 surface->clip_on_stencil_buffer = NULL;
1109 status = _cairo_gl_context_release (ctx, status);
1111 status = _cairo_surface_set_error (abstract_surface, status);
1116 _cairo_gl_surface_size_valid (cairo_gl_surface_t *surface,
1117 int width, int height)
1119 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1120 return width > 0 && height > 0 &&
1121 width <= ctx->max_framebuffer_size &&
1122 height <= ctx->max_framebuffer_size;
1125 static cairo_surface_t *
1126 _cairo_gl_surface_create_similar (void *abstract_surface,
1127 cairo_content_t content,
1131 cairo_surface_t *surface = abstract_surface;
1132 cairo_gl_context_t *ctx;
1133 cairo_status_t status;
1135 if (! _cairo_gl_surface_size_valid (abstract_surface, width, height))
1136 return _cairo_image_surface_create_with_content (content, width, height);
1138 status = _cairo_gl_context_acquire (surface->device, &ctx);
1139 if (unlikely (status))
1140 return _cairo_surface_create_in_error (status);
1142 surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
1144 status = _cairo_gl_context_release (ctx, status);
1145 if (unlikely (status)) {
1146 cairo_surface_destroy (surface);
1147 return _cairo_surface_create_in_error (status);
1153 static cairo_int_status_t
1154 _cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
1155 cairo_gl_context_t *ctx,
1157 int width, int height)
1159 cairo_gl_composite_t setup;
1160 cairo_status_t status;
1162 _cairo_gl_composite_flush (ctx);
1163 ctx->dispatch.ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
1165 status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE,
1167 if (unlikely (status))
1170 _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);
1172 status = _cairo_gl_composite_begin (&setup, &ctx);
1173 if (unlikely (status))
1176 _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height);
1178 status = _cairo_gl_context_release (ctx, status);
1181 _cairo_gl_composite_fini (&setup);
1183 _cairo_gl_composite_flush (ctx);
1184 ctx->dispatch.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1190 _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
1191 cairo_image_surface_t *src,
1192 int src_x, int src_y,
1193 int width, int height,
1194 int dst_x, int dst_y,
1195 cairo_bool_t force_flush)
1197 GLenum internal_format, format, type;
1198 cairo_bool_t has_alpha, needs_swap;
1199 cairo_image_surface_t *clone = NULL;
1200 cairo_gl_context_t *ctx;
1202 cairo_image_surface_t *rgba_clone = NULL;
1203 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
1205 status = _cairo_gl_context_acquire (dst->base.device, &ctx);
1206 if (unlikely (status))
1209 if (_cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES2 ||
1210 _cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES3) {
1211 pixman_format_code_t pixman_format;
1212 cairo_surface_pattern_t pattern;
1213 cairo_bool_t require_conversion = FALSE;
1214 pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
1216 if (src->base.content != CAIRO_CONTENT_ALPHA) {
1217 if (src->pixman_format != pixman_format)
1218 require_conversion = TRUE;
1220 else if (dst->base.content != CAIRO_CONTENT_ALPHA)
1221 require_conversion = TRUE;
1223 if (src->pixman_format == PIXMAN_a1) {
1224 pixman_format = PIXMAN_a8;
1225 require_conversion = TRUE;
1229 if (require_conversion) {
1230 rgba_clone = (cairo_image_surface_t *)
1231 _cairo_image_surface_create_with_pixman_format (NULL,
1236 if (unlikely (rgba_clone->base.status))
1239 _cairo_pattern_init_for_surface (&pattern, &src->base);
1240 status = _cairo_surface_paint (&rgba_clone->base,
1241 CAIRO_OPERATOR_SOURCE,
1242 &pattern.base, NULL);
1243 _cairo_pattern_fini (&pattern.base);
1244 if (unlikely (status))
1251 if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
1259 cairo_bool_t is_supported;
1261 clone = _cairo_image_surface_coerce (src);
1262 if (unlikely (status = clone->base.status))
1266 _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
1267 clone->pixman_format,
1273 assert (is_supported);
1274 assert (!needs_swap);
1278 cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;
1281 status = _cairo_gl_surface_flush (&dst->base, 0);
1282 if (unlikely (status))
1286 if (_cairo_gl_surface_is_texture (dst)) {
1287 void *data_start = src->data + src_y * src->stride + src_x * cpp;
1288 void *data_start_gles2 = NULL;
1291 * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the
1292 * image data ourselves in some cases. In particular, we must extract
1294 * a. we don't want full-length lines or
1295 * b. the row stride cannot be handled by GL itself using a 4 byte
1296 * alignment constraint
1298 if (src->stride < 0 ||
1299 (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
1300 (src->width * cpp < src->stride - 3 ||
1301 width != src->width)))
1303 ctx->dispatch.PixelStorei (GL_UNPACK_ALIGNMENT, 1);
1304 status = _cairo_gl_surface_extract_image_data (src, src_x, src_y,
1307 if (unlikely (status))
1310 data_start = data_start_gles2;
1314 ctx->dispatch.PixelStorei (GL_UNPACK_ALIGNMENT, 4);
1315 if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
1316 ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1317 ctx->dispatch.PixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
1320 /* we must resolve the renderbuffer to texture before we
1322 status = _cairo_gl_surface_resolve_multisampling (dst);
1323 if (unlikely (status)) {
1324 free (data_start_gles2);
1328 _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
1329 ctx->dispatch.BindTexture (ctx->tex_target, dst->tex);
1330 ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1331 ctx->dispatch.TexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1332 ctx->dispatch.TexSubImage2D (ctx->tex_target, 0,
1333 dst_x, dst_y, width, height,
1334 format, type, data_start);
1336 free (data_start_gles2);
1338 /* If we just treated some rgb-only data as rgba, then we have to
1339 * go back and fix up the alpha channel where we filled in this
1343 _cairo_gl_surface_fill_alpha_channel (dst, ctx,
1348 dst->content_synced = FALSE;
1350 cairo_surface_t *tmp;
1352 tmp = _cairo_gl_surface_create_scratch (ctx,
1355 if (unlikely (tmp->status))
1358 status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
1363 if (status == CAIRO_INT_STATUS_SUCCESS) {
1364 cairo_surface_pattern_t tmp_pattern;
1365 cairo_rectangle_int_t r;
1368 _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
1369 cairo_matrix_init_translate (&tmp_pattern.base.matrix,
1371 tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
1372 tmp_pattern.base.extend = CAIRO_EXTEND_NONE;
1378 clip = _cairo_clip_intersect_rectangle (NULL, &r);
1379 status = _cairo_surface_paint (&dst->base,
1380 CAIRO_OPERATOR_SOURCE,
1383 _cairo_clip_destroy (clip);
1384 _cairo_pattern_fini (&tmp_pattern.base);
1387 cairo_surface_destroy (tmp);
1391 status = _cairo_gl_context_release (ctx, status);
1394 cairo_surface_destroy (&clone->base);
1397 cairo_surface_destroy (&rgba_clone->base);
1399 if (status == CAIRO_INT_STATUS_SUCCESS) {
1400 dst->content_changed = TRUE;
1401 dst->content_synced = FALSE;
1407 static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface)
1409 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1410 return ctx->gl_flavor;
1413 static cairo_status_t
1414 _cairo_gl_surface_finish (void *abstract_surface)
1416 cairo_gl_surface_t *surface = abstract_surface;
1417 cairo_status_t status;
1418 cairo_gl_context_t *ctx;
1420 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1421 if (unlikely (status))
1424 if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE ||
1425 ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1426 ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface)
1427 _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
1428 if ((ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE ||
1429 ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1430 ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface)
1431 _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);
1432 if (ctx->current_target == surface)
1433 ctx->current_target = NULL;
1436 ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
1437 if (surface->depth_stencil)
1438 ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
1439 if (surface->owns_tex)
1440 ctx->dispatch.DeleteTextures (1, &surface->tex);
1442 if (surface->msaa_depth_stencil)
1443 ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
1444 if (surface->msaa_fb)
1445 ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
1446 if (surface->msaa_rb)
1447 ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb);
1449 if (surface->image_node) {
1450 surface->image_node->node.pinned = FALSE;
1451 _cairo_rtree_node_remove (&ctx->image_cache->rtree,
1452 &surface->image_node->node);
1455 if (surface->clip_on_stencil_buffer)
1456 _cairo_clip_destroy (surface->clip_on_stencil_buffer);
1458 return _cairo_gl_context_release (ctx, status);
1461 static cairo_image_surface_t *
1462 _cairo_gl_surface_map_to_image (void *abstract_surface,
1463 const cairo_rectangle_int_t *extents)
1465 cairo_gl_surface_t *surface = abstract_surface;
1466 cairo_image_surface_t *image;
1467 cairo_gl_context_t *ctx;
1468 GLenum format, type;
1469 pixman_format_code_t pixman_format;
1471 cairo_bool_t flipped, mesa_invert;
1472 cairo_status_t status;
1475 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1476 if (unlikely (status)) {
1477 return _cairo_image_surface_create_in_error (status);
1480 /* Want to use a switch statement here but the compiler gets whiny. */
1481 if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
1483 pixman_format = PIXMAN_a8r8g8b8;
1484 type = GL_UNSIGNED_INT_8_8_8_8_REV;
1486 } else if (surface->base.content == CAIRO_CONTENT_COLOR) {
1488 pixman_format = PIXMAN_x8r8g8b8;
1489 type = GL_UNSIGNED_INT_8_8_8_8_REV;
1491 } else if (surface->base.content == CAIRO_CONTENT_ALPHA) {
1493 pixman_format = PIXMAN_a8;
1494 type = GL_UNSIGNED_BYTE;
1501 if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2 ||
1502 _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3) {
1503 /* If only RGBA is supported, we must download data in a compatible
1504 * format. This means that pixman will convert the data on the CPU when
1505 * interacting with other image surfaces. For ALPHA, GLES2 does not
1506 * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
1507 * pixman image that is created has row_stride = row_width * bpp. */
1508 if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) {
1509 cairo_bool_t little_endian = _cairo_is_little_endian ();
1512 if (surface->base.content == CAIRO_CONTENT_COLOR) {
1513 pixman_format = little_endian ?
1514 PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8;
1516 pixman_format = little_endian ?
1517 PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
1521 /* GLES2 only supports GL_UNSIGNED_BYTE. */
1522 type = GL_UNSIGNED_BYTE;
1526 image = (cairo_image_surface_t*)
1527 _cairo_image_surface_create_with_pixman_format (NULL,
1532 if (unlikely (image->base.status)) {
1533 status = _cairo_gl_context_release (ctx, status);
1537 cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
1539 /* If the original surface has not been modified or
1540 * is clear, we can avoid downloading data. */
1541 if (surface->base.is_clear || surface->base.serial == 0) {
1542 status = _cairo_gl_context_release (ctx, status);
1546 /* This is inefficient, as we'd rather just read the thing without making
1547 * it the destination. But then, this is the fallback path, so let's not
1548 * fall back instead.
1550 _cairo_gl_composite_flush (ctx);
1552 _cairo_gl_context_set_destination (ctx, surface, FALSE);
1554 flipped = ! _cairo_gl_surface_is_texture (surface);
1555 mesa_invert = flipped && ctx->has_mesa_pack_invert;
1557 ctx->dispatch.PixelStorei (GL_PACK_ALIGNMENT, 4);
1558 if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
1559 ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1560 ctx->dispatch.PixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
1562 ctx->dispatch.PixelStorei (GL_PACK_INVERT_MESA, 1);
1566 y = surface->height - extents->y - extents->height;
1568 ctx->dispatch.ReadPixels (extents->x, y,
1569 extents->width, extents->height,
1570 format, type, image->data);
1572 ctx->dispatch.PixelStorei (GL_PACK_INVERT_MESA, 0);
1574 status = _cairo_gl_context_release (ctx, status);
1575 if (unlikely (status)) {
1576 cairo_surface_destroy (&image->base);
1577 return _cairo_image_surface_create_in_error (status);
1580 /* We must invert the image manualy if we lack GL_MESA_pack_invert */
1581 if (flipped && ! mesa_invert) {
1582 uint8_t stack[1024], *row = stack;
1583 uint8_t *top = image->data;
1584 uint8_t *bot = image->data + (image->height-1)*image->stride;
1586 if (image->stride > (int)sizeof(stack)) {
1587 row = malloc (image->stride);
1588 if (unlikely (row == NULL)) {
1589 cairo_surface_destroy (&image->base);
1590 return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1595 memcpy (row, top, image->stride);
1596 memcpy (top, bot, image->stride);
1597 memcpy (bot, row, image->stride);
1598 top += image->stride;
1599 bot -= image->stride;
1606 image->base.is_clear = FALSE;
1611 static cairo_surface_t *
1612 _cairo_gl_surface_source (void *abstract_surface,
1613 cairo_rectangle_int_t *extents)
1615 cairo_gl_surface_t *surface = abstract_surface;
1618 extents->x = extents->y = 0;
1619 extents->width = surface->width;
1620 extents->height = surface->height;
1623 return &surface->base;
1626 static cairo_status_t
1627 _cairo_gl_surface_acquire_source_image (void *abstract_surface,
1628 cairo_image_surface_t **image_out,
1631 cairo_gl_surface_t *surface = abstract_surface;
1632 cairo_rectangle_int_t extents;
1634 *image_extra = NULL;
1636 extents.x = extents.y = 0;
1637 extents.width = surface->width;
1638 extents.height = surface->height;
1640 *image_out = (cairo_image_surface_t *)
1641 _cairo_gl_surface_map_to_image (surface, &extents);
1642 return (*image_out)->base.status;
1646 _cairo_gl_surface_release_source_image (void *abstract_surface,
1647 cairo_image_surface_t *image,
1650 cairo_surface_destroy (&image->base);
1653 static cairo_int_status_t
1654 _cairo_gl_surface_unmap_image (void *abstract_surface,
1655 cairo_image_surface_t *image)
1657 cairo_int_status_t status;
1659 status = _cairo_gl_surface_draw_image (abstract_surface, image,
1661 image->width, image->height,
1662 image->base.device_transform_inverse.x0,
1663 image->base.device_transform_inverse.y0,
1666 cairo_surface_finish (&image->base);
1667 cairo_surface_destroy (&image->base);
1673 _cairo_gl_surface_get_extents (void *abstract_surface,
1674 cairo_rectangle_int_t *rectangle)
1676 cairo_gl_surface_t *surface = abstract_surface;
1680 rectangle->width = surface->width;
1681 rectangle->height = surface->height;
1686 static cairo_status_t
1687 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags)
1689 cairo_gl_surface_t *surface = abstract_surface;
1690 cairo_status_t status;
1691 cairo_gl_context_t *ctx;
1694 return CAIRO_STATUS_SUCCESS;
1696 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1697 if (unlikely (status))
1700 if (((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE ||
1701 ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1702 ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) ||
1703 ((ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE ||
1704 ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1705 ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) ||
1706 (ctx->current_target == surface))
1707 _cairo_gl_composite_flush (ctx);
1709 status = _cairo_gl_surface_resolve_multisampling (surface);
1711 if (ctx->msaa_type != CAIRO_GL_NONE_MULTISAMPLE_TO_TEXTURE)
1712 ctx->dispatch.Flush ();
1714 return _cairo_gl_context_release (ctx, status);
1718 _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
1720 cairo_gl_context_t *ctx;
1721 cairo_int_status_t status;
1723 if (surface->base.device == NULL)
1724 return CAIRO_INT_STATUS_SUCCESS;
1726 if (! surface->content_cleared) {
1727 /* GLES surfaces do not need explicit resolution. */
1728 if (! surface->msaa_active)
1729 return CAIRO_INT_STATUS_SUCCESS;
1730 else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
1731 !((cairo_gl_context_t *) surface->base.device)->has_angle_multisampling)
1732 return CAIRO_INT_STATUS_SUCCESS;
1733 else if (! _cairo_gl_surface_is_texture (surface))
1734 return CAIRO_INT_STATUS_SUCCESS;
1737 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1738 if (unlikely (status))
1741 _cairo_gl_context_set_destination (ctx, surface, FALSE);
1743 status = _cairo_gl_context_release (ctx, status);
1745 surface->content_cleared = FALSE;
1750 static const cairo_compositor_t *
1751 get_compositor (cairo_gl_surface_t *surface)
1753 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1754 return ctx->compositor;
1757 static cairo_int_status_t
1758 _cairo_gl_surface_paint (void *surface,
1759 cairo_operator_t op,
1760 const cairo_pattern_t *source,
1761 const cairo_clip_t *clip)
1763 cairo_int_status_t status;
1764 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
1765 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
1767 status = cairo_device_acquire (dst->base.device);
1768 if (unlikely (status))
1771 status = _cairo_surface_shadow_paint (surface, op, source, clip,
1773 ctx->source_scratch_in_use = FALSE;
1774 if (unlikely (status)) {
1775 cairo_device_release (dst->base.device);
1779 if (source->shadow.draw_shadow_only) {
1780 if (status == CAIRO_INT_STATUS_SUCCESS) {
1781 dst->content_changed = TRUE;
1782 dst->content_synced = FALSE;
1785 ctx->source_scratch_in_use = FALSE;
1786 cairo_device_release (dst->base.device);
1790 #if 0 // Currently glClear does not get flushed to GPU so do not use this fast path for the time being
1791 /* simplify the common case of clearing the surface */
1793 if (op == CAIRO_OPERATOR_CLEAR) {
1794 status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
1795 cairo_device_release (dst->base.device);
1798 else if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1799 (op == CAIRO_OPERATOR_SOURCE ||
1800 (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) {
1801 status = _cairo_gl_surface_clear (surface,
1802 &((cairo_solid_pattern_t *) source)->color);
1803 cairo_device_release (dst->base.device);
1809 status = _cairo_compositor_paint (get_compositor (surface), surface,
1811 if (status == CAIRO_INT_STATUS_SUCCESS) {
1812 dst->content_changed = TRUE;
1813 dst->content_synced = FALSE;
1816 ctx->source_scratch_in_use = FALSE;
1817 cairo_device_release (dst->base.device);
1821 static cairo_int_status_t
1822 _cairo_gl_surface_mask (void *surface,
1823 cairo_operator_t op,
1824 const cairo_pattern_t *source,
1825 const cairo_pattern_t *mask,
1826 const cairo_clip_t *clip)
1828 cairo_int_status_t status;
1829 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) surface;
1830 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
1832 status = cairo_device_acquire (dst->base.device);
1833 if (unlikely (status))
1836 status = _cairo_surface_shadow_mask (surface, op, source, mask, clip,
1838 ctx->source_scratch_in_use = FALSE;
1839 if (unlikely (status)) {
1840 cairo_device_release (dst->base.device);
1844 if (source->shadow.draw_shadow_only) {
1845 if (status == CAIRO_INT_STATUS_SUCCESS) {
1846 dst->content_changed = TRUE;
1847 dst->content_synced = FALSE;
1850 ctx->source_scratch_in_use = FALSE;
1851 cairo_device_release (dst->base.device);
1855 status = _cairo_compositor_mask (get_compositor (surface), surface,
1856 op, source, mask, clip);
1857 if (status == CAIRO_INT_STATUS_SUCCESS) {
1858 dst->content_changed = TRUE;
1859 dst->content_synced = FALSE;
1861 ctx->source_scratch_in_use = FALSE;
1862 cairo_device_release (dst->base.device);
1866 status = _cairo_compositor_mask (get_compositor (surface), surface,
1867 op, source, mask, clip);
1868 if (status == CAIRO_INT_STATUS_SUCCESS) {
1869 dst->content_changed = TRUE;
1870 dst->content_synced = FALSE;
1873 ctx->source_scratch_in_use = FALSE;
1874 cairo_device_release (dst->base.device);
1878 static cairo_int_status_t
1879 _cairo_gl_surface_stroke (void *surface,
1880 cairo_operator_t op,
1881 const cairo_pattern_t *source,
1882 const cairo_path_fixed_t *path,
1883 const cairo_stroke_style_t *style,
1884 const cairo_matrix_t *ctm,
1885 const cairo_matrix_t *ctm_inverse,
1887 cairo_antialias_t antialias,
1888 const cairo_clip_t *clip)
1890 cairo_int_status_t status;
1891 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
1892 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
1893 cairo_shadow_type_t shadow_type = source->shadow.type;
1895 status = cairo_device_acquire (dst->base.device);
1896 if (unlikely (status))
1899 if (shadow_type != CAIRO_SHADOW_INSET)
1900 status = _cairo_surface_shadow_stroke (surface, op, source, path,
1901 style, ctm, ctm_inverse,
1902 tolerance, antialias,
1903 clip, &source->shadow);
1905 ctx->source_scratch_in_use = FALSE;
1906 if (unlikely (status)) {
1907 cairo_device_release (dst->base.device);
1911 dst->content_changed = TRUE;
1912 dst->content_synced = FALSE;
1914 if (shadow_type == CAIRO_SHADOW_DROP &&
1915 source->shadow.draw_shadow_only) {
1916 ctx->source_scratch_in_use = FALSE;
1917 cairo_device_release (dst->base.device);
1921 ctx->source_scratch_in_use = FALSE;
1923 if (! source->shadow.draw_shadow_only)
1924 status = _cairo_compositor_stroke (get_compositor (surface), surface,
1925 op, source, path, style,
1926 ctm, ctm_inverse, tolerance,
1928 if (unlikely (status)) {
1929 ctx->source_scratch_in_use = FALSE;
1930 cairo_device_release (dst->base.device);
1934 ctx->source_scratch_in_use = FALSE;
1936 if (shadow_type == CAIRO_SHADOW_INSET)
1937 status = _cairo_surface_shadow_stroke (surface, op, source, path,
1938 style, ctm, ctm_inverse,
1939 tolerance, antialias,
1940 clip, &source->shadow);
1942 ctx->source_scratch_in_use = FALSE;
1943 cairo_device_release (dst->base.device);
1947 static cairo_int_status_t
1948 _cairo_gl_surface_fill (void *surface,
1949 cairo_operator_t op,
1950 const cairo_pattern_t *source,
1951 const cairo_path_fixed_t*path,
1952 cairo_fill_rule_t fill_rule,
1954 cairo_antialias_t antialias,
1955 const cairo_clip_t *clip)
1957 cairo_status_t status;
1958 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
1959 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
1960 cairo_shadow_type_t shadow_type = source->shadow.type;
1962 status = cairo_device_acquire (dst->base.device);
1963 if (unlikely (status))
1966 if (shadow_type != CAIRO_SHADOW_INSET)
1967 status = _cairo_surface_shadow_fill (surface, op, source, path,
1968 fill_rule, tolerance, antialias,
1969 clip, &source->shadow);
1971 ctx->source_scratch_in_use = FALSE;
1972 if (unlikely (status)) {
1973 cairo_device_release (dst->base.device);
1977 dst->content_changed = TRUE;
1978 dst->content_synced = FALSE;
1980 if (shadow_type == CAIRO_SHADOW_DROP &&
1981 source->shadow.draw_shadow_only) {
1982 ctx->source_scratch_in_use = FALSE;
1983 cairo_device_release (dst->base.device);
1987 ctx->source_scratch_in_use = FALSE;
1989 if (! source->shadow.draw_shadow_only) {
1990 if (! source->shadow.path_is_fill_with_spread ||
1991 source->shadow.type != CAIRO_SHADOW_INSET)
1992 status = _cairo_compositor_fill (get_compositor (surface),
1995 fill_rule, tolerance,
1999 status = _cairo_compositor_paint (get_compositor (surface),
2000 surface, op, source,
2004 if (unlikely (status)) {
2005 ctx->source_scratch_in_use = FALSE;
2006 cairo_device_release (dst->base.device);
2010 ctx->source_scratch_in_use = FALSE;
2012 if (shadow_type == CAIRO_SHADOW_INSET)
2013 status = _cairo_surface_shadow_fill (surface, op, source, path,
2014 fill_rule, tolerance, antialias,
2015 clip, &source->shadow);
2017 ctx->source_scratch_in_use = FALSE;
2018 cairo_device_release (dst->base.device);
2023 static cairo_int_status_t
2024 _cairo_gl_surface_glyphs (void *surface,
2025 cairo_operator_t op,
2026 const cairo_pattern_t *source,
2027 cairo_glyph_t *glyphs,
2029 cairo_scaled_font_t *font,
2030 const cairo_clip_t *clip)
2032 cairo_int_status_t status;
2033 cairo_gl_surface_t *dst = (cairo_gl_surface_t *)surface;
2034 cairo_gl_context_t *ctx = (cairo_gl_context_t *)dst->base.device;
2035 cairo_shadow_type_t shadow_type = source->shadow.type;
2037 status = cairo_device_acquire (dst->base.device);
2038 if (unlikely (status))
2041 if (shadow_type != CAIRO_SHADOW_INSET)
2042 status = _cairo_surface_shadow_glyphs (surface, op, source,
2045 clip, &source->shadow);
2047 ctx->source_scratch_in_use = FALSE;
2048 if (unlikely (status)) {
2049 cairo_device_release (dst->base.device);
2053 dst->content_changed = TRUE;
2054 dst->content_synced = FALSE;
2056 if (shadow_type == CAIRO_SHADOW_DROP &&
2057 source->shadow.draw_shadow_only) {
2058 ctx->source_scratch_in_use = FALSE;
2059 cairo_device_release (dst->base.device);
2063 ctx->source_scratch_in_use = FALSE;
2065 if (! source->shadow.draw_shadow_only)
2066 status = _cairo_compositor_glyphs (get_compositor (surface), surface,
2067 op, source, glyphs, num_glyphs,
2070 if (unlikely (status)) {
2071 ctx->source_scratch_in_use = FALSE;
2072 cairo_device_release (dst->base.device);
2076 ctx->source_scratch_in_use = FALSE;
2078 if (shadow_type == CAIRO_SHADOW_INSET)
2079 status = _cairo_surface_shadow_glyphs (surface, op, source,
2082 clip, &source->shadow);
2084 ctx->source_scratch_in_use = FALSE;
2085 cairo_device_release (dst->base.device);
2089 static const cairo_surface_backend_t _cairo_gl_surface_backend = {
2090 CAIRO_SURFACE_TYPE_GL,
2091 _cairo_gl_surface_finish,
2092 _cairo_default_context_create,
2094 _cairo_gl_surface_create_similar,
2095 NULL, /* similar image */
2096 _cairo_gl_surface_map_to_image,
2097 _cairo_gl_surface_unmap_image,
2099 _cairo_gl_surface_source,
2100 _cairo_gl_surface_acquire_source_image,
2101 _cairo_gl_surface_release_source_image,
2102 NULL, /* snapshot */
2104 NULL, /* copy_page */
2105 NULL, /* show_page */
2107 _cairo_gl_surface_get_extents,
2108 _cairo_image_surface_get_font_options,
2110 _cairo_gl_surface_flush,
2111 NULL, /* mark_dirty_rectangle */
2113 _cairo_gl_surface_paint,
2114 _cairo_gl_surface_mask,
2115 _cairo_gl_surface_stroke,
2116 _cairo_gl_surface_fill,
2117 NULL, /* fill/stroke */
2118 _cairo_gl_surface_glyphs,
2119 NULL, /* has_text_glyphs */
2120 NULL, /* show_text_glyphs */
2121 NULL, /* get_supported_mime_types */
2122 _cairo_gl_surface_shadow_surface,
2123 _cairo_gl_surface_glyph_shadow_surface,
2124 _cairo_gl_surface_shadow_mask_surface,
2125 _cairo_gl_surface_glyph_shadow_mask_surface,
2129 cairo_gl_surface_set_binding_texture (cairo_surface_t *abstract_surface,
2130 unsigned int texture)
2132 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
2134 if ((cairo_surface_get_type (&surface->base) != CAIRO_SURFACE_TYPE_GL) ||
2136 return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
2138 surface->bounded_tex = texture;
2139 surface->operand.texture.tex = texture;
2141 return CAIRO_STATUS_SUCCESS;