[PATCH v2 3/3] gl: add support for OpenGL ES 3.0
Bryce Harrington <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[email protected]> |
This improves the OpenGL ES support to extend it to version 3.0. A number of new features are available in glesv3 including creation of multi-sampled renderbuffers. These renderbuffers can be blitted to single sample textures (but not the other way around). Other features such as PBO for image uploading, are left as followon work. For this preliminary implementation, glesv3 backends always create renderbuffers, which can be set as single sample or multisample. The renderbuffer's content is blitted to the texture only when used as a source or a mask. Images uploaded to a texture stay there until the surface is used as a rendering target, at which point its painted to the renderbuffer. This patch is heavily based off of Henry Song's GLESv3 patch 6f7f3795 from his cairogles fork of Cairo. Signed-off-by: Bryce Harrington <[email protected]> --- This v2 of the patch rolls in some of the subsequent fixes from Henry's tree, and makes a few other changes based on code reviews: * Drop unneeded uninstall .pc file * Note in configure.ac why we link against -lGLESv2 for v3 support * Don't allow configuring both --enable-glesv3 and --enable-gl * Allow --enable-glesv3 and --enable-glesv2 to both be specified, in which case v3 will be preferred with v2 used as fallback. * Flavor should always track the system's GLES version instead of pretending to be v2 if only cairo v2 surfaces were configured. * Try ES3_BIT_KHR first, then retry with ES2_BIT * Restructure tests throughout code to try glesv3 1st, v2 2nd * Improve cairo-gl-info handling of glesv3 * Improve docs for the gl enum * Improve FIXME to explain that ANGLE functionality needs implemented first, which will require much more code. * Fix num_samples type in cairo-gl-private.h * Remove glDrawBuffer and glReadBuffer for glesv3. There is no need to call these once glBindFramebuffer is called. * Preserve non-glesv3 behavior for the _cairo_gl_surface_resolve_multisampling current_target setting * Simplify gl_flavor if statement checks * Straighten out if clause bracketing in cairo-gl-surface.c * Do not blit stencil buffer for glesv3 surface. For glesv3 surface, there is no need to blit the stencil buffer from the multisample renderbuffer to the texture, because the texture is never a rendering target. * Free data_start_gles2 if resolve multisampling fails in upload image. * Added a comment in configure.ac that yes, indeed, to build the glesv3 code you need to link against -lGLESv2 (there is no libGLESv3 provided by mesa.) * The FIXME added to cairo-gl-composite.c is now explained better, as requested by Uli. The FIXME can only really be resolved once ANGLE is implemented, but that'll require a fair bit more code to be landed first. There's no functional regression caused by leaving this out for the time being. * Non-glesv3 behavior is preserved for the _cairo_gl_surface_resolve_multisampling current_target setting. Uli noted the glesv3 patch was introducing a side-effect for glesv2. I don't think it would cause any functional regression but I've restructured the code to avoid the situation when glesv3 is not enabled. * Fix num_samples type in cairo-gl-private.h. It was erroneously being defined as a cairo_bool_t but since it's a number it obviously needs to be a GLint. * Remove glDrawBuffer and glReadBuffer for glesv3. This code had been added in the original glesv3 patch but Henry later found it to be unneeded. * Added GL_STENCIL_BUFFER_BIT for the BlitFramebuffer call. For glesv3 surfaces, there is no need to blit the stencil buffer from the multisample renderbuffer to the texture, because the texture is never a rendering target. From Henry Song's fork. boilerplate/Makefile.win32.features | 12 +++++ boilerplate/cairo-boilerplate-egl.c | 30 ++++++++--- build/Makefile.win32.features | 1 + build/Makefile.win32.features-h | 3 ++ build/configure.ac.features | 1 + configure.ac | 23 ++++++++ src/Makefile.sources | 4 ++ src/Makefile.win32.features | 16 ++++++ src/cairo-gl-composite.c | 103 +++++++++++++++++++++++++++++++++++- src/cairo-gl-device.c | 91 +++++++++++++++++++++++-------- src/cairo-gl-dispatch.c | 12 +++++ src/cairo-gl-gradient-private.h | 9 ++-- src/cairo-gl-gradient.c | 3 +- src/cairo-gl-info.c | 2 + src/cairo-gl-msaa-compositor.c | 10 +++- src/cairo-gl-operand.c | 3 +- src/cairo-gl-private.h | 20 ++++--- src/cairo-gl-shaders.c | 15 ++++-- src/cairo-gl-surface.c | 73 ++++++++++++++++++++----- src/cairo-gl.h | 2 +- 20 files changed, 369 insertions(+), 64 deletions(-) diff --git a/boilerplate/Makefile.win32.features b/boilerplate/Makefile.win32.features index e60a95b..abb198d 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 99bee64..c44441c 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 8cb155d..7f62d97 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 13904cf..2825f0c 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 77f2035..aa48652 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 93953a7..264623d 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 b1e3eb1..89417ac 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 2274f4a..e8be9f7 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 a95712e..ecf03a5 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 2f56a5f..38582fd 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 3e37219..a49199d 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 77f9bbd..0d9f41f 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 db82c23..0ab01ac 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 39541aa..032e256 100644 --- a/src/cairo-gl-info.c +++ b/src/cairo-gl-info.c @@ -65,6 +65,8 @@ _cairo_gl_get_flavor (void) if (version == NULL) flavor = CAIRO_GL_FLAVOR_NONE; + 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 diff --git a/src/cairo-gl-msaa-compositor.c b/src/cairo-gl-msaa-compositor.c index 507459d..f9cd7c2 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 ca1fa4b..8626329 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 b2d8545..f02a587 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 aceb5d2..7d4fefb 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 8ecc3a9..6be6d98 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 9fd7608..7cd869c 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 -- 2.7.4 -- cairo mailing list [email protected] https://lists.cairographics.org/mailman/listinfo/cairo