mirror of
https://github.com/brl/mutter.git
synced 2024-11-25 17:40:40 -05:00
renderer/native: Retry page flip after one vsync if EBUSY
We might fail to page flip a new buffer, often after resuming, due to the FIFO being full. Prior to this commit, we handled this by switching over to plain mode setting instead of page flipping. This is bad because we won't be synchronized to the refresh rate anymore, but just the clock. Instead, deal with this by trying again until the FIFO is no longer full. Do this on a v-sync based interval, until it works. This also changes the error handling code for drivers not supporting page flipping to rely on them returning -EINVAL. The handling is moved from pretending a page flip working to explicit mode setting in meta-renderer-native.c. Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/460
This commit is contained in:
parent
2c1ab8b3cc
commit
979e689278
@ -74,8 +74,6 @@ struct _MetaGpuKms
|
|||||||
int max_buffer_width;
|
int max_buffer_width;
|
||||||
int max_buffer_height;
|
int max_buffer_height;
|
||||||
|
|
||||||
gboolean page_flips_not_supported;
|
|
||||||
|
|
||||||
gboolean resources_init_failed_before;
|
gboolean resources_init_failed_before;
|
||||||
|
|
||||||
MetaGpuKmsFlag flags;
|
MetaGpuKmsFlag flags;
|
||||||
@ -199,7 +197,6 @@ invoke_flip_closure (GClosure *flip_closure,
|
|||||||
g_value_init (¶ms[3], G_TYPE_INT64);
|
g_value_init (¶ms[3], G_TYPE_INT64);
|
||||||
g_value_set_int64 (¶ms[3], page_flip_time_ns);
|
g_value_set_int64 (¶ms[3], page_flip_time_ns);
|
||||||
g_closure_invoke (flip_closure, NULL, 4, params, NULL);
|
g_closure_invoke (flip_closure, NULL, 4, params, NULL);
|
||||||
g_closure_unref (flip_closure);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -245,7 +242,7 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
|||||||
|
|
||||||
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
|
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
|
||||||
*closure_container = (MetaGpuKmsFlipClosureContainer) {
|
*closure_container = (MetaGpuKmsFlipClosureContainer) {
|
||||||
.flip_closure = flip_closure,
|
.flip_closure = g_closure_ref (flip_closure),
|
||||||
.gpu_kms = gpu_kms,
|
.gpu_kms = gpu_kms,
|
||||||
.crtc = crtc
|
.crtc = crtc
|
||||||
};
|
};
|
||||||
@ -256,20 +253,21 @@ meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
|||||||
void
|
void
|
||||||
meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container)
|
meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container)
|
||||||
{
|
{
|
||||||
|
g_closure_unref (closure_container->flip_closure);
|
||||||
g_free (closure_container);
|
g_free (closure_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||||
MetaCrtc *crtc,
|
MetaCrtc *crtc,
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
uint32_t fb_id,
|
uint32_t fb_id,
|
||||||
GClosure *flip_closure,
|
GClosure *flip_closure,
|
||||||
gboolean *fb_in_use)
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaGpu *gpu = META_GPU (gpu_kms);
|
MetaGpu *gpu = META_GPU (gpu_kms);
|
||||||
MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
|
MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
|
||||||
|
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||||
|
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||||
uint32_t *connectors;
|
uint32_t *connectors;
|
||||||
unsigned int n_connectors;
|
unsigned int n_connectors;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
@ -283,11 +281,6 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
|||||||
|
|
||||||
g_assert (fb_id != 0);
|
g_assert (fb_id != 0);
|
||||||
|
|
||||||
if (!gpu_kms->page_flips_not_supported)
|
|
||||||
{
|
|
||||||
MetaGpuKmsFlipClosureContainer *closure_container;
|
|
||||||
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
|
||||||
|
|
||||||
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
|
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
|
||||||
crtc,
|
crtc,
|
||||||
flip_closure);
|
flip_closure);
|
||||||
@ -297,28 +290,14 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
|||||||
fb_id,
|
fb_id,
|
||||||
DRM_MODE_PAGE_FLIP_EVENT,
|
DRM_MODE_PAGE_FLIP_EVENT,
|
||||||
closure_container);
|
closure_container);
|
||||||
if (ret != 0 && ret != -EACCES)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
meta_gpu_kms_flip_closure_container_free (closure_container);
|
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||||
g_warning ("Failed to flip: %s", strerror (-ret));
|
g_set_error (error, G_IO_ERROR,
|
||||||
gpu_kms->page_flips_not_supported = TRUE;
|
g_io_error_from_errno (-ret),
|
||||||
}
|
"drmModePageFlip failed: %s", g_strerror (-ret));
|
||||||
}
|
|
||||||
|
|
||||||
if (gpu_kms->page_flips_not_supported)
|
|
||||||
{
|
|
||||||
if (meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id))
|
|
||||||
{
|
|
||||||
*fb_in_use = TRUE;
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != 0)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
*fb_in_use = TRUE;
|
|
||||||
g_closure_ref (flip_closure);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -365,13 +344,6 @@ meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
|
|||||||
{
|
{
|
||||||
drmEventContext evctx;
|
drmEventContext evctx;
|
||||||
|
|
||||||
if (gpu_kms->page_flips_not_supported)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"Page flips not supported");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (&evctx, 0, sizeof evctx);
|
memset (&evctx, 0, sizeof evctx);
|
||||||
evctx.version = 2;
|
evctx.version = 2;
|
||||||
evctx.page_flip_handler = page_flip_handler;
|
evctx.page_flip_handler = page_flip_handler;
|
||||||
|
@ -72,11 +72,9 @@ gboolean meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms);
|
|||||||
|
|
||||||
gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
gboolean meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||||
MetaCrtc *crtc,
|
MetaCrtc *crtc,
|
||||||
int x,
|
|
||||||
int y,
|
|
||||||
uint32_t fb_id,
|
uint32_t fb_id,
|
||||||
GClosure *flip_closure,
|
GClosure *flip_closure,
|
||||||
gboolean *fb_in_use);
|
GError **error);
|
||||||
|
|
||||||
gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
|
gboolean meta_gpu_kms_wait_for_flip (MetaGpuKms *gpu_kms,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
@ -192,6 +192,9 @@ typedef struct _MetaOnscreenNative
|
|||||||
int64_t pending_queue_swap_notify_frame_count;
|
int64_t pending_queue_swap_notify_frame_count;
|
||||||
int64_t pending_swap_notify_frame_count;
|
int64_t pending_swap_notify_frame_count;
|
||||||
|
|
||||||
|
GList *pending_page_flip_retries;
|
||||||
|
GSource *retry_page_flips_source;
|
||||||
|
|
||||||
MetaRendererView *view;
|
MetaRendererView *view;
|
||||||
int total_pending_flips;
|
int total_pending_flips;
|
||||||
} MetaOnscreenNative;
|
} MetaOnscreenNative;
|
||||||
@ -302,6 +305,13 @@ meta_create_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
|
|||||||
return g_new0 (MetaRendererNativeGpuData, 1);
|
return g_new0 (MetaRendererNativeGpuData, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaOnscreenNativeSecondaryGpuState *
|
||||||
|
meta_onscreen_native_get_secondary_gpu_state (MetaOnscreenNative *onscreen_native,
|
||||||
|
MetaGpuKms *gpu_kms)
|
||||||
|
{
|
||||||
|
return g_hash_table_lookup (onscreen_native->secondary_gpu_states, gpu_kms);
|
||||||
|
}
|
||||||
|
|
||||||
static MetaOnscreenNativeSecondaryGpuState *
|
static MetaOnscreenNativeSecondaryGpuState *
|
||||||
get_secondary_gpu_state (CoglOnscreen *onscreen,
|
get_secondary_gpu_state (CoglOnscreen *onscreen,
|
||||||
MetaGpuKms *gpu_kms)
|
MetaGpuKms *gpu_kms)
|
||||||
@ -309,7 +319,8 @@ get_secondary_gpu_state (CoglOnscreen *onscreen,
|
|||||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
|
|
||||||
return g_hash_table_lookup (onscreen_native->secondary_gpu_states, gpu_kms);
|
return meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
|
||||||
|
gpu_kms);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaEgl *
|
static MetaEgl *
|
||||||
@ -1507,19 +1518,202 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_closure_ref (flip_closure);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_EGL_DEVICE */
|
#endif /* HAVE_EGL_DEVICE */
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_timestamp_earlier_than (uint64_t ts1,
|
||||||
|
uint64_t ts2)
|
||||||
|
{
|
||||||
|
if (ts1 == ts2)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return ts2 - ts1 < UINT64_MAX / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _RetryPageFlipData
|
||||||
|
{
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
uint32_t fb_id;
|
||||||
|
GClosure *flip_closure;
|
||||||
|
uint64_t retry_time_us;
|
||||||
|
} RetryPageFlipData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
|
||||||
|
{
|
||||||
|
g_closure_unref (retry_page_flip_data->flip_closure);
|
||||||
|
g_free (retry_page_flip_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
retry_page_flips (gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaOnscreenNative *onscreen_native = user_data;
|
||||||
|
uint64_t now_us;
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
now_us = g_source_get_time (onscreen_native->retry_page_flips_source);
|
||||||
|
|
||||||
|
l = onscreen_native->pending_page_flip_retries;
|
||||||
|
while (l)
|
||||||
|
{
|
||||||
|
RetryPageFlipData *retry_page_flip_data = l->data;
|
||||||
|
MetaCrtc *crtc = retry_page_flip_data->crtc;
|
||||||
|
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||||
|
GList *l_next = l->next;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
gboolean did_flip;
|
||||||
|
|
||||||
|
if (is_timestamp_earlier_than (now_us,
|
||||||
|
retry_page_flip_data->retry_time_us))
|
||||||
|
{
|
||||||
|
l = l_next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
did_flip = meta_gpu_kms_flip_crtc (gpu_kms,
|
||||||
|
crtc,
|
||||||
|
retry_page_flip_data->fb_id,
|
||||||
|
retry_page_flip_data->flip_closure,
|
||||||
|
&error);
|
||||||
|
if (!did_flip &&
|
||||||
|
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_BUSY))
|
||||||
|
{
|
||||||
|
retry_page_flip_data->retry_time_us +=
|
||||||
|
G_USEC_PER_SEC / crtc->current_mode->refresh_rate;
|
||||||
|
l = l_next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
onscreen_native->pending_page_flip_retries =
|
||||||
|
g_list_remove_link (onscreen_native->pending_page_flip_retries, l);
|
||||||
|
|
||||||
|
if (!did_flip)
|
||||||
|
{
|
||||||
|
if (!g_error_matches (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_PERMISSION_DENIED))
|
||||||
|
g_critical ("Failed to page flip: %s", error->message);
|
||||||
|
|
||||||
|
if (gpu_kms != onscreen_native->render_gpu)
|
||||||
|
{
|
||||||
|
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
|
||||||
|
|
||||||
|
secondary_gpu_state =
|
||||||
|
meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
|
||||||
|
gpu_kms);
|
||||||
|
secondary_gpu_state->pending_flips--;
|
||||||
|
}
|
||||||
|
|
||||||
|
onscreen_native->total_pending_flips--;
|
||||||
|
}
|
||||||
|
|
||||||
|
retry_page_flip_data_free (retry_page_flip_data);
|
||||||
|
|
||||||
|
l = l_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (onscreen_native->pending_page_flip_retries)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
uint64_t earliest_retry_time_us = 0;
|
||||||
|
|
||||||
|
for (l = onscreen_native->pending_page_flip_retries; l; l = l->next)
|
||||||
|
{
|
||||||
|
RetryPageFlipData *retry_page_flip_data = l->data;
|
||||||
|
|
||||||
|
if (l == onscreen_native->pending_page_flip_retries ||
|
||||||
|
is_timestamp_earlier_than (retry_page_flip_data->retry_time_us,
|
||||||
|
earliest_retry_time_us))
|
||||||
|
earliest_retry_time_us = retry_page_flip_data->retry_time_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_source_set_ready_time (onscreen_native->retry_page_flips_source,
|
||||||
|
earliest_retry_time_us);
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_clear_pointer (&onscreen_native->retry_page_flips_source,
|
||||||
|
g_source_unref);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
retry_page_flips_source_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
return callback (user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs retry_page_flips_source_funcs = {
|
||||||
|
.dispatch = retry_page_flips_source_dispatch,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
schedule_retry_page_flip (MetaOnscreenNative *onscreen_native,
|
||||||
|
MetaCrtc *crtc,
|
||||||
|
uint32_t fb_id,
|
||||||
|
GClosure *flip_closure)
|
||||||
|
{
|
||||||
|
RetryPageFlipData *retry_page_flip_data;
|
||||||
|
uint64_t now_us;
|
||||||
|
uint64_t retry_time_us;
|
||||||
|
|
||||||
|
now_us = g_get_monotonic_time ();
|
||||||
|
retry_time_us =
|
||||||
|
now_us + (G_USEC_PER_SEC / crtc->current_mode->refresh_rate);
|
||||||
|
|
||||||
|
retry_page_flip_data = g_new0 (RetryPageFlipData, 1);
|
||||||
|
retry_page_flip_data->crtc = crtc;
|
||||||
|
retry_page_flip_data->fb_id = fb_id;
|
||||||
|
retry_page_flip_data->flip_closure = g_closure_ref (flip_closure);
|
||||||
|
retry_page_flip_data->retry_time_us = retry_time_us;
|
||||||
|
|
||||||
|
if (!onscreen_native->retry_page_flips_source)
|
||||||
|
{
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
source = g_source_new (&retry_page_flips_source_funcs, sizeof (GSource));
|
||||||
|
g_source_set_callback (source, retry_page_flips, onscreen_native, NULL);
|
||||||
|
g_source_set_ready_time (source, retry_time_us);
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
|
||||||
|
onscreen_native->retry_page_flips_source = source;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = onscreen_native->pending_page_flip_retries; l; l = l->next)
|
||||||
|
{
|
||||||
|
RetryPageFlipData *pending_retry_page_flip_data = l->data;
|
||||||
|
uint64_t pending_retry_time_us =
|
||||||
|
pending_retry_page_flip_data->retry_time_us;
|
||||||
|
|
||||||
|
if (is_timestamp_earlier_than (retry_time_us, pending_retry_time_us))
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (onscreen_native->retry_page_flips_source,
|
||||||
|
retry_time_us);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onscreen_native->pending_page_flip_retries =
|
||||||
|
g_list_append (onscreen_native->pending_page_flip_retries,
|
||||||
|
retry_page_flip_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
||||||
GClosure *flip_closure,
|
GClosure *flip_closure,
|
||||||
MetaCrtc *crtc,
|
MetaCrtc *crtc,
|
||||||
int x,
|
GError **error)
|
||||||
int y,
|
|
||||||
gboolean *fb_in_use)
|
|
||||||
{
|
{
|
||||||
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
@ -1533,8 +1727,9 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||||||
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||||
if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc))
|
if (!meta_gpu_kms_is_crtc_active (gpu_kms, crtc))
|
||||||
{
|
{
|
||||||
*fb_in_use = FALSE;
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
return;
|
"Tried to flip inactive CRTC");
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
||||||
@ -1554,11 +1749,23 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||||||
|
|
||||||
if (!meta_gpu_kms_flip_crtc (gpu_kms,
|
if (!meta_gpu_kms_flip_crtc (gpu_kms,
|
||||||
crtc,
|
crtc,
|
||||||
x, y,
|
|
||||||
fb_id,
|
fb_id,
|
||||||
flip_closure,
|
flip_closure,
|
||||||
fb_in_use))
|
error))
|
||||||
return;
|
{
|
||||||
|
if (g_error_matches (*error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_BUSY))
|
||||||
|
{
|
||||||
|
g_clear_error (error);
|
||||||
|
schedule_retry_page_flip (onscreen_native, crtc,
|
||||||
|
fb_id, flip_closure);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onscreen_native->total_pending_flips++;
|
onscreen_native->total_pending_flips++;
|
||||||
if (secondary_gpu_state)
|
if (secondary_gpu_state)
|
||||||
@ -1570,35 +1777,30 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen,
|
|||||||
if (flip_egl_stream (onscreen_native,
|
if (flip_egl_stream (onscreen_native,
|
||||||
flip_closure))
|
flip_closure))
|
||||||
onscreen_native->total_pending_flips++;
|
onscreen_native->total_pending_flips++;
|
||||||
*fb_in_use = TRUE;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _SetCrtcFbData
|
|
||||||
{
|
|
||||||
MetaGpuKms *render_gpu;
|
|
||||||
CoglOnscreen *onscreen;
|
|
||||||
uint32_t fb_id;
|
|
||||||
} SetCrtcFbData;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_crtc_fb (MetaLogicalMonitor *logical_monitor,
|
set_crtc_fb (CoglOnscreen *onscreen,
|
||||||
|
MetaLogicalMonitor *logical_monitor,
|
||||||
MetaCrtc *crtc,
|
MetaCrtc *crtc,
|
||||||
gpointer user_data)
|
uint32_t render_fb_id)
|
||||||
{
|
{
|
||||||
SetCrtcFbData *data = user_data;
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
MetaGpuKms *render_gpu = data->render_gpu;
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
CoglOnscreen *onscreen = data->onscreen;
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
||||||
MetaGpuKms *gpu_kms;
|
MetaGpuKms *gpu_kms;
|
||||||
uint32_t fb_id;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
uint32_t fb_id;
|
||||||
|
|
||||||
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||||
if (gpu_kms == render_gpu)
|
if (gpu_kms == render_gpu)
|
||||||
{
|
{
|
||||||
fb_id = data->fb_id;
|
fb_id = render_fb_id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1617,6 +1819,23 @@ set_crtc_fb (MetaLogicalMonitor *logical_monitor,
|
|||||||
meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id);
|
meta_gpu_kms_apply_crtc_mode (gpu_kms, crtc, x, y, fb_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _SetCrtcFbData
|
||||||
|
{
|
||||||
|
CoglOnscreen *onscreen;
|
||||||
|
uint32_t fb_id;
|
||||||
|
} SetCrtcFbData;
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_crtc_fb_cb (MetaLogicalMonitor *logical_monitor,
|
||||||
|
MetaCrtc *crtc,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
SetCrtcFbData *data = user_data;
|
||||||
|
CoglOnscreen *onscreen = data->onscreen;
|
||||||
|
|
||||||
|
set_crtc_fb (onscreen, logical_monitor, crtc, data->fb_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
|
meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
|
||||||
{
|
{
|
||||||
@ -1649,13 +1868,12 @@ meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
|
|||||||
if (logical_monitor)
|
if (logical_monitor)
|
||||||
{
|
{
|
||||||
SetCrtcFbData data = {
|
SetCrtcFbData data = {
|
||||||
.render_gpu = render_gpu,
|
|
||||||
.onscreen = onscreen,
|
.onscreen = onscreen,
|
||||||
.fb_id = fb_id
|
.fb_id = fb_id
|
||||||
};
|
};
|
||||||
|
|
||||||
meta_logical_monitor_foreach_crtc (logical_monitor,
|
meta_logical_monitor_foreach_crtc (logical_monitor,
|
||||||
set_crtc_fb,
|
set_crtc_fb_cb,
|
||||||
&data);
|
&data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1674,12 +1892,47 @@ meta_onscreen_native_set_crtc_modes (CoglOnscreen *onscreen)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
crtc_mode_set_fallback (CoglOnscreen *onscreen,
|
||||||
|
MetaLogicalMonitor *logical_monitor,
|
||||||
|
MetaCrtc *crtc)
|
||||||
|
{
|
||||||
|
CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
|
||||||
|
MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
|
||||||
|
MetaGpuKms *render_gpu = onscreen_native->render_gpu;
|
||||||
|
MetaRendererNative *renderer_native;
|
||||||
|
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||||
|
uint32_t fb_id;
|
||||||
|
static gboolean warned_once = FALSE;
|
||||||
|
|
||||||
|
if (!warned_once)
|
||||||
|
{
|
||||||
|
g_warning ("Page flipping not supported by driver, "
|
||||||
|
"relying on the clock from now on");
|
||||||
|
warned_once = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer_native = meta_renderer_native_from_gpu (render_gpu);
|
||||||
|
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
||||||
|
render_gpu);
|
||||||
|
if (renderer_gpu_data->mode != META_RENDERER_NATIVE_MODE_GBM)
|
||||||
|
{
|
||||||
|
g_warning ("Mode set fallback not handled for EGLStreams");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb_id = onscreen_native->gbm.next_fb_id;
|
||||||
|
set_crtc_fb (onscreen, logical_monitor, crtc, fb_id);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _FlipCrtcData
|
typedef struct _FlipCrtcData
|
||||||
{
|
{
|
||||||
CoglOnscreen *onscreen;
|
CoglOnscreen *onscreen;
|
||||||
GClosure *flip_closure;
|
GClosure *flip_closure;
|
||||||
|
|
||||||
gboolean out_fb_in_use;
|
gboolean did_flip;
|
||||||
|
gboolean did_mode_set;
|
||||||
} FlipCrtcData;
|
} FlipCrtcData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1688,15 +1941,28 @@ flip_crtc (MetaLogicalMonitor *logical_monitor,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
FlipCrtcData *data = user_data;
|
FlipCrtcData *data = user_data;
|
||||||
int x, y;
|
GError *error = NULL;
|
||||||
|
|
||||||
x = crtc->rect.x - logical_monitor->rect.x;
|
if (!meta_onscreen_native_flip_crtc (data->onscreen,
|
||||||
y = crtc->rect.y - logical_monitor->rect.y;
|
|
||||||
|
|
||||||
meta_onscreen_native_flip_crtc (data->onscreen,
|
|
||||||
data->flip_closure,
|
data->flip_closure,
|
||||||
crtc, x, y,
|
crtc,
|
||||||
&data->out_fb_in_use);
|
&error))
|
||||||
|
{
|
||||||
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT))
|
||||||
|
{
|
||||||
|
if (crtc_mode_set_fallback (data->onscreen, logical_monitor, crtc))
|
||||||
|
data->did_mode_set = TRUE;
|
||||||
|
}
|
||||||
|
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED))
|
||||||
|
{
|
||||||
|
g_warning ("Failed to flip onscreen: %s", error->message);
|
||||||
|
}
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data->did_flip = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1707,7 +1973,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
|
|||||||
MetaRendererView *view = onscreen_native->view;
|
MetaRendererView *view = onscreen_native->view;
|
||||||
GClosure *flip_closure;
|
GClosure *flip_closure;
|
||||||
MetaLogicalMonitor *logical_monitor;
|
MetaLogicalMonitor *logical_monitor;
|
||||||
gboolean fb_in_use = FALSE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a closure that either will be invoked or destructed.
|
* Create a closure that either will be invoked or destructed.
|
||||||
@ -1735,29 +2000,12 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen *onscreen)
|
|||||||
meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
|
meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the framebuffer is in use, but we don't have any pending flips it means
|
* If we didn't queue a page flip, but instead directly changed the mode due
|
||||||
* that flipping is not supported and we set the next framebuffer directly.
|
* to the driver not supporting mode setting, wes must swap the buffers
|
||||||
* Since we won't receive a flip callback, lets just notify listeners
|
* directly as we won't get a page flip callback.
|
||||||
* directly.
|
|
||||||
*/
|
*/
|
||||||
if (fb_in_use && onscreen_native->total_pending_flips == 0)
|
if (!data.did_flip && data.did_mode_set)
|
||||||
{
|
|
||||||
MetaRendererNative *renderer_native = onscreen_native->renderer_native;
|
|
||||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
|
||||||
|
|
||||||
renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
|
|
||||||
render_gpu);
|
|
||||||
switch (renderer_gpu_data->mode)
|
|
||||||
{
|
|
||||||
case META_RENDERER_NATIVE_MODE_GBM:
|
|
||||||
meta_onscreen_native_swap_drm_fb (onscreen);
|
meta_onscreen_native_swap_drm_fb (onscreen);
|
||||||
break;
|
|
||||||
#ifdef HAVE_EGL_DEVICE
|
|
||||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onscreen_native->pending_queue_swap_notify = TRUE;
|
onscreen_native->pending_queue_swap_notify = TRUE;
|
||||||
|
|
||||||
@ -2720,6 +2968,11 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
|
|||||||
|
|
||||||
onscreen_native = onscreen_egl->platform;
|
onscreen_native = onscreen_egl->platform;
|
||||||
|
|
||||||
|
g_list_free_full (onscreen_native->pending_page_flip_retries,
|
||||||
|
(GDestroyNotify) retry_page_flip_data_free);
|
||||||
|
g_clear_pointer (&onscreen_native->retry_page_flips_source,
|
||||||
|
g_source_destroy);
|
||||||
|
|
||||||
if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
|
if (onscreen_egl->egl_surface != EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
||||||
|
Loading…
Reference in New Issue
Block a user