beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-gl-surface.c
blobcfccf4dfda53a08e2414ca7dd8038bceff558273
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.
34 * Contributor(s):
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>
41 #include "cairoint.h"
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"
52 static const cairo_surface_backend_t _cairo_gl_surface_backend;
54 static cairo_status_t
55 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags);
57 static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
59 return surface->backend == &_cairo_gl_surface_backend;
62 static cairo_bool_t
63 _cairo_gl_get_image_format_and_type_gles2 (pixman_format_code_t pixman_format,
64 GLenum *internal_format, GLenum *format,
65 GLenum *type, cairo_bool_t *has_alpha,
66 cairo_bool_t *needs_swap)
68 cairo_bool_t is_little_endian = _cairo_is_little_endian ();
70 *has_alpha = TRUE;
72 switch ((int) pixman_format) {
73 case PIXMAN_a8r8g8b8:
74 *internal_format = GL_BGRA;
75 *format = GL_BGRA;
76 *type = GL_UNSIGNED_BYTE;
77 *needs_swap = !is_little_endian;
78 return TRUE;
80 case PIXMAN_x8r8g8b8:
81 *internal_format = GL_BGRA;
82 *format = GL_BGRA;
83 *type = GL_UNSIGNED_BYTE;
84 *has_alpha = FALSE;
85 *needs_swap = !is_little_endian;
86 return TRUE;
88 case PIXMAN_a8b8g8r8:
89 *internal_format = GL_RGBA;
90 *format = GL_RGBA;
91 *type = GL_UNSIGNED_BYTE;
92 *needs_swap = !is_little_endian;
93 return TRUE;
95 case PIXMAN_x8b8g8r8:
96 *internal_format = GL_RGBA;
97 *format = GL_RGBA;
98 *type = GL_UNSIGNED_BYTE;
99 *has_alpha = FALSE;
100 *needs_swap = !is_little_endian;
101 return TRUE;
103 case PIXMAN_b8g8r8a8:
104 *internal_format = GL_BGRA;
105 *format = GL_BGRA;
106 *type = GL_UNSIGNED_BYTE;
107 *needs_swap = is_little_endian;
108 return TRUE;
110 case PIXMAN_b8g8r8x8:
111 *internal_format = GL_BGRA;
112 *format = GL_BGRA;
113 *type = GL_UNSIGNED_BYTE;
114 *has_alpha = FALSE;
115 *needs_swap = is_little_endian;
116 return TRUE;
118 case PIXMAN_r8g8b8:
119 *internal_format = GL_RGB;
120 *format = GL_RGB;
121 *type = GL_UNSIGNED_BYTE;
122 *needs_swap = is_little_endian;
123 return TRUE;
125 case PIXMAN_b8g8r8:
126 *internal_format = GL_RGB;
127 *format = GL_RGB;
128 *type = GL_UNSIGNED_BYTE;
129 *needs_swap = !is_little_endian;
130 return TRUE;
132 case PIXMAN_r5g6b5:
133 *internal_format = GL_RGB;
134 *format = GL_RGB;
135 *type = GL_UNSIGNED_SHORT_5_6_5;
136 *needs_swap = FALSE;
137 return TRUE;
139 case PIXMAN_b5g6r5:
140 *internal_format = GL_RGB;
141 *format = GL_RGB;
142 *type = GL_UNSIGNED_SHORT_5_6_5;
143 *needs_swap = TRUE;
144 return TRUE;
146 case PIXMAN_a1b5g5r5:
147 *internal_format = GL_RGBA;
148 *format = GL_RGBA;
149 *type = GL_UNSIGNED_SHORT_5_5_5_1;
150 *needs_swap = TRUE;
151 return TRUE;
153 case PIXMAN_x1b5g5r5:
154 *internal_format = GL_RGBA;
155 *format = GL_RGBA;
156 *type = GL_UNSIGNED_SHORT_5_5_5_1;
157 *has_alpha = FALSE;
158 *needs_swap = TRUE;
159 return TRUE;
161 case PIXMAN_a8:
162 *internal_format = GL_ALPHA;
163 *format = GL_ALPHA;
164 *type = GL_UNSIGNED_BYTE;
165 *needs_swap = FALSE;
166 return TRUE;
168 default:
169 return FALSE;
173 static cairo_bool_t
174 _cairo_gl_get_image_format_and_type_gl (pixman_format_code_t pixman_format,
175 GLenum *internal_format, GLenum *format,
176 GLenum *type, cairo_bool_t *has_alpha,
177 cairo_bool_t *needs_swap)
179 *has_alpha = TRUE;
180 *needs_swap = FALSE;
182 switch (pixman_format) {
183 case PIXMAN_a8r8g8b8:
184 *internal_format = GL_RGBA;
185 *format = GL_BGRA;
186 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
187 return TRUE;
188 case PIXMAN_x8r8g8b8:
189 *internal_format = GL_RGB;
190 *format = GL_BGRA;
191 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
192 *has_alpha = FALSE;
193 return TRUE;
194 case PIXMAN_a8b8g8r8:
195 *internal_format = GL_RGBA;
196 *format = GL_RGBA;
197 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
198 return TRUE;
199 case PIXMAN_x8b8g8r8:
200 *internal_format = GL_RGB;
201 *format = GL_RGBA;
202 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
203 *has_alpha = FALSE;
204 return TRUE;
205 case PIXMAN_b8g8r8a8:
206 *internal_format = GL_RGBA;
207 *format = GL_BGRA;
208 *type = GL_UNSIGNED_INT_8_8_8_8;
209 return TRUE;
210 case PIXMAN_b8g8r8x8:
211 *internal_format = GL_RGB;
212 *format = GL_BGRA;
213 *type = GL_UNSIGNED_INT_8_8_8_8;
214 *has_alpha = FALSE;
215 return TRUE;
216 case PIXMAN_r8g8b8:
217 *internal_format = GL_RGB;
218 *format = GL_RGB;
219 *type = GL_UNSIGNED_BYTE;
220 return TRUE;
221 case PIXMAN_b8g8r8:
222 *internal_format = GL_RGB;
223 *format = GL_BGR;
224 *type = GL_UNSIGNED_BYTE;
225 return TRUE;
226 case PIXMAN_r5g6b5:
227 *internal_format = GL_RGB;
228 *format = GL_RGB;
229 *type = GL_UNSIGNED_SHORT_5_6_5;
230 return TRUE;
231 case PIXMAN_b5g6r5:
232 *internal_format = GL_RGB;
233 *format = GL_RGB;
234 *type = GL_UNSIGNED_SHORT_5_6_5_REV;
235 return TRUE;
236 case PIXMAN_a1r5g5b5:
237 *internal_format = GL_RGBA;
238 *format = GL_BGRA;
239 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
240 return TRUE;
241 case PIXMAN_x1r5g5b5:
242 *internal_format = GL_RGB;
243 *format = GL_BGRA;
244 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
245 *has_alpha = FALSE;
246 return TRUE;
247 case PIXMAN_a1b5g5r5:
248 *internal_format = GL_RGBA;
249 *format = GL_RGBA;
250 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
251 return TRUE;
252 case PIXMAN_x1b5g5r5:
253 *internal_format = GL_RGB;
254 *format = GL_RGBA;
255 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
256 *has_alpha = FALSE;
257 return TRUE;
258 case PIXMAN_a8:
259 *internal_format = GL_ALPHA;
260 *format = GL_ALPHA;
261 *type = GL_UNSIGNED_BYTE;
262 return TRUE;
264 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2)
265 case PIXMAN_a8r8g8b8_sRGB:
266 #endif
267 case PIXMAN_a2b10g10r10:
268 case PIXMAN_x2b10g10r10:
269 case PIXMAN_a4r4g4b4:
270 case PIXMAN_x4r4g4b4:
271 case PIXMAN_a4b4g4r4:
272 case PIXMAN_x4b4g4r4:
273 case PIXMAN_r3g3b2:
274 case PIXMAN_b2g3r3:
275 case PIXMAN_a2r2g2b2:
276 case PIXMAN_a2b2g2r2:
277 case PIXMAN_c8:
278 case PIXMAN_x4a4:
279 /* case PIXMAN_x4c4: */
280 case PIXMAN_x4g4:
281 case PIXMAN_a4:
282 case PIXMAN_r1g2b1:
283 case PIXMAN_b1g2r1:
284 case PIXMAN_a1r1g1b1:
285 case PIXMAN_a1b1g1r1:
286 case PIXMAN_c4:
287 case PIXMAN_g4:
288 case PIXMAN_a1:
289 case PIXMAN_g1:
290 case PIXMAN_yuy2:
291 case PIXMAN_yv12:
292 case PIXMAN_x2r10g10b10:
293 case PIXMAN_a2r10g10b10:
294 case PIXMAN_r8g8b8x8:
295 case PIXMAN_r8g8b8a8:
296 case PIXMAN_x14r6g6b6:
297 default:
298 return FALSE;
303 * Extracts pixel data from an image surface.
305 static cairo_status_t
306 _cairo_gl_surface_extract_image_data (cairo_image_surface_t *image,
307 int x, int y,
308 int width, int height,
309 void **output)
311 int cpp = PIXMAN_FORMAT_BPP (image->pixman_format) / 8;
312 char *data = _cairo_malloc_ab (width * height, cpp);
313 char *dst = data;
314 unsigned char *src = image->data + y * image->stride + x * cpp;
315 int i;
317 if (unlikely (data == NULL))
318 return CAIRO_STATUS_NO_MEMORY;
320 for (i = 0; i < height; i++) {
321 memcpy (dst, src, width * cpp);
322 src += image->stride;
323 dst += width * cpp;
326 *output = data;
328 return CAIRO_STATUS_SUCCESS;
331 cairo_bool_t
332 _cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor,
333 pixman_format_code_t pixman_format,
334 GLenum *internal_format, GLenum *format,
335 GLenum *type, cairo_bool_t *has_alpha,
336 cairo_bool_t *needs_swap)
338 if (flavor == CAIRO_GL_FLAVOR_DESKTOP)
339 return _cairo_gl_get_image_format_and_type_gl (pixman_format,
340 internal_format, format,
341 type, has_alpha,
342 needs_swap);
343 else
344 return _cairo_gl_get_image_format_and_type_gles2 (pixman_format,
345 internal_format, format,
346 type, has_alpha,
347 needs_swap);
351 cairo_bool_t
352 _cairo_gl_operator_is_supported (cairo_operator_t op)
354 return op < CAIRO_OPERATOR_SATURATE;
357 static void
358 _cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
360 cairo_gl_operand_t *operand = &surface->operand;
361 cairo_surface_attributes_t *attributes = &operand->texture.attributes;
363 memset (operand, 0, sizeof (cairo_gl_operand_t));
365 operand->type = CAIRO_GL_OPERAND_TEXTURE;
366 operand->texture.surface = surface;
367 operand->texture.tex = surface->tex;
369 if (_cairo_gl_device_requires_power_of_two_textures (surface->base.device)) {
370 cairo_matrix_init_identity (&attributes->matrix);
371 } else {
372 cairo_matrix_init_scale (&attributes->matrix,
373 1.0 / surface->width,
374 1.0 / surface->height);
377 attributes->extend = CAIRO_EXTEND_NONE;
378 attributes->filter = CAIRO_FILTER_NEAREST;
381 void
382 _cairo_gl_surface_init (cairo_device_t *device,
383 cairo_gl_surface_t *surface,
384 cairo_content_t content,
385 int width, int height)
387 assert (width > 0 && height > 0);
389 _cairo_surface_init (&surface->base,
390 &_cairo_gl_surface_backend,
391 device,
392 content);
394 surface->width = width;
395 surface->height = height;
396 surface->needs_update = FALSE;
398 _cairo_gl_surface_embedded_operand_init (surface);
401 static cairo_bool_t
402 _cairo_gl_surface_size_valid_for_context (cairo_gl_context_t *ctx,
403 int width, int height)
405 return width > 0 && height > 0 &&
406 width <= ctx->max_framebuffer_size &&
407 height <= ctx->max_framebuffer_size;
410 static cairo_bool_t
411 _cairo_gl_surface_size_valid (cairo_gl_surface_t *surface,
412 int width, int height)
414 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
415 return _cairo_gl_surface_size_valid_for_context (ctx, width, height);
418 static cairo_surface_t *
419 _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
420 cairo_content_t content,
421 GLuint tex,
422 int width,
423 int height)
425 cairo_gl_surface_t *surface;
427 surface = calloc (1, sizeof (cairo_gl_surface_t));
428 if (unlikely (surface == NULL))
429 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
431 surface->tex = tex;
432 _cairo_gl_surface_init (&ctx->base, surface, content, width, height);
434 surface->supports_msaa = ctx->supports_msaa;
435 surface->supports_stencil = TRUE;
437 /* Create the texture used to store the surface's data. */
438 _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
439 glBindTexture (ctx->tex_target, surface->tex);
440 glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
441 glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
443 return &surface->base;
446 static cairo_surface_t *
447 _create_scratch_internal (cairo_gl_context_t *ctx,
448 cairo_content_t content,
449 int width,
450 int height,
451 cairo_bool_t for_caching)
453 cairo_gl_surface_t *surface;
454 GLenum format;
455 GLuint tex;
457 glGenTextures (1, &tex);
458 surface = (cairo_gl_surface_t *)
459 _cairo_gl_surface_create_scratch_for_texture (ctx, content,
460 tex, width, height);
461 if (unlikely (surface->base.status))
462 return &surface->base;
464 surface->owns_tex = TRUE;
466 /* adjust the texture size after setting our real extents */
467 if (width < 1)
468 width = 1;
469 if (height < 1)
470 height = 1;
472 switch (content) {
473 default:
474 ASSERT_NOT_REACHED;
475 case CAIRO_CONTENT_COLOR_ALPHA:
476 format = GL_RGBA;
477 break;
478 case CAIRO_CONTENT_ALPHA:
479 /* When using GL_ALPHA, compositing doesn't work properly, but for
480 * caching surfaces, we are just uploading pixel data, so it isn't
481 * an issue. */
482 if (for_caching)
483 format = GL_ALPHA;
484 else
485 format = GL_RGBA;
486 break;
487 case CAIRO_CONTENT_COLOR:
488 /* GL_RGB is almost what we want here -- sampling 1 alpha when
489 * texturing, using 1 as destination alpha factor in blending,
490 * etc. However, when filtering with GL_CLAMP_TO_BORDER, the
491 * alpha channel of the border color will also be clamped to
492 * 1, when we actually want the border color we explicitly
493 * specified. So, we have to store RGBA, and fill the alpha
494 * channel with 1 when blending.
496 format = GL_RGBA;
497 break;
500 glTexImage2D (ctx->tex_target, 0, format, width, height, 0,
501 format, GL_UNSIGNED_BYTE, NULL);
503 return &surface->base;
506 cairo_surface_t *
507 _cairo_gl_surface_create_scratch (cairo_gl_context_t *ctx,
508 cairo_content_t content,
509 int width,
510 int height)
512 return _create_scratch_internal (ctx, content, width, height, FALSE);
515 cairo_surface_t *
516 _cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx,
517 cairo_content_t content,
518 int width,
519 int height)
521 return _create_scratch_internal (ctx, content, width, height, TRUE);
524 static cairo_status_t
525 _cairo_gl_surface_clear (cairo_gl_surface_t *surface,
526 const cairo_color_t *color)
528 cairo_gl_context_t *ctx;
529 cairo_status_t status;
530 double r, g, b, a;
532 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
533 if (unlikely (status))
534 return status;
536 _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active);
537 if (surface->base.content & CAIRO_CONTENT_COLOR) {
538 r = color->red * color->alpha;
539 g = color->green * color->alpha;
540 b = color->blue * color->alpha;
541 } else {
542 r = g = b = 0;
544 if (surface->base.content & CAIRO_CONTENT_ALPHA) {
545 a = color->alpha;
546 } else {
547 a = 1.0;
550 glDisable (GL_SCISSOR_TEST);
551 glClearColor (r, g, b, a);
552 glClear (GL_COLOR_BUFFER_BIT);
554 if (a == 0)
555 surface->base.is_clear = TRUE;
557 return _cairo_gl_context_release (ctx, status);
560 static cairo_surface_t *
561 _cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx,
562 cairo_content_t content,
563 int width,
564 int height)
566 cairo_gl_surface_t *surface;
567 cairo_int_status_t status;
569 surface = (cairo_gl_surface_t *)
570 _cairo_gl_surface_create_scratch (ctx, content, width, height);
571 if (unlikely (surface->base.status))
572 return &surface->base;
574 /* Cairo surfaces start out initialized to transparent (black) */
575 status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
576 if (unlikely (status)) {
577 cairo_surface_destroy (&surface->base);
578 return _cairo_surface_create_in_error (status);
581 return &surface->base;
584 cairo_surface_t *
585 cairo_gl_surface_create (cairo_device_t *abstract_device,
586 cairo_content_t content,
587 int width,
588 int height)
590 cairo_gl_context_t *ctx;
591 cairo_gl_surface_t *surface;
592 cairo_status_t status;
594 if (! CAIRO_CONTENT_VALID (content))
595 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
597 if (abstract_device == NULL)
598 return _cairo_image_surface_create_with_content (content, width, height);
600 if (abstract_device->status)
601 return _cairo_surface_create_in_error (abstract_device->status);
603 if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
604 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
606 status = _cairo_gl_context_acquire (abstract_device, &ctx);
607 if (unlikely (status))
608 return _cairo_surface_create_in_error (status);
610 if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
611 status = _cairo_gl_context_release (ctx, status);
612 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
615 surface = (cairo_gl_surface_t *)
616 _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
617 if (unlikely (surface->base.status)) {
618 status = _cairo_gl_context_release (ctx, surface->base.status);
619 cairo_surface_destroy (&surface->base);
620 return _cairo_surface_create_in_error (status);
623 status = _cairo_gl_context_release (ctx, status);
624 if (unlikely (status)) {
625 cairo_surface_destroy (&surface->base);
626 return _cairo_surface_create_in_error (status);
629 return &surface->base;
631 slim_hidden_def (cairo_gl_surface_create);
634 * cairo_gl_surface_create_for_texture:
635 * @content: type of content in the surface
636 * @tex: name of texture to use for storage of surface pixels
637 * @width: width of the surface, in pixels
638 * @height: height of the surface, in pixels
640 * Creates a GL surface for the specified texture with the specified
641 * content and dimensions. The texture must be kept around until the
642 * #cairo_surface_t is destroyed or cairo_surface_finish() is called
643 * on the surface. The initial contents of @tex will be used as the
644 * initial image contents; you must explicitly clear the buffer,
645 * using, for example, cairo_rectangle() and cairo_fill() if you want
646 * it cleared. The format of @tex should be compatible with @content,
647 * in the sense that it must have the color components required by
648 * @content.
650 * Return value: a pointer to the newly created surface. The caller
651 * owns the surface and should call cairo_surface_destroy() when done
652 * with it.
654 * This function always returns a valid pointer, but it will return a
655 * pointer to a "nil" surface if an error such as out of memory
656 * occurs. You can use cairo_surface_status() to check for this.
658 * Since: TBD
660 cairo_surface_t *
661 cairo_gl_surface_create_for_texture (cairo_device_t *abstract_device,
662 cairo_content_t content,
663 unsigned int tex,
664 int width,
665 int height)
667 cairo_gl_context_t *ctx;
668 cairo_gl_surface_t *surface;
669 cairo_status_t status;
671 if (! CAIRO_CONTENT_VALID (content))
672 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
674 if (abstract_device == NULL)
675 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
677 if (abstract_device->status)
678 return _cairo_surface_create_in_error (abstract_device->status);
680 if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
681 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH));
683 status = _cairo_gl_context_acquire (abstract_device, &ctx);
684 if (unlikely (status))
685 return _cairo_surface_create_in_error (status);
687 if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
688 status = _cairo_gl_context_release (ctx, status);
689 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
692 surface = (cairo_gl_surface_t *)
693 _cairo_gl_surface_create_scratch_for_texture (ctx, content,
694 tex, width, height);
695 status = _cairo_gl_context_release (ctx, status);
697 return &surface->base;
699 slim_hidden_def (cairo_gl_surface_create_for_texture);
702 void
703 cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
704 int width,
705 int height)
707 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
709 if (unlikely (abstract_surface->status))
710 return;
711 if (unlikely (abstract_surface->finished)) {
712 _cairo_surface_set_error (abstract_surface,
713 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
714 return;
717 if (! _cairo_surface_is_gl (abstract_surface) ||
718 _cairo_gl_surface_is_texture (surface)) {
719 _cairo_surface_set_error (abstract_surface,
720 _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
721 return;
724 if (surface->width != width || surface->height != height) {
725 surface->needs_update = TRUE;
726 surface->width = width;
727 surface->height = height;
732 cairo_gl_surface_get_width (cairo_surface_t *abstract_surface)
734 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
736 if (! _cairo_surface_is_gl (abstract_surface))
737 return 0;
739 return surface->width;
743 cairo_gl_surface_get_height (cairo_surface_t *abstract_surface)
745 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
747 if (! _cairo_surface_is_gl (abstract_surface))
748 return 0;
750 return surface->height;
753 void
754 cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
756 cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
758 if (unlikely (abstract_surface->status))
759 return;
760 if (unlikely (abstract_surface->finished)) {
761 _cairo_surface_set_error (abstract_surface,
762 _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
763 return;
766 if (! _cairo_surface_is_gl (abstract_surface)) {
767 _cairo_surface_set_error (abstract_surface,
768 CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
769 return;
772 if (! _cairo_gl_surface_is_texture (surface)) {
773 cairo_gl_context_t *ctx;
774 cairo_status_t status;
776 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
777 if (unlikely (status))
778 return;
780 /* For swapping on EGL, at least, we need a valid context/target. */
781 _cairo_gl_context_set_destination (ctx, surface, FALSE);
782 /* And in any case we should flush any pending operations. */
783 _cairo_gl_composite_flush (ctx);
785 ctx->swap_buffers (ctx, surface);
787 status = _cairo_gl_context_release (ctx, status);
788 if (status)
789 status = _cairo_surface_set_error (abstract_surface, status);
793 static cairo_surface_t *
794 _cairo_gl_surface_create_similar (void *abstract_surface,
795 cairo_content_t content,
796 int width,
797 int height)
799 cairo_surface_t *surface = abstract_surface;
800 cairo_gl_context_t *ctx;
801 cairo_status_t status;
803 if (! _cairo_gl_surface_size_valid (abstract_surface, width, height))
804 return _cairo_image_surface_create_with_content (content, width, height);
806 status = _cairo_gl_context_acquire (surface->device, &ctx);
807 if (unlikely (status))
808 return _cairo_surface_create_in_error (status);
810 surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
812 status = _cairo_gl_context_release (ctx, status);
813 if (unlikely (status)) {
814 cairo_surface_destroy (surface);
815 return _cairo_surface_create_in_error (status);
818 return surface;
821 static cairo_int_status_t
822 _cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
823 cairo_gl_context_t *ctx,
824 int x, int y,
825 int width, int height)
827 cairo_gl_composite_t setup;
828 cairo_status_t status;
830 _cairo_gl_composite_flush (ctx);
831 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
833 status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE,
834 dst, FALSE);
835 if (unlikely (status))
836 goto CLEANUP;
838 _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);
840 status = _cairo_gl_composite_begin (&setup, &ctx);
841 if (unlikely (status))
842 goto CLEANUP;
844 _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height);
846 status = _cairo_gl_context_release (ctx, status);
848 CLEANUP:
849 _cairo_gl_composite_fini (&setup);
851 _cairo_gl_composite_flush (ctx);
852 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
854 return status;
857 cairo_status_t
858 _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
859 cairo_image_surface_t *src,
860 int src_x, int src_y,
861 int width, int height,
862 int dst_x, int dst_y,
863 cairo_bool_t force_flush)
865 GLenum internal_format, format, type;
866 cairo_bool_t has_alpha, needs_swap;
867 cairo_image_surface_t *clone = NULL;
868 cairo_gl_context_t *ctx;
869 int cpp;
870 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
872 status = _cairo_gl_context_acquire (dst->base.device, &ctx);
873 if (unlikely (status))
874 return status;
876 if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
877 src->pixman_format,
878 &internal_format,
879 &format,
880 &type,
881 &has_alpha,
882 &needs_swap))
884 cairo_bool_t is_supported;
886 clone = _cairo_image_surface_coerce (src);
887 if (unlikely (status = clone->base.status))
888 goto FAIL;
890 is_supported =
891 _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
892 clone->pixman_format,
893 &internal_format,
894 &format,
895 &type,
896 &has_alpha,
897 &needs_swap);
898 assert (is_supported);
899 assert (!needs_swap);
900 src = clone;
903 cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;
905 if (force_flush) {
906 status = _cairo_gl_surface_flush (&dst->base, 0);
907 if (unlikely (status))
908 goto FAIL;
911 if (_cairo_gl_surface_is_texture (dst)) {
912 void *data_start = src->data + src_y * src->stride + src_x * cpp;
913 void *data_start_gles2 = NULL;
916 * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the
917 * image data ourselves in some cases. In particular, we must extract
918 * the pixels if:
919 * a. we don't want full-length lines or
920 * b. the row stride cannot be handled by GL itself using a 4 byte
921 * alignment constraint
923 if (src->stride < 0 ||
924 (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
925 (src->width * cpp < src->stride - 3 ||
926 width != src->width)))
928 glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
929 status = _cairo_gl_surface_extract_image_data (src, src_x, src_y,
930 width, height,
931 &data_start_gles2);
932 if (unlikely (status))
933 goto FAIL;
935 data_start = data_start_gles2;
937 else
939 glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
940 if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
941 glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
944 _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
945 glBindTexture (ctx->tex_target, dst->tex);
946 glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
947 glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
948 glTexSubImage2D (ctx->tex_target, 0,
949 dst_x, dst_y, width, height,
950 format, type, data_start);
952 free (data_start_gles2);
954 /* If we just treated some rgb-only data as rgba, then we have to
955 * go back and fix up the alpha channel where we filled in this
956 * texture data.
958 if (!has_alpha) {
959 _cairo_gl_surface_fill_alpha_channel (dst, ctx,
960 dst_x, dst_y,
961 width, height);
963 } else {
964 cairo_surface_t *tmp;
966 tmp = _cairo_gl_surface_create_scratch (ctx,
967 dst->base.content,
968 width, height);
969 if (unlikely (tmp->status))
970 goto FAIL;
972 status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
973 src,
974 src_x, src_y,
975 width, height,
976 0, 0, force_flush);
977 if (status == CAIRO_INT_STATUS_SUCCESS) {
978 cairo_surface_pattern_t tmp_pattern;
979 cairo_rectangle_int_t r;
980 cairo_clip_t *clip;
982 _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
983 cairo_matrix_init_translate (&tmp_pattern.base.matrix,
984 -dst_x, -dst_y);
985 tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
986 tmp_pattern.base.extend = CAIRO_EXTEND_NONE;
988 r.x = dst_x;
989 r.y = dst_y;
990 r.width = width;
991 r.height = height;
992 clip = _cairo_clip_intersect_rectangle (NULL, &r);
993 status = _cairo_surface_paint (&dst->base,
994 CAIRO_OPERATOR_SOURCE,
995 &tmp_pattern.base,
996 clip);
997 _cairo_clip_destroy (clip);
998 _cairo_pattern_fini (&tmp_pattern.base);
1001 cairo_surface_destroy (tmp);
1004 FAIL:
1005 status = _cairo_gl_context_release (ctx, status);
1007 if (clone)
1008 cairo_surface_destroy (&clone->base);
1010 return status;
1013 static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface)
1015 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1016 return ctx->gl_flavor;
1019 static cairo_status_t
1020 _cairo_gl_surface_finish (void *abstract_surface)
1022 cairo_gl_surface_t *surface = abstract_surface;
1023 cairo_status_t status;
1024 cairo_gl_context_t *ctx;
1026 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1027 if (unlikely (status))
1028 return status;
1030 if (ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE &&
1031 ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface)
1032 _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
1033 if (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE &&
1034 ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface)
1035 _cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);
1036 if (ctx->current_target == surface)
1037 ctx->current_target = NULL;
1039 if (surface->fb)
1040 ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
1041 if (surface->depth_stencil)
1042 ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
1043 if (surface->owns_tex)
1044 glDeleteTextures (1, &surface->tex);
1046 if (surface->msaa_depth_stencil)
1047 ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
1049 #if CAIRO_HAS_GL_SURFACE
1050 if (surface->msaa_fb)
1051 ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
1052 if (surface->msaa_rb)
1053 ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb);
1054 #endif
1056 _cairo_clip_destroy (surface->clip_on_stencil_buffer);
1058 return _cairo_gl_context_release (ctx, status);
1061 static cairo_image_surface_t *
1062 _cairo_gl_surface_map_to_image (void *abstract_surface,
1063 const cairo_rectangle_int_t *extents)
1065 cairo_gl_surface_t *surface = abstract_surface;
1066 cairo_image_surface_t *image;
1067 cairo_gl_context_t *ctx;
1068 GLenum format, type;
1069 pixman_format_code_t pixman_format;
1070 unsigned int cpp;
1071 cairo_bool_t flipped, mesa_invert;
1072 cairo_status_t status;
1073 int y;
1075 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1076 if (unlikely (status)) {
1077 return _cairo_image_surface_create_in_error (status);
1080 /* Want to use a switch statement here but the compiler gets whiny. */
1081 if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
1082 format = GL_BGRA;
1083 pixman_format = PIXMAN_a8r8g8b8;
1084 type = GL_UNSIGNED_INT_8_8_8_8_REV;
1085 cpp = 4;
1086 } else if (surface->base.content == CAIRO_CONTENT_COLOR) {
1087 format = GL_BGRA;
1088 pixman_format = PIXMAN_x8r8g8b8;
1089 type = GL_UNSIGNED_INT_8_8_8_8_REV;
1090 cpp = 4;
1091 } else if (surface->base.content == CAIRO_CONTENT_ALPHA) {
1092 format = GL_ALPHA;
1093 pixman_format = PIXMAN_a8;
1094 type = GL_UNSIGNED_BYTE;
1095 cpp = 1;
1096 } else {
1097 ASSERT_NOT_REACHED;
1098 return NULL;
1101 if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES) {
1102 /* If only RGBA is supported, we must download data in a compatible
1103 * format. This means that pixman will convert the data on the CPU when
1104 * interacting with other image surfaces. For ALPHA, GLES2 does not
1105 * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
1106 * pixman image that is created has row_stride = row_width * bpp. */
1107 if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) {
1108 cairo_bool_t little_endian = _cairo_is_little_endian ();
1109 format = GL_RGBA;
1111 if (surface->base.content == CAIRO_CONTENT_COLOR) {
1112 pixman_format = little_endian ?
1113 PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8;
1114 } else {
1115 pixman_format = little_endian ?
1116 PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
1120 /* GLES2 only supports GL_UNSIGNED_BYTE. */
1121 type = GL_UNSIGNED_BYTE;
1122 cpp = 4;
1125 image = (cairo_image_surface_t*)
1126 _cairo_image_surface_create_with_pixman_format (NULL,
1127 pixman_format,
1128 extents->width,
1129 extents->height,
1130 -1);
1131 if (unlikely (image->base.status)) {
1132 status = _cairo_gl_context_release (ctx, status);
1133 return image;
1136 cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
1138 /* If the original surface has not been modified or
1139 * is clear, we can avoid downloading data. */
1140 if (surface->base.is_clear || surface->base.serial == 0) {
1141 status = _cairo_gl_context_release (ctx, status);
1142 return image;
1145 /* This is inefficient, as we'd rather just read the thing without making
1146 * it the destination. But then, this is the fallback path, so let's not
1147 * fall back instead.
1149 _cairo_gl_composite_flush (ctx);
1150 _cairo_gl_context_set_destination (ctx, surface, FALSE);
1152 flipped = ! _cairo_gl_surface_is_texture (surface);
1153 mesa_invert = flipped && ctx->has_mesa_pack_invert;
1155 glPixelStorei (GL_PACK_ALIGNMENT, 4);
1156 if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
1157 glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
1158 if (mesa_invert)
1159 glPixelStorei (GL_PACK_INVERT_MESA, 1);
1161 y = extents->y;
1162 if (flipped)
1163 y = surface->height - extents->y - extents->height;
1165 glReadPixels (extents->x, y,
1166 extents->width, extents->height,
1167 format, type, image->data);
1168 if (mesa_invert)
1169 glPixelStorei (GL_PACK_INVERT_MESA, 0);
1171 status = _cairo_gl_context_release (ctx, status);
1172 if (unlikely (status)) {
1173 cairo_surface_destroy (&image->base);
1174 return _cairo_image_surface_create_in_error (status);
1177 /* We must invert the image manualy if we lack GL_MESA_pack_invert */
1178 if (flipped && ! mesa_invert) {
1179 uint8_t stack[1024], *row = stack;
1180 uint8_t *top = image->data;
1181 uint8_t *bot = image->data + (image->height-1)*image->stride;
1183 if (image->stride > (int)sizeof(stack)) {
1184 row = malloc (image->stride);
1185 if (unlikely (row == NULL)) {
1186 cairo_surface_destroy (&image->base);
1187 return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1191 while (top < bot) {
1192 memcpy (row, top, image->stride);
1193 memcpy (top, bot, image->stride);
1194 memcpy (bot, row, image->stride);
1195 top += image->stride;
1196 bot -= image->stride;
1199 if (row != stack)
1200 free(row);
1203 image->base.is_clear = FALSE;
1204 return image;
1207 static cairo_surface_t *
1208 _cairo_gl_surface_source (void *abstract_surface,
1209 cairo_rectangle_int_t *extents)
1211 cairo_gl_surface_t *surface = abstract_surface;
1213 if (extents) {
1214 extents->x = extents->y = 0;
1215 extents->width = surface->width;
1216 extents->height = surface->height;
1219 return &surface->base;
1222 static cairo_status_t
1223 _cairo_gl_surface_acquire_source_image (void *abstract_surface,
1224 cairo_image_surface_t **image_out,
1225 void **image_extra)
1227 cairo_gl_surface_t *surface = abstract_surface;
1228 cairo_rectangle_int_t extents;
1230 *image_extra = NULL;
1232 extents.x = extents.y = 0;
1233 extents.width = surface->width;
1234 extents.height = surface->height;
1236 *image_out = (cairo_image_surface_t *)
1237 _cairo_gl_surface_map_to_image (surface, &extents);
1238 return (*image_out)->base.status;
1241 static void
1242 _cairo_gl_surface_release_source_image (void *abstract_surface,
1243 cairo_image_surface_t *image,
1244 void *image_extra)
1246 cairo_surface_destroy (&image->base);
1249 static cairo_int_status_t
1250 _cairo_gl_surface_unmap_image (void *abstract_surface,
1251 cairo_image_surface_t *image)
1253 cairo_int_status_t status;
1255 status = _cairo_gl_surface_draw_image (abstract_surface, image,
1256 0, 0,
1257 image->width, image->height,
1258 image->base.device_transform_inverse.x0,
1259 image->base.device_transform_inverse.y0,
1260 TRUE);
1262 cairo_surface_finish (&image->base);
1263 cairo_surface_destroy (&image->base);
1265 return status;
1268 static cairo_bool_t
1269 _cairo_gl_surface_get_extents (void *abstract_surface,
1270 cairo_rectangle_int_t *rectangle)
1272 cairo_gl_surface_t *surface = abstract_surface;
1274 rectangle->x = 0;
1275 rectangle->y = 0;
1276 rectangle->width = surface->width;
1277 rectangle->height = surface->height;
1279 return TRUE;
1282 static cairo_status_t
1283 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags)
1285 cairo_gl_surface_t *surface = abstract_surface;
1286 cairo_status_t status;
1287 cairo_gl_context_t *ctx;
1289 if (flags)
1290 return CAIRO_STATUS_SUCCESS;
1292 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1293 if (unlikely (status))
1294 return status;
1296 if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE &&
1297 ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) ||
1298 (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE &&
1299 ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) ||
1300 (ctx->current_target == surface))
1301 _cairo_gl_composite_flush (ctx);
1303 status = _cairo_gl_surface_resolve_multisampling (surface);
1305 return _cairo_gl_context_release (ctx, status);
1308 cairo_int_status_t
1309 _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
1311 cairo_gl_context_t *ctx;
1312 cairo_int_status_t status;
1314 if (! surface->msaa_active)
1315 return CAIRO_INT_STATUS_SUCCESS;
1317 if (surface->base.device == NULL)
1318 return CAIRO_INT_STATUS_SUCCESS;
1320 /* GLES surfaces do not need explicit resolution. */
1321 if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES)
1322 return CAIRO_INT_STATUS_SUCCESS;
1324 if (! _cairo_gl_surface_is_texture (surface))
1325 return CAIRO_INT_STATUS_SUCCESS;
1327 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1328 if (unlikely (status))
1329 return status;
1331 ctx->current_target = surface;
1333 #if CAIRO_HAS_GL_SURFACE
1334 _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
1335 #endif
1337 status = _cairo_gl_context_release (ctx, status);
1338 return status;
1341 static const cairo_compositor_t *
1342 get_compositor (cairo_gl_surface_t *surface)
1344 cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1345 return ctx->compositor;
1348 static cairo_int_status_t
1349 _cairo_gl_surface_paint (void *surface,
1350 cairo_operator_t op,
1351 const cairo_pattern_t *source,
1352 const cairo_clip_t *clip)
1354 /* simplify the common case of clearing the surface */
1355 if (clip == NULL) {
1356 if (op == CAIRO_OPERATOR_CLEAR)
1357 return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
1358 else if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1359 (op == CAIRO_OPERATOR_SOURCE ||
1360 (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) {
1361 return _cairo_gl_surface_clear (surface,
1362 &((cairo_solid_pattern_t *) source)->color);
1366 return _cairo_compositor_paint (get_compositor (surface), surface,
1367 op, source, clip);
1370 static cairo_int_status_t
1371 _cairo_gl_surface_mask (void *surface,
1372 cairo_operator_t op,
1373 const cairo_pattern_t *source,
1374 const cairo_pattern_t *mask,
1375 const cairo_clip_t *clip)
1377 return _cairo_compositor_mask (get_compositor (surface), surface,
1378 op, source, mask, clip);
1381 static cairo_int_status_t
1382 _cairo_gl_surface_stroke (void *surface,
1383 cairo_operator_t op,
1384 const cairo_pattern_t *source,
1385 const cairo_path_fixed_t *path,
1386 const cairo_stroke_style_t *style,
1387 const cairo_matrix_t *ctm,
1388 const cairo_matrix_t *ctm_inverse,
1389 double tolerance,
1390 cairo_antialias_t antialias,
1391 const cairo_clip_t *clip)
1393 return _cairo_compositor_stroke (get_compositor (surface), surface,
1394 op, source, path, style,
1395 ctm, ctm_inverse, tolerance, antialias,
1396 clip);
1399 static cairo_int_status_t
1400 _cairo_gl_surface_fill (void *surface,
1401 cairo_operator_t op,
1402 const cairo_pattern_t *source,
1403 const cairo_path_fixed_t*path,
1404 cairo_fill_rule_t fill_rule,
1405 double tolerance,
1406 cairo_antialias_t antialias,
1407 const cairo_clip_t *clip)
1409 return _cairo_compositor_fill (get_compositor (surface), surface,
1410 op, source, path,
1411 fill_rule, tolerance, antialias,
1412 clip);
1415 static cairo_int_status_t
1416 _cairo_gl_surface_glyphs (void *surface,
1417 cairo_operator_t op,
1418 const cairo_pattern_t *source,
1419 cairo_glyph_t *glyphs,
1420 int num_glyphs,
1421 cairo_scaled_font_t *font,
1422 const cairo_clip_t *clip)
1424 return _cairo_compositor_glyphs (get_compositor (surface), surface,
1425 op, source, glyphs, num_glyphs, font,
1426 clip);
1429 static const cairo_surface_backend_t _cairo_gl_surface_backend = {
1430 CAIRO_SURFACE_TYPE_GL,
1431 _cairo_gl_surface_finish,
1432 _cairo_default_context_create,
1434 _cairo_gl_surface_create_similar,
1435 NULL, /* similar image */
1436 _cairo_gl_surface_map_to_image,
1437 _cairo_gl_surface_unmap_image,
1439 _cairo_gl_surface_source,
1440 _cairo_gl_surface_acquire_source_image,
1441 _cairo_gl_surface_release_source_image,
1442 NULL, /* snapshot */
1444 NULL, /* copy_page */
1445 NULL, /* show_page */
1447 _cairo_gl_surface_get_extents,
1448 _cairo_image_surface_get_font_options,
1450 _cairo_gl_surface_flush,
1451 NULL, /* mark_dirty_rectangle */
1453 _cairo_gl_surface_paint,
1454 _cairo_gl_surface_mask,
1455 _cairo_gl_surface_stroke,
1456 _cairo_gl_surface_fill,
1457 NULL, /* fill/stroke */
1458 _cairo_gl_surface_glyphs,