summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boilerplate/Makefile.win32.features12
-rw-r--r--boilerplate/cairo-boilerplate-egl.c30
-rw-r--r--build/Makefile.win32.features1
-rw-r--r--build/Makefile.win32.features-h3
-rw-r--r--build/configure.ac.features1
-rw-r--r--configure.ac23
-rw-r--r--src/Makefile.sources4
-rw-r--r--src/Makefile.win32.features16
-rw-r--r--src/cairo-gl-composite.c103
-rw-r--r--src/cairo-gl-device.c91
-rw-r--r--src/cairo-gl-dispatch.c12
-rw-r--r--src/cairo-gl-gradient-private.h9
-rw-r--r--src/cairo-gl-gradient.c3
-rw-r--r--src/cairo-gl-info.c4
-rw-r--r--src/cairo-gl-msaa-compositor.c10
-rw-r--r--src/cairo-gl-operand.c3
-rw-r--r--src/cairo-gl-private.h20
-rw-r--r--src/cairo-gl-shaders.c15
-rw-r--r--src/cairo-gl-surface.c73
-rw-r--r--src/cairo-gl.h2
20 files changed, 370 insertions, 65 deletions
diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features
index e60a95ba6..abb198dee 100644
--- a/boilerplate/Makefile.win32.features
+++ b/boilerplate/Makefile.win32.features
@@ -247,6 +247,18 @@ enabled_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_glesv2_cxx_sources)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_glesv2_sources)
endif
+unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_glesv3_headers)
+all_cairo_boilerplate_headers += $(cairo_boilerplate_glesv3_headers)
+all_cairo_boilerplate_private += $(cairo_boilerplate_glesv3_private)
+all_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_glesv3_cxx_sources)
+all_cairo_boilerplate_sources += $(cairo_boilerplate_glesv3_sources)
+ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
+enabled_cairo_boilerplate_headers += $(cairo_boilerplate_glesv3_headers)
+enabled_cairo_boilerplate_private += $(cairo_boilerplate_glesv3_private)
+enabled_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_glesv3_cxx_sources)
+enabled_cairo_boilerplate_sources += $(cairo_boilerplate_glesv3_sources)
+endif
+
unsupported_cairo_boilerplate_headers += $(cairo_boilerplate_cogl_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_cogl_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_cogl_private)
diff --git a/boilerplate/cairo-boilerplate-egl.c b/boilerplate/cairo-boilerplate-egl.c
index 99bee64cf..c44441cc5 100644
--- a/boilerplate/cairo-boilerplate-egl.c
+++ b/boilerplate/cairo-boilerplate-egl.c
@@ -33,10 +33,13 @@
#include "cairo-boilerplate-private.h"
#include <cairo-gl.h>
-#if CAIRO_HAS_GL_SURFACE
-#include <GL/gl.h>
+#if CAIRO_HAS_GLESV3_SURFACE
+#include <GLES3/gl3.h>
+#include <EGL/eglext.h>
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
+#elif CAIRO_HAS_GL_SURFACE
+#include <GL/gl.h>
#endif
static const cairo_user_data_key_t gl_closure_key;
@@ -85,15 +88,19 @@ _cairo_boilerplate_egl_create_surface (const char *name,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
-#if CAIRO_HAS_GL_SURFACE
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+#if CAIRO_HAS_GLESV3_SURFACE
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
#elif CAIRO_HAS_GLESV2_SURFACE
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#elif CAIRO_HAS_GL_SURFACE
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
#endif
EGL_NONE
};
const EGLint ctx_attribs[] = {
-#if CAIRO_HAS_GLESV2_SURFACE
+#if CAIRO_HAS_GLESV3_SURFACE
+ EGL_CONTEXT_CLIENT_VERSION, 3,
+#elif CAIRO_HAS_GLESV2_SURFACE
EGL_CONTEXT_CLIENT_VERSION, 2,
#endif
EGL_NONE
@@ -110,15 +117,22 @@ _cairo_boilerplate_egl_create_surface (const char *name,
}
eglChooseConfig (gltc->dpy, config_attribs, &config, 1, &numConfigs);
+#if CAIRO_HAS_GLESV3_SURFACE && CAIRO_HAS_GLESV2_SURFACE
+ if (numConfigs == 0) {
+ /* retry with ES2_BIT */
+ config_attribs[11] = ES2_BIT; /* FIXME: Ick */
+ eglChooseConfig (gltc->dpy, config_attribs, &config, 1, &numConfigs);
+ }
+#endif
if (numConfigs == 0) {
free (gltc);
return NULL;
}
-#if CAIRO_HAS_GL_SURFACE
- eglBindAPI (EGL_OPENGL_API);
-#elif CAIRO_HAS_GLESV2_SURFACE
+#if CAIRO_HAS_GLESV3_SURFACE || CAIRO_HAS_GLESV2_SURFACE
eglBindAPI (EGL_OPENGL_ES_API);
+#elif CAIRO_HAS_GL_SURFACE
+ eglBindAPI (EGL_OPENGL_API);
#endif
gltc->ctx = eglCreateContext (gltc->dpy, config, EGL_NO_CONTEXT,
diff --git a/build/Makefile.win32.features b/build/Makefile.win32.features
index 8cb155dc0..7f62d975e 100644
--- a/build/Makefile.win32.features
+++ b/build/Makefile.win32.features
@@ -19,6 +19,7 @@ CAIRO_HAS_GALLIUM_SURFACE=0
CAIRO_HAS_PNG_FUNCTIONS=1
CAIRO_HAS_GL_SURFACE=0
CAIRO_HAS_GLESV2_SURFACE=0
+CAIRO_HAS_GLESV3_SURFACE=0
CAIRO_HAS_COGL_SURFACE=0
CAIRO_HAS_DIRECTFB_SURFACE=0
CAIRO_HAS_VG_SURFACE=0
diff --git a/build/Makefile.win32.features-h b/build/Makefile.win32.features-h
index 13904cfa9..2825f0c3c 100644
--- a/build/Makefile.win32.features-h
+++ b/build/Makefile.win32.features-h
@@ -62,6 +62,9 @@ endif
ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1)
@echo "#define CAIRO_HAS_GLESV2_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
endif
+ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
+ @echo "#define CAIRO_HAS_GLESV3_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
+endif
ifeq ($(CAIRO_HAS_COGL_SURFACE),1)
@echo "#define CAIRO_HAS_COGL_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
endif
diff --git a/build/configure.ac.features b/build/configure.ac.features
index 77f203588..aa48652f2 100644
--- a/build/configure.ac.features
+++ b/build/configure.ac.features
@@ -384,6 +384,7 @@ AC_DEFUN([CAIRO_REPORT],
echo " SVG: $use_svg"
echo " OpenGL: $use_gl"
echo " OpenGL ES 2.0: $use_glesv2"
+ echo " OpenGL ES 3.0: $use_glesv3"
echo " BeOS: $use_beos"
echo " DirectFB: $use_directfb"
echo " OpenVG: $use_vg"
diff --git a/configure.ac b/configure.ac
index 93953a7f2..264623d8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -386,6 +386,29 @@ CAIRO_ENABLE_SURFACE_BACKEND(glesv2, OpenGLESv2, no, [
])
dnl ===========================================================================
+CAIRO_ENABLE_SURFACE_BACKEND(glesv3, OpenGLESv3, no, [
+ glesv3_REQUIRES="glesv3"
+ PKG_CHECK_MODULES(glesv3, $glesv3_REQUIRES,, [
+ dnl Fallback to searching for headers
+ AC_CHECK_HEADER(GLES3/gl3.h,, [use_glesv3="no (glesv3.pc nor OpenGL ES 3.0 headers not found)"])
+ if test "x$use_glesv3" = "xyes"; then
+ glesv3_NONPKGCONFIG_CFLAGS=
+ dnl glesv3 is provided by the libGLESv2 library (there is no separate libGLESv3)
+ glesv3_NONPKGCONFIG_LIBS="-lGLESv2"
+ fi])
+
+ if test "x$have_dl" = "xyes" -a "x$have_dlsym" = "xyes"; then
+ glesv3_LIBS="$glesv3_LIBS -ldl"
+ fi
+
+ if test "x$use_glesv3" = "xyes" -a "x$use_gl" = "xyes"; then
+ AC_MSG_ERROR([use either --enable-gl=yes or --enable-glesv3=yes. Not both at the same time.])
+ fi
+
+ need_egl_functions=yes
+])
+
+dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(cogl, Cogl, no, [
cogl_REQUIRES="cogl-2.0-experimental"
PKG_CHECK_MODULES(cogl, $cogl_REQUIRES,, [use_cogl="no"])
diff --git a/src/Makefile.sources b/src/Makefile.sources
index b1e3eb13e..89417ac86 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -407,6 +407,10 @@ cairo_glesv2_headers = $(cairo_gl_headers)
cairo_glesv2_private = $(cairo_gl_private)
cairo_glesv2_sources = $(cairo_gl_sources)
+cairo_glesv3_headers = $(cairo_gl_headers)
+cairo_glesv3_private = $(cairo_gl_private)
+cairo_glesv3_sources = $(cairo_gl_sources)
+
cairo_egl_sources += cairo-egl-context.c
cairo_glx_sources += cairo-glx-context.c
cairo_wgl_sources += cairo-wgl-context.c
diff --git a/src/Makefile.win32.features b/src/Makefile.win32.features
index 2274f4ad6..e8be9f748 100644
--- a/src/Makefile.win32.features
+++ b/src/Makefile.win32.features
@@ -325,6 +325,22 @@ ifeq ($(CAIRO_HAS_GLESV2_SURFACE),1)
enabled_cairo_pkgconf += cairo-glesv2.pc
endif
+unsupported_cairo_headers += $(cairo_glesv3_headers)
+all_cairo_headers += $(cairo_glesv3_headers)
+all_cairo_private += $(cairo_glesv3_private)
+all_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
+all_cairo_sources += $(cairo_glesv3_sources)
+ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
+enabled_cairo_headers += $(cairo_glesv3_headers)
+enabled_cairo_private += $(cairo_glesv3_private)
+enabled_cairo_cxx_sources += $(cairo_glesv3_cxx_sources)
+enabled_cairo_sources += $(cairo_glesv3_sources)
+endif
+all_cairo_pkgconf += cairo-glesv3.pc
+ifeq ($(CAIRO_HAS_GLESV3_SURFACE),1)
+enabled_cairo_pkgconf += cairo-glesv3.pc
+endif
+
unsupported_cairo_headers += $(cairo_cogl_headers)
all_cairo_headers += $(cairo_cogl_headers)
all_cairo_private += $(cairo_cogl_private)
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index a95712e1c..ecf03a559 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -52,6 +52,93 @@
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
+/* FIXME: Copy of same routine in cairo-gl-msaa-compositor.c */
+static cairo_int_status_t
+_draw_int_rect (cairo_gl_context_t *ctx,
+ cairo_gl_composite_t *setup,
+ cairo_rectangle_int_t *rect)
+{
+ cairo_box_t box;
+ cairo_point_t quad[4];
+
+ _cairo_box_from_rectangle (&box, rect);
+ quad[0].x = box.p1.x;
+ quad[0].y = box.p1.y;
+ quad[1].x = box.p1.x;
+ quad[1].y = box.p2.y;
+ quad[2].x = box.p2.x;
+ quad[2].y = box.p2.y;
+ quad[3].x = box.p2.x;
+ quad[3].y = box.p1.y;
+
+ return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
+}
+
+static cairo_int_status_t
+_blit_texture_to_renderbuffer (cairo_gl_surface_t *surface)
+{
+ cairo_gl_context_t *ctx = NULL;
+ cairo_gl_composite_t setup;
+ cairo_surface_pattern_t pattern;
+ cairo_rectangle_int_t extents;
+ cairo_int_status_t status;
+
+ /* FIXME: This only permits blit when glesv3 is enabled. But note that
+ glesv2 with the ANGLE extension should also be able to support this feature,
+ so once the ANGLE support code is in place this check can be relaxed. */
+ if (((cairo_gl_context_t *)surface->base.device)->gl_flavor != CAIRO_GL_FLAVOR_ES3)
+ return CAIRO_INT_STATUS_SUCCESS;
+
+ if (! surface->content_in_texture)
+ return CAIRO_INT_STATUS_SUCCESS;
+
+ memset (&setup, 0, sizeof (cairo_gl_composite_t));
+
+ status = _cairo_gl_composite_set_operator (&setup,
+ CAIRO_OPERATOR_SOURCE,
+ FALSE);
+
+ if (status)
+ return status;
+
+ setup.dst = surface;
+ setup.clip_region = surface->clip_region;
+
+ _cairo_pattern_init_for_surface (&pattern, &surface->base);
+ status = _cairo_gl_composite_set_source (&setup, &pattern.base,
+ NULL, NULL, FALSE);
+ _cairo_pattern_fini (&pattern.base);
+
+ if (unlikely (status))
+ goto FAIL;
+
+ _cairo_gl_composite_set_multisample (&setup);
+
+ status = _cairo_gl_composite_begin (&setup, &ctx);
+
+ if (unlikely (status))
+ goto FAIL;
+
+ extents.x = extents.y = 0;
+ extents.width = surface->width;
+ extents.height = surface->height;
+
+ status = _draw_int_rect (ctx, &setup, &extents);
+
+ if (status == CAIRO_INT_STATUS_SUCCESS)
+ surface->content_in_texture = FALSE;
+
+FAIL:
+ _cairo_gl_composite_fini (&setup);
+
+ if (ctx) {
+ _cairo_gl_composite_flush (ctx);
+ status = _cairo_gl_context_release (ctx, status);
+ }
+
+ return status;
+}
+
cairo_int_status_t
_cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
const cairo_pattern_t *pattern,
@@ -68,8 +155,13 @@ void
_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
const cairo_gl_operand_t *source)
{
+ cairo_int_status_t status;
+
_cairo_gl_operand_destroy (&setup->src);
_cairo_gl_operand_copy (&setup->src, source);
+
+ if (source->type == CAIRO_GL_OPERAND_TEXTURE)
+ status = _cairo_gl_surface_resolve_multisampling (source->texture.surface);
}
void
@@ -99,9 +191,13 @@ void
_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
const cairo_gl_operand_t *mask)
{
+ cairo_int_status_t status;
_cairo_gl_operand_destroy (&setup->mask);
- if (mask)
+ if (mask) {
_cairo_gl_operand_copy (&setup->mask, mask);
+ if (mask->type == CAIRO_GL_OPERAND_TEXTURE)
+ status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface);
+ }
}
void
@@ -174,7 +270,8 @@ _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx,
switch (extend) {
case CAIRO_EXTEND_NONE:
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2)
wrap_mode = GL_CLAMP_TO_EDGE;
else
wrap_mode = GL_CLAMP_TO_BORDER;
@@ -1178,6 +1275,8 @@ _cairo_gl_composite_init (cairo_gl_composite_t *setup,
{
cairo_status_t status;
+ status = _blit_texture_to_renderbuffer (dst);
+
memset (setup, 0, sizeof (cairo_gl_composite_t));
status = _cairo_gl_composite_set_operator (setup, op,
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index 2f56a5fd8..38582fd24 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -171,7 +171,8 @@ test_can_read_bgra (cairo_gl_flavor_t gl_flavor)
if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
return TRUE;
- assert (gl_flavor == CAIRO_GL_FLAVOR_ES2);
+ assert (gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ gl_flavor == CAIRO_GL_FLAVOR_ES2);
/* For OpenGL ES we have to look for the specific extension and BGRA only
* matches cairo's integer packed bytes on little-endian machines. */
@@ -190,7 +191,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
int n;
cairo_bool_t is_desktop = gl_flavor == CAIRO_GL_FLAVOR_DESKTOP;
- cairo_bool_t is_gles = gl_flavor == CAIRO_GL_FLAVOR_ES2;
+ cairo_bool_t is_gles = (gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ gl_flavor == CAIRO_GL_FLAVOR_ES2);
_cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
@@ -263,25 +265,31 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
}
#endif
-#if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT)
+#if CAIRO_HAS_GLESV3_SURFACE
+ if (is_gles && ctx->has_packed_depth_stencil) {
+ glGetIntegerv(GL_MAX_SAMPLES, &ctx->num_samples);
+ }
+
+#elif CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_EXT)
if (is_gles && ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension ("GL_EXT_multisampled_render_to_texture")) {
glGetIntegerv(GL_MAX_SAMPLES_EXT, &ctx->num_samples);
}
-#endif
-#if CAIRO_HAS_GLESV2_SURFACE && defined(GL_MAX_SAMPLES_IMG)
if (is_gles && ctx->has_packed_depth_stencil &&
_cairo_gl_has_extension ("GL_IMG_multisampled_render_to_texture")) {
glGetIntegerv(GL_MAX_SAMPLES_IMG, &ctx->num_samples);
}
#endif
- ctx->supports_msaa = ctx->num_samples > 1;
+ /* we always use renderbuffer for rendering in glesv3 */
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ ctx->supports_msaa = TRUE;
+ else
+ ctx->supports_msaa = ctx->num_samples > 1;
if (ctx->num_samples > MAX_MSAA_SAMPLES)
ctx->num_samples = MAX_MSAA_SAMPLES;
-
ctx->current_operator = -1;
ctx->gl_flavor = gl_flavor;
@@ -349,13 +357,15 @@ _get_depth_stencil_format (cairo_gl_context_t *ctx)
return GL_DEPTH_STENCIL;
#endif
-#if CAIRO_HAS_GLESV2_SURFACE
+#if CAIRO_HAS_GLESV2_SURFACE && !CAIRO_HAS_GLESV3_SURFACE
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
return GL_DEPTH24_STENCIL8_OES;
#endif
#if CAIRO_HAS_GL_SURFACE
return GL_DEPTH_STENCIL;
+#elif CAIRO_HAS_GLESV3_SURFACE
+ return GL_DEPTH24_STENCIL8;
#elif CAIRO_HAS_GLESV2_SURFACE
return GL_DEPTH24_STENCIL8_OES;
#endif
@@ -436,13 +446,14 @@ _cairo_gl_ensure_framebuffer (cairo_gl_context_t *ctx,
str, status);
}
}
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
_cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
{
assert (surface->supports_msaa);
- assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
+ assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
if (surface->msaa_fb)
return;
@@ -460,7 +471,11 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
this information. */
ctx->dispatch.RenderbufferStorageMultisample (GL_RENDERBUFFER,
ctx->num_samples,
+#if CAIRO_HAS_GLESV3_SURFACE
+ GL_RGBA8,
+#else
GL_RGBA,
+#endif
surface->width,
surface->height);
ctx->dispatch.FramebufferRenderbuffer (GL_FRAMEBUFFER,
@@ -472,6 +487,11 @@ _cairo_gl_ensure_multisampling (cairo_gl_context_t *ctx,
glDisable (GL_SCISSOR_TEST);
glClearColor (0, 0, 0, 0);
glClear (GL_COLOR_BUFFER_BIT);
+
+ /* for glesv3 with multisample renderbuffer, we always render to
+ this renderbuffer */
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ surface->msaa_active = TRUE;
}
#endif
@@ -484,8 +504,9 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
return TRUE;
_cairo_gl_ensure_framebuffer (ctx, surface);
-#if CAIRO_HAS_GL_SURFACE
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
_cairo_gl_ensure_multisampling (ctx, surface);
#endif
@@ -499,8 +520,9 @@ _cairo_gl_ensure_msaa_depth_stencil_buffer (cairo_gl_context_t *ctx,
surface->width,
surface->height);
-#if CAIRO_HAS_GL_SURFACE
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP) {
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) {
dispatch->FramebufferRenderbuffer (GL_FRAMEBUFFER,
GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
@@ -615,7 +637,7 @@ _gl_identity_ortho (GLfloat *m,
#undef M
}
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
bind_multisample_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
@@ -624,14 +646,19 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx,
cairo_bool_t scissor_test_enabled;
assert (surface->supports_msaa);
- assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
+ assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
_cairo_gl_ensure_framebuffer (ctx, surface);
_cairo_gl_ensure_multisampling (ctx, surface);
if (surface->msaa_active) {
+#if CAIRO_HAS_GL_SURFACE
glEnable (GL_MULTISAMPLE);
+#endif
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ surface->content_in_texture = FALSE;
return;
}
@@ -642,7 +669,9 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx,
glDisable (GL_STENCIL_TEST);
glDisable (GL_SCISSOR_TEST);
+#if CAIRO_HAS_GL_SURFACE
glEnable (GL_MULTISAMPLE);
+#endif
/* The last time we drew to the surface, we were not using multisampling,
so we need to blit from the non-multisampling framebuffer into the
@@ -651,17 +680,24 @@ bind_multisample_framebuffer (cairo_gl_context_t *ctx,
ctx->dispatch.BindFramebuffer (GL_READ_FRAMEBUFFER, surface->fb);
ctx->dispatch.BlitFramebuffer (0, 0, surface->width, surface->height,
0, 0, surface->width, surface->height,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ GL_COLOR_BUFFER_BIT
+#if CAIRO_HAS_GL_SURFACE
+ | GL_STENCIL_BUFFER_BIT
+#endif
+ ,
+ GL_NEAREST);
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
if (stencil_test_enabled)
glEnable (GL_STENCIL_TEST);
if (scissor_test_enabled)
glEnable (GL_SCISSOR_TEST);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ surface->content_in_texture = FALSE;
}
#endif
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
static void
bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
cairo_gl_surface_t *surface)
@@ -669,11 +705,15 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
cairo_bool_t stencil_test_enabled;
cairo_bool_t scissor_test_enabled;
- assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
+ assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3);
_cairo_gl_ensure_framebuffer (ctx, surface);
if (! surface->msaa_active) {
+#if CAIRO_HAS_GL_SURFACE
glDisable (GL_MULTISAMPLE);
+#endif
+
ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
return;
}
@@ -685,7 +725,9 @@ bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
glDisable (GL_STENCIL_TEST);
glDisable (GL_SCISSOR_TEST);
+#if CAIRO_HAS_GL_SURFACE
glDisable (GL_MULTISAMPLE);
+#endif
/* The last time we drew to the surface, we were using multisampling,
so we need to blit from the multisampling framebuffer into the
@@ -718,7 +760,7 @@ _cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
return;
}
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (multisampling)
bind_multisample_framebuffer (ctx, surface);
else
@@ -737,7 +779,8 @@ _cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
#endif
}
- surface->msaa_active = multisampling;
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ surface->msaa_active = multisampling;
}
void
@@ -751,9 +794,13 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
* we create an OpenGL ES surface, so we can never switch modes. */
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2)
multisampling = surface->msaa_active;
+ /* For GLESV3, we always use renderbuffer for drawing */
+ else if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ multisampling = TRUE;
changing_surface = ctx->current_target != surface || surface->needs_update;
- changing_sampling = surface->msaa_active != multisampling;
+ changing_sampling = (surface->msaa_active != multisampling ||
+ surface->content_in_texture);
if (! changing_surface && ! changing_sampling)
return;
diff --git a/src/cairo-gl-dispatch.c b/src/cairo-gl-dispatch.c
index 3e3721922..a49199dbb 100644
--- a/src/cairo-gl-dispatch.c
+++ b/src/cairo-gl-dispatch.c
@@ -124,6 +124,10 @@ _cairo_gl_dispatch_init_buffers (cairo_gl_dispatch_t *dispatch,
else
return CAIRO_STATUS_DEVICE_ERROR;
}
+ else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ {
+ dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
+ }
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
@@ -156,6 +160,10 @@ _cairo_gl_dispatch_init_shaders (cairo_gl_dispatch_t *dispatch,
else
return CAIRO_STATUS_DEVICE_ERROR;
}
+ else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ {
+ dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
+ }
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
@@ -189,6 +197,10 @@ _cairo_gl_dispatch_init_fbo (cairo_gl_dispatch_t *dispatch,
else
return CAIRO_STATUS_DEVICE_ERROR;
}
+ else if (gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ {
+ dispatch_name = CAIRO_GL_DISPATCH_NAME_CORE;
+ }
else if (gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
gl_version >= CAIRO_GL_VERSION_ENCODE (2, 0))
{
diff --git a/src/cairo-gl-gradient-private.h b/src/cairo-gl-gradient-private.h
index 77f9bbdc5..0d9f41f54 100644
--- a/src/cairo-gl-gradient-private.h
+++ b/src/cairo-gl-gradient-private.h
@@ -51,12 +51,15 @@
#include "cairo-gl.h"
-#if CAIRO_HAS_GL_SURFACE
-#include <GL/gl.h>
-#include <GL/glext.h>
+#if CAIRO_HAS_GLESV3_SURFACE
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#elif CAIRO_HAS_GL_SURFACE
+#include <GL/gl.h>
+#include <GL/glext.h>
#endif
#define CAIRO_GL_GRADIENT_CACHE_SIZE 4096
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index db82c23d8..0ab01ac3e 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -282,7 +282,8 @@ _cairo_gl_gradient_create (cairo_gl_context_t *ctx,
* In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat'
* must match 'format' in glTexImage2D.
*/
- if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2)
+ if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 ||
+ _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2)
internal_format = GL_BGRA;
else
internal_format = GL_RGBA;
diff --git a/src/cairo-gl-info.c b/src/cairo-gl-info.c
index a4b42715d..032e2568e 100644
--- a/src/cairo-gl-info.c
+++ b/src/cairo-gl-info.c
@@ -65,7 +65,9 @@ _cairo_gl_get_flavor (void)
if (version == NULL)
flavor = CAIRO_GL_FLAVOR_NONE;
- else if (strstr (version, "OpenGL ES") != NULL)
+ else if (strstr (version, "OpenGL ES 3") != NULL)
+ flavor = CAIRO_GL_FLAVOR_ES3;
+ else if (strstr (version, "OpenGL ES 2") != NULL)
flavor = CAIRO_GL_FLAVOR_ES2;
else
flavor = CAIRO_GL_FLAVOR_DESKTOP;
diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c
index 507459de3..f9cd7c296 100644
--- a/src/cairo-gl-msaa-compositor.c
+++ b/src/cairo-gl-msaa-compositor.c
@@ -273,6 +273,8 @@ static cairo_bool_t
can_use_msaa_compositor (cairo_gl_surface_t *surface,
cairo_antialias_t antialias)
{
+ cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor;
+
query_surface_capabilities (surface);
if (! surface->supports_stencil)
return FALSE;
@@ -280,8 +282,10 @@ can_use_msaa_compositor (cairo_gl_surface_t *surface,
/* Multisampling OpenGL ES surfaces only maintain one multisampling
framebuffer and thus must use the spans compositor to do non-antialiased
rendering. */
- if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2
+ if ((gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ gl_flavor == CAIRO_GL_FLAVOR_ES2)
&& surface->supports_msaa
+ && surface->num_samples > 1
&& antialias == CAIRO_ANTIALIAS_NONE)
return FALSE;
@@ -378,6 +382,9 @@ _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compos
FALSE);
if (unlikely (status))
goto finish;
+
+ _cairo_gl_context_set_destination (ctx, dst, setup.multisample);
+
status = _cairo_gl_set_operands_and_operator (&setup, ctx);
if (unlikely (status))
goto finish;
@@ -634,6 +641,7 @@ query_surface_capabilities (cairo_gl_surface_t *surface)
glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
surface->supports_stencil = stencil_bits > 0;
surface->supports_msaa = samples > 1;
+ surface->num_samples = samples;
status = _cairo_gl_context_release (ctx, status);
}
diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c
index ca1fa4b6b..8626329e0 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -658,7 +658,8 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
* with CAIRO_EXTEND_NONE). When bilinear filtering is enabled,
* these shaders need the texture dimensions for their calculations.
*/
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE &&
_cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR)
{
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index b2d8545ce..f02a58763 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -60,12 +60,15 @@
#include <assert.h>
-#if CAIRO_HAS_GL_SURFACE
-#include <GL/gl.h>
-#include <GL/glext.h>
+#if CAIRO_HAS_GLESV3_SURFACE
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
#elif CAIRO_HAS_GLESV2_SURFACE
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#elif CAIRO_HAS_GL_SURFACE
+#include <GL/gl.h>
+#include <GL/glext.h>
#endif
#include "cairo-gl-ext-def-private.h"
@@ -99,11 +102,12 @@
typedef struct _cairo_gl_surface cairo_gl_surface_t;
-/* GL flavor */
+/* GL flavor is the type of GL supported by the underlying platform. */
typedef enum cairo_gl_flavor {
CAIRO_GL_FLAVOR_NONE = 0,
CAIRO_GL_FLAVOR_DESKTOP = 1,
- CAIRO_GL_FLAVOR_ES2 = 2
+ CAIRO_GL_FLAVOR_ES2 = 2,
+ CAIRO_GL_FLAVOR_ES3 = 3
} cairo_gl_flavor_t;
/* Indices for vertex attributes used by BindAttribLocation, etc. */
@@ -169,7 +173,7 @@ struct _cairo_gl_surface {
GLuint fb; /* GL framebuffer object wrapping our data. */
GLuint depth_stencil; /* GL renderbuffer object for holding stencil buffer clip. */
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
GLuint msaa_rb; /* The ARB MSAA path uses a renderbuffer. */
GLuint msaa_fb;
#endif
@@ -178,8 +182,12 @@ struct _cairo_gl_surface {
cairo_bool_t stencil_and_msaa_caps_initialized;
cairo_bool_t supports_stencil; /* Stencil support for for non-texture surfaces. */
cairo_bool_t supports_msaa;
+ GLint num_samples;
cairo_bool_t msaa_active; /* Whether the multisampling
framebuffer is active or not. */
+ cairo_bool_t content_in_texture; /* whether we just uploaded image
+ to texture, used for certain
+ gles2 extensions and glesv3 */
cairo_clip_t *clip_on_stencil_buffer;
int owns_tex;
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index aceb5d255..7d4fefbbc 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -398,7 +398,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
"vec4 get_%s()\n"
"{\n",
rectstr, namestr, namestr, namestr, namestr);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
@@ -425,7 +426,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
"vec4 get_%s()\n"
"{\n",
namestr, namestr, rectstr, namestr, namestr);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
@@ -462,7 +464,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
" float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n",
namestr, namestr, rectstr, namestr, namestr, namestr, namestr,
namestr, namestr, namestr, namestr, namestr);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
@@ -507,7 +510,8 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
" float upper_t = mix (t.y, t.x, is_valid.x);\n",
namestr, namestr, rectstr, namestr, namestr, namestr, namestr,
namestr, namestr, namestr, namestr, namestr, namestr);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 &&
+ if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) &&
_cairo_gl_shader_needs_border_fade (op))
{
_cairo_output_stream_printf (stream,
@@ -674,7 +678,8 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
_cairo_gl_shader_emit_wrap (ctx, stream, src, CAIRO_GL_TEX_SOURCE);
_cairo_gl_shader_emit_wrap (ctx, stream, mask, CAIRO_GL_TEX_MASK);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2) {
if (_cairo_gl_shader_needs_border_fade (src))
_cairo_gl_shader_emit_border_fade (stream, src, CAIRO_GL_TEX_SOURCE);
if (_cairo_gl_shader_needs_border_fade (mask))
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 8ecc3a92e..6be6d9868 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -395,6 +395,7 @@ _cairo_gl_surface_init (cairo_device_t *device,
surface->width = width;
surface->height = height;
surface->needs_update = FALSE;
+ surface->content_in_texture = FALSE;
_cairo_gl_surface_embedded_operand_init (surface);
}
@@ -433,6 +434,7 @@ _cairo_gl_surface_create_scratch_for_texture (cairo_gl_context_t *ctx,
_cairo_gl_surface_init (&ctx->base, surface, content, width, height);
surface->supports_msaa = ctx->supports_msaa;
+ surface->num_samples = ctx->num_samples;
surface->supports_stencil = TRUE;
/* Create the texture used to store the surface's data. */
@@ -875,7 +877,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
if (unlikely (status))
return status;
- if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
+ if (_cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES3 ||
+ _cairo_gl_get_flavor () == CAIRO_GL_FLAVOR_ES2) {
pixman_format_code_t pixman_format;
cairo_surface_pattern_t pattern;
cairo_bool_t require_conversion = FALSE;
@@ -885,13 +888,12 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
if (src->pixman_format != pixman_format)
require_conversion = TRUE;
}
- else if (dst->base.content != CAIRO_CONTENT_ALPHA)
+ else if (dst->base.content != CAIRO_CONTENT_ALPHA) {
+ require_conversion = TRUE;
+ }
+ else if (src->pixman_format != PIXMAN_a8) {
+ pixman_format = PIXMAN_a8;
require_conversion = TRUE;
- else {
- if (src->pixman_format == PIXMAN_a1) {
- pixman_format = PIXMAN_a8;
- require_conversion = TRUE;
- }
}
if (require_conversion) {
@@ -980,10 +982,19 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
else
{
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
glPixelStorei (GL_UNPACK_ROW_LENGTH, src->stride / cpp);
}
+ /* we must resolve the renderbuffer to texture before we
+ upload image */
+ status = _cairo_gl_surface_resolve_multisampling (dst);
+ if (unlikely (status)) {
+ free (data_start_gles2);
+ goto FAIL;
+ }
+
_cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP);
glBindTexture (ctx->tex_target, dst->tex);
glTexParameteri (ctx->tex_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -1003,6 +1014,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
dst_x, dst_y,
width, height);
}
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ dst->content_in_texture = TRUE;
} else {
cairo_surface_t *tmp;
@@ -1042,6 +1055,8 @@ _cairo_gl_surface_draw_image (cairo_gl_surface_t *dst,
}
cairo_surface_destroy (tmp);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ dst->content_in_texture = TRUE;
}
FAIL:
@@ -1092,7 +1107,7 @@ _cairo_gl_surface_finish (void *abstract_surface)
if (surface->msaa_depth_stencil)
ctx->dispatch.DeleteRenderbuffers (1, &surface->msaa_depth_stencil);
-#if CAIRO_HAS_GL_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV3_SURFACE
if (surface->msaa_fb)
ctx->dispatch.DeleteFramebuffers (1, &surface->msaa_fb);
if (surface->msaa_rb)
@@ -1144,7 +1159,8 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
return NULL;
}
- if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) {
+ if (_cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES3 ||
+ _cairo_gl_surface_flavor (surface) == CAIRO_GL_FLAVOR_ES2) {
/* If only RGBA is supported, we must download data in a compatible
* format. This means that pixman will convert the data on the CPU when
* interacting with other image surfaces. For ALPHA, GLES2 does not
@@ -1193,13 +1209,29 @@ _cairo_gl_surface_map_to_image (void *abstract_surface,
* fall back instead.
*/
_cairo_gl_composite_flush (ctx);
- _cairo_gl_context_set_destination (ctx, surface, FALSE);
+
+ if (ctx->gl_flavor != CAIRO_GL_FLAVOR_ES3) {
+ _cairo_gl_context_set_destination (ctx, surface, FALSE);
+ } else {
+ if (surface->content_in_texture) {
+ _cairo_gl_ensure_framebuffer (ctx, surface);
+ ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
+ } else {
+ status = _cairo_gl_surface_resolve_multisampling (surface);
+ if (unlikely (status)) {
+ status = _cairo_gl_context_release (ctx, status);
+ cairo_surface_destroy (&image->base);
+ return _cairo_image_surface_create_in_error (status);
+ }
+ }
+ }
flipped = ! _cairo_gl_surface_is_texture (surface);
mesa_invert = flipped && ctx->has_mesa_pack_invert;
glPixelStorei (GL_PACK_ALIGNMENT, 4);
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP ||
+ ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
glPixelStorei (GL_PACK_ROW_LENGTH, image->stride / cpp);
if (mesa_invert)
glPixelStorei (GL_PACK_INVERT_MESA, 1);
@@ -1366,6 +1398,9 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
/* GLES surfaces do not need explicit resolution. */
if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES2)
return CAIRO_INT_STATUS_SUCCESS;
+ else if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES3 &&
+ surface->content_in_texture)
+ return CAIRO_INT_STATUS_SUCCESS;
if (! _cairo_gl_surface_is_texture (surface))
return CAIRO_INT_STATUS_SUCCESS;
@@ -1374,10 +1409,20 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
if (unlikely (status))
return status;
- ctx->current_target = surface;
+#if CAIRO_HAS_GLESV3_SURFACE
+ _cairo_gl_composite_flush (ctx);
+ ctx->current_target = NULL;
+ _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
+ if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
+ surface->content_in_texture = TRUE;
-#if CAIRO_HAS_GL_SURFACE
+#elif CAIRO_HAS_GL_SURFACE
+ ctx->current_target = surface;
_cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
+
+#else
+ ctx->current_target = surface;
+
#endif
status = _cairo_gl_context_release (ctx, status);
diff --git a/src/cairo-gl.h b/src/cairo-gl.h
index 9fd7608f5..7cd869c76 100644
--- a/src/cairo-gl.h
+++ b/src/cairo-gl.h
@@ -62,7 +62,7 @@
#include "cairo.h"
-#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE
+#if CAIRO_HAS_GL_SURFACE || CAIRO_HAS_GLESV2_SURFACE || CAIRO_HAS_GLESV3_SURFACE
CAIRO_BEGIN_DECLS