From bac385833fddb5dadb3be1eaf7b6071991c4b048 Mon Sep 17 00:00:00 2001 From: Ray Strode 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