123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- From ced3b5d803cd044526672c8458029b5a6519b86a Mon Sep 17 00:00:00 2001
- From: Silvestrs Timofejevs <silvestrs.timofejevs@imgtec.com>
- Date: Mon, 2 Sep 2019 09:32:01 +0100
- Subject: [PATCH] null_platform: add support for explicit synchronisation
- This change adds support for the 'in' fence, the 'out' fence will
- potentially be added in subsequent optimisation changes.
- Explicit synchronisation KMS 'in' and 'out' properties have been first
- added in Linux kernel 4.10 as an additional feature to the atomic mode
- setting.
- 9626014258a5957ff120b3987ee72decdbe0c798 - 'in' property
- beaf5af48034c9e2ebb8b2b1fb12dc4d8aeba99e - 'out' property
- Unlike many other features - it doesn't have an in kernel capability
- flag, so the support for it can be tested in the following way:
- KMS creates an additional set of properties when the version of kernel
- is new enough to support it ('in' and 'out' fence properties). When
- the user-space requests all the properties from the kernel via
- drmModeObjectGetProperties it is possible to determine whether the
- required property is supported by the kernel or not.
- The explicit synchronisation is used when available, otherwise the
- implicit sync model is used instead. If explicit synchronisation is
- available but 'in' fence failed to attach in KMS, the system falls
- back to the implicit synchronisation model.
- egl_dri2.c already creates the GPU 'out' fence that is then used by
- the null_platform as KMS 'in' fence. null_platform takes owenership of
- this fence fd during the swap buffers operation, at which point the
- fence fd is no longer available to be used outside of null_platform.
- EGL_LOG_LEVEL=debug should give some useful information in case of
- explicit synchronisation failure. As mentioned above, this failure
- will result in implicit synchronisation being used instead.
- Change-Id: Ib9c4a0bc3ea1b21192ee37909d7580d6b7b366ec
- ---
- src/egl/drivers/dri2/egl_dri2.h | 2 +
- src/egl/drivers/dri2/platform_null.c | 77 +++++++++++++++++++++++++++-
- 2 files changed, 77 insertions(+), 2 deletions(-)
- diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
- index 64d60ed..eb6e455 100644
- --- a/src/egl/drivers/dri2/egl_dri2.h
- +++ b/src/egl/drivers/dri2/egl_dri2.h
- @@ -106,6 +106,7 @@ struct wl_buffer;
- #ifdef HAVE_NULL_PLATFORM
- struct display_output {
- bool in_use;
- + bool in_fence_supported;
- uint32_t connector_id;
- drmModePropertyRes **connector_prop_res;
- uint32_t crtc_id;
- @@ -338,6 +339,7 @@ struct swap_queue_elem
- uint32_t swap_interval;
- uint32_t back_id;
- uint32_t fb_id;
- + int kms_in_fence_fd;
- };
-
- enum {
- diff --git a/src/egl/drivers/dri2/platform_null.c b/src/egl/drivers/dri2/platform_null.c
- index 5b7c1ec..d36dc0c 100644
- --- a/src/egl/drivers/dri2/platform_null.c
- +++ b/src/egl/drivers/dri2/platform_null.c
- @@ -401,6 +401,9 @@ display_output_atomic_init(int fd, struct display_output *output)
- if (!output->atomic_state)
- goto err_destroy_mode_prop_blob;
-
- + if (property_id_get_for_name(plane_prop_res, "IN_FENCE_FD"))
- + output->in_fence_supported = true;
- +
- output->connector_prop_res = connector_prop_res;
- output->crtc_prop_res = crtc_prop_res;
- output->plane_prop_res = plane_prop_res;
- @@ -418,6 +421,53 @@ err_free_connector_prop_res:
- return false;
- }
-
- +static void
- +display_output_atomic_add_in_fence(struct display_output *output,
- + int kms_in_fence_fd)
- +{
- + const struct object_property obj_sync_props[] = {
- + object_property_set_named(output, plane, "IN_FENCE_FD", kms_in_fence_fd),
- + };
- + int err;
- +
- + /* Explicit synchronisation is not being used */
- + if (kms_in_fence_fd < 0)
- + return;
- +
- + err = atomic_state_add_object_properties(output->atomic_state,
- + obj_sync_props,
- + ARRAY_SIZE(obj_sync_props));
- + if (err)
- + _eglLog(_EGL_DEBUG, "%s: failed to add props ERR = %d", __func__, err);
- +}
- +
- +static void
- +atomic_claim_in_fence_fd(struct dri2_egl_surface *dri2_surf,
- + struct swap_queue_elem *swap_data)
- +{
- + /* Explicit synchronisation is not being used */
- + if (!dri2_surf->enable_out_fence)
- + return;
- +
- + if (dri2_surf->out_fence_fd < 0) {
- + _eglLog(_EGL_DEBUG, "%s: missing 'in' fence", __func__);
- + return;
- + }
- +
- + /* Take ownership of the fd */
- + swap_data->kms_in_fence_fd = dri2_surf->out_fence_fd;
- + dri2_surf->out_fence_fd = -1;
- +}
- +
- +static void
- +atomic_relinquish_in_fence_fd(struct dri2_egl_surface *dri2_surf,
- + struct swap_queue_elem *swap_data)
- +{
- + /* KMS is now in control of the fence (post drmModeAtomicCommit) */
- + close(swap_data->kms_in_fence_fd);
- + swap_data->kms_in_fence_fd = -1;
- +}
- +
- static int
- display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id,
- uint32_t flags, void *flip_data)
- @@ -425,6 +475,8 @@ display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id
- const struct object_property obj_props[] = {
- object_property_set_named(output, plane, "FB_ID", fb_id),
- };
- + struct dri2_egl_surface *dri2_surf = flip_data;
- + struct swap_queue_elem *swap_data = dri2_surf->swap_data;
- int err;
-
- /* Reset atomic state */
- @@ -435,13 +487,19 @@ display_output_atomic_flip(int fd, struct display_output *output, uint32_t fb_id
- if (err)
- return err;
-
- + display_output_atomic_add_in_fence(output, swap_data->kms_in_fence_fd);
- +
- /*
- * Don't block - like drmModePageFlip, drmModeAtomicCommit will return
- * -EBUSY if the commit can't be queued in the kernel.
- */
- flags |= DRM_MODE_ATOMIC_NONBLOCK;
-
- - return drmModeAtomicCommit(fd, output->atomic_state, flags, flip_data);
- + err = drmModeAtomicCommit(fd, output->atomic_state, flags, flip_data);
- +
- + atomic_relinquish_in_fence_fd(dri2_surf, swap_data);
- +
- + return err;
- }
-
- static int
- @@ -489,6 +547,8 @@ swap_enqueue_data(struct dri2_egl_surface *dri2_surf, uint32_t back_id,
- swap_data->fb_id = dri2_surf->back->fb_id;
- swap_data->back_id = back_id;
-
- + atomic_claim_in_fence_fd(dri2_surf, swap_data);
- +
- dri2_surf->swap_queue_idx_tail++;
- dri2_surf->swap_queue_idx_tail %= ARRAY_SIZE(dri2_surf->swap_queue);
-
- @@ -1025,11 +1085,21 @@ err_unlock:
- return false;
- }
-
- +static void surface_swap_queue_init(struct dri2_egl_surface *dri2_surf)
- +{
- + struct swap_queue_elem *swap_queue = &dri2_surf->swap_queue[0];
- + const int num_el = ARRAY_SIZE(dri2_surf->swap_queue);
- +
- + for (int i = 0; i < num_el; i++)
- + swap_queue[i].kms_in_fence_fd = -1;
- +}
- +
- static _EGLSurface *
- create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
- const EGLint *attrib_list)
- {
- struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
- + struct display_output *output = &dri2_dpy->output;
- struct dri2_egl_config *dri2_config = dri2_egl_config(config);
- struct dri2_egl_surface *dri2_surf;
- const __DRIconfig *dri_config;
- @@ -1043,7 +1113,8 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
- }
- surf = &dri2_surf->base;
-
- - if (!dri2_init_surface(surf, disp, type, config, attrib_list, false, NULL))
- + if (!dri2_init_surface(surf, disp, type, config, attrib_list,
- + output->in_fence_supported, NULL))
- goto err_free_surface;
-
- dri_config = dri2_get_dri_config(dri2_config, type,
- @@ -1066,6 +1137,8 @@ create_surface(_EGLDisplay *disp, _EGLConfig *config, EGLint type,
-
- dri2_surf->format = dri2_null_formats[format_idx].dri_image_format;
-
- + surface_swap_queue_init(dri2_surf);
- +
- return surf;
-
- err_free_surface:
|