From bac385833fddb5dadb3be1eaf7b6071991c4b048 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Jan 2019 11:01:38 -0500
Subject: [PATCH 1/9] cogl: add new UNSTABLE_TEXTURES feature
The proprietary nvidia driver garbles texture memory on suspend.
Before we can address that, we need to be able to detect it.
This commit adds a new UNSTABLE_TEXTURES feature that gets set if
the proprietary nvidia driver is in use.
---
cogl/cogl/cogl-context.h | 1 +
cogl/cogl/cogl-types.h | 5 ++++-
cogl/cogl/winsys/cogl-winsys-egl.c | 11 +++++++++++
cogl/cogl/winsys/cogl-winsys-glx.c | 13 +++++++++++--
4 files changed, 27 insertions(+), 3 deletions(-)
diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h
index add575b49..985ce336d 100644
--- a/cogl/cogl/cogl-context.h
+++ b/cogl/cogl/cogl-context.h
@@ -236,60 +236,61 @@ cogl_is_context (void *object);
* Since: 1.10
*/
typedef enum _CoglFeatureID
{
COGL_FEATURE_ID_TEXTURE_NPOT_BASIC = 1,
COGL_FEATURE_ID_TEXTURE_NPOT_MIPMAP,
COGL_FEATURE_ID_TEXTURE_NPOT_REPEAT,
COGL_FEATURE_ID_TEXTURE_NPOT,
COGL_FEATURE_ID_TEXTURE_RECTANGLE,
COGL_FEATURE_ID_TEXTURE_3D,
COGL_FEATURE_ID_GLSL,
COGL_FEATURE_ID_ARBFP,
COGL_FEATURE_ID_OFFSCREEN,
COGL_FEATURE_ID_OFFSCREEN_MULTISAMPLE,
COGL_FEATURE_ID_ONSCREEN_MULTIPLE,
COGL_FEATURE_ID_UNSIGNED_INT_INDICES,
COGL_FEATURE_ID_DEPTH_RANGE,
COGL_FEATURE_ID_POINT_SPRITE,
COGL_FEATURE_ID_MAP_BUFFER_FOR_READ,
COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE,
COGL_FEATURE_ID_MIRRORED_REPEAT,
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
COGL_FEATURE_ID_GLES2_CONTEXT,
COGL_FEATURE_ID_DEPTH_TEXTURE,
COGL_FEATURE_ID_PRESENTATION_TIME,
COGL_FEATURE_ID_FENCE,
COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
COGL_FEATURE_ID_TEXTURE_RG,
COGL_FEATURE_ID_BUFFER_AGE,
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
+ COGL_FEATURE_ID_UNSTABLE_TEXTURES,
/*< private >*/
_COGL_N_FEATURE_IDS /*< skip >*/
} CoglFeatureID;
/**
* cogl_has_feature:
* @context: A #CoglContext pointer
* @feature: A #CoglFeatureID
*
* Checks if a given @feature is currently available
*
* Cogl does not aim to be a lowest common denominator API, it aims to
* expose all the interesting features of GPUs to application which
* means applications have some responsibility to explicitly check
* that certain features are available before depending on them.
*
* Returns: %TRUE if the @feature is currently supported or %FALSE if
* not.
*
* Since: 1.10
* Stability: unstable
*/
CoglBool
cogl_has_feature (CoglContext *context, CoglFeatureID feature);
/**
* cogl_has_features:
* @context: A #CoglContext pointer
diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h
index f67895dd9..8338e284d 100644
--- a/cogl/cogl/cogl-types.h
+++ b/cogl/cogl/cogl-types.h
@@ -371,91 +371,94 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
* @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
* @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs
* @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
* @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
* @COGL_FEATURE_VBOS: VBO support
* @COGL_FEATURE_PBOS: PBO support
* @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
* cogl_vertex_buffer_indices_new().
* @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support
* @COGL_FEATURE_TEXTURE_NPOT_BASIC: The hardware supports non power
* of two textures, but you also need to check the
* %COGL_FEATURE_TEXTURE_NPOT_MIPMAP and %COGL_FEATURE_TEXTURE_NPOT_REPEAT
* features to know if the hardware supports npot texture mipmaps
* or repeat modes other than
* %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE respectively.
* @COGL_FEATURE_TEXTURE_NPOT_MIPMAP: Mipmapping is supported in
* conjuntion with non power of two textures.
* @COGL_FEATURE_TEXTURE_NPOT_REPEAT: Repeat modes other than
* %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE are supported by the
* hardware.
* @COGL_FEATURE_POINT_SPRITE: Whether
* cogl_material_set_layer_point_sprite_coords_enabled() is supported.
* @COGL_FEATURE_TEXTURE_3D: 3D texture support
* @COGL_FEATURE_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including read support.
* @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
* supported with CoglBufferAccess including write support.
* @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
* depth buffer to a texture.
+ * @COGL_FEATURE_UNSTABLE_TEXTURES: Whether textures require redrawing on
+ * resume or not.
*
* Flags for the supported features.
*
* Since: 0.8
*/
typedef enum
{
COGL_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
COGL_FEATURE_TEXTURE_NPOT = (1 << 2),
COGL_FEATURE_TEXTURE_YUV = (1 << 3),
COGL_FEATURE_TEXTURE_READ_PIXELS = (1 << 4),
COGL_FEATURE_SHADERS_GLSL = (1 << 5),
COGL_FEATURE_OFFSCREEN = (1 << 6),
COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7),
COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8),
COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9),
COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
COGL_FEATURE_VBOS = (1 << 11),
COGL_FEATURE_PBOS = (1 << 12),
COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13),
COGL_FEATURE_DEPTH_RANGE = (1 << 14),
COGL_FEATURE_TEXTURE_NPOT_BASIC = (1 << 15),
COGL_FEATURE_TEXTURE_NPOT_MIPMAP = (1 << 16),
COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17),
COGL_FEATURE_POINT_SPRITE = (1 << 18),
COGL_FEATURE_TEXTURE_3D = (1 << 19),
COGL_FEATURE_SHADERS_ARBFP = (1 << 20),
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),
- COGL_FEATURE_DEPTH_TEXTURE = (1 << 24)
+ COGL_FEATURE_DEPTH_TEXTURE = (1 << 24),
+ COGL_FEATURE_UNSTABLE_TEXTURES = (1 << 25)
} CoglFeatureFlags;
/**
* CoglBufferTarget:
* @COGL_WINDOW_BUFFER: FIXME
* @COGL_OFFSCREEN_BUFFER: FIXME
*
* Target flags for FBOs.
*
* Since: 0.8
*/
typedef enum
{
COGL_WINDOW_BUFFER = (1 << 1),
COGL_OFFSCREEN_BUFFER = (1 << 2)
} CoglBufferTarget;
/**
* CoglColor:
* @red: amount of red
* @green: amount of green
* @blue: amount of green
* @alpha: alpha
*
* A structure for holding a color definition. The contents of
* the CoglColor structure are private and should never by accessed
* directly.
*
* Since: 1.0
*/
diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c
index 73648f663..66c2661b3 100644
--- a/cogl/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/cogl/winsys/cogl-winsys-egl.c
@@ -475,72 +475,83 @@ _cogl_winsys_display_setup (CoglDisplay *display,
CoglRendererEGL *egl_renderer = display->renderer->winsys;
if (egl_renderer->pf_eglBindWaylandDisplay)
egl_renderer->pf_eglBindWaylandDisplay (egl_renderer->edpy,
wayland_display);
}
#endif
if (egl_renderer->platform_vtable->display_setup &&
!egl_renderer->platform_vtable->display_setup (display, error))
goto error;
if (!try_create_context (display, error))
goto error;
egl_display->found_egl_config = TRUE;
return TRUE;
error:
_cogl_winsys_display_destroy (display);
return FALSE;
}
static CoglBool
_cogl_winsys_context_init (CoglContext *context, CoglError **error)
{
CoglRenderer *renderer = context->display->renderer;
CoglDisplayEGL *egl_display = context->display->winsys;
CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglGpuInfo *info;
context->winsys = g_new0 (CoglContextEGL, 1);
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
memset (context->winsys_features, 0, sizeof (context->winsys_features));
check_egl_extensions (renderer);
if (!_cogl_context_update_features (context, error))
return FALSE;
+ info = &context->gpu;
+
+ if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
+ {
+ context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
+ COGL_FLAGS_SET (context->features,
+ COGL_FEATURE_ID_UNSTABLE_TEXTURES,
+ TRUE);
+ }
+
if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION)
{
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
}
if ((egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_FENCE_SYNC) &&
_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_OES_EGL_SYNC))
COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_FENCE, TRUE);
if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_BUFFER_AGE)
{
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_BUFFER_AGE,
TRUE);
COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_BUFFER_AGE, TRUE);
}
/* NB: We currently only support creating standalone GLES2 contexts
* for offscreen rendering and so we need a dummy (non-visible)
* surface to be able to bind those contexts */
if (egl_display->dummy_surface != EGL_NO_SURFACE &&
context->driver == COGL_DRIVER_GLES2)
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_GLES2_CONTEXT, TRUE);
if (egl_renderer->platform_vtable->context_init &&
!egl_renderer->platform_vtable->context_init (context, error))
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
index 74b0895d1..4a033c0c6 100644
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -805,149 +805,158 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
/* XXX: Note: For a long time Mesa exported a hybrid GLX, exporting
* extensions specified to require GLX 1.3, but still reporting 1.2
* via glXQueryVersion. */
if (!glx_renderer->glXQueryVersion (xlib_renderer->xdpy,
&glx_renderer->glx_major,
&glx_renderer->glx_minor)
|| !(glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 2))
{
_cogl_set_error (error, COGL_WINSYS_ERROR,
COGL_WINSYS_ERROR_INIT,
"XServer appears to lack required GLX 1.2 support");
goto error;
}
update_base_winsys_features (renderer);
glx_renderer->dri_fd = -1;
return TRUE;
error:
_cogl_winsys_renderer_disconnect (renderer);
return FALSE;
}
static CoglBool
update_winsys_features (CoglContext *context, CoglError **error)
{
CoglGLXDisplay *glx_display = context->display->winsys;
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
+ CoglGpuInfo *info;
_COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE);
if (!_cogl_context_update_features (context, error))
return FALSE;
+ info = &context->gpu;
+
memcpy (context->winsys_features,
glx_renderer->base_winsys_features,
sizeof (context->winsys_features));
context->feature_flags |= glx_renderer->legacy_feature_flags;
context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer)
{
- CoglGpuInfo *info = &context->gpu;
CoglGpuInfoArchitecture arch = info->architecture;
COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
/*
* "The "drisw" binding in Mesa for loading sofware renderers is
* broken, and neither glBlitFramebuffer nor glXCopySubBuffer
* work correctly."
* - ajax
* - https://bugzilla.gnome.org/show_bug.cgi?id=674208
*
* This is broken in software Mesa at least as of 7.10 and got
* fixed in Mesa 10.1
*/
if (info->driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA &&
info->driver_package_version < COGL_VERSION_ENCODE (10, 1, 0) &&
(arch == COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE ||
arch == COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE ||
arch == COGL_GPU_INFO_ARCHITECTURE_SWRAST))
{
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_REGION, FALSE);
}
}
/* Note: glXCopySubBuffer and glBlitFramebuffer won't be throttled
* by the SwapInterval so we have to throttle swap_region requests
* manually... */
if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) &&
(glx_display->have_vblank_counter || glx_display->can_vblank_wait))
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT))
{
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, TRUE);
/* TODO: remove this deprecated feature */
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
TRUE);
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_PRESENTATION_TIME,
TRUE);
}
else
{
- CoglGpuInfo *info = &context->gpu;
if (glx_display->have_vblank_counter &&
context->display->renderer->xlib_enable_threaded_swap_wait &&
info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
{
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, TRUE);
COGL_FLAGS_SET (context->winsys_features,
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, TRUE);
/* TODO: remove this deprecated feature */
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_SWAP_BUFFERS_EVENT,
TRUE);
COGL_FLAGS_SET (context->features,
COGL_FEATURE_ID_PRESENTATION_TIME,
TRUE);
COGL_FLAGS_SET (context->private_features,
COGL_PRIVATE_FEATURE_THREADED_SWAP_WAIT,
TRUE);
}
}
+ if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
+ {
+ context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
+ COGL_FLAGS_SET (context->features,
+ COGL_FEATURE_ID_UNSTABLE_TEXTURES,
+ TRUE);
+ }
+
/* We'll manually handle queueing dirty events in response to
* Expose events from X */
COGL_FLAGS_SET (context->private_features,
COGL_PRIVATE_FEATURE_DIRTY_EVENTS,
TRUE);
if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_BUFFER_AGE))
COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_BUFFER_AGE, TRUE);
return TRUE;
}
static void
glx_attributes_from_framebuffer_config (CoglDisplay *display,
CoglFramebufferConfig *config,
int *attributes)
{
CoglGLXRenderer *glx_renderer = display->renderer->winsys;
int i = 0;
attributes[i++] = GLX_DRAWABLE_TYPE;
attributes[i++] = GLX_WINDOW_BIT;
attributes[i++] = GLX_RENDER_TYPE;
attributes[i++] = GLX_RGBA_BIT;
attributes[i++] = GLX_DOUBLEBUFFER;
attributes[i++] = GL_TRUE;
attributes[i++] = GLX_RED_SIZE;
--
2.18.1