1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Eric Anholt
4  * Copyright © 2009 Chris Wilson
5  * Copyright © 2005,2010 Red Hat, Inc
6  *
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.
14  *
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
20  *
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/
25  *
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.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is Red Hat, Inc.
33  *
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>
39  */
40 
41 #include "cairoint.h"
42 
43 #include "cairo-gl-private.h"
44 
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 
52 static const cairo_surface_backend_t _cairo_gl_surface_backend;
53 
54 static cairo_status_t
55 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags);
56 
_cairo_surface_is_gl(cairo_surface_t * surface)57 static cairo_bool_t _cairo_surface_is_gl (cairo_surface_t *surface)
58 {
59     return surface->backend == &_cairo_gl_surface_backend;
60 }
61 
62 static cairo_bool_t
_cairo_gl_get_image_format_and_type_gles2(pixman_format_code_t pixman_format,GLenum * internal_format,GLenum * format,GLenum * type,cairo_bool_t * has_alpha,cairo_bool_t * needs_swap)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)
67 {
68     cairo_bool_t is_little_endian = _cairo_is_little_endian ();
69 
70     *has_alpha = TRUE;
71 
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;
79 
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;
87 
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;
94 
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;
102 
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;
109 
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;
117 
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;
124 
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;
131 
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;
138 
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;
145 
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;
152 
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;
160 
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;
167 
168     default:
169 	return FALSE;
170     }
171 }
172 
173 static cairo_bool_t
_cairo_gl_get_image_format_and_type_gl(pixman_format_code_t pixman_format,GLenum * internal_format,GLenum * format,GLenum * type,cairo_bool_t * has_alpha,cairo_bool_t * needs_swap)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)
178 {
179     *has_alpha = TRUE;
180     *needs_swap = FALSE;
181 
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;
263 
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;
299     }
300 }
301 
302 /*
303  * Extracts pixel data from an image surface.
304  */
305 static cairo_status_t
_cairo_gl_surface_extract_image_data(cairo_image_surface_t * image,int x,int y,int width,int height,void ** output)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)
310 {
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;
316 
317     if (unlikely (data == NULL))
318 	return CAIRO_STATUS_NO_MEMORY;
319 
320     for (i = 0; i < height; i++) {
321 	memcpy (dst, src, width * cpp);
322 	src += image->stride;
323 	dst += width * cpp;
324     }
325 
326     *output = data;
327 
328     return CAIRO_STATUS_SUCCESS;
329 }
330 
331 cairo_bool_t
_cairo_gl_get_image_format_and_type(cairo_gl_flavor_t flavor,pixman_format_code_t pixman_format,GLenum * internal_format,GLenum * format,GLenum * type,cairo_bool_t * has_alpha,cairo_bool_t * needs_swap)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)
337 {
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);
348 
349 }
350 
351 cairo_bool_t
_cairo_gl_operator_is_supported(cairo_operator_t op)352 _cairo_gl_operator_is_supported (cairo_operator_t op)
353 {
354     return op < CAIRO_OPERATOR_SATURATE;
355 }
356 
357 static void
_cairo_gl_surface_embedded_operand_init(cairo_gl_surface_t * surface)358 _cairo_gl_surface_embedded_operand_init (cairo_gl_surface_t *surface)
359 {
360     cairo_gl_operand_t *operand = &surface->operand;
361     cairo_surface_attributes_t *attributes = &operand->texture.attributes;
362 
363     memset (operand, 0, sizeof (cairo_gl_operand_t));
364 
365     operand->type = CAIRO_GL_OPERAND_TEXTURE;
366     operand->texture.surface = surface;
367     operand->texture.tex = surface->tex;
368 
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);
375     }
376 
377     attributes->extend = CAIRO_EXTEND_NONE;
378     attributes->filter = CAIRO_FILTER_NEAREST;
379 }
380 
381 void
_cairo_gl_surface_init(cairo_device_t * device,cairo_gl_surface_t * surface,cairo_content_t content,int width,int height)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)
386 {
387     assert (width > 0 && height > 0);
388 
389     _cairo_surface_init (&surface->base,
390 			 &_cairo_gl_surface_backend,
391 			 device,
392 			 content,
393 			 FALSE); /* is_vector */
394 
395     surface->width = width;
396     surface->height = height;
397     surface->needs_update = FALSE;
398     surface->content_in_texture = FALSE;
399 
400     _cairo_gl_surface_embedded_operand_init (surface);
401 }
402 
403 static cairo_bool_t
_cairo_gl_surface_size_valid_for_context(cairo_gl_context_t * ctx,int width,int height)404 _cairo_gl_surface_size_valid_for_context (cairo_gl_context_t *ctx,
405 					  int width, int height)
406 {
407     return width > 0 && height > 0 &&
408 	width <= ctx->max_framebuffer_size &&
409 	height <= ctx->max_framebuffer_size;
410 }
411 
412 static cairo_bool_t
_cairo_gl_surface_size_valid(cairo_gl_surface_t * surface,int width,int height)413 _cairo_gl_surface_size_valid (cairo_gl_surface_t *surface,
414 			      int width, int height)
415 {
416     cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
417     return _cairo_gl_surface_size_valid_for_context (ctx, width, height);
418 }
419 
420 static cairo_surface_t *
_cairo_gl_surface_create_scratch_for_texture(cairo_gl_context_t * ctx,cairo_content_t content,GLuint tex,int width,int height)421 _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t   *ctx,
422 					      cairo_content_t	    content,
423 					      GLuint		    tex,
424 					      int		    width,
425 					      int		    height)
426 {
427     cairo_gl_surface_t *surface;
428 
429     surface = calloc (1, sizeof (cairo_gl_surface_t));
430     if (unlikely (surface == NULL))
431 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
432 
433     surface->tex = tex;
434     _cairo_gl_surface_init (&ctx->base, surface, content, width, height);
435 
436     surface->supports_msaa = ctx->supports_msaa;
437     surface->num_samples = ctx->num_samples;
438     surface->supports_stencil = TRUE;
439 
440     /* Create the texture used to store the surface's data. */
441     _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
442     glBindTexture (ctx->tex_target, surface->tex);
443     glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
444     glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
445 
446     return &surface->base;
447 }
448 
449 static cairo_surface_t *
_create_scratch_internal(cairo_gl_context_t * ctx,cairo_content_t content,int width,int height,cairo_bool_t for_caching)450 _create_scratch_internal (cairo_gl_context_t *ctx,
451 			  cairo_content_t content,
452 			  int width,
453 			  int height,
454 			  cairo_bool_t for_caching)
455 {
456     cairo_gl_surface_t *surface;
457     GLenum format;
458     GLuint tex;
459 
460     glGenTextures (1, &tex);
461     surface = (cairo_gl_surface_t *)
462 	_cairo_gl_surface_create_scratch_for_texture (ctx, content,
463 						      tex, width, height);
464     if (unlikely (surface->base.status))
465 	return &surface->base;
466 
467     surface->owns_tex = TRUE;
468 
469     /* adjust the texture size after setting our real extents */
470     if (width < 1)
471 	width = 1;
472     if (height < 1)
473 	height = 1;
474 
475     switch (content) {
476     default:
477 	ASSERT_NOT_REACHED;
478     case CAIRO_CONTENT_COLOR_ALPHA:
479 	format = GL_RGBA;
480 	break;
481     case CAIRO_CONTENT_ALPHA:
482 	/* When using GL_ALPHA, compositing doesn't work properly, but for
483 	 * caching surfaces, we are just uploading pixel data, so it isn't
484 	 * an issue. */
485 	if (for_caching)
486 	    format = GL_ALPHA;
487 	else
488 	    format = GL_RGBA;
489 	break;
490     case CAIRO_CONTENT_COLOR:
491 	/* GL_RGB is almost what we want here -- sampling 1 alpha when
492 	 * texturing, using 1 as destination alpha factor in blending,
493 	 * etc.  However, when filtering with GL_CLAMP_TO_BORDER, the
494 	 * alpha channel of the border color will also be clamped to
495 	 * 1, when we actually want the border color we explicitly
496 	 * specified.  So, we have to store RGBA, and fill the alpha
497 	 * channel with 1 when blending.
498 	 */
499 	format = GL_RGBA;
500 	break;
501     }
502 
503     glTexImage2D (ctx->tex_target, 0, format, width, height, 0,
504 		  format, GL_UNSIGNED_BYTE, NULL);
505 
506     return &surface->base;
507 }
508 
509 cairo_surface_t *
_cairo_gl_surface_create_scratch(cairo_gl_context_t * ctx,cairo_content_t content,int width,int height)510 _cairo_gl_surface_create_scratch (cairo_gl_context_t   *ctx,
511 				  cairo_content_t	content,
512 				  int			width,
513 				  int			height)
514 {
515     return _create_scratch_internal (ctx, content, width, height, FALSE);
516 }
517 
518 cairo_surface_t *
_cairo_gl_surface_create_scratch_for_caching(cairo_gl_context_t * ctx,cairo_content_t content,int width,int height)519 _cairo_gl_surface_create_scratch_for_caching (cairo_gl_context_t *ctx,
520 					      cairo_content_t content,
521 					      int width,
522 					      int height)
523 {
524     return _create_scratch_internal (ctx, content, width, height, TRUE);
525 }
526 
527 static cairo_status_t
_cairo_gl_surface_clear(cairo_gl_surface_t * surface,const cairo_color_t * color)528 _cairo_gl_surface_clear (cairo_gl_surface_t  *surface,
529 			 const cairo_color_t *color)
530 {
531     cairo_gl_context_t *ctx;
532     cairo_status_t status;
533     double r, g, b, a;
534 
535     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
536     if (unlikely (status))
537 	return status;
538 
539     _cairo_gl_context_set_destination (ctx, surface, surface->msaa_active);
540     if (surface->base.content & CAIRO_CONTENT_COLOR) {
541 	r = color->red   * color->alpha;
542 	g = color->green * color->alpha;
543 	b = color->blue  * color->alpha;
544     } else {
545 	r = g = b = 0;
546     }
547     if (surface->base.content & CAIRO_CONTENT_ALPHA) {
548 	a = color->alpha;
549     } else {
550 	a = 1.0;
551     }
552 
553     glDisable (GL_SCISSOR_TEST);
554     glClearColor (r, g, b, a);
555     glClear (GL_COLOR_BUFFER_BIT);
556 
557     if (a == 0)
558 	surface->base.is_clear = TRUE;
559 
560     return _cairo_gl_context_release (ctx, status);
561 }
562 
563 static cairo_surface_t *
_cairo_gl_surface_create_and_clear_scratch(cairo_gl_context_t * ctx,cairo_content_t content,int width,int height)564 _cairo_gl_surface_create_and_clear_scratch (cairo_gl_context_t *ctx,
565 					    cairo_content_t content,
566 					    int width,
567 					    int height)
568 {
569     cairo_gl_surface_t *surface;
570     cairo_int_status_t status;
571 
572     surface = (cairo_gl_surface_t *)
573 	_cairo_gl_surface_create_scratch (ctx, content, width, height);
574     if (unlikely (surface->base.status))
575 	return &surface->base;
576 
577     /* Cairo surfaces start out initialized to transparent (black) */
578     status = _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
579     if (unlikely (status)) {
580 	cairo_surface_destroy (&surface->base);
581 	return _cairo_surface_create_in_error (status);
582     }
583 
584     return &surface->base;
585 }
586 
587 cairo_surface_t *
cairo_gl_surface_create(cairo_device_t * abstract_device,cairo_content_t content,int width,int height)588 cairo_gl_surface_create (cairo_device_t		*abstract_device,
589 			 cairo_content_t	 content,
590 			 int			 width,
591 			 int			 height)
592 {
593     cairo_gl_context_t *ctx;
594     cairo_gl_surface_t *surface;
595     cairo_status_t status;
596 
597     if (! CAIRO_CONTENT_VALID (content))
598 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
599 
600     if (abstract_device == NULL)
601 	return _cairo_image_surface_create_with_content (content, width, height);
602 
603     if (abstract_device->status)
604 	return _cairo_surface_create_in_error (abstract_device->status);
605 
606     if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
607 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
608 
609     status = _cairo_gl_context_acquire (abstract_device, &ctx);
610     if (unlikely (status))
611 	return _cairo_surface_create_in_error (status);
612 
613     if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
614 	status = _cairo_gl_context_release (ctx, status);
615 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
616     }
617 
618     surface = (cairo_gl_surface_t *)
619 	_cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
620     if (unlikely (surface->base.status)) {
621 	status = _cairo_gl_context_release (ctx, surface->base.status);
622 	cairo_surface_destroy (&surface->base);
623 	return _cairo_surface_create_in_error (status);
624     }
625 
626     status = _cairo_gl_context_release (ctx, status);
627     if (unlikely (status)) {
628 	cairo_surface_destroy (&surface->base);
629 	return _cairo_surface_create_in_error (status);
630     }
631 
632     return &surface->base;
633 }
634 slim_hidden_def (cairo_gl_surface_create);
635 
636 /**
637  * cairo_gl_surface_create_for_texture:
638  * @content: type of content in the surface
639  * @tex: name of texture to use for storage of surface pixels
640  * @width: width of the surface, in pixels
641  * @height: height of the surface, in pixels
642  *
643  * Creates a GL surface for the specified texture with the specified
644  * content and dimensions.  The texture must be kept around until the
645  * #cairo_surface_t is destroyed or cairo_surface_finish() is called
646  * on the surface.  The initial contents of @tex will be used as the
647  * initial image contents; you must explicitly clear the buffer,
648  * using, for example, cairo_rectangle() and cairo_fill() if you want
649  * it cleared.  The format of @tex should be compatible with @content,
650  * in the sense that it must have the color components required by
651  * @content.
652  *
653  * Return value: a pointer to the newly created surface. The caller
654  * owns the surface and should call cairo_surface_destroy() when done
655  * with it.
656  *
657  * This function always returns a valid pointer, but it will return a
658  * pointer to a "nil" surface if an error such as out of memory
659  * occurs. You can use cairo_surface_status() to check for this.
660  *
661  * Since: TBD
662  **/
663 cairo_surface_t *
cairo_gl_surface_create_for_texture(cairo_device_t * abstract_device,cairo_content_t content,unsigned int tex,int width,int height)664 cairo_gl_surface_create_for_texture (cairo_device_t	*abstract_device,
665 				     cairo_content_t	 content,
666 				     unsigned int	 tex,
667 				     int		 width,
668 				     int		 height)
669 {
670     cairo_gl_context_t *ctx;
671     cairo_gl_surface_t *surface;
672     cairo_status_t status;
673 
674     if (! CAIRO_CONTENT_VALID (content))
675 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
676 
677     if (abstract_device == NULL)
678 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER));
679 
680     if (abstract_device->status)
681 	return _cairo_surface_create_in_error (abstract_device->status);
682 
683     if (abstract_device->backend->type != CAIRO_DEVICE_TYPE_GL)
684 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_TYPE_MISMATCH));
685 
686     status = _cairo_gl_context_acquire (abstract_device, &ctx);
687     if (unlikely (status))
688 	return _cairo_surface_create_in_error (status);
689 
690     if (! _cairo_gl_surface_size_valid_for_context (ctx, width, height)) {
691 	status = _cairo_gl_context_release (ctx, status);
692 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
693     }
694 
695     surface = (cairo_gl_surface_t *)
696 	_cairo_gl_surface_create_scratch_for_texture (ctx, content,
697 						      tex, width, height);
698     status = _cairo_gl_context_release (ctx, status);
699 
700     return &surface->base;
701 }
702 slim_hidden_def (cairo_gl_surface_create_for_texture);
703 
704 
705 void
cairo_gl_surface_set_size(cairo_surface_t * abstract_surface,int width,int height)706 cairo_gl_surface_set_size (cairo_surface_t *abstract_surface,
707 			   int              width,
708 			   int              height)
709 {
710     cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
711 
712     if (unlikely (abstract_surface->status))
713 	return;
714     if (unlikely (abstract_surface->finished)) {
715 	_cairo_surface_set_error (abstract_surface,
716 				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
717 	return;
718     }
719 
720     if (! _cairo_surface_is_gl (abstract_surface) ||
721 	_cairo_gl_surface_is_texture (surface)) {
722 	_cairo_surface_set_error (abstract_surface,
723 				  _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
724 	return;
725     }
726 
727     if (surface->width != width || surface->height != height) {
728 	surface->needs_update = TRUE;
729 	surface->width = width;
730 	surface->height = height;
731     }
732 }
733 
734 int
cairo_gl_surface_get_width(cairo_surface_t * abstract_surface)735 cairo_gl_surface_get_width (cairo_surface_t *abstract_surface)
736 {
737     cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
738 
739     if (! _cairo_surface_is_gl (abstract_surface))
740 	return 0;
741 
742     return surface->width;
743 }
744 
745 int
cairo_gl_surface_get_height(cairo_surface_t * abstract_surface)746 cairo_gl_surface_get_height (cairo_surface_t *abstract_surface)
747 {
748     cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
749 
750     if (! _cairo_surface_is_gl (abstract_surface))
751 	return 0;
752 
753     return surface->height;
754 }
755 
756 void
cairo_gl_surface_swapbuffers(cairo_surface_t * abstract_surface)757 cairo_gl_surface_swapbuffers (cairo_surface_t *abstract_surface)
758 {
759     cairo_gl_surface_t *surface = (cairo_gl_surface_t *) abstract_surface;
760 
761     if (unlikely (abstract_surface->status))
762 	return;
763     if (unlikely (abstract_surface->finished)) {
764 	_cairo_surface_set_error (abstract_surface,
765 				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
766 	return;
767     }
768 
769     if (! _cairo_surface_is_gl (abstract_surface)) {
770 	_cairo_surface_set_error (abstract_surface,
771 				  CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
772 	return;
773     }
774 
775     if (! _cairo_gl_surface_is_texture (surface)) {
776 	cairo_gl_context_t *ctx;
777 	cairo_status_t status;
778 
779 	status = _cairo_gl_context_acquire (surface->base.device, &ctx);
780 	if (unlikely (status))
781 	    return;
782 
783 	/* For swapping on EGL, at least, we need a valid context/target. */
784 	_cairo_gl_context_set_destination (ctx, surface, FALSE);
785 	/* And in any case we should flush any pending operations. */
786 	_cairo_gl_composite_flush (ctx);
787 
788 	ctx->swap_buffers (ctx, surface);
789 
790 	status = _cairo_gl_context_release (ctx, status);
791 	if (status)
792 	    status = _cairo_surface_set_error (abstract_surface, status);
793     }
794 }
795 
796 static cairo_surface_t *
_cairo_gl_surface_create_similar(void * abstract_surface,cairo_content_t content,int width,int height)797 _cairo_gl_surface_create_similar (void		 *abstract_surface,
798 				  cairo_content_t  content,
799 				  int		  width,
800 				  int		  height)
801 {
802     cairo_surface_t *surface = abstract_surface;
803     cairo_gl_context_t *ctx;
804     cairo_status_t status;
805 
806     if (! _cairo_gl_surface_size_valid (abstract_surface, width, height))
807 	return _cairo_image_surface_create_with_content (content, width, height);
808 
809     status = _cairo_gl_context_acquire (surface->device, &ctx);
810     if (unlikely (status))
811 	return _cairo_surface_create_in_error (status);
812 
813     surface = _cairo_gl_surface_create_and_clear_scratch (ctx, content, width, height);
814 
815     status = _cairo_gl_context_release (ctx, status);
816     if (unlikely (status)) {
817 	cairo_surface_destroy (surface);
818 	return _cairo_surface_create_in_error (status);
819     }
820 
821     return surface;
822 }
823 
824 static cairo_int_status_t
_cairo_gl_surface_fill_alpha_channel(cairo_gl_surface_t * dst,cairo_gl_context_t * ctx,int x,int y,int width,int height)825 _cairo_gl_surface_fill_alpha_channel (cairo_gl_surface_t *dst,
826 				      cairo_gl_context_t *ctx,
827 				      int x, int y,
828 				      int width, int height)
829 {
830     cairo_gl_composite_t setup;
831     cairo_status_t status;
832 
833     _cairo_gl_composite_flush (ctx);
834     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
835 
836     status = _cairo_gl_composite_init (&setup, CAIRO_OPERATOR_SOURCE,
837 				       dst, FALSE);
838     if (unlikely (status))
839 	goto CLEANUP;
840 
841     _cairo_gl_composite_set_solid_source (&setup, CAIRO_COLOR_BLACK);
842 
843     status = _cairo_gl_composite_begin (&setup, &ctx);
844     if (unlikely (status))
845 	goto CLEANUP;
846 
847     _cairo_gl_context_emit_rect (ctx, x, y, x + width, y + height);
848 
849     status = _cairo_gl_context_release (ctx, status);
850 
851   CLEANUP:
852     _cairo_gl_composite_fini (&setup);
853 
854     _cairo_gl_composite_flush (ctx);
855     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
856 
857     return status;
858 }
859 
860 cairo_status_t
_cairo_gl_surface_draw_image(cairo_gl_surface_t * dst,cairo_image_surface_t * src,int src_x,int src_y,int width,int height,int dst_x,int dst_y,cairo_bool_t force_flush)861 _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
862 			      cairo_image_surface_t *src,
863 			      int src_x, int src_y,
864 			      int width, int height,
865 			      int dst_x, int dst_y,
866 			      cairo_bool_t force_flush)
867 {
868     GLenum internal_format, format, type;
869     cairo_bool_t has_alpha, needs_swap;
870     cairo_image_surface_t *clone = NULL;
871     cairo_gl_context_t *ctx;
872     int cpp;
873     cairo_image_surface_t *rgba_clone = NULL;
874     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
875 
876     status = _cairo_gl_context_acquire (dst->base.device, &ctx);
877     if (unlikely (status))
878 	return status;
879 
880     if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 ||
881 	_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
882 	pixman_format_code_t pixman_format;
883 	cairo_surface_pattern_t pattern;
884 	cairo_bool_t require_conversion = FALSE;
885 	pixman_format = _cairo_is_little_endian () ? PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
886 
887 	if (src->base.content != CAIRO_CONTENT_ALPHA) {
888 	    if (src->pixman_format != pixman_format)
889 		require_conversion = TRUE;
890 	}
891 	else if (dst->base.content != CAIRO_CONTENT_ALPHA) {
892 	    require_conversion = TRUE;
893 	}
894 	else if (src->pixman_format != PIXMAN_a8) {
895 	    pixman_format = PIXMAN_a8;
896 	    require_conversion = TRUE;
897 	}
898 
899 	if (require_conversion) {
900 	    rgba_clone = (cairo_image_surface_t *)
901 		_cairo_image_surface_create_with_pixman_format (NULL,
902 								pixman_format,
903 								src->width,
904 								src->height,
905 								0);
906 	    if (unlikely (rgba_clone->base.status))
907 		goto FAIL;
908 
909 	    _cairo_pattern_init_for_surface (&pattern, &src->base);
910 	    status = _cairo_surface_paint (&rgba_clone->base,
911 					   CAIRO_OPERATOR_SOURCE,
912 					   &pattern.base, NULL);
913 	    _cairo_pattern_fini (&pattern.base);
914 	    if (unlikely (status))
915 		goto FAIL;
916 
917 	    src = rgba_clone;
918 	}
919     }
920 
921     if (! _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
922 					       src->pixman_format,
923 					       &internal_format,
924 					       &format,
925 					       &type,
926 					       &has_alpha,
927 					       &needs_swap))
928     {
929 	cairo_bool_t is_supported;
930 
931 	clone = _cairo_image_surface_coerce (src);
932 	if (unlikely (status = clone->base.status))
933 	    goto FAIL;
934 
935 	is_supported =
936 	    _cairo_gl_get_image_format_and_type (ctx->gl_flavor,
937 						 clone->pixman_format,
938 						 &internal_format,
939 						 &format,
940 						 &type,
941 						 &has_alpha,
942 						 &needs_swap);
943 	assert (is_supported);
944 	assert (!needs_swap);
945 	src = clone;
946     }
947 
948     cpp = PIXMAN_FORMAT_BPP (src->pixman_format) / 8;
949 
950     if (force_flush) {
951 	status = _cairo_gl_surface_flush (&dst->base, 0);
952 	if (unlikely (status))
953 	    goto FAIL;
954     }
955 
956     if (_cairo_gl_surface_is_texture (dst)) {
957 	void *data_start = src->data + src_y * src->stride + src_x * cpp;
958 	void *data_start_gles2 = NULL;
959 
960 	/*
961 	 * Due to GL_UNPACK_ROW_LENGTH missing in GLES2 we have to extract the
962 	 * image data ourselves in some cases. In particular, we must extract
963 	 * the pixels if:
964 	 * a. we don't want full-length lines or
965 	 * b. the row stride cannot be handled by GL itself using a 4 byte
966 	 *     alignment constraint
967 	 */
968 	if (src->stride < 0 ||
969 	    (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
970 	     (src->width * cpp < src->stride - 3 ||
971 	      width != src->width)))
972 	{
973 	    glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
974 	    status = _cairo_gl_surface_extract_image_data (src, src_x, src_y,
975 							   width, height,
976 							   &data_start_gles2);
977 	    if (unlikely (status))
978 		goto FAIL;
979 
980 	    data_start = data_start_gles2;
981 	}
982 	else
983 	{
984 	    glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
985 	    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
986 		ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
987 		glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
988 	}
989 
990 	/* we must resolve the renderbuffer to texture before we
991 	   upload image */
992 	status = _cairo_gl_surface_resolve_multisampling (dst);
993 	if (unlikely (status)) {
994 	    free (data_start_gles2);
995 	    goto FAIL;
996 	}
997 
998 	_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
999 	glBindTexture (ctx->tex_target, dst->tex);
1000 	glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1001 	glTexParameteri (ctx->tex_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1002 	glTexSubImage2D (ctx->tex_target, 0,
1003 			 dst_x, dst_y, width, height,
1004 			 format, type, data_start);
1005 
1006 	free (data_start_gles2);
1007 
1008 	/* If we just treated some rgb-only data as rgba, then we have to
1009 	 * go back and fix up the alpha channel where we filled in this
1010 	 * texture data.
1011 	 */
1012 	if (!has_alpha) {
1013 	    _cairo_gl_surface_fill_alpha_channel (dst, ctx,
1014 						  dst_x, dst_y,
1015 						  width, height);
1016 	}
1017 	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1018 	    dst->content_in_texture = TRUE;
1019     } else {
1020 	cairo_surface_t *tmp;
1021 
1022 	tmp = _cairo_gl_surface_create_scratch (ctx,
1023 						dst->base.content,
1024 						width, height);
1025 	if (unlikely (tmp->status))
1026 	    goto FAIL;
1027 
1028 	status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *) tmp,
1029 					       src,
1030 					       src_x, src_y,
1031 					       width, height,
1032 					       0, 0, force_flush);
1033 	if (status == CAIRO_INT_STATUS_SUCCESS) {
1034 	    cairo_surface_pattern_t tmp_pattern;
1035 	    cairo_rectangle_int_t r;
1036 	    cairo_clip_t *clip;
1037 
1038 	    _cairo_pattern_init_for_surface (&tmp_pattern, tmp);
1039 	    cairo_matrix_init_translate (&tmp_pattern.base.matrix,
1040 					 -dst_x, -dst_y);
1041 	    tmp_pattern.base.filter = CAIRO_FILTER_NEAREST;
1042 	    tmp_pattern.base.extend = CAIRO_EXTEND_NONE;
1043 
1044 	    r.x = dst_x;
1045 	    r.y = dst_y;
1046 	    r.width = width;
1047 	    r.height = height;
1048 	    clip = _cairo_clip_intersect_rectangle (NULL, &r);
1049 	    status = _cairo_surface_paint (&dst->base,
1050 					   CAIRO_OPERATOR_SOURCE,
1051 					   &tmp_pattern.base,
1052 					   clip);
1053 	    _cairo_clip_destroy (clip);
1054 	    _cairo_pattern_fini (&tmp_pattern.base);
1055 	}
1056 
1057 	cairo_surface_destroy (tmp);
1058 	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1059 	    dst->content_in_texture = TRUE;
1060     }
1061 
1062 FAIL:
1063     status = _cairo_gl_context_release (ctx, status);
1064 
1065     if (clone)
1066 	cairo_surface_destroy (&clone->base);
1067 
1068     if (rgba_clone)
1069 	cairo_surface_destroy (&rgba_clone->base);
1070 
1071     return status;
1072 }
1073 
_cairo_gl_surface_flavor(cairo_gl_surface_t * surface)1074 static int _cairo_gl_surface_flavor (cairo_gl_surface_t *surface)
1075 {
1076     cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1077     return ctx->gl_flavor;
1078 }
1079 
1080 static cairo_status_t
_cairo_gl_surface_finish(void * abstract_surface)1081 _cairo_gl_surface_finish (void *abstract_surface)
1082 {
1083     cairo_gl_surface_t *surface = abstract_surface;
1084     cairo_status_t status;
1085     cairo_gl_context_t *ctx;
1086 
1087     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1088     if (unlikely (status))
1089 	return status;
1090 
1091     if (ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE &&
1092 	ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface)
1093 	_cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_SOURCE);
1094     if (ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE &&
1095 	ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface)
1096 	_cairo_gl_context_destroy_operand (ctx, CAIRO_GL_TEX_MASK);
1097     if (ctx->current_target == surface)
1098 	ctx->current_target = NULL;
1099 
1100     if (surface->fb)
1101 	ctx->dispatch.DeleteFramebuffers (1, &surface->fb);
1102     if (surface->depth_stencil)
1103 	ctx->dispatch.DeleteRenderbuffers (1, &surface->depth_stencil);
1104     if (surface->owns_tex)
1105 	glDeleteTextures (1, &surface->tex);
1106 
1107     if (surface->msaa_depth_stencil)
1108 	ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
1109 
1110 #if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
1111     if (surface->msaa_fb)
1112 	ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
1113     if (surface->msaa_rb)
1114 	ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_rb);
1115 #endif
1116 
1117     _cairo_clip_destroy (surface->clip_on_stencil_buffer);
1118 
1119     return _cairo_gl_context_release (ctx, status);
1120 }
1121 
1122 static cairo_image_surface_t *
_cairo_gl_surface_map_to_image(void * abstract_surface,const cairo_rectangle_int_t * extents)1123 _cairo_gl_surface_map_to_image (void      *abstract_surface,
1124 				const cairo_rectangle_int_t   *extents)
1125 {
1126     cairo_gl_surface_t *surface = abstract_surface;
1127     cairo_image_surface_t *image;
1128     cairo_gl_context_t *ctx;
1129     GLenum format, type;
1130     pixman_format_code_t pixman_format;
1131     unsigned int cpp;
1132     cairo_bool_t flipped, mesa_invert;
1133     cairo_status_t status;
1134     int y;
1135 
1136     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1137     if (unlikely (status)) {
1138 	return _cairo_image_surface_create_in_error (status);
1139     }
1140 
1141     /* Want to use a switch statement here but the compiler gets whiny. */
1142     if (surface->base.content == CAIRO_CONTENT_COLOR_ALPHA) {
1143 	format = GL_BGRA;
1144 	pixman_format = PIXMAN_a8r8g8b8;
1145 	type = GL_UNSIGNED_INT_8_8_8_8_REV;
1146 	cpp = 4;
1147     } else if (surface->base.content == CAIRO_CONTENT_COLOR) {
1148 	format = GL_BGRA;
1149 	pixman_format = PIXMAN_x8r8g8b8;
1150 	type = GL_UNSIGNED_INT_8_8_8_8_REV;
1151 	cpp = 4;
1152     } else if (surface->base.content == CAIRO_CONTENT_ALPHA) {
1153 	format = GL_ALPHA;
1154 	pixman_format = PIXMAN_a8;
1155 	type = GL_UNSIGNED_BYTE;
1156 	cpp = 1;
1157     } else {
1158 	ASSERT_NOT_REACHED;
1159 	return NULL;
1160     }
1161 
1162     if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 ||
1163 	_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) {
1164 	/* If only RGBA is supported, we must download data in a compatible
1165 	 * format. This means that pixman will convert the data on the CPU when
1166 	 * interacting with other image surfaces. For ALPHA, GLES2 does not
1167 	 * support GL_PACK_ROW_LENGTH anyway, and this makes sure that the
1168 	 * pixman image that is created has row_stride = row_width * bpp. */
1169 	if (surface->base.content == CAIRO_CONTENT_ALPHA || !ctx->can_read_bgra) {
1170 	    cairo_bool_t little_endian = _cairo_is_little_endian ();
1171 	    format = GL_RGBA;
1172 
1173 	    if (surface->base.content == CAIRO_CONTENT_COLOR) {
1174 		pixman_format = little_endian ?
1175 		    PIXMAN_x8b8g8r8 : PIXMAN_r8g8b8x8;
1176 	    } else {
1177 		pixman_format = little_endian ?
1178 		    PIXMAN_a8b8g8r8 : PIXMAN_r8g8b8a8;
1179 	    }
1180 	}
1181 
1182 	/* GLES2 only supports GL_UNSIGNED_BYTE. */
1183 	type = GL_UNSIGNED_BYTE;
1184 	cpp = 4;
1185     }
1186 
1187     image = (cairo_image_surface_t*)
1188 	_cairo_image_surface_create_with_pixman_format (NULL,
1189 							pixman_format,
1190 							extents->width,
1191 							extents->height,
1192 							-1);
1193     if (unlikely (image->base.status)) {
1194 	status = _cairo_gl_context_release (ctx, status);
1195 	return image;
1196     }
1197 
1198     cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
1199 
1200     /* If the original surface has not been modified or
1201      * is clear, we can avoid downloading data. */
1202     if (surface->base.is_clear || surface->base.serial == 0) {
1203 	status = _cairo_gl_context_release (ctx, status);
1204 	return image;
1205     }
1206 
1207     /* This is inefficient, as we'd rather just read the thing without making
1208      * it the destination.  But then, this is the fallback path, so let's not
1209      * fall back instead.
1210      */
1211     _cairo_gl_composite_flush (ctx);
1212 
1213     if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) {
1214 	_cairo_gl_context_set_destination (ctx, surface, FALSE);
1215     } else {
1216 	if (surface->content_in_texture) {
1217 	    _cairo_gl_ensure_framebuffer (ctx, surface);
1218 	    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
1219 	} else {
1220 	    status = _cairo_gl_surface_resolve_multisampling (surface);
1221 	    if (unlikely (status)) {
1222 		status = _cairo_gl_context_release (ctx, status);
1223 		cairo_surface_destroy (&image->base);
1224 		return _cairo_image_surface_create_in_error (status);
1225 	    }
1226 	}
1227     }
1228 
1229     flipped = ! _cairo_gl_surface_is_texture (surface);
1230     mesa_invert = flipped && ctx->has_mesa_pack_invert;
1231 
1232     glPixelStorei (GL_PACK_ALIGNMENT, 4);
1233     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
1234 	ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1235 	glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
1236     if (mesa_invert)
1237 	glPixelStorei (GL_PACK_INVERT_MESA, 1);
1238 
1239     y = extents->y;
1240     if (flipped)
1241 	y = surface->height - extents->y - extents->height;
1242 
1243     glReadPixels (extents->x, y,
1244 		  extents->width, extents->height,
1245 		  format, type, image->data);
1246     if (mesa_invert)
1247 	glPixelStorei (GL_PACK_INVERT_MESA, 0);
1248 
1249     status = _cairo_gl_context_release (ctx, status);
1250     if (unlikely (status)) {
1251 	cairo_surface_destroy (&image->base);
1252 	return _cairo_image_surface_create_in_error (status);
1253     }
1254 
1255     /* We must invert the image manually if we lack GL_MESA_pack_invert */
1256     if (flipped && ! mesa_invert) {
1257 	uint8_t stack[1024], *row = stack;
1258 	uint8_t *top = image->data;
1259 	uint8_t *bot = image->data + (image->height-1)*image->stride;
1260 
1261 	if (image->stride > (int)sizeof(stack)) {
1262 	    row = _cairo_malloc (image->stride);
1263 	    if (unlikely (row == NULL)) {
1264 		cairo_surface_destroy (&image->base);
1265 		return _cairo_image_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1266 	    }
1267 	}
1268 
1269 	while (top < bot) {
1270 	    memcpy (row, top, image->stride);
1271 	    memcpy (top, bot, image->stride);
1272 	    memcpy (bot, row, image->stride);
1273 	    top += image->stride;
1274 	    bot -= image->stride;
1275 	}
1276 
1277 	if (row != stack)
1278 	    free(row);
1279     }
1280 
1281     image->base.is_clear = FALSE;
1282     return image;
1283 }
1284 
1285 static cairo_surface_t *
_cairo_gl_surface_source(void * abstract_surface,cairo_rectangle_int_t * extents)1286 _cairo_gl_surface_source (void		       *abstract_surface,
1287 			  cairo_rectangle_int_t *extents)
1288 {
1289     cairo_gl_surface_t *surface = abstract_surface;
1290 
1291     if (extents) {
1292 	extents->x = extents->y = 0;
1293 	extents->width  = surface->width;
1294 	extents->height = surface->height;
1295     }
1296 
1297     return &surface->base;
1298 }
1299 
1300 static cairo_status_t
_cairo_gl_surface_acquire_source_image(void * abstract_surface,cairo_image_surface_t ** image_out,void ** image_extra)1301 _cairo_gl_surface_acquire_source_image (void		       *abstract_surface,
1302 					cairo_image_surface_t **image_out,
1303 					void		      **image_extra)
1304 {
1305     cairo_gl_surface_t *surface = abstract_surface;
1306     cairo_rectangle_int_t extents;
1307 
1308     *image_extra = NULL;
1309 
1310     extents.x = extents.y = 0;
1311     extents.width = surface->width;
1312     extents.height = surface->height;
1313 
1314     *image_out = (cairo_image_surface_t *)
1315 	_cairo_gl_surface_map_to_image (surface, &extents);
1316     return (*image_out)->base.status;
1317 }
1318 
1319 static void
_cairo_gl_surface_release_source_image(void * abstract_surface,cairo_image_surface_t * image,void * image_extra)1320 _cairo_gl_surface_release_source_image (void		      *abstract_surface,
1321 					cairo_image_surface_t *image,
1322 					void		      *image_extra)
1323 {
1324     cairo_surface_destroy (&image->base);
1325 }
1326 
1327 static cairo_int_status_t
_cairo_gl_surface_unmap_image(void * abstract_surface,cairo_image_surface_t * image)1328 _cairo_gl_surface_unmap_image (void		      *abstract_surface,
1329 			       cairo_image_surface_t *image)
1330 {
1331     cairo_int_status_t status;
1332 
1333     status = _cairo_gl_surface_draw_image (abstract_surface, image,
1334 					   0, 0,
1335 					   image->width, image->height,
1336 					   image->base.device_transform_inverse.x0,
1337 					   image->base.device_transform_inverse.y0,
1338 					   TRUE);
1339 
1340     cairo_surface_finish (&image->base);
1341     cairo_surface_destroy (&image->base);
1342 
1343     return status;
1344 }
1345 
1346 static cairo_bool_t
_cairo_gl_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)1347 _cairo_gl_surface_get_extents (void		     *abstract_surface,
1348 			       cairo_rectangle_int_t *rectangle)
1349 {
1350     cairo_gl_surface_t *surface = abstract_surface;
1351 
1352     rectangle->x = 0;
1353     rectangle->y = 0;
1354     rectangle->width  = surface->width;
1355     rectangle->height = surface->height;
1356 
1357     return TRUE;
1358 }
1359 
1360 static cairo_status_t
_cairo_gl_surface_flush(void * abstract_surface,unsigned flags)1361 _cairo_gl_surface_flush (void *abstract_surface, unsigned flags)
1362 {
1363     cairo_gl_surface_t *surface = abstract_surface;
1364     cairo_status_t status;
1365     cairo_gl_context_t *ctx;
1366 
1367     if (flags)
1368 	return CAIRO_STATUS_SUCCESS;
1369 
1370     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1371     if (unlikely (status))
1372 	return status;
1373 
1374     if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE &&
1375 	 ctx->operands[CAIRO_GL_TEX_SOURCE].texture.surface == surface) ||
1376 	(ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE &&
1377 	 ctx->operands[CAIRO_GL_TEX_MASK].texture.surface == surface) ||
1378 	(ctx->current_target == surface))
1379       _cairo_gl_composite_flush (ctx);
1380 
1381     status = _cairo_gl_surface_resolve_multisampling (surface);
1382 
1383     return _cairo_gl_context_release (ctx, status);
1384 }
1385 
1386 cairo_int_status_t
_cairo_gl_surface_resolve_multisampling(cairo_gl_surface_t * surface)1387 _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
1388 {
1389     cairo_gl_context_t *ctx;
1390     cairo_int_status_t status;
1391 
1392     if (! surface->msaa_active)
1393 	return CAIRO_INT_STATUS_SUCCESS;
1394 
1395     if (surface->base.device == NULL)
1396 	return CAIRO_INT_STATUS_SUCCESS;
1397 
1398     /* GLES surfaces do not need explicit resolution. */
1399     if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2)
1400 	return CAIRO_INT_STATUS_SUCCESS;
1401     else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 &&
1402 	     surface->content_in_texture)
1403 	return CAIRO_INT_STATUS_SUCCESS;
1404 
1405     if (! _cairo_gl_surface_is_texture (surface))
1406 	return CAIRO_INT_STATUS_SUCCESS;
1407 
1408     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
1409     if (unlikely (status))
1410 	return status;
1411 
1412 #if CAIRO_HAS_GLESV3_SURFACE
1413     _cairo_gl_composite_flush (ctx);
1414     ctx->current_target = NULL;
1415     _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
1416     if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
1417 	surface->content_in_texture = TRUE;
1418 
1419 #elif CAIRO_HAS_GL_SURFACE
1420     ctx->current_target = surface;
1421     _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
1422 
1423 #else
1424     ctx->current_target = surface;
1425 
1426 #endif
1427 
1428     status = _cairo_gl_context_release (ctx, status);
1429     return status;
1430 }
1431 
1432 static const cairo_compositor_t *
get_compositor(cairo_gl_surface_t * surface)1433 get_compositor (cairo_gl_surface_t *surface)
1434 {
1435     cairo_gl_context_t *ctx = (cairo_gl_context_t *)surface->base.device;
1436     return ctx->compositor;
1437 }
1438 
1439 static cairo_int_status_t
_cairo_gl_surface_paint(void * surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_clip_t * clip)1440 _cairo_gl_surface_paint (void			*surface,
1441 			 cairo_operator_t	 op,
1442 			 const cairo_pattern_t	*source,
1443 			 const cairo_clip_t	*clip)
1444 {
1445     /* simplify the common case of clearing the surface */
1446     if (clip == NULL) {
1447 	if (op == CAIRO_OPERATOR_CLEAR)
1448 	    return _cairo_gl_surface_clear (surface, CAIRO_COLOR_TRANSPARENT);
1449        else if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
1450 		(op == CAIRO_OPERATOR_SOURCE ||
1451 		 (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque_solid (source)))) {
1452 	    return _cairo_gl_surface_clear (surface,
1453 					    &((cairo_solid_pattern_t *) source)->color);
1454 	}
1455     }
1456 
1457     return _cairo_compositor_paint (get_compositor (surface), surface,
1458 				    op, source, clip);
1459 }
1460 
1461 static cairo_int_status_t
_cairo_gl_surface_mask(void * surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_pattern_t * mask,const cairo_clip_t * clip)1462 _cairo_gl_surface_mask (void			 *surface,
1463 			cairo_operator_t	  op,
1464 			const cairo_pattern_t	*source,
1465 			const cairo_pattern_t	*mask,
1466 			const cairo_clip_t	*clip)
1467 {
1468     return _cairo_compositor_mask (get_compositor (surface), surface,
1469 				   op, source, mask, clip);
1470 }
1471 
1472 static cairo_int_status_t
_cairo_gl_surface_stroke(void * surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_antialias_t antialias,const cairo_clip_t * clip)1473 _cairo_gl_surface_stroke (void				*surface,
1474 			  cairo_operator_t		 op,
1475 			  const cairo_pattern_t		*source,
1476 			  const cairo_path_fixed_t	*path,
1477 			  const cairo_stroke_style_t	*style,
1478 			  const cairo_matrix_t		*ctm,
1479 			  const cairo_matrix_t		*ctm_inverse,
1480 			  double			 tolerance,
1481 			  cairo_antialias_t		 antialias,
1482 			  const cairo_clip_t		*clip)
1483 {
1484     return _cairo_compositor_stroke (get_compositor (surface), surface,
1485 				     op, source, path, style,
1486 				     ctm, ctm_inverse, tolerance, antialias,
1487 				     clip);
1488 }
1489 
1490 static cairo_int_status_t
_cairo_gl_surface_fill(void * surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias,const cairo_clip_t * clip)1491 _cairo_gl_surface_fill (void			*surface,
1492 			cairo_operator_t	 op,
1493 			const cairo_pattern_t	*source,
1494 			const cairo_path_fixed_t*path,
1495 			cairo_fill_rule_t	 fill_rule,
1496 			double			 tolerance,
1497 			cairo_antialias_t	 antialias,
1498 			const cairo_clip_t	*clip)
1499 {
1500     return _cairo_compositor_fill (get_compositor (surface), surface,
1501 				   op, source, path,
1502 				   fill_rule, tolerance, antialias,
1503 				   clip);
1504 }
1505 
1506 static cairo_int_status_t
_cairo_gl_surface_glyphs(void * surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_glyph_t * glyphs,int num_glyphs,cairo_scaled_font_t * font,const cairo_clip_t * clip)1507 _cairo_gl_surface_glyphs (void			*surface,
1508 			  cairo_operator_t	 op,
1509 			  const cairo_pattern_t	*source,
1510 			  cairo_glyph_t		*glyphs,
1511 			  int			 num_glyphs,
1512 			  cairo_scaled_font_t	*font,
1513 			  const cairo_clip_t	*clip)
1514 {
1515     return _cairo_compositor_glyphs (get_compositor (surface), surface,
1516 				     op, source, glyphs, num_glyphs, font,
1517 				     clip);
1518 }
1519 
1520 static const cairo_surface_backend_t _cairo_gl_surface_backend = {
1521     CAIRO_SURFACE_TYPE_GL,
1522     _cairo_gl_surface_finish,
1523     _cairo_default_context_create,
1524 
1525     _cairo_gl_surface_create_similar,
1526     NULL, /* similar image */
1527     _cairo_gl_surface_map_to_image,
1528     _cairo_gl_surface_unmap_image,
1529 
1530     _cairo_gl_surface_source,
1531     _cairo_gl_surface_acquire_source_image,
1532     _cairo_gl_surface_release_source_image,
1533     NULL, /* snapshot */
1534 
1535     NULL, /* copy_page */
1536     NULL, /* show_page */
1537 
1538     _cairo_gl_surface_get_extents,
1539     _cairo_image_surface_get_font_options,
1540 
1541     _cairo_gl_surface_flush,
1542     NULL, /* mark_dirty_rectangle */
1543 
1544     _cairo_gl_surface_paint,
1545     _cairo_gl_surface_mask,
1546     _cairo_gl_surface_stroke,
1547     _cairo_gl_surface_fill,
1548     NULL, /* fill/stroke */
1549     _cairo_gl_surface_glyphs,
1550 };
1551