[PATCH hwc v2 09/18] drm_hwcomposer: Handle writeback connectors
Sean Paul
seanpaul at chromium.org
Tue Apr 17 15:45:30 UTC 2018
On Wed, Apr 11, 2018 at 04:22:20PM +0100, Alexandru Gheorghe wrote:
> When writeback connectors are available assign them to displays, in
> order to be able to use them for flattening of the current displayed
> scene. The pipeline for each display will look like this:
>
> CRTC ---- encoder ------------ display connector.
> |------- writeback enc ------ writeback connector.
>
> However, the writeback connector will be later used/enabled only if
> one of the following conditions are met:
> - Could be a clone of the display connector, as pointed by the
> possible_clones property.
> - The display_connector is disconnected, so we are safe to use it for
> flattening the scene that's already presented on another display.
>
> Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe at arm.com>
> ---
> drmresources.cpp | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
> drmresources.h | 3 +++
> 2 files changed, 63 insertions(+), 2 deletions(-)
>
> diff --git a/drmresources.cpp b/drmresources.cpp
> index 39f50be..fef6835 100644
> --- a/drmresources.cpp
> +++ b/drmresources.cpp
> @@ -64,6 +64,14 @@ int DrmResources::Init(ResourceManager *resource_manager, char *path,
> return ret;
> }
>
> +#ifdef DRM_CLIENT_CAP_WRITEBACK_CONNECTORS
> + ret = drmSetClientCap(fd(), DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
> + if (ret) {
> + ALOGI("Failed to set writeback cap %d", ret);
> + ret = 0;
> + }
> +#endif
> +
> drmModeResPtr res = drmModeGetResources(fd());
> if (!res) {
> ALOGE("Failed to get DrmResources resources");
> @@ -169,7 +177,7 @@ int DrmResources::Init(ResourceManager *resource_manager, char *path,
> conn->set_display(0);
> displays_[0] = 0;
> found_primary = true;
> - } else {
> + } else if (conn->external()) {
> conn->set_display(display_num);
> displays_[display_num] = display_num;
> ++display_num;
> @@ -230,6 +238,8 @@ int DrmResources::Init(ResourceManager *resource_manager, char *path,
> }
>
> for (auto &conn : connectors_) {
> + if (conn->writeback())
> + continue;
> ret = CreateDisplayPipe(conn.get());
> if (ret) {
> ALOGE("Failed CreateDisplayPipe %d with %d", conn->id(), ret);
> @@ -245,7 +255,15 @@ bool DrmResources::HandlesDisplay(int display) const {
>
> DrmConnector *DrmResources::GetConnectorForDisplay(int display) const {
> for (auto &conn : connectors_) {
> - if (conn->display() == display)
> + if (conn->display() == display && !conn->writeback())
> + return conn.get();
> + }
> + return NULL;
> +}
> +
> +DrmConnector *DrmResources::GetWritebackConnectorForDisplay(int display) const {
> + for (auto &conn : connectors_) {
> + if (conn->display() == display && conn->writeback())
> return conn.get();
> }
> return NULL;
> @@ -280,6 +298,7 @@ int DrmResources::TryEncoderForDisplay(int display, DrmEncoder *enc) {
> DrmCrtc *crtc = enc->crtc();
> if (crtc && crtc->can_bind(display)) {
> crtc->set_display(display);
> + enc->set_display(display);
> return 0;
> }
>
> @@ -306,6 +325,7 @@ int DrmResources::CreateDisplayPipe(DrmConnector *connector) {
> if (connector->encoder()) {
> int ret = TryEncoderForDisplay(display, connector->encoder());
> if (!ret) {
> + AttachWriteback(connector);
AttachWriteback returns int, but you throw it away here. Additionally,
AttachWriteback always follows a successful TryEncoderForDisplay, so it makes
sense to just call it from there.
> return 0;
> } else if (ret != -EAGAIN) {
> ALOGE("Could not set mode %d/%d", display, ret);
> @@ -317,6 +337,7 @@ int DrmResources::CreateDisplayPipe(DrmConnector *connector) {
> int ret = TryEncoderForDisplay(display, enc);
> if (!ret) {
> connector->set_encoder(enc);
> + AttachWriteback(connector);
> return 0;
> } else if (ret != -EAGAIN) {
> ALOGE("Could not set mode %d/%d", display, ret);
> @@ -328,6 +349,43 @@ int DrmResources::CreateDisplayPipe(DrmConnector *connector) {
> return -ENODEV;
> }
>
> +/*
> + * Attach writeback connector to the CRTC linked to the display_conn
> + *
> + */
> +int DrmResources::AttachWriteback(DrmConnector *display_conn) {
> + int ret = -EINVAL;
This isn't really used, just return the error code directly at the bottom.
> + if (display_conn->writeback())
> + return -EINVAL;
This condition would benefit from a log
> + DrmEncoder *display_enc = display_conn->encoder();
> + if (!display_enc)
> + return -EINVAL;
> + DrmCrtc *display_crtc = display_enc->crtc();
> + if (!display_crtc)
> + return -EINVAL;
Are these possible given this is only called after a successful
TryEncoderForDisplay()?
> + if (GetWritebackConnectorForDisplay(display_crtc->display()) != NULL)
> + return -EINVAL;
Again, logging would be useful.
> + for (auto &writeback_conn : connectors_) {
> + if (writeback_conn->display() >= 0 || !writeback_conn->writeback())
There doesn't seem to be any situation where you iterate through connectors_ and
you don't have some type of writeback() check. So it seems like it'd make sense
to track these in different vectors.
> + continue;
> + for (DrmEncoder *writeback_enc : writeback_conn->possible_encoders()) {
> + for (DrmCrtc *possible_crtc : writeback_enc->possible_crtcs()) {
> + if (possible_crtc != display_crtc)
> + continue;
> + // Use just encoders which had not been bound already
> + if (writeback_enc->can_bind(display_crtc->display())) {
> + writeback_enc->set_crtc(display_crtc);
> + writeback_conn->set_encoder(writeback_enc);
> + writeback_conn->set_display(display_crtc->display());
> + writeback_conn->UpdateModes();
> + return 0;
> + }
> + }
> + }
> + }
> + return ret;
> +}
> +
> int DrmResources::CreatePropertyBlob(void *data, size_t length,
> uint32_t *blob_id) {
> struct drm_mode_create_blob create_blob;
> diff --git a/drmresources.h b/drmresources.h
> index 4cdcd87..4fb17fc 100644
> --- a/drmresources.h
> +++ b/drmresources.h
> @@ -59,6 +59,8 @@ class DrmResources {
> }
>
> DrmConnector *GetConnectorForDisplay(int display) const;
> + DrmConnector *GetWritebackConnectorForDisplay(int display) const;
> + DrmConnector *FindWritebackConnector(int display) const;
> DrmCrtc *GetCrtcForDisplay(int display) const;
> DrmPlane *GetPlane(uint32_t id) const;
> DrmEventListener *event_listener();
> @@ -84,6 +86,7 @@ class DrmResources {
> DrmProperty *property);
>
> int CreateDisplayPipe(DrmConnector *connector);
> + int AttachWriteback(DrmConnector *display_conn);
>
> UniqueFd fd_;
> uint32_t mode_id_ = 0;
> --
> 2.7.4
>
--
Sean Paul, Software Engineer, Google / Chromium OS
More information about the dri-devel
mailing list