cogl/onscreen: Add API to scanout a buffer directly

Instead of always swapping buffers and flipping the back buffer, make it
possible to scan out a provided buffer directly without swapping any EGL
buffers.

A buffer is passed as an object implementing the empty CoglScanout
interface. It is only possible to do this in the native backend; and the
interface is implemented by MetaDrmBufferGbm. When directly scanned out,
instead of calling gbm_surface_lock_front_buffer() to get the gbm_bo and
fbid, get it directly from the MetaDrmBufferGbm, and use that to create
the page flip KMS update.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/798
This commit is contained in:
Jonas Ådahl
2019-09-12 10:47:46 +02:00
parent f8ee974628
commit 3da8c1bfdc
9 changed files with 185 additions and 16 deletions

View File

@ -44,7 +44,12 @@ struct _MetaDrmBufferGbm
uint32_t fb_id;
};
G_DEFINE_TYPE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER)
static void
cogl_scanout_iface_init (CoglScanoutInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaDrmBufferGbm, meta_drm_buffer_gbm, META_TYPE_DRM_BUFFER,
G_IMPLEMENT_INTERFACE (COGL_TYPE_SCANOUT,
cogl_scanout_iface_init))
struct gbm_bo *
meta_drm_buffer_gbm_get_bo (MetaDrmBufferGbm *buffer_gbm)
@ -161,6 +166,11 @@ meta_drm_buffer_gbm_get_fb_id (MetaDrmBuffer *buffer)
return META_DRM_BUFFER_GBM (buffer)->fb_id;
}
static void
cogl_scanout_iface_init (CoglScanoutInterface *iface)
{
}
static void
meta_drm_buffer_gbm_finalize (GObject *object)
{

View File

@ -2013,6 +2013,34 @@ retry:
}
}
static void
ensure_crtc_modes (CoglOnscreen *onscreen,
MetaKmsUpdate *kms_update)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
MetaRenderer *renderer = META_RENDERER (renderer_native);
MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaPowerSave power_save_mode;
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
if (onscreen_native->pending_set_crtc &&
power_save_mode == META_POWER_SAVE_ON)
{
meta_onscreen_native_set_crtc_mode (onscreen,
renderer_gpu_data,
kms_update);
onscreen_native->pending_set_crtc = FALSE;
}
}
static void
meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
const int *rectangles,
@ -2026,8 +2054,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
MetaRenderer *renderer = META_RENDERER (renderer_native);
MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaMonitorManager *monitor_manager =
meta_backend_get_monitor_manager (backend);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
@ -2036,7 +2062,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
CoglFrameInfo *frame_info;
gboolean egl_context_changed = FALSE;
MetaKmsUpdate *kms_update;
MetaPowerSave power_save_mode;
g_autoptr (GError) error = NULL;
MetaDrmBufferGbm *buffer_gbm;
g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
@ -2095,18 +2120,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
/* If this is the first framebuffer to be presented then we now setup the
* crtc modes, else we flip from the previous buffer */
power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
if (onscreen_native->pending_set_crtc &&
power_save_mode == META_POWER_SAVE_ON)
{
meta_onscreen_native_set_crtc_mode (onscreen,
renderer_gpu_data,
kms_update);
onscreen_native->pending_set_crtc = FALSE;
}
ensure_crtc_modes (onscreen, kms_update);
onscreen_native->pending_queue_swap_notify_frame_count = renderer_native->frame_counter;
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
@ -2200,6 +2214,50 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
return NULL;
}
static void
meta_onscreen_native_direct_scanout (CoglOnscreen *onscreen,
CoglScanout *scanout)
{
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
CoglRenderer *cogl_renderer = cogl_context->display->renderer;
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
MetaRenderer *renderer = META_RENDERER (renderer_native);
MetaBackend *backend = meta_renderer_get_backend (renderer);
MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
MetaKms *kms = meta_backend_native_get_kms (backend_native);
CoglFrameInfo *frame_info;
MetaKmsUpdate *kms_update;
g_autoptr (GError) error = NULL;
kms_update = meta_kms_ensure_pending_update (kms);
wait_for_pending_flips (onscreen);
frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
frame_info->global_frame_counter = renderer_native->frame_counter;
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
render_gpu);
g_return_if_fail (renderer_gpu_data->mode == META_RENDERER_NATIVE_MODE_GBM);
g_warn_if_fail (!onscreen_native->gbm.next_fb);
g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout));
ensure_crtc_modes (onscreen, kms_update);
onscreen_native->pending_queue_swap_notify_frame_count =
renderer_native->frame_counter;
meta_onscreen_native_flip_crtcs (onscreen, kms_update);
meta_kms_post_pending_update_sync (kms);
}
static gboolean
meta_renderer_native_init_egl_context (CoglContext *cogl_context,
GError **error)
@ -2923,6 +2981,7 @@ get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer)
vtable.onscreen_swap_region = NULL;
vtable.onscreen_swap_buffers_with_damage =
meta_onscreen_native_swap_buffers_with_damage;
vtable.onscreen_direct_scanout = meta_onscreen_native_direct_scanout;
vtable.context_get_clock_time = meta_renderer_native_get_clock_time;