summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cogl/cogl-context-private.h5
-rw-r--r--cogl/driver/gl/cogl-framebuffer-gl.c29
-rw-r--r--cogl/gl-prototypes/cogl-all-functions.h8
-rw-r--r--cogl/winsys/cogl-winsys-egl-feature-functions.h6
-rw-r--r--cogl/winsys/cogl-winsys-egl-kms.c48
-rw-r--r--cogl/winsys/cogl-winsys-egl-private.h3
-rw-r--r--cogl/winsys/cogl-winsys-egl-wayland.c68
-rw-r--r--cogl/winsys/cogl-winsys-egl-x11.c58
8 files changed, 154 insertions, 71 deletions
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index c5a125de..32f2aa29 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -200,6 +200,11 @@ struct _CoglContext
CoglGLES2Context *current_gles2_context;
GQueue gles2_context_stack;
+ /* This becomes TRUE the first time the context is bound to an
+ * onscreen buffer. This is used by cogl-framebuffer-gl to determine
+ * when to initialise the glDrawBuffer state */
+ CoglBool was_bound_to_onscreen;
+
/* Primitives */
CoglPipeline *stencil_pipeline;
diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c
index ce2b5b57..5ef84867 100644
--- a/cogl/driver/gl/cogl-framebuffer-gl.c
+++ b/cogl/driver/gl/cogl-framebuffer-gl.c
@@ -255,6 +255,35 @@ _cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
/* glBindFramebuffer is an an extension with OpenGL ES 1.1 */
if (cogl_has_feature (ctx, COGL_FEATURE_ID_OFFSCREEN))
GE (ctx, glBindFramebuffer (target, 0));
+
+ /* Initialise the glDrawBuffer state the first time the context
+ * is bound to the default framebuffer. If the winsys is using a
+ * surfaceless context for the initial make current then the
+ * default draw buffer will be GL_NONE so we need to correct
+ * that. We can't do it any earlier because binding GL_BACK when
+ * there is no default framebuffer won't work */
+ if (!ctx->was_bound_to_onscreen)
+ {
+ if (ctx->glDrawBuffer)
+ {
+ GE (ctx, glDrawBuffer (GL_BACK));
+ }
+ else if (ctx->glDrawBuffers)
+ {
+ /* glDrawBuffer isn't available on GLES 3.0 so we need
+ * to be able to use glDrawBuffers as well. On GLES 2
+ * neither is available but the state should always be
+ * GL_BACK anyway so we don't need to set anything. On
+ * desktop GL this must be GL_BACK_LEFT instead of
+ * GL_BACK but as this code path will only be hit for
+ * GLES we can just use GL_BACK. */
+ static const GLenum buffers[] = { GL_BACK };
+
+ GE (ctx, glDrawBuffers (G_N_ELEMENTS (buffers), buffers));
+ }
+
+ ctx->was_bound_to_onscreen = TRUE;
+ }
}
}
diff --git a/cogl/gl-prototypes/cogl-all-functions.h b/cogl/gl-prototypes/cogl-all-functions.h
index b3d7739e..a8a6e61a 100644
--- a/cogl/gl-prototypes/cogl-all-functions.h
+++ b/cogl/gl-prototypes/cogl-all-functions.h
@@ -318,3 +318,11 @@ COGL_EXT_FUNCTION (void, glDeleteSync,
(GLsync sync))
COGL_EXT_END ()
#endif
+
+COGL_EXT_BEGIN (draw_buffers, 2, 0,
+ COGL_EXT_IN_GLES3,
+ "ARB\0EXT\0",
+ "draw_buffers\0")
+COGL_EXT_FUNCTION (void, glDrawBuffers,
+ (GLsizei n, const GLenum *bufs))
+COGL_EXT_END ()
diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h
index ae2acfe9..8433e19a 100644
--- a/cogl/winsys/cogl-winsys-egl-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h
@@ -142,3 +142,9 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroySync,
EGLSyncKHR sync))
COGL_WINSYS_FEATURE_END ()
#endif
+
+COGL_WINSYS_FEATURE_BEGIN (surfaceless_context,
+ "KHR\0",
+ "surfaceless_context\0",
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT)
+COGL_WINSYS_FEATURE_END ()
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 6d498d4a..eb89b60a 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -782,29 +782,35 @@ _cogl_winsys_egl_context_created (CoglDisplay *display,
CoglRendererEGL *egl_renderer = renderer->winsys;
CoglRendererKMS *kms_renderer = egl_renderer->platform;
- kms_display->dummy_gbm_surface = gbm_surface_create (kms_renderer->gbm,
- 16, 16,
- GBM_FORMAT_XRGB8888,
- GBM_BO_USE_RENDERING);
- if (!kms_display->dummy_gbm_surface)
+ if ((egl_renderer->private_features &
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0)
{
- _cogl_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Failed to create dummy GBM surface");
- return FALSE;
- }
+ kms_display->dummy_gbm_surface =
+ gbm_surface_create (kms_renderer->gbm,
+ 16, 16,
+ GBM_FORMAT_XRGB8888,
+ GBM_BO_USE_RENDERING);
+ if (!kms_display->dummy_gbm_surface)
+ {
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to create dummy GBM surface");
+ return FALSE;
+ }
- egl_display->dummy_surface =
- eglCreateWindowSurface (egl_renderer->edpy,
- egl_display->egl_config,
- (NativeWindowType) kms_display->dummy_gbm_surface,
- NULL);
- if (egl_display->dummy_surface == EGL_NO_SURFACE)
- {
- _cogl_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Failed to create dummy EGL surface");
- return FALSE;
+ egl_display->dummy_surface =
+ eglCreateWindowSurface (egl_renderer->edpy,
+ egl_display->egl_config,
+ (NativeWindowType)
+ kms_display->dummy_gbm_surface,
+ NULL);
+ if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ {
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to create dummy EGL surface");
+ return FALSE;
+ }
}
if (!_cogl_winsys_egl_make_current (display,
diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h
index ff05226a..3cee0fc9 100644
--- a/cogl/winsys/cogl-winsys-egl-private.h
+++ b/cogl/winsys/cogl-winsys-egl-private.h
@@ -99,7 +99,8 @@ typedef enum _CoglEGLWinsysFeature
COGL_EGL_WINSYS_FEATURE_EGL_IMAGE_FROM_WAYLAND_BUFFER =1L<<2,
COGL_EGL_WINSYS_FEATURE_CREATE_CONTEXT =1L<<3,
COGL_EGL_WINSYS_FEATURE_BUFFER_AGE =1L<<4,
- COGL_EGL_WINSYS_FEATURE_FENCE_SYNC =1L<<5
+ COGL_EGL_WINSYS_FEATURE_FENCE_SYNC =1L<<5,
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT =1L<<6
} CoglEGLWinsysFeature;
typedef struct _CoglRendererEGL
diff --git a/cogl/winsys/cogl-winsys-egl-wayland.c b/cogl/winsys/cogl-winsys-egl-wayland.c
index fb84eec9..6a68bd63 100644
--- a/cogl/winsys/cogl-winsys-egl-wayland.c
+++ b/cogl/winsys/cogl-winsys-egl-wayland.c
@@ -64,8 +64,8 @@ typedef struct _CoglRendererWayland
typedef struct _CoglDisplayWayland
{
- struct wl_surface *wayland_surface;
- struct wl_egl_window *wayland_egl_native_window;
+ struct wl_surface *dummy_wayland_surface;
+ struct wl_egl_window *dummy_wayland_egl_native_window;
} CoglDisplayWayland;
typedef struct _CoglOnscreenWayland
@@ -324,8 +324,8 @@ _cogl_winsys_egl_display_destroy (CoglDisplay *display)
}
static CoglBool
-_cogl_winsys_egl_context_created (CoglDisplay *display,
- CoglError **error)
+make_dummy_surface (CoglDisplay *display,
+ CoglError **error)
{
CoglRenderer *renderer = display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
@@ -334,19 +334,19 @@ _cogl_winsys_egl_context_created (CoglDisplay *display,
CoglDisplayWayland *wayland_display = egl_display->platform;
const char *error_message;
- wayland_display->wayland_surface =
+ wayland_display->dummy_wayland_surface =
wl_compositor_create_surface (wayland_renderer->wayland_compositor);
- if (!wayland_display->wayland_surface)
+ if (!wayland_display->dummy_wayland_surface)
{
error_message= "Failed to create a dummy wayland surface";
goto fail;
}
- wayland_display->wayland_egl_native_window =
- wl_egl_window_create (wayland_display->wayland_surface,
+ wayland_display->dummy_wayland_egl_native_window =
+ wl_egl_window_create (wayland_display->dummy_wayland_surface,
1,
1);
- if (!wayland_display->wayland_egl_native_window)
+ if (!wayland_display->dummy_wayland_egl_native_window)
{
error_message= "Failed to create a dummy wayland native egl surface";
goto fail;
@@ -356,7 +356,7 @@ _cogl_winsys_egl_context_created (CoglDisplay *display,
eglCreateWindowSurface (egl_renderer->edpy,
egl_display->egl_config,
(EGLNativeWindowType)
- wayland_display->wayland_egl_native_window,
+ wayland_display->dummy_wayland_egl_native_window,
NULL);
if (egl_display->dummy_surface == EGL_NO_SURFACE)
{
@@ -364,22 +364,42 @@ _cogl_winsys_egl_context_created (CoglDisplay *display,
goto fail;
}
+ return TRUE;
+
+ fail:
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "%s", error_message);
+
+ return FALSE;
+}
+
+static CoglBool
+_cogl_winsys_egl_context_created (CoglDisplay *display,
+ CoglError **error)
+{
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglDisplayEGL *egl_display = display->winsys;
+
+ if ((egl_renderer->private_features &
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0 &&
+ !make_dummy_surface(display, error))
+ return FALSE;
+
if (!_cogl_winsys_egl_make_current (display,
egl_display->dummy_surface,
egl_display->dummy_surface,
egl_display->egl_context))
{
- error_message = "Unable to eglMakeCurrent with dummy surface";
- goto fail;
+ _cogl_set_error (error,
+ COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "%s",
+ "Unable to eglMakeCurrent with dummy surface");
}
return TRUE;
-
- fail:
- _cogl_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "%s", error_message);
- return FALSE;
}
static void
@@ -396,16 +416,16 @@ _cogl_winsys_egl_cleanup_context (CoglDisplay *display)
egl_display->dummy_surface = EGL_NO_SURFACE;
}
- if (wayland_display->wayland_egl_native_window)
+ if (wayland_display->dummy_wayland_egl_native_window)
{
- wl_egl_window_destroy (wayland_display->wayland_egl_native_window);
- wayland_display->wayland_egl_native_window = NULL;
+ wl_egl_window_destroy (wayland_display->dummy_wayland_egl_native_window);
+ wayland_display->dummy_wayland_egl_native_window = NULL;
}
- if (wayland_display->wayland_surface)
+ if (wayland_display->dummy_wayland_surface)
{
- wl_surface_destroy (wayland_display->wayland_surface);
- wayland_display->wayland_surface = NULL;
+ wl_surface_destroy (wayland_display->dummy_wayland_surface);
+ wayland_display->dummy_wayland_surface = NULL;
}
}
diff --git a/cogl/winsys/cogl-winsys-egl-x11.c b/cogl/winsys/cogl-winsys-egl-x11.c
index c530fd1b..02b54fe6 100644
--- a/cogl/winsys/cogl-winsys-egl-x11.c
+++ b/cogl/winsys/cogl-winsys-egl-x11.c
@@ -610,39 +610,47 @@ _cogl_winsys_egl_context_created (CoglDisplay *display,
AllocNone);
attrs.border_pixel = 0;
- xlib_display->dummy_xwin =
- XCreateWindow (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- -100, -100, 1, 1,
- 0,
- xvisinfo->depth,
- CopyFromParent,
- xvisinfo->visual,
- CWOverrideRedirect |
- CWColormap |
- CWBorderPixel,
- &attrs);
-
- XFree (xvisinfo);
-
- egl_display->dummy_surface =
- eglCreateWindowSurface (egl_renderer->edpy,
- egl_display->egl_config,
- (NativeWindowType) xlib_display->dummy_xwin,
- NULL);
-
- if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ if ((egl_renderer->private_features &
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0)
{
- error_message = "Unable to create an EGL surface";
- goto fail;
+ xlib_display->dummy_xwin =
+ XCreateWindow (xlib_renderer->xdpy,
+ DefaultRootWindow (xlib_renderer->xdpy),
+ -100, -100, 1, 1,
+ 0,
+ xvisinfo->depth,
+ CopyFromParent,
+ xvisinfo->visual,
+ CWOverrideRedirect |
+ CWColormap |
+ CWBorderPixel,
+ &attrs);
+
+ egl_display->dummy_surface =
+ eglCreateWindowSurface (egl_renderer->edpy,
+ egl_display->egl_config,
+ (NativeWindowType) xlib_display->dummy_xwin,
+ NULL);
+
+ if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ {
+ error_message = "Unable to create an EGL surface";
+ XFree (xvisinfo);
+ goto fail;
+ }
}
+ XFree (xvisinfo);
+
if (!_cogl_winsys_egl_make_current (display,
egl_display->dummy_surface,
egl_display->dummy_surface,
egl_display->egl_context))
{
- error_message = "Unable to eglMakeCurrent with dummy surface";
+ if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ error_message = "Unable to eglMakeCurrent with no surface";
+ else
+ error_message = "Unable to eglMakeCurrent with dummy surface";
goto fail;
}