diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 65000cb52..f0c2fadaa 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -144,6 +144,12 @@ maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native) }; primary_gpu = meta_renderer_native_get_primary_gpu (renderer_native); + if (!primary_gpu) + { + g_message ("Disabling DMA buffer screen sharing (surfaceless)"); + goto disable_dma_bufs; + } + kms_device = meta_gpu_kms_get_kms_device (primary_gpu); driver_name = meta_kms_device_get_driver_name (kms_device); @@ -157,6 +163,7 @@ maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native) g_message ("Disabling DMA buffer screen sharing for driver '%s'.", driver_name); +disable_dma_bufs: meta_screen_cast_disable_dma_bufs (screen_cast); } #endif /* HAVE_REMOTE_DESKTOP */ @@ -473,7 +480,7 @@ init_gpus (MetaBackendNative *native, GList *l; devices = meta_udev_list_drm_devices (udev, error); - if (!devices) + if (*error) return FALSE; for (l = devices; l; l = l->next) @@ -498,7 +505,8 @@ init_gpus (MetaBackendNative *native, g_list_free_full (devices, g_object_unref); - if (g_list_length (meta_backend_get_gpus (backend)) == 0) + if (!native->is_headless && + g_list_length (meta_backend_get_gpus (backend)) == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "No GPUs found"); diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 4290eeeca..7c0fb5133 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -240,6 +240,9 @@ notify_view_crtc_presented (MetaRendererView *view, case META_RENDERER_NATIVE_MODE_GBM: meta_onscreen_native_swap_drm_fb (onscreen); break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: break; @@ -473,6 +476,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, meta_crtc_kms_assign_primary_plane (crtc_kms, buffer, kms_update); + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: @@ -511,6 +517,9 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen *onscreen, { case META_RENDERER_NATIVE_MODE_GBM: break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: { @@ -1050,6 +1059,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, onscreen_native->gbm.next_fb = META_DRM_BUFFER (buffer_gbm); + break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: @@ -1117,6 +1129,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen, return; } break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: if (meta_renderer_native_has_pending_mode_set (renderer_native)) @@ -1736,6 +1751,9 @@ meta_onscreen_native_allocate (CoglFramebuffer *framebuffer, onscreen_native->gbm.surface = gbm_surface; cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface); break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: render_kms_device = @@ -2091,6 +2109,9 @@ meta_onscreen_native_dispose (GObject *object) g_clear_pointer (&onscreen_native->gbm.surface, gbm_surface_destroy); break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + g_assert_not_reached (); + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: g_clear_object (&onscreen_native->egl.dumb_fb); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 95d2ffd77..f48db9ab8 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -206,13 +206,14 @@ meta_renderer_native_connect (CoglRenderer *cogl_renderer, GError **error) { CoglRendererEGL *cogl_renderer_egl; - MetaGpuKms *gpu_kms = cogl_renderer->custom_winsys_user_data; - MetaRendererNative *renderer_native = meta_renderer_native_from_gpu (gpu_kms); + MetaRendererNative *renderer_native = cogl_renderer->custom_winsys_user_data; + MetaGpuKms *gpu_kms; MetaRendererNativeGpuData *renderer_gpu_data; cogl_renderer->winsys = g_new0 (CoglRendererEGL, 1); cogl_renderer_egl = cogl_renderer->winsys; + gpu_kms = meta_renderer_native_get_primary_gpu (renderer_native); renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, gpu_kms); @@ -246,6 +247,10 @@ meta_renderer_native_add_egl_config_attributes (CoglDisplay *cog attributes[i++] = EGL_SURFACE_TYPE; attributes[i++] = EGL_WINDOW_BIT; break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: + attributes[i++] = EGL_SURFACE_TYPE; + attributes[i++] = EGL_PBUFFER_BIT; + break; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: attributes[i++] = EGL_SURFACE_TYPE; @@ -326,6 +331,9 @@ meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display, GBM_FORMAT_XRGB8888, out_config, error); + case META_RENDERER_NATIVE_MODE_SURFACELESS: + *out_config = EGL_NO_CONFIG_KHR; + return TRUE; #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: return meta_egl_choose_first_config (egl, @@ -778,10 +786,11 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer, return dmabuf_handle; } break; + case META_RENDERER_NATIVE_MODE_SURFACELESS: #ifdef HAVE_EGL_DEVICE case META_RENDERER_NATIVE_MODE_EGL_DEVICE: - break; #endif + break; } g_set_error (error, G_IO_ERROR, G_IO_ERROR_UNKNOWN, @@ -933,26 +942,17 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer) } static CoglRenderer * -create_cogl_renderer_for_gpu (MetaGpuKms *gpu_kms) +meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer) { CoglRenderer *cogl_renderer; cogl_renderer = cogl_renderer_new (); cogl_renderer_set_custom_winsys (cogl_renderer, get_native_cogl_winsys_vtable, - gpu_kms); - + renderer); return cogl_renderer; } -static CoglRenderer * -meta_renderer_native_create_cogl_renderer (MetaRenderer *renderer) -{ - MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); - - return create_cogl_renderer_for_gpu (renderer_native->primary_gpu_kms); -} - static MetaMonitorTransform calculate_view_transform (MetaMonitorManager *monitor_manager, MetaLogicalMonitor *logical_monitor, @@ -1244,6 +1244,7 @@ create_secondary_egl_config (MetaEgl *egl, switch (mode) { case META_RENDERER_NATIVE_MODE_GBM: + case META_RENDERER_NATIVE_MODE_SURFACELESS: return choose_egl_config_from_gbm_format (egl, egl_display, attributes, @@ -1490,6 +1491,65 @@ create_renderer_gpu_data_gbm (MetaRendererNative *renderer_native, return renderer_gpu_data; } +static EGLDisplay +init_surfaceless_egl_display (MetaRendererNative *renderer_native, + GError **error) +{ + MetaEgl *egl = meta_renderer_native_get_egl (renderer_native); + EGLDisplay egl_display; + + if (!meta_egl_has_extensions (egl, EGL_NO_DISPLAY, NULL, + "EGL_MESA_platform_surfaceless", + NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Missing EGL platform required for surfaceless context: " + "EGL_MESA_platform_surfaceless"); + return EGL_NO_DISPLAY; + } + + egl_display = meta_egl_get_platform_display (egl, + EGL_PLATFORM_SURFACELESS_MESA, + EGL_DEFAULT_DISPLAY, + NULL, error); + if (egl_display == EGL_NO_DISPLAY) + return EGL_NO_DISPLAY; + + if (!meta_egl_initialize (egl, egl_display, error)) + return EGL_NO_DISPLAY; + + if (!meta_egl_has_extensions (egl, egl_display, NULL, + "EGL_KHR_no_config_context", + NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Missing EGL extension required for surfaceless context: " + "EGL_KHR_no_config_context"); + return EGL_NO_DISPLAY; + } + + return egl_display; +} + +static MetaRendererNativeGpuData * +create_renderer_gpu_data_surfaceless (MetaRendererNative *renderer_native, + GError **error) +{ + MetaRendererNativeGpuData *renderer_gpu_data; + EGLDisplay egl_display; + + egl_display = init_surfaceless_egl_display (renderer_native, error); + if (egl_display == EGL_NO_DISPLAY) + return NULL; + + renderer_gpu_data = meta_create_renderer_native_gpu_data (NULL); + renderer_gpu_data->renderer_native = renderer_native; + renderer_gpu_data->mode = META_RENDERER_NATIVE_MODE_SURFACELESS; + renderer_gpu_data->egl_display = egl_display; + + return renderer_gpu_data; +} + #ifdef HAVE_EGL_DEVICE static const char * get_drm_device_file (MetaEgl *egl, @@ -1692,6 +1752,9 @@ meta_renderer_native_create_renderer_gpu_data (MetaRendererNative *renderer_nat GError *egl_device_error = NULL; #endif + if (!gpu_kms) + return create_renderer_gpu_data_surfaceless (renderer_native, error); + #ifdef HAVE_EGL_DEVICE /* Try to initialize the EGLDevice backend first. Whenever we use a * non-NVIDIA GPU, the EGLDevice enumeration function won't find a match, and @@ -1919,23 +1982,31 @@ meta_renderer_native_initable_init (GInitable *initable, GList *l; gpus = meta_backend_get_gpus (backend); - for (l = gpus; l; l = l->next) + if (gpus) { - MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); + for (l = gpus; l; l = l->next) + { + MetaGpuKms *gpu_kms = META_GPU_KMS (l->data); - if (!create_renderer_gpu_data (renderer_native, gpu_kms, error)) + if (!create_renderer_gpu_data (renderer_native, gpu_kms, error)) + return FALSE; + } + + renderer_native->primary_gpu_kms = choose_primary_gpu (backend, + renderer_native, + error); + if (!renderer_native->primary_gpu_kms) + return FALSE; + + if (meta_gpu_kms_requires_modifiers (renderer_native->primary_gpu_kms)) + renderer_native->use_modifiers = TRUE; + } + else + { + if (!create_renderer_gpu_data (renderer_native, NULL, error)) return FALSE; } - renderer_native->primary_gpu_kms = choose_primary_gpu (backend, - renderer_native, - error); - if (!renderer_native->primary_gpu_kms) - return FALSE; - - if (meta_gpu_kms_requires_modifiers (renderer_native->primary_gpu_kms)) - renderer_native->use_modifiers = TRUE; - return TRUE; } diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h index dd19eb014..9475e1857 100644 --- a/src/backends/native/meta-renderer-native.h +++ b/src/backends/native/meta-renderer-native.h @@ -41,6 +41,7 @@ G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native, typedef enum _MetaRendererNativeMode { META_RENDERER_NATIVE_MODE_GBM, + META_RENDERER_NATIVE_MODE_SURFACELESS, #ifdef HAVE_EGL_DEVICE META_RENDERER_NATIVE_MODE_EGL_DEVICE #endif diff --git a/src/backends/native/meta-udev.c b/src/backends/native/meta-udev.c index 649c9df27..9a6bfe03b 100644 --- a/src/backends/native/meta-udev.c +++ b/src/backends/native/meta-udev.c @@ -159,11 +159,7 @@ meta_udev_list_drm_devices (MetaUdev *udev, devices = g_udev_enumerator_execute (enumerator); if (!devices) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, - "No drm devices found"); - return FALSE; - } + return NULL; for (l = devices; l;) { @@ -179,13 +175,6 @@ meta_udev_list_drm_devices (MetaUdev *udev, l = l_next; } - if (!devices) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No DRM devices found"); - return NULL; - } - return devices; }