From: Sean Paul <seanpaul@chromium.org>
To: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
Cc: ayan.halder@arm.com, liviu.dudau@arm.com,
dri-devel@lists.freedesktop.org, nd@arm.com
Subject: Re: [PATCH hwc v2 17/18] drm_hwcomposer: Flatten scene synchronously
Date: Tue, 17 Apr 2018 13:47:46 -0400 [thread overview]
Message-ID: <20180417174746.GM73214@art_vandelay> (raw)
In-Reply-To: <1523460149-1740-18-git-send-email-alexandru-cosmin.gheorghe@arm.com>
On Wed, Apr 11, 2018 at 04:22:28PM +0100, Alexandru Gheorghe wrote:
> Flatten scene on the same CRTC as the one driving the display.
> The active composition is played back to the display with a buffer
> attached to the writeback connector.
> Then we build a composition that has only one plane enabled and that
> uses the result of the writeback as the input.
>
> Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
> ---
> drmdisplaycompositor.cpp | 203 +++++++++++++++++++++++++++++++++++++++++++++--
> drmdisplaycompositor.h | 7 +-
> 2 files changed, 204 insertions(+), 6 deletions(-)
>
> diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
> index e535e8a..cb670e6 100644
> --- a/drmdisplaycompositor.cpp
> +++ b/drmdisplaycompositor.cpp
> @@ -36,6 +36,7 @@
> #include "drmplane.h"
> #include "drmresources.h"
> #include "glworker.h"
> +static const uint32_t kWaitWritebackFence = 100; // ms
>
> namespace android {
>
> @@ -523,7 +524,9 @@ int DrmDisplayCompositor::PrepareFrame(DrmDisplayComposition *display_comp) {
> }
>
> int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
> - bool test_only) {
> + bool test_only,
> + DrmDisplayComposition *writeback_comp,
> + DrmConnector *writeback_conn) {
> ATRACE_CALL();
>
> int ret = 0;
> @@ -532,6 +535,7 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
> std::vector<DrmCompositionPlane> &comp_planes =
> display_comp->composition_planes();
> uint64_t out_fences[drm_->crtcs().size()];
> + int writeback_fence = -1;
>
> DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
> if (!connector) {
> @@ -550,9 +554,37 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
> return -ENOMEM;
> }
>
> + if (writeback_comp != NULL) {
> + if (writeback_conn == NULL)
> + return -EINVAL;
> + if (writeback_conn->writeback_fb_id().id() == 0 ||
> + writeback_conn->writeback_out_fence().id() == 0) {
> + ALOGE("Writeback properties don't exit");
> + return -EINVAL;
> + }
> + if (writeback_comp->layers().size() != 1) {
> + ALOGE("Invalid number of layers for writeback composition");
> + return -EINVAL;
> + }
> + ret = drmModeAtomicAddProperty(
> + pset, writeback_conn->id(), writeback_conn->writeback_fb_id().id(),
> + writeback_comp->layers().back().buffer->fb_id);
> + if (ret < 0) {
> + ALOGE("Failed to add writeback_fb_id");
> + return ret;
> + }
> + ret = drmModeAtomicAddProperty(pset, writeback_conn->id(),
> + writeback_conn->writeback_out_fence().id(),
> + (uint64_t)&writeback_fence);
Upcasting int to u64 isn't a great idea, please go the other way (as we do with
out_fences).
> + if (ret < 0) {
> + ALOGE("Failed to add writeback_out_fence");
> + return ret;
> + }
> + }
This would be more readable if it was split off into a function.
> if (crtc->out_fence_ptr_property().id() != 0) {
> - ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->out_fence_ptr_property().id(),
> - (uint64_t) &out_fences[crtc->pipe()]);
> + ret = drmModeAtomicAddProperty(pset, crtc->id(),
> + crtc->out_fence_ptr_property().id(),
> + (uint64_t)&out_fences[crtc->pipe()]);
> if (ret < 0) {
> ALOGE("Failed to add OUT_FENCE_PTR property to pset: %d", ret);
> drmModeAtomicFree(pset);
> @@ -580,6 +612,15 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
> }
> }
>
> + if (writeback_conn != NULL) {
> + ret = drmModeAtomicAddProperty(pset, writeback_conn->id(),
> + writeback_conn->crtc_id_property().id(),
> + crtc->id());
> + if (ret < 0) {
> + ALOGE("Failed to attach writeback");
> + }
> + }
Can you do this above with the rest of the writeback properties?
> +
> for (DrmCompositionPlane &comp_plane : comp_planes) {
> DrmPlane *plane = comp_plane.plane();
> DrmCrtc *crtc = comp_plane.crtc();
> @@ -729,8 +770,18 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
>
> if (!ret) {
> uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
> - if (test_only)
> + if (test_only) {
> flags |= DRM_MODE_ATOMIC_TEST_ONLY;
> + } else {
> + if (writeback_comp != NULL) {
> + if (!CountdownExpired() && active_composition_) {
Given that we're holding the lock throughout this function, can't you just
abort at the start?
> + ALOGE("Writeback composition not needed, abort commit");
> + drmModeAtomicFree(pset);
> + return -EINVAL;
> + };
> + flags |= DRM_MODE_ATOMIC_NONBLOCK;
I'm guessing this is the cause of the active_composition race you're fixing
earlier in the series? Could you please pull this out and squash it into that
patch as a "Use non-blocking commits" standalone? It might be useful for
testing, and this is something that's substantial enough to warrant the
additional visibility of its own patch.
> + }
> + }
>
> ret = drmModeAtomicCommit(drm_->fd(), pset, flags, drm_);
> if (ret) {
> @@ -769,6 +820,13 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
> if (crtc->out_fence_ptr_property().id()) {
> display_comp->set_out_fence((int) out_fences[crtc->pipe()]);
> }
> + if (writeback_fence >= 0) {
> + if (writeback_comp->layers().size() != 1) {
> + ALOGE("Invalid numbers of layer for writeback_comp");
> + return -EINVAL;
> + }
You already test this above?
> + writeback_comp->layers()[0].acquire_fence.Set(writeback_fence);
> + }
>
> return ret;
> }
> @@ -837,6 +895,8 @@ void DrmDisplayCompositor::ApplyFrame(
> if (active_composition_)
> active_composition_->SignalCompositionDone();
> active_composition_.swap(composition);
> + flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
> + vsync_worker_.VSyncControl(!writeback);
> }
> }
>
> @@ -913,8 +973,141 @@ int DrmDisplayCompositor::ApplyComposition(
> return ret;
> }
>
> +int DrmDisplayCompositor::WritebackComposite(DrmDisplayComposition *src,
> + DrmDisplayComposition *dst,
> + DrmConnector *writeback_conn) {
> + int ret = 0;
> + if (src == NULL || dst == NULL)
> + return -EINVAL;
> + std::vector<DrmCompositionPlane> &src_planes = src->composition_planes();
> + DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kPrecomp, NULL,
> + src->crtc());
> + for (DrmCompositionPlane &comp_plane : src_planes) {
> + if (comp_plane.plane() == NULL) {
> + ALOGE("Skipping squash all because of NULL plane");
> + ret = -EINVAL;
> + }
> + if (!squashed_comp.plane() &&
> + comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY)
> + squashed_comp.set_plane(comp_plane.plane());
> + else
> + dst->AddPlaneDisable(comp_plane.plane());
> + }
> +
> + DrmFramebuffer *writeback_fb = NULL;
> + AutoLock lock(&lock_, __FUNCTION__);
> + if ((ret = lock.Lock()))
Same comments regarding assignment in a conditional.
> + return ret;
> + writeback_fb = &framebuffers_[framebuffer_index_];
> + framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
> + ret = PrepareFramebuffer(*writeback_fb, dst, mode_.mode.h_display(),
> + mode_.mode.v_display());
> + if (ret) {
> + ALOGE("Failed to prepare destination buffer");
> + return ret;
> + }
> + lock.Unlock();
> + ret = CommitFrame(src, true, dst, writeback_conn);
> + if (ret) {
> + ALOGE("Atomic check failed");
> + return ret;
> + }
> + if ((ret = lock.Lock()))
All of these locks and unlocks are going to cause races, as mentioned below,
please re-evaluate.
> + return ret;
> + if (!CountdownExpired() && active_composition_) {
> + ALOGE("Writeback composition not needed abort");
> + return -EINVAL;
> + }
> + ret = CommitFrame(src, false, dst, writeback_conn);
> + lock.Unlock();
> + if (ret || dst->layers().size() != 1) {
> + ALOGE("Failed to flatten scene using writeback");
> + return -EINVAL;
> + }
> + squashed_comp.source_layers().push_back(0);
> + ret =
> + sync_wait(dst->layers()[0].acquire_fence.Release(), kWaitWritebackFence);
line break
> + if (ret) {
> + ALOGE("Failed to wait on writeback fence");
> + return ret;
> + }
> + ret = dst->AddPlaneComposition(std::move(squashed_comp));
> + if (ret) {
> + ALOGE("Failed to add flatten scene");
> + return ret;
> + }
> + ret = dst->FinalizeComposition();
> + if (ret) {
> + ALOGE("Failed to finalize composition");
> + return ret;
> + }
> + return 0;
> +}
> +
> +int DrmDisplayCompositor::FlattenSynchronously(DrmConnector *writeback_conn) {
> + if (writeback_conn->display() != display_) {
> + ALOGE("Cannot flatten synchronously on different display");
> + return -EINVAL;
> + }
You check this right before calling, so this isn't needed.
> + ALOGI("FlattenSynchronously using the same display");
I think you should downgrade this log level.
> + int ret = 0;
> + /* Flattened composition with only one layer that is built
> + * using the writeback connector
> + */
> + std::unique_ptr<DrmDisplayComposition> writeback_comp =
> + CreateInitializedComposition();
> + /* Copy of the active_composition_, we need a copy because
> + * if we use the active composition we have to hold the lock
> + * for the entire sequence of flattening.
> + */
> + std::unique_ptr<DrmDisplayComposition> copy_comp =
> + CreateInitializedComposition();
> +
> + if (!copy_comp || !writeback_comp)
> + return -EINVAL;
> + AutoLock lock(&lock_, __FUNCTION__);
> + if ((ret = lock.Lock()))
Assignments in if statements make me nervous. Since you don't need the
declaration above, just do:
int ret = lock.Lock();
if (ret)
> + return ret;
> + if (CountdownExpired()) {
> + ret = copy_comp->CopyLayers(active_composition_.get());
> + if (ret)
> + return ret;
> + copy_comp->CopyCompPlanes(active_composition_.get());
> + } else {
> + return -EINVAL;
> + }
if (!CountdownExpired())
return -EINVAL;
ret = copy_comp->CopyLayers(active_composition_.get());
if (ret)
return ret;
copy_comp->CopyCompPlanes(active_composition_.get());
> + lock.Unlock();
Just hold the lock through WritebackComposite(), and consider creating a
ApplyFrameLocked() to hold it through ApplyFrame(). You should be able to reduce
the number of times you have to check CountdownExpired() (or remove it)
significantly by just consistently locking things.
> + ret =
> + WritebackComposite(copy_comp.get(), writeback_comp.get(), writeback_conn);
> + if (ret) {
> + ALOGE("Failed to prepare writebackScene");
> + return ret;
> + }
> +
> + ApplyFrame(std::move(writeback_comp), 0, true);
> + return 0;
> +}
> +
> int DrmDisplayCompositor::FlattenScene() {
> - return -EINVAL;
> + DrmConnector *writeback_conn =
> + drm_->resource_manager()->AvailableWritebackConnector(display_);
> + if (!active_composition_ || !writeback_conn)
> + return -EINVAL;
> + std::vector<DrmCompositionPlane> &src_planes =
> + active_composition_->composition_planes();
> + size_t src_planes_with_layer = std::count_if(
> + src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) {
> + return p.type() != DrmCompositionPlane::Type::kDisable;
> + });
> +
> + if (src_planes_with_layer <= 1)
> + return -EALREADY;
> +
> + if (writeback_conn->display() == display_) {
> + return FlattenSynchronously(writeback_conn);
> + }
> +
> + return 0;
> }
>
> int DrmDisplayCompositor::SquashAll() {
> diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
> index 26201b9..4cc4a5e 100644
> --- a/drmdisplaycompositor.h
> +++ b/drmdisplaycompositor.h
> @@ -125,7 +125,9 @@ class DrmDisplayCompositor {
> int ApplySquash(DrmDisplayComposition *display_comp);
> int ApplyPreComposite(DrmDisplayComposition *display_comp);
> int PrepareFrame(DrmDisplayComposition *display_comp);
> - int CommitFrame(DrmDisplayComposition *display_comp, bool test_only);
> + int CommitFrame(DrmDisplayComposition *display_comp, bool test_only,
> + DrmDisplayComposition *writeback_comp = NULL,
> + DrmConnector *writeback_conn = NULL);
> int SquashFrame(DrmDisplayComposition *src, DrmDisplayComposition *dst);
> int ApplyDpms(DrmDisplayComposition *display_comp);
> int DisablePlanes(DrmDisplayComposition *display_comp);
> @@ -134,7 +136,10 @@ class DrmDisplayCompositor {
> void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
> int status, bool writeback = false);
> int FlattenScene();
> + int FlattenSynchronously(DrmConnector *writeback_conn);
Can we come up with a better name than Synchonrous/Asynchronous? Or at the very
least comment on what that means?
>
> + int WritebackComposite(DrmDisplayComposition *src, DrmDisplayComposition *dst,
> + DrmConnector *writeback_conn);
> bool CountdownExpired() const;
>
> std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode);
> --
> 2.7.4
>
--
Sean Paul, Software Engineer, Google / Chromium OS
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
next prev parent reply other threads:[~2018-04-17 17:47 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-11 15:22 [PATCH hwc v2 00/18] Add scene flattening support Alexandru Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 01/18] drm_hwcomposer: vsyncworker: Fix uninitialized enabled_ field Alexandru Gheorghe
2018-04-16 10:30 ` Robert Foss
2018-04-16 12:18 ` Alexandru-Cosmin Gheorghe
2018-04-17 13:45 ` Sean Paul
2018-04-17 14:09 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 02/18] drm_hwcomposer: vsyncworker: Fix deadlock on exit path Alexandru Gheorghe
2018-04-16 10:31 ` Robert Foss
2018-04-16 19:25 ` Sean Paul
2018-04-17 13:32 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 03/18] drm_hwcomposer: drmeventlistener: Set nl_pid to 0 Alexandru Gheorghe
2018-04-16 10:32 ` Robert Foss
2018-04-11 15:22 ` [PATCH hwc v2 04/18] drm_hwcomposer: Add resource manager class Alexandru Gheorghe
2018-04-17 15:33 ` Sean Paul
2018-04-17 16:08 ` Robert Foss
2018-04-18 10:12 ` Alexandru-Cosmin Gheorghe
2018-04-18 10:14 ` Robert Foss
2018-04-11 15:22 ` [PATCH hwc v2 05/18] drm_hwcomposer: Enable resource manager support Alexandru Gheorghe
2018-04-16 19:54 ` Sean Paul
2018-04-17 13:43 ` Alexandru-Cosmin Gheorghe
2018-04-17 14:22 ` Sean Paul
2018-04-17 14:26 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 06/18] drm_hwcomposer: Add writeback connector support Alexandru Gheorghe
2018-04-16 19:59 ` Sean Paul
2018-04-17 13:46 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 07/18] drm_hwcomposer: Add display field to Drmencoder Alexandru Gheorghe
2018-04-16 20:02 ` Sean Paul
2018-04-17 13:49 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 08/18] drm_hwcomposer: Parse and store possible_clones information Alexandru Gheorghe
2018-04-16 20:19 ` Sean Paul
2018-04-17 14:03 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 09/18] drm_hwcomposer: Handle writeback connectors Alexandru Gheorghe
2018-04-17 15:45 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 10/18] drm_hwcomposer: hwcutils: Add function for cloning a DrmHwcLayer Alexandru Gheorghe
2018-04-17 16:14 ` Sean Paul
2018-04-18 10:22 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 11/18] drm_hwcomposer: Add utility functions to copy displaycomposition internals Alexandru Gheorghe
2018-04-17 16:34 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 12/18] drm_hwcomposer: Add utility function to create an initialized composition Alexandru Gheorghe
2018-04-17 16:37 ` Sean Paul
2018-04-18 10:29 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 13/18] drm_hwcomposer: Pass buffer sizes to Prepareframebuffer Alexandru Gheorghe
2018-04-17 16:51 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 14/18] drm_hwcomposer: Fix race in ApplyFrame Alexandru Gheorghe
2018-04-17 17:02 ` Sean Paul
2018-04-18 10:43 ` Alexandru-Cosmin Gheorghe
2018-04-11 15:22 ` [PATCH hwc v2 15/18] drm_hwcomposer: Add worker to trigger scene flattenning Alexandru Gheorghe
2018-04-17 17:07 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 16/18] drm_hwcomposer: Find writeback connector for scene flattening Alexandru Gheorghe
2018-04-17 17:15 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 17/18] drm_hwcomposer: Flatten scene synchronously Alexandru Gheorghe
2018-04-17 17:47 ` Sean Paul [this message]
2018-04-18 11:14 ` Alexandru-Cosmin Gheorghe
2018-04-18 14:49 ` Sean Paul
2018-04-11 15:22 ` [PATCH hwc v2 18/18] drm_hwcomposer: Flatten scene asynchronously Alexandru Gheorghe
2018-04-12 23:18 ` [PATCH hwc v2 00/18] Add scene flattening support John Stultz
2018-04-13 9:52 ` Alexandru-Cosmin Gheorghe
2018-04-13 12:48 ` Alexandru-Cosmin Gheorghe
2018-04-18 17:21 ` John Stultz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180417174746.GM73214@art_vandelay \
--to=seanpaul@chromium.org \
--cc=alexandru-cosmin.gheorghe@arm.com \
--cc=ayan.halder@arm.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=liviu.dudau@arm.com \
--cc=nd@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox