Merge remote-tracking branch 'aosp/upstream-master' into aosp-fdo-merge
am: b3f8cbf754
Change-Id: I900311cab03a19bdaa540f3fe79d6157302ceadf
diff --git a/.clang-format b/.clang-format
index 5382f9b..984fa5e 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,4 +1,7 @@
BasedOnStyle: Google
+AllowAllParametersOfDeclarationOnNextLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
+PenaltyBreakAssignment: 10000000
+PenaltyBreakBeforeFirstCallParameter: 1000
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 43bce5f..24c4a0a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,7 +2,7 @@
before_script:
- apt-get --quiet update --yes >/dev/null
- - apt-get --quiet install --yes clang-format-3.5 git >/dev/null
+ - apt-get --quiet install --yes clang-format-5.0 git >/dev/null
stages:
- style
@@ -11,7 +11,7 @@
stage: style
script:
- git fetch https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer.git
- - git diff -U0 --no-color FETCH_HEAD...HEAD -- | clang-format-diff-3.5 -p 1 -style=file > format-fixup.patch
+ - git diff -U0 --no-color FETCH_HEAD...HEAD -- | clang-format-diff-5.0 -p 1 -style=file > format-fixup.patch
- if [ -s format-fixup.patch ]; then cat format-fixup.patch && exit 1; fi
artifacts:
when: on_failure
diff --git a/Android.mk b/Android.mk
index 3d48ba5..d5ee200 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,16 +14,13 @@
ifeq ($(strip $(BOARD_USES_DRM_HWCOMPOSER)),true)
+DRM_HWC_ANDROID_MAJOR_VERSION := $(word 1, $(subst ., , $(PLATFORM_VERSION)))
+
LOCAL_PATH := $(call my-dir)
common_drm_hwcomposer_cflags := \
-Wall \
-Werror \
- -Wno-unused-function \
- -Wno-unused-label \
- -Wno-unused-parameter \
- -Wno-unused-private-field \
- -Wno-unused-variable \
# =====================
# libdrmhwc_utils.a
@@ -61,7 +58,8 @@
LOCAL_SRC_FILES := \
autolock.cpp \
- drmresources.cpp \
+ resourcemanager.cpp \
+ drmdevice.cpp \
drmconnector.cpp \
drmcrtc.cpp \
drmdisplaycomposition.cpp \
@@ -83,6 +81,10 @@
-DHWC2_USE_CPP11 \
-DHWC2_INCLUDE_STRINGIFICATION
+ifneq ($(filter 2 3 4 5 6 7 8, $(DRM_HWC_ANDROID_MAJOR_VERSION)),)
+LOCAL_CPPFLAGS += -DHWC2_USE_OLD_GB_IMPORT
+endif
+
ifeq ($(TARGET_PRODUCT),hikey960)
LOCAL_CPPFLAGS += -DUSE_HISI_IMPORTER
diff --git a/autofd.h b/autofd.h
index 1edc9c5..9af6c22 100644
--- a/autofd.h
+++ b/autofd.h
@@ -101,6 +101,6 @@
private:
int *fd_ = NULL;
};
-}
+} // namespace android
#endif
diff --git a/autolock.cpp b/autolock.cpp
index 795a8c2..4e9552a 100644
--- a/autolock.cpp
+++ b/autolock.cpp
@@ -53,4 +53,4 @@
locked_ = false;
return 0;
}
-}
+} // namespace android
diff --git a/autolock.h b/autolock.h
index 3b824e2..006406a 100644
--- a/autolock.h
+++ b/autolock.h
@@ -39,4 +39,4 @@
bool locked_ = false;
const char *const name_;
};
-}
+} // namespace android
diff --git a/drmconnector.cpp b/drmconnector.cpp
index 10b96b5..756791f 100644
--- a/drmconnector.cpp
+++ b/drmconnector.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "hwc-drm-connector"
#include "drmconnector.h"
-#include "drmresources.h"
+#include "drmdevice.h"
#include <errno.h>
#include <stdint.h>
@@ -27,7 +27,7 @@
namespace android {
-DrmConnector::DrmConnector(DrmResources *drm, drmModeConnectorPtr c,
+DrmConnector::DrmConnector(DrmDevice *drm, drmModeConnectorPtr c,
DrmEncoder *current_encoder,
std::vector<DrmEncoder *> &possible_encoders)
: drm_(drm),
@@ -52,6 +52,26 @@
ALOGE("Could not get CRTC_ID property\n");
return ret;
}
+ if (writeback()) {
+ ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
+ &writeback_pixel_formats_);
+ if (ret) {
+ ALOGE("Could not get WRITEBACK_PIXEL_FORMATS connector_id = %d\n", id_);
+ return ret;
+ }
+ ret = drm_->GetConnectorProperty(*this, "WRITEBACK_FB_ID",
+ &writeback_fb_id_);
+ if (ret) {
+ ALOGE("Could not get WRITEBACK_FB_ID connector_id = %d\n", id_);
+ return ret;
+ }
+ ret = drm_->GetConnectorProperty(*this, "WRITEBACK_OUT_FENCE_PTR",
+ &writeback_out_fence_);
+ if (ret) {
+ ALOGE("Could not get WRITEBACK_OUT_FENCE_PTR connector_id = %d\n", id_);
+ return ret;
+ }
+ }
return 0;
}
@@ -73,13 +93,22 @@
}
bool DrmConnector::external() const {
- return type_ == DRM_MODE_CONNECTOR_HDMIA || type_ == DRM_MODE_CONNECTOR_DisplayPort ||
+ return type_ == DRM_MODE_CONNECTOR_HDMIA ||
+ type_ == DRM_MODE_CONNECTOR_DisplayPort ||
type_ == DRM_MODE_CONNECTOR_DVID || type_ == DRM_MODE_CONNECTOR_DVII ||
type_ == DRM_MODE_CONNECTOR_VGA;
}
+bool DrmConnector::writeback() const {
+#ifdef DRM_MODE_CONNECTOR_WRITEBACK
+ return type_ == DRM_MODE_CONNECTOR_WRITEBACK;
+#else
+ return false;
+#endif
+}
+
bool DrmConnector::valid_type() const {
- return internal() || external();
+ return internal() || external() || writeback();
}
int DrmConnector::UpdateModes() {
@@ -130,6 +159,18 @@
return crtc_id_property_;
}
+const DrmProperty &DrmConnector::writeback_pixel_formats() const {
+ return writeback_pixel_formats_;
+}
+
+const DrmProperty &DrmConnector::writeback_fb_id() const {
+ return writeback_fb_id_;
+}
+
+const DrmProperty &DrmConnector::writeback_out_fence() const {
+ return writeback_out_fence_;
+}
+
DrmEncoder *DrmConnector::encoder() const {
return encoder_;
}
@@ -149,4 +190,4 @@
uint32_t DrmConnector::mm_height() const {
return mm_height_;
}
-}
+} // namespace android
diff --git a/drmconnector.h b/drmconnector.h
index 5601e06..4f7f6a8 100644
--- a/drmconnector.h
+++ b/drmconnector.h
@@ -22,16 +22,16 @@
#include "drmproperty.h"
#include <stdint.h>
-#include <vector>
#include <xf86drmMode.h>
+#include <vector>
namespace android {
-class DrmResources;
+class DrmDevice;
class DrmConnector {
public:
- DrmConnector(DrmResources *drm, drmModeConnectorPtr c,
+ DrmConnector(DrmDevice *drm, drmModeConnectorPtr c,
DrmEncoder *current_encoder,
std::vector<DrmEncoder *> &possible_encoders);
DrmConnector(const DrmProperty &) = delete;
@@ -46,6 +46,7 @@
bool internal() const;
bool external() const;
+ bool writeback() const;
bool valid_type() const;
int UpdateModes();
@@ -58,6 +59,9 @@
const DrmProperty &dpms_property() const;
const DrmProperty &crtc_id_property() const;
+ const DrmProperty &writeback_pixel_formats() const;
+ const DrmProperty &writeback_fb_id() const;
+ const DrmProperty &writeback_out_fence() const;
const std::vector<DrmEncoder *> &possible_encoders() const {
return possible_encoders_;
@@ -71,7 +75,7 @@
uint32_t mm_height() const;
private:
- DrmResources *drm_;
+ DrmDevice *drm_;
uint32_t id_;
DrmEncoder *encoder_;
@@ -88,9 +92,12 @@
DrmProperty dpms_property_;
DrmProperty crtc_id_property_;
+ DrmProperty writeback_pixel_formats_;
+ DrmProperty writeback_fb_id_;
+ DrmProperty writeback_out_fence_;
std::vector<DrmEncoder *> possible_encoders_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_PLANE_H_
diff --git a/drmcrtc.cpp b/drmcrtc.cpp
index 4033269..b627291 100644
--- a/drmcrtc.cpp
+++ b/drmcrtc.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "hwc-drm-crtc"
#include "drmcrtc.h"
-#include "drmresources.h"
+#include "drmdevice.h"
#include <stdint.h>
#include <xf86drmMode.h>
@@ -26,12 +26,8 @@
namespace android {
-DrmCrtc::DrmCrtc(DrmResources *drm, drmModeCrtcPtr c, unsigned pipe)
- : drm_(drm),
- id_(c->crtc_id),
- pipe_(pipe),
- display_(-1),
- mode_(&c->mode) {
+DrmCrtc::DrmCrtc(DrmDevice *drm, drmModeCrtcPtr c, unsigned pipe)
+ : drm_(drm), id_(c->crtc_id), pipe_(pipe), display_(-1), mode_(&c->mode) {
}
int DrmCrtc::Init() {
@@ -86,4 +82,4 @@
const DrmProperty &DrmCrtc::out_fence_ptr_property() const {
return out_fence_ptr_property_;
}
-}
+} // namespace android
diff --git a/drmcrtc.h b/drmcrtc.h
index c5a5599..3075f9b 100644
--- a/drmcrtc.h
+++ b/drmcrtc.h
@@ -25,11 +25,11 @@
namespace android {
-class DrmResources;
+class DrmDevice;
class DrmCrtc {
public:
- DrmCrtc(DrmResources *drm, drmModeCrtcPtr c, unsigned pipe);
+ DrmCrtc(DrmDevice *drm, drmModeCrtcPtr c, unsigned pipe);
DrmCrtc(const DrmCrtc &) = delete;
DrmCrtc &operator=(const DrmCrtc &) = delete;
@@ -48,7 +48,7 @@
const DrmProperty &out_fence_ptr_property() const;
private:
- DrmResources *drm_;
+ DrmDevice *drm_;
uint32_t id_;
unsigned pipe_;
@@ -60,6 +60,6 @@
DrmProperty mode_property_;
DrmProperty out_fence_ptr_property_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_CRTC_H_
diff --git a/drmdevice.cpp b/drmdevice.cpp
new file mode 100644
index 0000000..2007fdd
--- /dev/null
+++ b/drmdevice.cpp
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-drm-device"
+
+#include "drmdevice.h"
+#include "drmconnector.h"
+#include "drmcrtc.h"
+#include "drmencoder.h"
+#include "drmeventlistener.h"
+#include "drmplane.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <cinttypes>
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+namespace android {
+
+DrmDevice::DrmDevice() : event_listener_(this) {
+}
+
+DrmDevice::~DrmDevice() {
+ event_listener_.Exit();
+}
+
+std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) {
+ /* TODO: Use drmOpenControl here instead */
+ fd_.Set(open(path, O_RDWR));
+ if (fd() < 0) {
+ ALOGE("Failed to open dri- %s", strerror(-errno));
+ return std::make_tuple(-ENODEV, 0);
+ }
+
+ int ret = drmSetClientCap(fd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
+ if (ret) {
+ ALOGE("Failed to set universal plane cap %d", ret);
+ return std::make_tuple(ret, 0);
+ }
+
+ ret = drmSetClientCap(fd(), DRM_CLIENT_CAP_ATOMIC, 1);
+ if (ret) {
+ ALOGE("Failed to set atomic cap %d", ret);
+ return std::make_tuple(ret, 0);
+ }
+
+#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 DrmDevice resources");
+ return std::make_tuple(-ENODEV, 0);
+ }
+
+ min_resolution_ = std::pair<uint32_t, uint32_t>(res->min_width,
+ res->min_height);
+ max_resolution_ = std::pair<uint32_t, uint32_t>(res->max_width,
+ res->max_height);
+
+ // Assumes that the primary display will always be in the first
+ // drm_device opened.
+ bool found_primary = num_displays != 0;
+
+ for (int i = 0; !ret && i < res->count_crtcs; ++i) {
+ drmModeCrtcPtr c = drmModeGetCrtc(fd(), res->crtcs[i]);
+ if (!c) {
+ ALOGE("Failed to get crtc %d", res->crtcs[i]);
+ ret = -ENODEV;
+ break;
+ }
+
+ std::unique_ptr<DrmCrtc> crtc(new DrmCrtc(this, c, i));
+ drmModeFreeCrtc(c);
+
+ ret = crtc->Init();
+ if (ret) {
+ ALOGE("Failed to initialize crtc %d", res->crtcs[i]);
+ break;
+ }
+ crtcs_.emplace_back(std::move(crtc));
+ }
+
+ std::vector<int> possible_clones;
+ for (int i = 0; !ret && i < res->count_encoders; ++i) {
+ drmModeEncoderPtr e = drmModeGetEncoder(fd(), res->encoders[i]);
+ if (!e) {
+ ALOGE("Failed to get encoder %d", res->encoders[i]);
+ ret = -ENODEV;
+ break;
+ }
+
+ std::vector<DrmCrtc *> possible_crtcs;
+ DrmCrtc *current_crtc = NULL;
+ for (auto &crtc : crtcs_) {
+ if ((1 << crtc->pipe()) & e->possible_crtcs)
+ possible_crtcs.push_back(crtc.get());
+
+ if (crtc->id() == e->crtc_id)
+ current_crtc = crtc.get();
+ }
+
+ std::unique_ptr<DrmEncoder> enc(
+ new DrmEncoder(e, current_crtc, possible_crtcs));
+ possible_clones.push_back(e->possible_clones);
+ drmModeFreeEncoder(e);
+
+ encoders_.emplace_back(std::move(enc));
+ }
+
+ for (unsigned int i = 0; i < encoders_.size(); i++) {
+ for (unsigned int j = 0; j < encoders_.size(); j++)
+ if (possible_clones[i] & (1 << j))
+ encoders_[i]->AddPossibleClone(encoders_[j].get());
+ }
+
+ for (int i = 0; !ret && i < res->count_connectors; ++i) {
+ drmModeConnectorPtr c = drmModeGetConnector(fd(), res->connectors[i]);
+ if (!c) {
+ ALOGE("Failed to get connector %d", res->connectors[i]);
+ ret = -ENODEV;
+ break;
+ }
+
+ std::vector<DrmEncoder *> possible_encoders;
+ DrmEncoder *current_encoder = NULL;
+ for (int j = 0; j < c->count_encoders; ++j) {
+ for (auto &encoder : encoders_) {
+ if (encoder->id() == c->encoders[j])
+ possible_encoders.push_back(encoder.get());
+ if (encoder->id() == c->encoder_id)
+ current_encoder = encoder.get();
+ }
+ }
+
+ std::unique_ptr<DrmConnector> conn(
+ new DrmConnector(this, c, current_encoder, possible_encoders));
+
+ drmModeFreeConnector(c);
+
+ ret = conn->Init();
+ if (ret) {
+ ALOGE("Init connector %d failed", res->connectors[i]);
+ break;
+ }
+
+ if (conn->writeback())
+ writeback_connectors_.emplace_back(std::move(conn));
+ else
+ connectors_.emplace_back(std::move(conn));
+ }
+
+ // First look for primary amongst internal connectors
+ for (auto &conn : connectors_) {
+ if (conn->internal() && !found_primary) {
+ conn->set_display(num_displays);
+ displays_[num_displays] = num_displays;
+ ++num_displays;
+ found_primary = true;
+ break;
+ }
+ }
+
+ // Then pick first available as primary and for the others assign
+ // consecutive display_numbers.
+ for (auto &conn : connectors_) {
+ if (conn->external() || conn->internal()) {
+ if (!found_primary) {
+ conn->set_display(num_displays);
+ displays_[num_displays] = num_displays;
+ found_primary = true;
+ ++num_displays;
+ } else if (conn->display() < 0) {
+ conn->set_display(num_displays);
+ displays_[num_displays] = num_displays;
+ ++num_displays;
+ }
+ }
+ }
+
+ if (res)
+ drmModeFreeResources(res);
+
+ // Catch-all for the above loops
+ if (ret)
+ return std::make_tuple(ret, 0);
+
+ drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd());
+ if (!plane_res) {
+ ALOGE("Failed to get plane resources");
+ return std::make_tuple(-ENOENT, 0);
+ }
+
+ for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
+ drmModePlanePtr p = drmModeGetPlane(fd(), plane_res->planes[i]);
+ if (!p) {
+ ALOGE("Failed to get plane %d", plane_res->planes[i]);
+ ret = -ENODEV;
+ break;
+ }
+
+ std::unique_ptr<DrmPlane> plane(new DrmPlane(this, p));
+
+ drmModeFreePlane(p);
+
+ ret = plane->Init();
+ if (ret) {
+ ALOGE("Init plane %d failed", plane_res->planes[i]);
+ break;
+ }
+
+ planes_.emplace_back(std::move(plane));
+ }
+ drmModeFreePlaneResources(plane_res);
+ if (ret)
+ return std::make_tuple(ret, 0);
+
+ ret = event_listener_.Init();
+ if (ret) {
+ ALOGE("Can't initialize event listener %d", ret);
+ return std::make_tuple(ret, 0);
+ }
+
+ for (auto &conn : connectors_) {
+ ret = CreateDisplayPipe(conn.get());
+ if (ret) {
+ ALOGE("Failed CreateDisplayPipe %d with %d", conn->id(), ret);
+ return std::make_tuple(ret, 0);
+ }
+ if (!AttachWriteback(conn.get())) {
+ ALOGI("Display %d has writeback attach to it", conn->display());
+ }
+ }
+ return std::make_tuple(ret, displays_.size());
+}
+
+bool DrmDevice::HandlesDisplay(int display) const {
+ return displays_.find(display) != displays_.end();
+}
+
+DrmConnector *DrmDevice::GetConnectorForDisplay(int display) const {
+ for (auto &conn : connectors_) {
+ if (conn->display() == display)
+ return conn.get();
+ }
+ return NULL;
+}
+
+DrmConnector *DrmDevice::GetWritebackConnectorForDisplay(int display) const {
+ for (auto &conn : writeback_connectors_) {
+ if (conn->display() == display)
+ return conn.get();
+ }
+ return NULL;
+}
+
+// TODO what happens when hotplugging
+DrmConnector *DrmDevice::AvailableWritebackConnector(int display) const {
+ DrmConnector *writeback_conn = GetWritebackConnectorForDisplay(display);
+ DrmConnector *display_conn = GetConnectorForDisplay(display);
+ // If we have a writeback already attached to the same CRTC just use that,
+ // if possible.
+ if (display_conn && writeback_conn &&
+ writeback_conn->encoder()->CanClone(display_conn->encoder()))
+ return writeback_conn;
+
+ // Use another CRTC if available and doesn't have any connector
+ for (auto &crtc : crtcs_) {
+ if (crtc->display() == display)
+ continue;
+ display_conn = GetConnectorForDisplay(crtc->display());
+ // If we have a display connected don't use it for writeback
+ if (display_conn && display_conn->state() == DRM_MODE_CONNECTED)
+ continue;
+ writeback_conn = GetWritebackConnectorForDisplay(crtc->display());
+ if (writeback_conn)
+ return writeback_conn;
+ }
+ return NULL;
+}
+
+DrmCrtc *DrmDevice::GetCrtcForDisplay(int display) const {
+ for (auto &crtc : crtcs_) {
+ if (crtc->display() == display)
+ return crtc.get();
+ }
+ return NULL;
+}
+
+DrmPlane *DrmDevice::GetPlane(uint32_t id) const {
+ for (auto &plane : planes_) {
+ if (plane->id() == id)
+ return plane.get();
+ }
+ return NULL;
+}
+
+const std::vector<std::unique_ptr<DrmCrtc>> &DrmDevice::crtcs() const {
+ return crtcs_;
+}
+
+uint32_t DrmDevice::next_mode_id() {
+ return ++mode_id_;
+}
+
+int DrmDevice::TryEncoderForDisplay(int display, DrmEncoder *enc) {
+ /* First try to use the currently-bound crtc */
+ DrmCrtc *crtc = enc->crtc();
+ if (crtc && crtc->can_bind(display)) {
+ crtc->set_display(display);
+ enc->set_crtc(crtc);
+ return 0;
+ }
+
+ /* Try to find a possible crtc which will work */
+ for (DrmCrtc *crtc : enc->possible_crtcs()) {
+ /* We've already tried this earlier */
+ if (crtc == enc->crtc())
+ continue;
+
+ if (crtc->can_bind(display)) {
+ crtc->set_display(display);
+ enc->set_crtc(crtc);
+ return 0;
+ }
+ }
+
+ /* We can't use the encoder, but nothing went wrong, try another one */
+ return -EAGAIN;
+}
+
+int DrmDevice::CreateDisplayPipe(DrmConnector *connector) {
+ int display = connector->display();
+ /* Try to use current setup first */
+ if (connector->encoder()) {
+ int ret = TryEncoderForDisplay(display, connector->encoder());
+ if (!ret) {
+ return 0;
+ } else if (ret != -EAGAIN) {
+ ALOGE("Could not set mode %d/%d", display, ret);
+ return ret;
+ }
+ }
+
+ for (DrmEncoder *enc : connector->possible_encoders()) {
+ int ret = TryEncoderForDisplay(display, enc);
+ if (!ret) {
+ connector->set_encoder(enc);
+ return 0;
+ } else if (ret != -EAGAIN) {
+ ALOGE("Could not set mode %d/%d", display, ret);
+ return ret;
+ }
+ }
+ ALOGE("Could not find a suitable encoder/crtc for display %d",
+ connector->display());
+ return -ENODEV;
+}
+
+// Attach writeback connector to the CRTC linked to the display_conn
+int DrmDevice::AttachWriteback(DrmConnector *display_conn) {
+ DrmCrtc *display_crtc = display_conn->encoder()->crtc();
+ if (GetWritebackConnectorForDisplay(display_crtc->display()) != NULL) {
+ ALOGE("Display already has writeback attach to it");
+ return -EINVAL;
+ }
+ for (auto &writeback_conn : writeback_connectors_) {
+ if (writeback_conn->display() >= 0)
+ 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 -EINVAL;
+}
+
+int DrmDevice::CreatePropertyBlob(void *data, size_t length,
+ uint32_t *blob_id) {
+ struct drm_mode_create_blob create_blob;
+ memset(&create_blob, 0, sizeof(create_blob));
+ create_blob.length = length;
+ create_blob.data = (__u64)data;
+
+ int ret = drmIoctl(fd(), DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
+ if (ret) {
+ ALOGE("Failed to create mode property blob %d", ret);
+ return ret;
+ }
+ *blob_id = create_blob.blob_id;
+ return 0;
+}
+
+int DrmDevice::DestroyPropertyBlob(uint32_t blob_id) {
+ if (!blob_id)
+ return 0;
+
+ struct drm_mode_destroy_blob destroy_blob;
+ memset(&destroy_blob, 0, sizeof(destroy_blob));
+ destroy_blob.blob_id = (__u32)blob_id;
+ int ret = drmIoctl(fd(), DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob);
+ if (ret) {
+ ALOGE("Failed to destroy mode property blob %" PRIu32 "/%d", blob_id, ret);
+ return ret;
+ }
+ return 0;
+}
+
+DrmEventListener *DrmDevice::event_listener() {
+ return &event_listener_;
+}
+
+int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type,
+ const char *prop_name, DrmProperty *property) {
+ drmModeObjectPropertiesPtr props;
+
+ props = drmModeObjectGetProperties(fd(), obj_id, obj_type);
+ if (!props) {
+ ALOGE("Failed to get properties for %d/%x", obj_id, obj_type);
+ return -ENODEV;
+ }
+
+ bool found = false;
+ for (int i = 0; !found && (size_t)i < props->count_props; ++i) {
+ drmModePropertyPtr p = drmModeGetProperty(fd(), props->props[i]);
+ if (!strcmp(p->name, prop_name)) {
+ property->Init(p, props->prop_values[i]);
+ found = true;
+ }
+ drmModeFreeProperty(p);
+ }
+
+ drmModeFreeObjectProperties(props);
+ return found ? 0 : -ENOENT;
+}
+
+int DrmDevice::GetPlaneProperty(const DrmPlane &plane, const char *prop_name,
+ DrmProperty *property) {
+ return GetProperty(plane.id(), DRM_MODE_OBJECT_PLANE, prop_name, property);
+}
+
+int DrmDevice::GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
+ DrmProperty *property) {
+ return GetProperty(crtc.id(), DRM_MODE_OBJECT_CRTC, prop_name, property);
+}
+
+int DrmDevice::GetConnectorProperty(const DrmConnector &connector,
+ const char *prop_name,
+ DrmProperty *property) {
+ return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
+ property);
+}
+} // namespace android
diff --git a/drmresources.h b/drmdevice.h
similarity index 83%
rename from drmresources.h
rename to drmdevice.h
index 4cca48c..da1b961 100644
--- a/drmresources.h
+++ b/drmdevice.h
@@ -22,17 +22,19 @@
#include "drmencoder.h"
#include "drmeventlistener.h"
#include "drmplane.h"
+#include "platform.h"
#include <stdint.h>
+#include <tuple>
namespace android {
-class DrmResources {
+class DrmDevice {
public:
- DrmResources();
- ~DrmResources();
+ DrmDevice();
+ ~DrmDevice();
- int Init();
+ std::tuple<int, int> Init(const char *path, int num_displays);
int fd() const {
return fd_.get();
@@ -55,6 +57,8 @@
}
DrmConnector *GetConnectorForDisplay(int display) const;
+ DrmConnector *GetWritebackConnectorForDisplay(int display) const;
+ DrmConnector *AvailableWritebackConnector(int display) const;
DrmCrtc *GetCrtcForDisplay(int display) const;
DrmPlane *GetPlane(uint32_t id) const;
DrmEventListener *event_listener();
@@ -71,6 +75,7 @@
int CreatePropertyBlob(void *data, size_t length, uint32_t *blob_id);
int DestroyPropertyBlob(uint32_t blob_id);
+ bool HandlesDisplay(int display) const;
private:
int TryEncoderForDisplay(int display, DrmEncoder *enc);
@@ -78,11 +83,13 @@
DrmProperty *property);
int CreateDisplayPipe(DrmConnector *connector);
+ int AttachWriteback(DrmConnector *display_conn);
UniqueFd fd_;
uint32_t mode_id_ = 0;
std::vector<std::unique_ptr<DrmConnector>> connectors_;
+ std::vector<std::unique_ptr<DrmConnector>> writeback_connectors_;
std::vector<std::unique_ptr<DrmEncoder>> encoders_;
std::vector<std::unique_ptr<DrmCrtc>> crtcs_;
std::vector<std::unique_ptr<DrmPlane>> planes_;
@@ -90,7 +97,8 @@
std::pair<uint32_t, uint32_t> min_resolution_;
std::pair<uint32_t, uint32_t> max_resolution_;
+ std::map<int, int> displays_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_H_
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index 129bec2..b710fe1 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -17,10 +17,10 @@
#define LOG_TAG "hwc-drm-display-composition"
#include "drmdisplaycomposition.h"
-#include "drmdisplaycompositor.h"
#include "drmcrtc.h"
+#include "drmdevice.h"
+#include "drmdisplaycompositor.h"
#include "drmplane.h"
-#include "drmresources.h"
#include "platform.h"
#include <stdlib.h>
@@ -37,7 +37,7 @@
DrmDisplayComposition::~DrmDisplayComposition() {
}
-int DrmDisplayComposition::Init(DrmResources *drm, DrmCrtc *crtc,
+int DrmDisplayComposition::Init(DrmDevice *drm, DrmCrtc *crtc,
Importer *importer, Planner *planner,
uint64_t frame_no) {
drm_ = drm;
@@ -107,9 +107,10 @@
to_composite.emplace(std::make_pair(i, &layers_[i]));
int ret;
- std::vector<DrmCompositionPlane> plan;
- std::tie(ret, composition_planes_) = planner_->ProvisionPlanes(
- to_composite, crtc_, primary_planes, overlay_planes);
+ std::tie(ret,
+ composition_planes_) = planner_->ProvisionPlanes(to_composite, crtc_,
+ primary_planes,
+ overlay_planes);
if (ret) {
ALOGE("Planner failed provisioning planes ret=%d", ret);
return ret;
@@ -295,4 +296,4 @@
*out << "\n";
}
}
-}
+} // namespace android
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index b4c5892..2a5b1a4 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -111,8 +111,8 @@
DrmDisplayComposition(const DrmDisplayComposition &) = delete;
~DrmDisplayComposition();
- int Init(DrmResources *drm, DrmCrtc *crtc, Importer *importer,
- Planner *planner, uint64_t frame_no);
+ int Init(DrmDevice *drm, DrmCrtc *crtc, Importer *importer, Planner *planner,
+ uint64_t frame_no);
int SetLayers(DrmHwcLayer *layers, size_t num_layers, bool geometry_changed);
int AddPlaneComposition(DrmCompositionPlane plane);
@@ -176,7 +176,7 @@
private:
bool validate_composition_type(DrmCompositionType desired);
- DrmResources *drm_ = NULL;
+ DrmDevice *drm_ = NULL;
DrmCrtc *crtc_ = NULL;
Importer *importer_ = NULL;
Planner *planner_ = NULL;
@@ -193,6 +193,6 @@
uint64_t frame_no_ = 0;
};
-}
+} // namespace android
#endif // ANDROID_DRM_DISPLAY_COMPOSITION_H_
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index e7e0694..f479f10 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -26,26 +26,44 @@
#include <sstream>
#include <vector>
-#include <log/log.h>
#include <drm/drm_mode.h>
+#include <log/log.h>
#include <sync/sync.h>
#include <utils/Trace.h>
#include "autolock.h"
#include "drmcrtc.h"
+#include "drmdevice.h"
#include "drmplane.h"
-#include "drmresources.h"
+
+static const uint32_t kWaitWritebackFence = 100; // ms
namespace android {
+class CompositorVsyncCallback : public VsyncCallback {
+ public:
+ CompositorVsyncCallback(DrmDisplayCompositor *compositor)
+ : compositor_(compositor) {
+ }
+
+ void Callback(int display, int64_t timestamp) {
+ compositor_->Vsync(display, timestamp);
+ }
+
+ private:
+ DrmDisplayCompositor *compositor_;
+};
+
DrmDisplayCompositor::DrmDisplayCompositor()
- : drm_(NULL),
+ : resource_manager_(NULL),
display_(-1),
initialized_(false),
active_(false),
use_hw_overlays_(true),
dump_frames_composited_(0),
- dump_last_timestamp_ns_(0) {
+ dump_last_timestamp_ns_(0),
+ flatten_countdown_(FLATTEN_COUNTDOWN_INIT),
+ writeback_fence_(-1) {
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
return;
@@ -56,14 +74,15 @@
if (!initialized_)
return;
+ vsync_worker_.Exit();
int ret = pthread_mutex_lock(&lock_);
if (ret)
ALOGE("Failed to acquire compositor lock %d", ret);
-
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
if (mode_.blob_id)
- drm_->DestroyPropertyBlob(mode_.blob_id);
+ drm->DestroyPropertyBlob(mode_.blob_id);
if (mode_.old_blob_id)
- drm_->DestroyPropertyBlob(mode_.old_blob_id);
+ drm->DestroyPropertyBlob(mode_.old_blob_id);
active_composition_.reset();
@@ -74,15 +93,24 @@
pthread_mutex_destroy(&lock_);
}
-int DrmDisplayCompositor::Init(DrmResources *drm, int display) {
- drm_ = drm;
+int DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display) {
+ resource_manager_ = resource_manager;
display_ = display;
-
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display);
+ if (!drm) {
+ ALOGE("Could not find drmdevice for display");
+ return -EINVAL;
+ }
int ret = pthread_mutex_init(&lock_, NULL);
if (ret) {
ALOGE("Failed to initialize drm compositor lock %d\n", ret);
return ret;
}
+ planner_ = Planner::CreateInstance(drm);
+
+ vsync_worker_.Init(drm, display_);
+ auto callback = std::make_shared<CompositorVsyncCallback>(this);
+ vsync_worker_.RegisterCallback(callback);
initialized_ = true;
return 0;
@@ -93,9 +121,32 @@
return std::unique_ptr<DrmDisplayComposition>(new DrmDisplayComposition());
}
+std::unique_ptr<DrmDisplayComposition>
+DrmDisplayCompositor::CreateInitializedComposition() const {
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ DrmCrtc *crtc = drm->GetCrtcForDisplay(display_);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display = %d", display_);
+ return std::unique_ptr<DrmDisplayComposition>();
+ }
+ std::unique_ptr<DrmDisplayComposition> comp = CreateComposition();
+ std::shared_ptr<Importer> importer = resource_manager_->GetImporter(display_);
+ if (!importer) {
+ ALOGE("Failed to find resources for display = %d", display_);
+ return std::unique_ptr<DrmDisplayComposition>();
+ }
+ int ret = comp->Init(drm, crtc, importer.get(), planner_.get(), 0);
+ if (ret) {
+ ALOGE("Failed to init composition for display = %d", display_);
+ return std::unique_ptr<DrmDisplayComposition>();
+ }
+ return comp;
+}
+
std::tuple<uint32_t, uint32_t, int>
DrmDisplayCompositor::GetActiveModeResolution() {
- DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ DrmConnector *connector = drm->GetConnectorForDisplay(display_);
if (connector == NULL) {
ALOGE("Failed to determine display mode: no connector for display %d",
display_);
@@ -114,8 +165,8 @@
}
int ret;
- std::vector<DrmCompositionPlane> &comp_planes =
- display_comp->composition_planes();
+ std::vector<DrmCompositionPlane> &comp_planes = display_comp
+ ->composition_planes();
for (DrmCompositionPlane &comp_plane : comp_planes) {
DrmPlane *plane = comp_plane.plane();
ret = drmModeAtomicAddProperty(pset, plane->id(),
@@ -128,8 +179,8 @@
return ret;
}
}
-
- ret = drmModeAtomicCommit(drm_->fd(), pset, 0, drm_);
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ ret = drmModeAtomicCommit(drm->fd(), pset, 0, drm);
if (ret) {
ALOGE("Failed to commit pset ret=%d\n", ret);
drmModeAtomicFree(pset);
@@ -140,23 +191,65 @@
return 0;
}
+int DrmDisplayCompositor::SetupWritebackCommit(drmModeAtomicReqPtr pset,
+ uint32_t crtc_id,
+ DrmConnector *writeback_conn,
+ DrmHwcBuffer *writeback_buffer) {
+ int ret = 0;
+ 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_buffer)->fb_id == 0) {
+ ALOGE("Invalid writeback buffer");
+ return -EINVAL;
+ }
+ ret = drmModeAtomicAddProperty(pset, writeback_conn->id(),
+ writeback_conn->writeback_fb_id().id(),
+ (*writeback_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_);
+ if (ret < 0) {
+ ALOGE("Failed to add writeback_out_fence");
+ return ret;
+ }
+
+ ret = drmModeAtomicAddProperty(pset, writeback_conn->id(),
+ writeback_conn->crtc_id_property().id(),
+ crtc_id);
+ if (ret < 0) {
+ ALOGE("Failed to attach writeback");
+ return ret;
+ }
+ return 0;
+}
+
int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
- bool test_only) {
+ bool test_only,
+ DrmConnector *writeback_conn,
+ DrmHwcBuffer *writeback_buffer) {
ATRACE_CALL();
int ret = 0;
std::vector<DrmHwcLayer> &layers = display_comp->layers();
- std::vector<DrmCompositionPlane> &comp_planes =
- display_comp->composition_planes();
- uint64_t out_fences[drm_->crtcs().size()];
+ std::vector<DrmCompositionPlane> &comp_planes = display_comp
+ ->composition_planes();
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ uint64_t out_fences[drm->crtcs().size()];
- DrmConnector *connector = drm_->GetConnectorForDisplay(display_);
+ DrmConnector *connector = drm->GetConnectorForDisplay(display_);
if (!connector) {
ALOGE("Could not locate connector for display %d", display_);
return -ENODEV;
}
- DrmCrtc *crtc = drm_->GetCrtcForDisplay(display_);
+ DrmCrtc *crtc = drm->GetCrtcForDisplay(display_);
if (!crtc) {
ALOGE("Could not locate crtc for display %d", display_);
return -ENODEV;
@@ -168,9 +261,22 @@
return -ENOMEM;
}
+ if (writeback_buffer != NULL) {
+ if (writeback_conn == NULL) {
+ ALOGE("Invalid arguments requested writeback without writeback conn");
+ return -EINVAL;
+ }
+ ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn,
+ writeback_buffer);
+ if (ret < 0) {
+ ALOGE("Failed to Setup Writeback Commit ret = %d", ret);
+ return ret;
+ }
+ }
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);
@@ -179,7 +285,8 @@
}
if (mode_.needs_modeset) {
- ret = drmModeAtomicAddProperty(pset, crtc->id(), crtc->active_property().id(), 1);
+ ret = drmModeAtomicAddProperty(pset, crtc->id(),
+ crtc->active_property().id(), 1);
if (ret < 0) {
ALOGE("Failed to add crtc active to pset\n");
drmModeAtomicFree(pset);
@@ -251,8 +358,8 @@
if (fence_fd >= 0) {
int prop_id = plane->in_fence_fd_property().id();
if (prop_id == 0) {
- ALOGE("Failed to get IN_FENCE_FD property id");
- break;
+ ALOGE("Failed to get IN_FENCE_FD property id");
+ break;
}
ret = drmModeAtomicAddProperty(pset, plane->id(), prop_id, fence_fd);
if (ret < 0) {
@@ -299,24 +406,28 @@
ret |= drmModeAtomicAddProperty(pset, plane->id(),
plane->crtc_y_property().id(),
display_frame.top) < 0;
- ret |= drmModeAtomicAddProperty(
- pset, plane->id(), plane->crtc_w_property().id(),
- display_frame.right - display_frame.left) < 0;
- ret |= drmModeAtomicAddProperty(
- pset, plane->id(), plane->crtc_h_property().id(),
- display_frame.bottom - display_frame.top) < 0;
+ ret |= drmModeAtomicAddProperty(pset, plane->id(),
+ plane->crtc_w_property().id(),
+ display_frame.right - display_frame.left) <
+ 0;
+ ret |= drmModeAtomicAddProperty(pset, plane->id(),
+ plane->crtc_h_property().id(),
+ display_frame.bottom - display_frame.top) <
+ 0;
ret |= drmModeAtomicAddProperty(pset, plane->id(),
plane->src_x_property().id(),
(int)(source_crop.left) << 16) < 0;
ret |= drmModeAtomicAddProperty(pset, plane->id(),
plane->src_y_property().id(),
(int)(source_crop.top) << 16) < 0;
- ret |= drmModeAtomicAddProperty(
- pset, plane->id(), plane->src_w_property().id(),
- (int)(source_crop.right - source_crop.left) << 16) < 0;
- ret |= drmModeAtomicAddProperty(
- pset, plane->id(), plane->src_h_property().id(),
- (int)(source_crop.bottom - source_crop.top) << 16) < 0;
+ ret |= drmModeAtomicAddProperty(pset, plane->id(),
+ plane->src_w_property().id(),
+ (int)(source_crop.right - source_crop.left)
+ << 16) < 0;
+ ret |= drmModeAtomicAddProperty(pset, plane->id(),
+ plane->src_h_property().id(),
+ (int)(source_crop.bottom - source_crop.top)
+ << 16) < 0;
if (ret) {
ALOGE("Failed to add plane %d to set", plane->id());
break;
@@ -335,8 +446,7 @@
if (plane->alpha_property().id()) {
ret = drmModeAtomicAddProperty(pset, plane->id(),
- plane->alpha_property().id(),
- alpha) < 0;
+ plane->alpha_property().id(), alpha) < 0;
if (ret) {
ALOGE("Failed to add alpha property %d to plane %d",
plane->alpha_property().id(), plane->id());
@@ -350,7 +460,7 @@
if (test_only)
flags |= DRM_MODE_ATOMIC_TEST_ONLY;
- ret = drmModeAtomicCommit(drm_->fd(), pset, flags, drm_);
+ ret = drmModeAtomicCommit(drm->fd(), pset, flags, drm);
if (ret) {
if (!test_only)
ALOGE("Failed to commit pset ret=%d\n", ret);
@@ -362,7 +472,7 @@
drmModeAtomicFree(pset);
if (!test_only && mode_.needs_modeset) {
- ret = drm_->DestroyPropertyBlob(mode_.old_blob_id);
+ ret = drm->DestroyPropertyBlob(mode_.old_blob_id);
if (ret) {
ALOGE("Failed to destroy old mode property blob %" PRIu32 "/%d",
mode_.old_blob_id, ret);
@@ -383,21 +493,22 @@
}
if (crtc->out_fence_ptr_property().id()) {
- display_comp->set_out_fence((int) out_fences[crtc->pipe()]);
+ display_comp->set_out_fence((int)out_fences[crtc->pipe()]);
}
return ret;
}
int DrmDisplayCompositor::ApplyDpms(DrmDisplayComposition *display_comp) {
- DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ DrmConnector *conn = drm->GetConnectorForDisplay(display_);
if (!conn) {
ALOGE("Failed to get DrmConnector for display %d", display_);
return -ENODEV;
}
const DrmProperty &prop = conn->dpms_property();
- int ret = drmModeConnectorSetProperty(drm_->fd(), conn->id(), prop.id(),
+ int ret = drmModeConnectorSetProperty(drm->fd(), conn->id(), prop.id(),
display_comp->dpms_mode());
if (ret) {
ALOGE("Failed to set DPMS property for connector %d", conn->id());
@@ -413,8 +524,9 @@
mode.ToDrmModeModeInfo(&drm_mode);
uint32_t id = 0;
- int ret = drm_->CreatePropertyBlob(&drm_mode,
- sizeof(struct drm_mode_modeinfo), &id);
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ int ret = drm->CreatePropertyBlob(&drm_mode, sizeof(struct drm_mode_modeinfo),
+ &id);
if (ret) {
ALOGE("Failed to create mode property blob %d", ret);
return std::make_tuple(ret, 0);
@@ -424,11 +536,6 @@
}
void DrmDisplayCompositor::ClearDisplay() {
- AutoLock lock(&lock_, "compositor");
- int ret = lock.Lock();
- if (ret)
- return;
-
if (!active_composition_)
return;
@@ -436,14 +543,24 @@
return;
active_composition_.reset(NULL);
+ vsync_worker_.VSyncControl(false);
}
void DrmDisplayCompositor::ApplyFrame(
- std::unique_ptr<DrmDisplayComposition> composition, int status) {
+ std::unique_ptr<DrmDisplayComposition> composition, int status,
+ bool writeback) {
+ AutoLock lock(&lock_, __func__);
+ if (lock.Lock())
+ return;
int ret = status;
- if (!ret)
+ if (!ret) {
+ if (writeback && !CountdownExpired()) {
+ ALOGE("Abort playing back scene");
+ return;
+ }
ret = CommitFrame(composition.get(), false);
+ }
if (ret) {
ALOGE("Composite failed for display %d", display_);
@@ -454,16 +571,10 @@
}
++dump_frames_composited_;
- ret = pthread_mutex_lock(&lock_);
- if (ret)
- ALOGE("Failed to acquire lock for active_composition swap");
-
active_composition_.swap(composition);
- if (!ret)
- ret = pthread_mutex_unlock(&lock_);
- if (ret)
- ALOGE("Failed to release lock for active_composition swap");
+ flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
+ vsync_worker_.VSyncControl(!writeback);
}
int DrmDisplayCompositor::ApplyComposition(
@@ -492,7 +603,8 @@
case DRM_COMPOSITION_TYPE_MODESET:
mode_.mode = composition->display_mode();
if (mode_.blob_id)
- drm_->DestroyPropertyBlob(mode_.blob_id);
+ resource_manager_->GetDrmDevice(display_)->DestroyPropertyBlob(
+ mode_.blob_id);
std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
if (ret) {
ALOGE("Failed to create mode blob for display %d", display_);
@@ -512,6 +624,337 @@
return CommitFrame(composition, true);
}
+// Flatten a scene on the display by using a writeback connector
+// and returns the composition result as a DrmHwcLayer.
+int DrmDisplayCompositor::FlattenOnDisplay(
+ std::unique_ptr<DrmDisplayComposition> &src, DrmConnector *writeback_conn,
+ DrmMode &src_mode, DrmHwcLayer *writeback_layer) {
+ int ret = 0;
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ ret = writeback_conn->UpdateModes();
+ if (ret) {
+ ALOGE("Failed to update modes %d", ret);
+ return ret;
+ }
+ for (const DrmMode &mode : writeback_conn->modes()) {
+ if (mode.h_display() == src_mode.h_display() &&
+ mode.v_display() == src_mode.v_display()) {
+ mode_.mode = mode;
+ if (mode_.blob_id)
+ drm->DestroyPropertyBlob(mode_.blob_id);
+ std::tie(ret, mode_.blob_id) = CreateModeBlob(mode_.mode);
+ if (ret) {
+ ALOGE("Failed to create mode blob for display %d", display_);
+ return ret;
+ }
+ mode_.needs_modeset = true;
+ break;
+ }
+ }
+ if (mode_.blob_id <= 0) {
+ ALOGE("Failed to find similar mode");
+ return -EINVAL;
+ }
+
+ DrmCrtc *crtc = drm->GetCrtcForDisplay(display_);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display %d", display_);
+ return -EINVAL;
+ }
+ // TODO what happens if planes could go to both CRTCs, I don't think it's
+ // handled anywhere
+ std::vector<DrmPlane *> primary_planes;
+ std::vector<DrmPlane *> overlay_planes;
+ for (auto &plane : drm->planes()) {
+ if (!plane->GetCrtcSupported(*crtc))
+ continue;
+ if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
+ primary_planes.push_back(plane.get());
+ else if (plane->type() == DRM_PLANE_TYPE_OVERLAY)
+ overlay_planes.push_back(plane.get());
+ }
+
+ ret = src->Plan(&primary_planes, &overlay_planes);
+ if (ret) {
+ ALOGE("Failed to plan the composition ret = %d", ret);
+ return ret;
+ }
+
+ // Disable the planes we're not using
+ for (auto i = primary_planes.begin(); i != primary_planes.end();) {
+ src->AddPlaneDisable(*i);
+ i = primary_planes.erase(i);
+ }
+ for (auto i = overlay_planes.begin(); i != overlay_planes.end();) {
+ src->AddPlaneDisable(*i);
+ i = overlay_planes.erase(i);
+ }
+
+ AutoLock lock(&lock_, __func__);
+ ret = lock.Lock();
+ if (ret)
+ return ret;
+ DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_];
+ framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
+ if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) {
+ ALOGE("Failed to allocate writeback buffer");
+ return -ENOMEM;
+ }
+ DrmHwcBuffer *writeback_buffer = &writeback_layer->buffer;
+ writeback_layer->sf_handle = writeback_fb->buffer()->handle;
+ ret = writeback_layer->ImportBuffer(
+ resource_manager_->GetImporter(display_).get());
+ if (ret) {
+ ALOGE("Failed to import writeback buffer");
+ return ret;
+ }
+
+ ret = CommitFrame(src.get(), true, writeback_conn, writeback_buffer);
+ if (ret) {
+ ALOGE("Atomic check failed");
+ return ret;
+ }
+ ret = CommitFrame(src.get(), false, writeback_conn, writeback_buffer);
+ if (ret) {
+ ALOGE("Atomic commit failed");
+ return ret;
+ }
+
+ ret = sync_wait(writeback_fence_, kWaitWritebackFence);
+ writeback_layer->acquire_fence.Set(writeback_fence_);
+ writeback_fence_ = -1;
+ if (ret) {
+ ALOGE("Failed to wait on writeback fence");
+ return ret;
+ }
+ return 0;
+}
+
+// Flatten a scene by enabling the writeback connector attached
+// to the same CRTC as the one driving the display.
+int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) {
+ ALOGV("FlattenSerial by enabling writeback connector to the same crtc");
+ // Flattened composition with only one layer that is obtained
+ // using the writeback connector
+ std::unique_ptr<DrmDisplayComposition>
+ writeback_comp = CreateInitializedComposition();
+ if (!writeback_comp)
+ return -EINVAL;
+
+ AutoLock lock(&lock_, __func__);
+ int ret = lock.Lock();
+ if (ret)
+ return ret;
+ if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+ ALOGV("Flattening is not needed");
+ return -EALREADY;
+ }
+
+ DrmFramebuffer *writeback_fb = &framebuffers_[framebuffer_index_];
+ framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
+ lock.Unlock();
+
+ if (!writeback_fb->Allocate(mode_.mode.h_display(), mode_.mode.v_display())) {
+ ALOGE("Failed to allocate writeback buffer");
+ return -ENOMEM;
+ }
+ writeback_comp->layers().emplace_back();
+
+ DrmHwcLayer &writeback_layer = writeback_comp->layers().back();
+ writeback_layer.sf_handle = writeback_fb->buffer()->handle;
+ writeback_layer.source_crop = {0, 0, (float)mode_.mode.h_display(),
+ (float)mode_.mode.v_display()};
+ writeback_layer.display_frame = {0, 0, (int)mode_.mode.h_display(),
+ (int)mode_.mode.v_display()};
+ ret = writeback_layer.ImportBuffer(
+ resource_manager_->GetImporter(display_).get());
+ if (ret || writeback_comp->layers().size() != 1) {
+ ALOGE("Failed to import writeback buffer");
+ return ret;
+ }
+
+ drmModeAtomicReqPtr pset = drmModeAtomicAlloc();
+ if (!pset) {
+ ALOGE("Failed to allocate property set");
+ return -ENOMEM;
+ }
+ DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
+ DrmCrtc *crtc = drm->GetCrtcForDisplay(display_);
+ if (!crtc) {
+ ALOGE("Failed to find crtc for display %d", display_);
+ return -EINVAL;
+ }
+ ret = SetupWritebackCommit(pset, crtc->id(), writeback_conn,
+ &writeback_layer.buffer);
+ if (ret < 0) {
+ ALOGE("Failed to Setup Writeback Commit");
+ return ret;
+ }
+ ret = drmModeAtomicCommit(drm->fd(), pset, 0, drm);
+ if (ret) {
+ ALOGE("Failed to enable writeback %d", ret);
+ return ret;
+ }
+ ret = sync_wait(writeback_fence_, kWaitWritebackFence);
+ writeback_layer.acquire_fence.Set(writeback_fence_);
+ writeback_fence_ = -1;
+ if (ret) {
+ ALOGE("Failed to wait on writeback fence");
+ return ret;
+ }
+
+ DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, NULL,
+ crtc);
+ for (auto &drmplane : drm->planes()) {
+ if (!drmplane->GetCrtcSupported(*crtc))
+ continue;
+ if (!squashed_comp.plane() && drmplane->type() == DRM_PLANE_TYPE_PRIMARY)
+ squashed_comp.set_plane(drmplane.get());
+ else
+ writeback_comp->AddPlaneDisable(drmplane.get());
+ }
+ squashed_comp.source_layers().push_back(0);
+ ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp));
+ if (ret) {
+ ALOGE("Failed to add flatten scene");
+ return ret;
+ }
+
+ ApplyFrame(std::move(writeback_comp), 0, true);
+ return 0;
+}
+
+// Flatten a scene by using a crtc which works concurrent with
+// the one driving the display.
+int DrmDisplayCompositor::FlattenConcurrent(DrmConnector *writeback_conn) {
+ ALOGV("FlattenConcurrent by using an unused crtc/display");
+ int ret = 0;
+ DrmDisplayCompositor drmdisplaycompositor;
+ ret = drmdisplaycompositor.Init(resource_manager_, writeback_conn->display());
+ if (ret) {
+ ALOGE("Failed to init drmdisplaycompositor = %d", ret);
+ return ret;
+ }
+ // Copy of the active_composition, needed because of two things:
+ // 1) Not to hold the lock for the whole time we are accessing
+ // active_composition
+ // 2) It will be committed on a crtc that might not be on the same
+ // dri node, so buffers need to be imported on the right node.
+ std::unique_ptr<DrmDisplayComposition>
+ copy_comp = drmdisplaycompositor.CreateInitializedComposition();
+
+ // Writeback composition that will be committed to the display.
+ std::unique_ptr<DrmDisplayComposition>
+ writeback_comp = CreateInitializedComposition();
+
+ if (!copy_comp || !writeback_comp)
+ return -EINVAL;
+ AutoLock lock(&lock_, __func__);
+ ret = lock.Lock();
+ if (ret)
+ return ret;
+ if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+ ALOGV("Flattening is not needed");
+ return -EALREADY;
+ }
+ DrmCrtc *crtc = active_composition_->crtc();
+
+ std::vector<DrmHwcLayer> copy_layers;
+ for (DrmHwcLayer &src_layer : active_composition_->layers()) {
+ DrmHwcLayer copy;
+ ret = copy.InitFromDrmHwcLayer(&src_layer,
+ resource_manager_
+ ->GetImporter(writeback_conn->display())
+ .get());
+ if (ret) {
+ ALOGE("Failed to import buffer ret = %d", ret);
+ return -EINVAL;
+ }
+ copy_layers.emplace_back(std::move(copy));
+ }
+ ret = copy_comp->SetLayers(copy_layers.data(), copy_layers.size(), true);
+ if (ret) {
+ ALOGE("Failed to set copy_comp layers");
+ return ret;
+ }
+
+ lock.Unlock();
+ DrmHwcLayer writeback_layer;
+ ret = drmdisplaycompositor.FlattenOnDisplay(copy_comp, writeback_conn,
+ mode_.mode, &writeback_layer);
+ if (ret) {
+ ALOGE("Failed to flatten on display ret = %d", ret);
+ return ret;
+ }
+
+ DrmCompositionPlane squashed_comp(DrmCompositionPlane::Type::kLayer, NULL,
+ crtc);
+ for (auto &drmplane : resource_manager_->GetDrmDevice(display_)->planes()) {
+ if (!drmplane->GetCrtcSupported(*crtc))
+ continue;
+ if (drmplane->type() == DRM_PLANE_TYPE_PRIMARY)
+ squashed_comp.set_plane(drmplane.get());
+ else
+ writeback_comp->AddPlaneDisable(drmplane.get());
+ }
+ writeback_comp->layers().emplace_back();
+ DrmHwcLayer &next_layer = writeback_comp->layers().back();
+ next_layer.sf_handle = writeback_layer.get_usable_handle();
+ next_layer.blending = DrmHwcBlending::kPreMult;
+ next_layer.source_crop = {0, 0, (float)mode_.mode.h_display(),
+ (float)mode_.mode.v_display()};
+ next_layer.display_frame = {0, 0, (int)mode_.mode.h_display(),
+ (int)mode_.mode.v_display()};
+ ret = next_layer.ImportBuffer(resource_manager_->GetImporter(display_).get());
+ if (ret) {
+ ALOGE("Failed to import framebuffer for display %d", ret);
+ return ret;
+ }
+ squashed_comp.source_layers().push_back(0);
+ ret = writeback_comp->AddPlaneComposition(std::move(squashed_comp));
+ if (ret) {
+ ALOGE("Failed to add plane composition %d", ret);
+ return ret;
+ }
+ ApplyFrame(std::move(writeback_comp), 0, true);
+ return ret;
+}
+
+int DrmDisplayCompositor::FlattenActiveComposition() {
+ DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector(
+ display_);
+ if (!active_composition_ || !writeback_conn) {
+ ALOGV("No writeback connector available");
+ return -EINVAL;
+ }
+
+ if (writeback_conn->display() != display_) {
+ return FlattenConcurrent(writeback_conn);
+ } else {
+ return FlattenSerial(writeback_conn);
+ }
+
+ return 0;
+}
+
+bool DrmDisplayCompositor::CountdownExpired() const {
+ return flatten_countdown_ <= 0;
+}
+
+void DrmDisplayCompositor::Vsync(int display, int64_t timestamp) {
+ AutoLock lock(&lock_, __func__);
+ if (lock.Lock())
+ return;
+ flatten_countdown_--;
+ if (!CountdownExpired())
+ return;
+ lock.Unlock();
+ int ret = FlattenActiveComposition();
+ ALOGV("scene flattening triggered for display %d at timestamp %" PRIu64
+ " result = %d \n",
+ display, timestamp, ret);
+}
+
void DrmDisplayCompositor::Dump(std::ostringstream *out) const {
int ret = pthread_mutex_lock(&lock_);
if (ret)
@@ -539,4 +982,4 @@
pthread_mutex_unlock(&lock_);
}
-}
+} // namespace android
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 0d85949..67f6334 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -17,9 +17,11 @@
#ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_
#define ANDROID_DRM_DISPLAY_COMPOSITOR_H_
-#include "drmhwcomposer.h"
#include "drmdisplaycomposition.h"
#include "drmframebuffer.h"
+#include "drmhwcomposer.h"
+#include "resourcemanager.h"
+#include "vsyncworker.h"
#include <pthread.h>
#include <memory>
@@ -33,6 +35,10 @@
// squash a frame that the hw can't display with hw overlays.
#define DRM_DISPLAY_BUFFERS 3
+// If a scene is still for this number of vblanks flatten it to reduce power
+// consumption.
+#define FLATTEN_COUNTDOWN_INIT 60
+
namespace android {
class DrmDisplayCompositor {
@@ -40,13 +46,15 @@
DrmDisplayCompositor();
~DrmDisplayCompositor();
- int Init(DrmResources *drm, int display);
+ int Init(ResourceManager *resource_manager, int display);
std::unique_ptr<DrmDisplayComposition> CreateComposition() const;
+ std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
int TestComposition(DrmDisplayComposition *composition);
int Composite();
void Dump(std::ostringstream *out) const;
+ void Vsync(int display, int64_t timestamp);
std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
@@ -65,20 +73,30 @@
static const int kAcquireWaitTries = 5;
static const int kAcquireWaitTimeoutMs = 100;
- int PrepareFramebuffer(DrmFramebuffer &fb,
- DrmDisplayComposition *display_comp);
- int PrepareFrame(DrmDisplayComposition *display_comp);
- int CommitFrame(DrmDisplayComposition *display_comp, bool test_only);
+ int CommitFrame(DrmDisplayComposition *display_comp, bool test_only,
+ DrmConnector *writeback_conn = NULL,
+ DrmHwcBuffer *writeback_buffer = NULL);
+ int SetupWritebackCommit(drmModeAtomicReqPtr pset, uint32_t crtc_id,
+ DrmConnector *writeback_conn,
+ DrmHwcBuffer *writeback_buffer);
int ApplyDpms(DrmDisplayComposition *display_comp);
int DisablePlanes(DrmDisplayComposition *display_comp);
void ClearDisplay();
void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
- int status);
+ int status, bool writeback = false);
+ int FlattenActiveComposition();
+ int FlattenSerial(DrmConnector *writeback_conn);
+ int FlattenConcurrent(DrmConnector *writeback_conn);
+ int FlattenOnDisplay(std::unique_ptr<DrmDisplayComposition> &src,
+ DrmConnector *writeback_conn, DrmMode &src_mode,
+ DrmHwcLayer *writeback_layer);
+
+ bool CountdownExpired() const;
std::tuple<int, uint32_t> CreateModeBlob(const DrmMode &mode);
- DrmResources *drm_;
+ ResourceManager *resource_manager_;
int display_;
std::unique_ptr<DrmDisplayComposition> active_composition_;
@@ -99,7 +117,11 @@
// we need to reset them on every Dump() call.
mutable uint64_t dump_frames_composited_;
mutable uint64_t dump_last_timestamp_ns_;
+ VSyncWorker vsync_worker_;
+ int64_t flatten_countdown_;
+ std::unique_ptr<Planner> planner_;
+ int writeback_fence_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_DISPLAY_COMPOSITOR_H_
diff --git a/drmencoder.cpp b/drmencoder.cpp
index 3d762f3..c36fca1 100644
--- a/drmencoder.cpp
+++ b/drmencoder.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "drmcrtc.h"
#include "drmencoder.h"
-#include "drmresources.h"
+#include "drmcrtc.h"
+#include "drmdevice.h"
#include <stdint.h>
#include <xf86drmMode.h>
@@ -27,6 +27,7 @@
const std::vector<DrmCrtc *> &possible_crtcs)
: id_(e->encoder_id),
crtc_(current_crtc),
+ display_(-1),
possible_crtcs_(possible_crtcs) {
}
@@ -38,7 +39,24 @@
return crtc_;
}
+bool DrmEncoder::CanClone(DrmEncoder *possible_clone) {
+ return possible_clones_.find(possible_clone) != possible_clones_.end();
+}
+
+void DrmEncoder::AddPossibleClone(DrmEncoder *possible_clone) {
+ possible_clones_.insert(possible_clone);
+}
+
void DrmEncoder::set_crtc(DrmCrtc *crtc) {
crtc_ = crtc;
+ display_ = crtc->display();
}
+
+int DrmEncoder::display() const {
+ return display_;
}
+
+bool DrmEncoder::can_bind(int display) const {
+ return display_ == -1 || display_ == display;
+}
+} // namespace android
diff --git a/drmencoder.h b/drmencoder.h
index 58ccbfb..8a7f682 100644
--- a/drmencoder.h
+++ b/drmencoder.h
@@ -20,8 +20,9 @@
#include "drmcrtc.h"
#include <stdint.h>
-#include <vector>
#include <xf86drmMode.h>
+#include <set>
+#include <vector>
namespace android {
@@ -36,17 +37,23 @@
DrmCrtc *crtc() const;
void set_crtc(DrmCrtc *crtc);
+ bool can_bind(int display) const;
+ int display() const;
const std::vector<DrmCrtc *> &possible_crtcs() const {
return possible_crtcs_;
}
+ bool CanClone(DrmEncoder *encoder);
+ void AddPossibleClone(DrmEncoder *possible_clone);
private:
uint32_t id_;
DrmCrtc *crtc_;
+ int display_;
std::vector<DrmCrtc *> possible_crtcs_;
+ std::set<DrmEncoder *> possible_clones_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_ENCODER_H_
diff --git a/drmeventlistener.cpp b/drmeventlistener.cpp
index 9cdff81..6aab6fb 100644
--- a/drmeventlistener.cpp
+++ b/drmeventlistener.cpp
@@ -17,23 +17,22 @@
#define LOG_TAG "hwc-drm-event-listener"
#include "drmeventlistener.h"
-#include "drmresources.h"
+#include "drmdevice.h"
#include <assert.h>
#include <errno.h>
#include <linux/netlink.h>
#include <sys/socket.h>
-#include <log/log.h>
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
+#include <log/log.h>
#include <xf86drm.h>
namespace android {
-DrmEventListener::DrmEventListener(DrmResources *drm)
- : Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY),
- drm_(drm) {
+DrmEventListener::DrmEventListener(DrmDevice *drm)
+ : Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY), drm_(drm) {
}
int DrmEventListener::Init() {
@@ -126,14 +125,14 @@
} while (ret == -1 && errno == EINTR);
if (FD_ISSET(drm_->fd(), &fds_)) {
- drmEventContext event_context = {
- .version = 2,
- .vblank_handler = NULL,
- .page_flip_handler = DrmEventListener::FlipHandler};
+ drmEventContext event_context =
+ {.version = 2,
+ .vblank_handler = NULL,
+ .page_flip_handler = DrmEventListener::FlipHandler};
drmHandleEvent(drm_->fd(), &event_context);
}
if (FD_ISSET(uevent_fd_.get(), &fds_))
UEventHandler();
}
-}
+} // namespace android
diff --git a/drmeventlistener.h b/drmeventlistener.h
index 61eefe8..d8a61a5 100644
--- a/drmeventlistener.h
+++ b/drmeventlistener.h
@@ -22,7 +22,7 @@
namespace android {
-class DrmResources;
+class DrmDevice;
class DrmEventHandler {
public:
@@ -36,7 +36,7 @@
class DrmEventListener : public Worker {
public:
- DrmEventListener(DrmResources *drm);
+ DrmEventListener(DrmDevice *drm);
virtual ~DrmEventListener() {
}
@@ -57,9 +57,9 @@
UniqueFd uevent_fd_;
int max_fd_ = -1;
- DrmResources *drm_;
+ DrmDevice *drm_;
DrmEventHandler *hotplug_handler_ = NULL;
};
-}
+} // namespace android
#endif
diff --git a/drmframebuffer.h b/drmframebuffer.h
index 897589c..9032d3a 100644
--- a/drmframebuffer.h
+++ b/drmframebuffer.h
@@ -65,7 +65,7 @@
}
Clear();
}
- buffer_ = new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888,
+ buffer_ = new GraphicBuffer(w, h, PIXEL_FORMAT_RGB_888,
GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
release_fence_fd_ = -1;
@@ -102,6 +102,6 @@
sp<GraphicBuffer> buffer_;
int release_fence_fd_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_FRAMEBUFFER_
diff --git a/drmhwcgralloc.h b/drmhwcgralloc.h
index 759746a..65a4007 100644
--- a/drmhwcgralloc.h
+++ b/drmhwcgralloc.h
@@ -19,14 +19,17 @@
#include <stdint.h>
+#define HWC_DRM_BO_MAX_PLANES 4
typedef struct hwc_drm_bo {
uint32_t width;
uint32_t height;
- uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */
+ uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */
+ uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */
uint32_t usage;
- uint32_t pitches[4];
- uint32_t offsets[4];
- uint32_t gem_handles[4];
+ uint32_t pixel_stride;
+ uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
+ uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
+ uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
uint32_t fb_id;
int acquire_fence_fd;
void *priv;
diff --git a/drmhwcomposer.h b/drmhwcomposer.h
index ab8f087..2af7e6e 100644
--- a/drmhwcomposer.h
+++ b/drmhwcomposer.h
@@ -142,6 +142,7 @@
OutputFd release_fence;
int ImportBuffer(Importer *importer);
+ int InitFromDrmHwcLayer(DrmHwcLayer *layer, Importer *importer);
void SetTransform(int32_t sf_transform);
void SetSourceCrop(hwc_frect_t const &crop);
@@ -161,6 +162,6 @@
OutputFd retire_fence;
std::vector<DrmHwcLayer> layers;
};
-}
+} // namespace android
#endif
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index 6bab17b..c801f2e 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -17,19 +17,19 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#define LOG_TAG "hwc-drm-two"
+#include "drmhwctwo.h"
#include "drmdisplaycomposition.h"
#include "drmhwcomposer.h"
-#include "drmhwctwo.h"
#include "platform.h"
#include "vsyncworker.h"
#include <inttypes.h>
#include <string>
-#include <log/log.h>
#include <cutils/properties.h>
#include <hardware/hardware.h>
#include <hardware/hwcomposer2.h>
+#include <log/log.h>
namespace android {
@@ -58,24 +58,27 @@
}
HWC2::Error DrmHwcTwo::Init() {
- int ret = drm_.Init();
+ int ret = resource_manager_.Init();
if (ret) {
- ALOGE("Can't initialize drm object %d", ret);
+ ALOGE("Can't initialize the resource manager %d", ret);
return HWC2::Error::NoResources;
}
- importer_.reset(Importer::CreateInstance(&drm_));
- if (!importer_) {
- ALOGE("Failed to create importer instance");
+ DrmDevice *drm = resource_manager_.GetDrmDevice(HWC_DISPLAY_PRIMARY);
+ std::shared_ptr<Importer> importer = resource_manager_.GetImporter(
+ HWC_DISPLAY_PRIMARY);
+ if (!drm || !importer) {
+ ALOGE("Failed to get a valid drmresource and importer");
return HWC2::Error::NoResources;
}
displays_.emplace(std::piecewise_construct,
std::forward_as_tuple(HWC_DISPLAY_PRIMARY),
- std::forward_as_tuple(&drm_, importer_, HWC_DISPLAY_PRIMARY,
+ std::forward_as_tuple(&resource_manager_, drm, importer,
+ HWC_DISPLAY_PRIMARY,
HWC2::DisplayType::Physical));
- DrmCrtc *crtc = drm_.GetCrtcForDisplay(static_cast<int>(HWC_DISPLAY_PRIMARY));
+ DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(HWC_DISPLAY_PRIMARY));
if (!crtc) {
ALOGE("Failed to get crtc for display %d",
static_cast<int>(HWC_DISPLAY_PRIMARY));
@@ -83,7 +86,7 @@
}
std::vector<DrmPlane *> display_planes;
- for (auto &plane : drm_.planes()) {
+ for (auto &plane : drm->planes()) {
if (plane->GetCrtcSupported(*crtc))
display_planes.push_back(plane.get());
}
@@ -150,10 +153,15 @@
return HWC2::Error::None;
}
-DrmHwcTwo::HwcDisplay::HwcDisplay(DrmResources *drm,
+DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
+ DrmDevice *drm,
std::shared_ptr<Importer> importer,
hwc2_display_t handle, HWC2::DisplayType type)
- : drm_(drm), importer_(importer), handle_(handle), type_(type) {
+ : resource_manager_(resource_manager),
+ drm_(drm),
+ importer_(importer),
+ handle_(handle),
+ type_(type) {
supported(__func__);
}
@@ -166,7 +174,7 @@
}
int display = static_cast<int>(handle_);
- int ret = compositor_.Init(drm_, display);
+ int ret = compositor_.Init(resource_manager_, display);
if (ret) {
ALOGE("Failed display compositor init for display %d (%d)", display, ret);
return HWC2::Error::NoResources;
@@ -314,9 +322,11 @@
int32_t attribute_in,
int32_t *value) {
supported(__func__);
- auto mode =
- std::find_if(connector_->modes().begin(), connector_->modes().end(),
- [config](DrmMode const &m) { return m.id() == config; });
+ auto mode = std::find_if(connector_->modes().begin(),
+ connector_->modes().end(),
+ [config](DrmMode const &m) {
+ return m.id() == config;
+ });
if (mode == connector_->modes().end()) {
ALOGE("Could not find active mode for %d", config);
return HWC2::Error::BadConfig;
@@ -425,8 +435,8 @@
}
HWC2::Error DrmHwcTwo::HwcDisplay::GetHdrCapabilities(
- uint32_t *num_types, int32_t */*types*/, float */*max_luminance*/,
- float */*max_average_luminance*/, float */*min_luminance*/) {
+ uint32_t *num_types, int32_t * /*types*/, float * /*max_luminance*/,
+ float * /*max_average_luminance*/, float * /*min_luminance*/) {
supported(__func__);
*num_types = 0;
return HWC2::Error::None;
@@ -517,8 +527,8 @@
map.layers.emplace_back(std::move(layer));
}
- std::unique_ptr<DrmDisplayComposition> composition =
- compositor_.CreateComposition();
+ std::unique_ptr<DrmDisplayComposition> composition = compositor_
+ .CreateComposition();
composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
// TODO: Don't always assume geometry changed
@@ -584,16 +594,18 @@
HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) {
supported(__func__);
- auto mode =
- std::find_if(connector_->modes().begin(), connector_->modes().end(),
- [config](DrmMode const &m) { return m.id() == config; });
+ auto mode = std::find_if(connector_->modes().begin(),
+ connector_->modes().end(),
+ [config](DrmMode const &m) {
+ return m.id() == config;
+ });
if (mode == connector_->modes().end()) {
ALOGE("Could not find active mode for %d", config);
return HWC2::Error::BadConfig;
}
- std::unique_ptr<DrmDisplayComposition> composition =
- compositor_.CreateComposition();
+ std::unique_ptr<DrmDisplayComposition> composition = compositor_
+ .CreateComposition();
composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
int ret = composition->SetDisplayMode(*mode);
ret = compositor_.ApplyComposition(std::move(composition));
@@ -672,8 +684,8 @@
return HWC2::Error::Unsupported;
};
- std::unique_ptr<DrmDisplayComposition> composition =
- compositor_.CreateComposition();
+ std::unique_ptr<DrmDisplayComposition> composition = compositor_
+ .CreateComposition();
composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
composition->SetDpmsMode(dpms_value);
int ret = compositor_.ApplyComposition(std::move(composition));
@@ -693,10 +705,10 @@
HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
uint32_t *num_requests) {
supported(__func__);
- size_t plane_count = 0;
*num_types = 0;
*num_requests = 0;
size_t avail_planes = primary_planes_.size() + overlay_planes_.size();
+ bool comp_failed = false;
HWC2::Error ret;
@@ -705,8 +717,7 @@
ret = CreateComposition(true);
if (ret != HWC2::Error::None)
- // Assume the test failed due to overlay planes
- avail_planes = 1;
+ comp_failed = true;
std::map<uint32_t, DrmHwcTwo::HwcLayer *, std::greater<int>> z_map;
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
@@ -722,7 +733,7 @@
avail_planes--;
for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
- if (!avail_planes--)
+ if (comp_failed || !avail_planes--)
break;
l.second->set_validated_type(HWC2::Composition::Device);
}
@@ -896,7 +907,7 @@
return ToHook<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
DeviceHook<int32_t, decltype(&DrmHwcTwo::CreateVirtualDisplay),
&DrmHwcTwo::CreateVirtualDisplay, uint32_t, uint32_t,
- int32_t*, hwc2_display_t *>);
+ int32_t *, hwc2_display_t *>);
case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
return ToHook<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
DeviceHook<int32_t, decltype(&DrmHwcTwo::DestroyVirtualDisplay),
@@ -947,13 +958,15 @@
DisplayHook<decltype(&HwcDisplay::GetColorModes),
&HwcDisplay::GetColorModes, uint32_t *, int32_t *>);
case HWC2::FunctionDescriptor::GetDisplayAttribute:
- return ToHook<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(DisplayHook<
- decltype(&HwcDisplay::GetDisplayAttribute),
- &HwcDisplay::GetDisplayAttribute, hwc2_config_t, int32_t, int32_t *>);
+ return ToHook<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+ DisplayHook<decltype(&HwcDisplay::GetDisplayAttribute),
+ &HwcDisplay::GetDisplayAttribute, hwc2_config_t, int32_t,
+ int32_t *>);
case HWC2::FunctionDescriptor::GetDisplayConfigs:
- return ToHook<HWC2_PFN_GET_DISPLAY_CONFIGS>(DisplayHook<
- decltype(&HwcDisplay::GetDisplayConfigs),
- &HwcDisplay::GetDisplayConfigs, uint32_t *, hwc2_config_t *>);
+ return ToHook<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+ DisplayHook<decltype(&HwcDisplay::GetDisplayConfigs),
+ &HwcDisplay::GetDisplayConfigs, uint32_t *,
+ hwc2_config_t *>);
case HWC2::FunctionDescriptor::GetDisplayName:
return ToHook<HWC2_PFN_GET_DISPLAY_NAME>(
DisplayHook<decltype(&HwcDisplay::GetDisplayName),
@@ -990,9 +1003,10 @@
DisplayHook<decltype(&HwcDisplay::SetActiveConfig),
&HwcDisplay::SetActiveConfig, hwc2_config_t>);
case HWC2::FunctionDescriptor::SetClientTarget:
- return ToHook<HWC2_PFN_SET_CLIENT_TARGET>(DisplayHook<
- decltype(&HwcDisplay::SetClientTarget), &HwcDisplay::SetClientTarget,
- buffer_handle_t, int32_t, int32_t, hwc_region_t>);
+ return ToHook<HWC2_PFN_SET_CLIENT_TARGET>(
+ DisplayHook<decltype(&HwcDisplay::SetClientTarget),
+ &HwcDisplay::SetClientTarget, buffer_handle_t, int32_t,
+ int32_t, hwc_region_t>);
case HWC2::FunctionDescriptor::SetColorMode:
return ToHook<HWC2_PFN_SET_COLOR_MODE>(
DisplayHook<decltype(&HwcDisplay::SetColorMode),
@@ -1052,9 +1066,10 @@
LayerHook<decltype(&HwcLayer::SetLayerPlaneAlpha),
&HwcLayer::SetLayerPlaneAlpha, float>);
case HWC2::FunctionDescriptor::SetLayerSidebandStream:
- return ToHook<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(LayerHook<
- decltype(&HwcLayer::SetLayerSidebandStream),
- &HwcLayer::SetLayerSidebandStream, const native_handle_t *>);
+ return ToHook<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+ LayerHook<decltype(&HwcLayer::SetLayerSidebandStream),
+ &HwcLayer::SetLayerSidebandStream,
+ const native_handle_t *>);
case HWC2::FunctionDescriptor::SetLayerSourceCrop:
return ToHook<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
LayerHook<decltype(&HwcLayer::SetLayerSourceCrop),
@@ -1107,7 +1122,7 @@
ctx.release();
return 0;
}
-}
+} // namespace android
static struct hw_module_methods_t hwc2_module_methods = {
.open = android::DrmHwcTwo::HookDevOpen,
diff --git a/drmhwctwo.h b/drmhwctwo.h
index 82a9768..fd14b1f 100644
--- a/drmhwctwo.h
+++ b/drmhwctwo.h
@@ -16,8 +16,8 @@
#include "drmdisplaycompositor.h"
#include "drmhwcomposer.h"
-#include "drmresources.h"
#include "platform.h"
+#include "resourcemanager.h"
#include "vsyncworker.h"
#include <hardware/hwcomposer2.h>
@@ -135,8 +135,9 @@
class HwcDisplay {
public:
- HwcDisplay(DrmResources *drm, std::shared_ptr<Importer> importer,
- hwc2_display_t handle, HWC2::DisplayType type);
+ HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
+ std::shared_ptr<Importer> importer, hwc2_display_t handle,
+ HWC2::DisplayType type);
HwcDisplay(const HwcDisplay &) = delete;
HWC2::Error Init(std::vector<DrmPlane *> *planes);
@@ -188,7 +189,8 @@
HWC2::Error CreateComposition(bool test);
void AddFenceToRetireFence(int fd);
- DrmResources *drm_;
+ ResourceManager *resource_manager_;
+ DrmDevice *drm_;
DrmDisplayCompositor compositor_;
std::shared_ptr<Importer> importer_;
std::unique_ptr<Planner> planner_;
@@ -253,17 +255,15 @@
// Device functions
HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height,
- int32_t *format,
- hwc2_display_t *display);
+ int32_t *format, hwc2_display_t *display);
HWC2::Error DestroyVirtualDisplay(hwc2_display_t display);
void Dump(uint32_t *size, char *buffer);
uint32_t GetMaxVirtualDisplayCount();
HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data,
hwc2_function_pointer_t function);
- DrmResources drm_;
- std::shared_ptr<Importer> importer_; // Shared with HwcDisplay
+ ResourceManager resource_manager_;
std::map<hwc2_display_t, HwcDisplay> displays_;
std::map<HWC2::Callback, HwcCallback> callbacks_;
};
-}
+} // namespace android
diff --git a/drmmode.cpp b/drmmode.cpp
index 081efcd..5f2e7c2 100644
--- a/drmmode.cpp
+++ b/drmmode.cpp
@@ -15,11 +15,11 @@
*/
#include "drmmode.h"
-#include "drmresources.h"
+#include "drmdevice.h"
#include <stdint.h>
-#include <string>
#include <xf86drmMode.h>
+#include <string>
namespace android {
@@ -122,8 +122,8 @@
}
float DrmMode::v_refresh() const {
- return v_refresh_ ? v_refresh_ * 1.0f :
- clock_ / (float)(v_total_ * h_total_) * 1000.0f;
+ return v_refresh_ ? v_refresh_ * 1.0f
+ : clock_ / (float)(v_total_ * h_total_) * 1000.0f;
}
uint32_t DrmMode::flags() const {
@@ -137,4 +137,4 @@
std::string DrmMode::name() const {
return name_;
}
-}
+} // namespace android
diff --git a/drmmode.h b/drmmode.h
index b383168..4cc06b1 100644
--- a/drmmode.h
+++ b/drmmode.h
@@ -18,8 +18,8 @@
#define ANDROID_DRM_MODE_H_
#include <stdint.h>
-#include <string>
#include <xf86drmMode.h>
+#include <string>
namespace android {
@@ -77,6 +77,6 @@
std::string name_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_MODE_H_
diff --git a/drmplane.cpp b/drmplane.cpp
index 4449256..2603e16 100644
--- a/drmplane.cpp
+++ b/drmplane.cpp
@@ -17,18 +17,18 @@
#define LOG_TAG "hwc-drm-plane"
#include "drmplane.h"
-#include "drmresources.h"
+#include "drmdevice.h"
-#include <cinttypes>
#include <errno.h>
#include <stdint.h>
+#include <cinttypes>
#include <log/log.h>
#include <xf86drmMode.h>
namespace android {
-DrmPlane::DrmPlane(DrmResources *drm, drmModePlanePtr p)
+DrmPlane::DrmPlane(DrmDevice *drm, drmModePlanePtr p)
: drm_(drm), id_(p->plane_id), possible_crtc_mask_(p->possible_crtcs) {
}
@@ -196,4 +196,4 @@
const DrmProperty &DrmPlane::in_fence_fd_property() const {
return in_fence_fd_property_;
}
-}
+} // namespace android
diff --git a/drmplane.h b/drmplane.h
index 5b73b08..46dbc94 100644
--- a/drmplane.h
+++ b/drmplane.h
@@ -26,11 +26,11 @@
namespace android {
-class DrmResources;
+class DrmDevice;
class DrmPlane {
public:
- DrmPlane(DrmResources *drm, drmModePlanePtr p);
+ DrmPlane(DrmDevice *drm, drmModePlanePtr p);
DrmPlane(const DrmPlane &) = delete;
DrmPlane &operator=(const DrmPlane &) = delete;
@@ -57,7 +57,7 @@
const DrmProperty &in_fence_fd_property() const;
private:
- DrmResources *drm_;
+ DrmDevice *drm_;
uint32_t id_;
uint32_t possible_crtc_mask_;
@@ -78,6 +78,6 @@
DrmProperty alpha_property_;
DrmProperty in_fence_fd_property_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_PLANE_H_
diff --git a/drmproperty.cpp b/drmproperty.cpp
index 6f65dac..e71c159 100644
--- a/drmproperty.cpp
+++ b/drmproperty.cpp
@@ -15,7 +15,7 @@
*/
#include "drmproperty.h"
-#include "drmresources.h"
+#include "drmdevice.h"
#include <errno.h>
#include <stdint.h>
@@ -99,4 +99,4 @@
return -EINVAL;
}
}
-}
+} // namespace android
diff --git a/drmproperty.h b/drmproperty.h
index 648eda7..dc01c88 100644
--- a/drmproperty.h
+++ b/drmproperty.h
@@ -18,8 +18,8 @@
#define ANDROID_DRM_PROPERTY_H_
#include <stdint.h>
-#include <string>
#include <xf86drmMode.h>
+#include <string>
#include <vector>
namespace android {
@@ -67,6 +67,6 @@
std::vector<DrmPropertyEnum> enums_;
std::vector<uint32_t> blob_ids_;
};
-}
+} // namespace android
#endif // ANDROID_DRM_PROPERTY_H_
diff --git a/drmresources.cpp b/drmresources.cpp
deleted file mode 100644
index ec6664c..0000000
--- a/drmresources.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "hwc-drm-resources"
-
-#include "drmconnector.h"
-#include "drmcrtc.h"
-#include "drmencoder.h"
-#include "drmeventlistener.h"
-#include "drmplane.h"
-#include "drmresources.h"
-
-#include <cinttypes>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <log/log.h>
-#include <cutils/properties.h>
-
-namespace android {
-
-DrmResources::DrmResources() : event_listener_(this) {
-}
-
-DrmResources::~DrmResources() {
- event_listener_.Exit();
-}
-
-int DrmResources::Init() {
- char path[PROPERTY_VALUE_MAX];
- property_get("hwc.drm.device", path, "/dev/dri/card0");
-
- /* TODO: Use drmOpenControl here instead */
- fd_.Set(open(path, O_RDWR));
- if (fd() < 0) {
- ALOGE("Failed to open dri- %s", strerror(-errno));
- return -ENODEV;
- }
-
- int ret = drmSetClientCap(fd(), DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
- if (ret) {
- ALOGE("Failed to set universal plane cap %d", ret);
- return ret;
- }
-
- ret = drmSetClientCap(fd(), DRM_CLIENT_CAP_ATOMIC, 1);
- if (ret) {
- ALOGE("Failed to set atomic cap %d", ret);
- return ret;
- }
-
- drmModeResPtr res = drmModeGetResources(fd());
- if (!res) {
- ALOGE("Failed to get DrmResources resources");
- return -ENODEV;
- }
-
- min_resolution_ =
- std::pair<uint32_t, uint32_t>(res->min_width, res->min_height);
- max_resolution_ =
- std::pair<uint32_t, uint32_t>(res->max_width, res->max_height);
-
- bool found_primary = false;
- int display_num = 1;
-
- for (int i = 0; !ret && i < res->count_crtcs; ++i) {
- drmModeCrtcPtr c = drmModeGetCrtc(fd(), res->crtcs[i]);
- if (!c) {
- ALOGE("Failed to get crtc %d", res->crtcs[i]);
- ret = -ENODEV;
- break;
- }
-
- std::unique_ptr<DrmCrtc> crtc(new DrmCrtc(this, c, i));
- drmModeFreeCrtc(c);
-
- ret = crtc->Init();
- if (ret) {
- ALOGE("Failed to initialize crtc %d", res->crtcs[i]);
- break;
- }
- crtcs_.emplace_back(std::move(crtc));
- }
-
- for (int i = 0; !ret && i < res->count_encoders; ++i) {
- drmModeEncoderPtr e = drmModeGetEncoder(fd(), res->encoders[i]);
- if (!e) {
- ALOGE("Failed to get encoder %d", res->encoders[i]);
- ret = -ENODEV;
- break;
- }
-
- std::vector<DrmCrtc *> possible_crtcs;
- DrmCrtc *current_crtc = NULL;
- for (auto &crtc : crtcs_) {
- if ((1 << crtc->pipe()) & e->possible_crtcs)
- possible_crtcs.push_back(crtc.get());
-
- if (crtc->id() == e->crtc_id)
- current_crtc = crtc.get();
- }
-
- std::unique_ptr<DrmEncoder> enc(
- new DrmEncoder(e, current_crtc, possible_crtcs));
-
- drmModeFreeEncoder(e);
-
- encoders_.emplace_back(std::move(enc));
- }
-
- for (int i = 0; !ret && i < res->count_connectors; ++i) {
- drmModeConnectorPtr c = drmModeGetConnector(fd(), res->connectors[i]);
- if (!c) {
- ALOGE("Failed to get connector %d", res->connectors[i]);
- ret = -ENODEV;
- break;
- }
-
- std::vector<DrmEncoder *> possible_encoders;
- DrmEncoder *current_encoder = NULL;
- for (int j = 0; j < c->count_encoders; ++j) {
- for (auto &encoder : encoders_) {
- if (encoder->id() == c->encoders[j])
- possible_encoders.push_back(encoder.get());
- if (encoder->id() == c->encoder_id)
- current_encoder = encoder.get();
- }
- }
-
- std::unique_ptr<DrmConnector> conn(
- new DrmConnector(this, c, current_encoder, possible_encoders));
-
- drmModeFreeConnector(c);
-
- ret = conn->Init();
- if (ret) {
- ALOGE("Init connector %d failed", res->connectors[i]);
- break;
- }
-
- connectors_.emplace_back(std::move(conn));
- }
-
- // First look for primary amongst internal connectors
- for (auto &conn : connectors_) {
- if (conn->internal() && !found_primary) {
- conn->set_display(0);
- found_primary = true;
- } else {
- conn->set_display(display_num);
- ++display_num;
- }
- }
-
- // Then look for primary amongst external connectors
- for (auto &conn : connectors_) {
- if (conn->external() && !found_primary) {
- conn->set_display(0);
- found_primary = true;
- }
- }
-
- if (res)
- drmModeFreeResources(res);
-
- // Catch-all for the above loops
- if (ret)
- return ret;
-
- drmModePlaneResPtr plane_res = drmModeGetPlaneResources(fd());
- if (!plane_res) {
- ALOGE("Failed to get plane resources");
- return -ENOENT;
- }
-
- for (uint32_t i = 0; i < plane_res->count_planes; ++i) {
- drmModePlanePtr p = drmModeGetPlane(fd(), plane_res->planes[i]);
- if (!p) {
- ALOGE("Failed to get plane %d", plane_res->planes[i]);
- ret = -ENODEV;
- break;
- }
-
- std::unique_ptr<DrmPlane> plane(new DrmPlane(this, p));
-
- drmModeFreePlane(p);
-
- ret = plane->Init();
- if (ret) {
- ALOGE("Init plane %d failed", plane_res->planes[i]);
- break;
- }
-
- planes_.emplace_back(std::move(plane));
- }
- drmModeFreePlaneResources(plane_res);
- if (ret)
- return ret;
-
- ret = event_listener_.Init();
- if (ret) {
- ALOGE("Can't initialize event listener %d", ret);
- return ret;
- }
-
- for (auto &conn : connectors_) {
- ret = CreateDisplayPipe(conn.get());
- if (ret) {
- ALOGE("Failed CreateDisplayPipe %d with %d", conn->id(), ret);
- return ret;
- }
- }
- return 0;
-}
-
-DrmConnector *DrmResources::GetConnectorForDisplay(int display) const {
- for (auto &conn : connectors_) {
- if (conn->display() == display)
- return conn.get();
- }
- return NULL;
-}
-
-DrmCrtc *DrmResources::GetCrtcForDisplay(int display) const {
- for (auto &crtc : crtcs_) {
- if (crtc->display() == display)
- return crtc.get();
- }
- return NULL;
-}
-
-DrmPlane *DrmResources::GetPlane(uint32_t id) const {
- for (auto &plane : planes_) {
- if (plane->id() == id)
- return plane.get();
- }
- return NULL;
-}
-
-const std::vector<std::unique_ptr<DrmCrtc>> & DrmResources::crtcs() const {
- return crtcs_;
-}
-
-uint32_t DrmResources::next_mode_id() {
- return ++mode_id_;
-}
-
-int DrmResources::TryEncoderForDisplay(int display, DrmEncoder *enc) {
- /* First try to use the currently-bound crtc */
- DrmCrtc *crtc = enc->crtc();
- if (crtc && crtc->can_bind(display)) {
- crtc->set_display(display);
- return 0;
- }
-
- /* Try to find a possible crtc which will work */
- for (DrmCrtc *crtc : enc->possible_crtcs()) {
- /* We've already tried this earlier */
- if (crtc == enc->crtc())
- continue;
-
- if (crtc->can_bind(display)) {
- enc->set_crtc(crtc);
- crtc->set_display(display);
- return 0;
- }
- }
-
- /* We can't use the encoder, but nothing went wrong, try another one */
- return -EAGAIN;
-}
-
-int DrmResources::CreateDisplayPipe(DrmConnector *connector) {
- int display = connector->display();
- /* Try to use current setup first */
- if (connector->encoder()) {
- int ret = TryEncoderForDisplay(display, connector->encoder());
- if (!ret) {
- return 0;
- } else if (ret != -EAGAIN) {
- ALOGE("Could not set mode %d/%d", display, ret);
- return ret;
- }
- }
-
- for (DrmEncoder *enc : connector->possible_encoders()) {
- int ret = TryEncoderForDisplay(display, enc);
- if (!ret) {
- connector->set_encoder(enc);
- return 0;
- } else if (ret != -EAGAIN) {
- ALOGE("Could not set mode %d/%d", display, ret);
- return ret;
- }
- }
- ALOGE("Could not find a suitable encoder/crtc for display %d",
- connector->display());
- return -ENODEV;
-}
-
-int DrmResources::CreatePropertyBlob(void *data, size_t length,
- uint32_t *blob_id) {
- struct drm_mode_create_blob create_blob;
- memset(&create_blob, 0, sizeof(create_blob));
- create_blob.length = length;
- create_blob.data = (__u64)data;
-
- int ret = drmIoctl(fd(), DRM_IOCTL_MODE_CREATEPROPBLOB, &create_blob);
- if (ret) {
- ALOGE("Failed to create mode property blob %d", ret);
- return ret;
- }
- *blob_id = create_blob.blob_id;
- return 0;
-}
-
-int DrmResources::DestroyPropertyBlob(uint32_t blob_id) {
- if (!blob_id)
- return 0;
-
- struct drm_mode_destroy_blob destroy_blob;
- memset(&destroy_blob, 0, sizeof(destroy_blob));
- destroy_blob.blob_id = (__u32)blob_id;
- int ret = drmIoctl(fd(), DRM_IOCTL_MODE_DESTROYPROPBLOB, &destroy_blob);
- if (ret) {
- ALOGE("Failed to destroy mode property blob %" PRIu32 "/%d", blob_id, ret);
- return ret;
- }
- return 0;
-}
-
-DrmEventListener *DrmResources::event_listener() {
- return &event_listener_;
-}
-
-int DrmResources::GetProperty(uint32_t obj_id, uint32_t obj_type,
- const char *prop_name, DrmProperty *property) {
- drmModeObjectPropertiesPtr props;
-
- props = drmModeObjectGetProperties(fd(), obj_id, obj_type);
- if (!props) {
- ALOGE("Failed to get properties for %d/%x", obj_id, obj_type);
- return -ENODEV;
- }
-
- bool found = false;
- for (int i = 0; !found && (size_t)i < props->count_props; ++i) {
- drmModePropertyPtr p = drmModeGetProperty(fd(), props->props[i]);
- if (!strcmp(p->name, prop_name)) {
- property->Init(p, props->prop_values[i]);
- found = true;
- }
- drmModeFreeProperty(p);
- }
-
- drmModeFreeObjectProperties(props);
- return found ? 0 : -ENOENT;
-}
-
-int DrmResources::GetPlaneProperty(const DrmPlane &plane, const char *prop_name,
- DrmProperty *property) {
- return GetProperty(plane.id(), DRM_MODE_OBJECT_PLANE, prop_name, property);
-}
-
-int DrmResources::GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
- DrmProperty *property) {
- return GetProperty(crtc.id(), DRM_MODE_OBJECT_CRTC, prop_name, property);
-}
-
-int DrmResources::GetConnectorProperty(const DrmConnector &connector,
- const char *prop_name,
- DrmProperty *property) {
- return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
- property);
-}
-}
diff --git a/hwcutils.cpp b/hwcutils.cpp
index be70a39..87e3c42 100644
--- a/hwcutils.cpp
+++ b/hwcutils.cpp
@@ -23,6 +23,8 @@
#include <log/log.h>
#include <ui/GraphicBufferMapper.h>
+#define UNUSED(x) (void)(x)
+
namespace android {
const hwc_drm_bo *DrmHwcBuffer::operator->() const {
@@ -60,13 +62,24 @@
}
int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width,
- int height, int layerCount,
- int format, int usage, int stride) {
+ int height, int layerCount, int format,
+ int usage, int stride) {
native_handle_t *handle_copy;
GraphicBufferMapper &gm(GraphicBufferMapper::get());
- int ret =
- gm.importBuffer(handle, width, height, layerCount, format, usage,
- stride, const_cast<buffer_handle_t *>(&handle_copy));
+ int ret;
+
+#ifdef HWC2_USE_OLD_GB_IMPORT
+ UNUSED(width);
+ UNUSED(height);
+ UNUSED(layerCount);
+ UNUSED(format);
+ UNUSED(usage);
+ UNUSED(stride);
+ ret = gm.importBuffer(handle, const_cast<buffer_handle_t *>(&handle_copy));
+#else
+ ret = gm.importBuffer(handle, width, height, layerCount, format, usage,
+ stride, const_cast<buffer_handle_t *>(&handle_copy));
+#endif
if (ret) {
ALOGE("Failed to import buffer handle %d", ret);
return ret;
@@ -101,9 +114,13 @@
const hwc_drm_bo *bo = buffer.operator->();
- // FIXME: Add layerCount and a pixel stride to the hwc_drm_bo
- ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height,
- 1, bo->format, bo->usage, bo->width);
+ unsigned int layer_count;
+ for (layer_count = 0; layer_count < HWC_DRM_BO_MAX_PLANES; ++layer_count)
+ if (bo->gem_handles[layer_count] == 0)
+ break;
+
+ ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height, layer_count,
+ bo->hal_format, bo->usage, bo->pixel_stride);
if (ret)
return ret;
@@ -112,6 +129,18 @@
return 0;
}
+int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer,
+ Importer *importer) {
+ blending = src_layer->blending;
+ sf_handle = src_layer->sf_handle;
+ acquire_fence = -1;
+ display_frame = src_layer->display_frame;
+ alpha = src_layer->alpha;
+ source_crop = src_layer->source_crop;
+ transform = src_layer->transform;
+ return ImportBuffer(importer);
+}
+
void DrmHwcLayer::SetSourceCrop(hwc_frect_t const &crop) {
source_crop = crop;
}
@@ -139,4 +168,4 @@
transform |= DrmHwcTransform::kRotate90;
}
}
-}
+} // namespace android
diff --git a/platform.cpp b/platform.cpp
index b6c39d0..af18124 100644
--- a/platform.cpp
+++ b/platform.cpp
@@ -16,8 +16,8 @@
#define LOG_TAG "hwc-platform"
-#include "drmresources.h"
#include "platform.h"
+#include "drmdevice.h"
#include <log/log.h>
@@ -41,8 +41,8 @@
std::vector<DrmPlane *> *primary_planes,
std::vector<DrmPlane *> *overlay_planes) {
std::vector<DrmCompositionPlane> composition;
- std::vector<DrmPlane *> planes =
- GetUsablePlanes(crtc, primary_planes, overlay_planes);
+ std::vector<DrmPlane *> planes = GetUsablePlanes(crtc, primary_planes,
+ overlay_planes);
if (planes.empty()) {
ALOGE("Display %d has no usable planes", crtc->display());
return std::make_tuple(-ENODEV, std::vector<DrmCompositionPlane>());
@@ -101,4 +101,4 @@
return 0;
}
-}
+} // namespace android
diff --git a/platform.h b/platform.h
index 068499e..37c4647 100644
--- a/platform.h
+++ b/platform.h
@@ -28,7 +28,7 @@
namespace android {
-class DrmResources;
+class DrmDevice;
class Importer {
public:
@@ -36,7 +36,7 @@
}
// Creates a platform-specific importer instance
- static Importer *CreateInstance(DrmResources *drm);
+ static Importer *CreateInstance(DrmDevice *drm);
// Imports the buffer referred to by handle into bo.
//
@@ -88,7 +88,7 @@
};
// Creates a planner instance with platform-specific planning stages
- static std::unique_ptr<Planner> CreateInstance(DrmResources *drm);
+ static std::unique_ptr<Planner> CreateInstance(DrmDevice *drm);
// Takes a stack of layers and provisions hardware planes for them. If the
// entire stack can't fit in hardware, FIXME
@@ -136,5 +136,5 @@
std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
std::vector<DrmPlane *> *planes);
};
-}
+} // namespace android
#endif
diff --git a/platformdrmgeneric.cpp b/platformdrmgeneric.cpp
index 7c4758d..24d0650 100644
--- a/platformdrmgeneric.cpp
+++ b/platformdrmgeneric.cpp
@@ -16,23 +16,23 @@
#define LOG_TAG "hwc-platform-drm-generic"
-#include "drmresources.h"
-#include "platform.h"
#include "platformdrmgeneric.h"
+#include "drmdevice.h"
+#include "platform.h"
#include <drm/drm_fourcc.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <log/log.h>
#include <gralloc_handle.h>
#include <hardware/gralloc.h>
+#include <log/log.h>
namespace android {
#ifdef USE_DRM_GENERIC_IMPORTER
// static
-Importer *Importer::CreateInstance(DrmResources *drm) {
+Importer *Importer::CreateInstance(DrmDevice *drm) {
DrmGenericImporter *importer = new DrmGenericImporter(drm);
if (!importer)
return NULL;
@@ -47,7 +47,7 @@
}
#endif
-DrmGenericImporter::DrmGenericImporter(DrmResources *drm) : drm_(drm) {
+DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) {
}
DrmGenericImporter::~DrmGenericImporter() {
@@ -83,6 +83,24 @@
}
}
+uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) {
+ switch (drm_format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_ABGR8888:
+ return 32;
+ case DRM_FORMAT_BGR888:
+ return 24;
+ case DRM_FORMAT_BGR565:
+ return 16;
+ case DRM_FORMAT_YVU420:
+ return 12;
+ default:
+ ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format);
+ return 32;
+ }
+}
+
int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
gralloc_handle_t *gr_handle = gralloc_handle(handle);
if (!gr_handle)
@@ -98,8 +116,11 @@
memset(bo, 0, sizeof(hwc_drm_bo_t));
bo->width = gr_handle->width;
bo->height = gr_handle->height;
+ bo->hal_format = gr_handle->format;
bo->format = ConvertHalFormatToDrm(gr_handle->format);
bo->usage = gr_handle->usage;
+ bo->pixel_stride = (gr_handle->stride * 8) /
+ DrmFormatToBitsPerPixel(bo->format);
bo->pitches[0] = gr_handle->stride;
bo->gem_handles[0] = gem_handle;
bo->offsets[0] = 0;
@@ -121,8 +142,8 @@
struct drm_gem_close gem_close;
memset(&gem_close, 0, sizeof(gem_close));
- int num_gem_handles = sizeof(bo->gem_handles) / sizeof(bo->gem_handles[0]);
- for (int i = 0; i < num_gem_handles; i++) {
+
+ for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
if (!bo->gem_handles[i])
continue;
@@ -131,7 +152,7 @@
if (ret) {
ALOGE("Failed to close gem handle %d %d", i, ret);
} else {
- for (int j = i + 1; j < num_gem_handles; j++)
+ for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
if (bo->gem_handles[j] == bo->gem_handles[i])
bo->gem_handles[j] = 0;
bo->gem_handles[i] = 0;
@@ -141,7 +162,7 @@
}
#ifdef USE_DRM_GENERIC_IMPORTER
-std::unique_ptr<Planner> Planner::CreateInstance(DrmResources *) {
+std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
std::unique_ptr<Planner> planner(new Planner);
planner->AddStage<PlanStageGreedy>();
return planner;
diff --git a/platformdrmgeneric.h b/platformdrmgeneric.h
index 0339e1e..d46e8b0 100644
--- a/platformdrmgeneric.h
+++ b/platformdrmgeneric.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_PLATFORM_DRM_GENERIC_H_
#define ANDROID_PLATFORM_DRM_GENERIC_H_
-#include "drmresources.h"
+#include "drmdevice.h"
#include "platform.h"
#include <hardware/gralloc.h>
@@ -26,7 +26,7 @@
class DrmGenericImporter : public Importer {
public:
- DrmGenericImporter(DrmResources *drm);
+ DrmGenericImporter(DrmDevice *drm);
~DrmGenericImporter() override;
int Init();
@@ -35,12 +35,13 @@
int ReleaseBuffer(hwc_drm_bo_t *bo) override;
uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
- private:
+ uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format);
- DrmResources *drm_;
+ private:
+ DrmDevice *drm_;
const gralloc_module_t *gralloc_;
};
-}
+} // namespace android
#endif
diff --git a/platformhisi.cpp b/platformhisi.cpp
index d4428d0..68bb5a7 100644
--- a/platformhisi.cpp
+++ b/platformhisi.cpp
@@ -16,26 +16,25 @@
#define LOG_TAG "hwc-platform-hisi"
-#include "drmresources.h"
-#include "platform.h"
#include "platformhisi.h"
-
+#include "drmdevice.h"
+#include "platform.h"
#include <drm/drm_fourcc.h>
-#include <cinttypes>
#include <stdatomic.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include <cinttypes>
-#include <log/log.h>
#include <hardware/gralloc.h>
+#include <log/log.h>
#include "gralloc_priv.h"
#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
namespace android {
-Importer *Importer::CreateInstance(DrmResources *drm) {
+Importer *Importer::CreateInstance(DrmDevice *drm) {
HisiImporter *importer = new HisiImporter(drm);
if (!importer)
return NULL;
@@ -49,7 +48,8 @@
return importer;
}
-HisiImporter::HisiImporter(DrmResources *drm) : DrmGenericImporter(drm), drm_(drm) {
+HisiImporter::HisiImporter(DrmDevice *drm)
+ : DrmGenericImporter(drm), drm_(drm) {
}
HisiImporter::~HisiImporter() {
@@ -71,11 +71,18 @@
}
int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
- private_handle_t const *hnd =
- reinterpret_cast<private_handle_t const *>(handle);
+ memset(bo, 0, sizeof(hwc_drm_bo_t));
+
+ private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
+ handle);
if (!hnd)
return -EINVAL;
+ // We can't import these types of buffers, so pretend we did and rely on the
+ // planner to skip them when choosing layers for planes
+ if (!(hnd->usage & GRALLOC_USAGE_HW_FB))
+ return 0;
+
uint32_t gem_handle;
int ret = drmPrimeFDToHandle(drm_->fd(), hnd->share_fd, &gem_handle);
if (ret) {
@@ -87,12 +94,12 @@
if (fmt < 0)
return fmt;
- memset(bo, 0, sizeof(hwc_drm_bo_t));
bo->width = hnd->width;
bo->height = hnd->height;
+ bo->hal_format = hnd->req_format;
bo->format = fmt;
bo->usage = hnd->usage;
-
+ bo->pixel_stride = hnd->stride;
bo->pitches[0] = hnd->byte_stride;
bo->gem_handles[0] = gem_handle;
bo->offsets[0] = 0;
@@ -132,9 +139,45 @@
return ret;
}
-std::unique_ptr<Planner> Planner::CreateInstance(DrmResources *) {
+class PlanStageHiSi : public Planner::PlanStage {
+ public:
+ int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition,
+ std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
+ std::vector<DrmPlane *> *planes) {
+ int layers_added = 0;
+ int initial_layers = layers.size();
+ // Fill up as many planes as we can with buffers that do not have HW_FB
+ // usage
+ for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) {
+ if (!(i->second->gralloc_buffer_usage & GRALLOC_USAGE_HW_FB))
+ continue;
+
+ int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer,
+ crtc, i->first);
+ layers_added++;
+ // We don't have any planes left
+ if (ret == -ENOENT)
+ break;
+ else if (ret)
+ ALOGE("Failed to emplace layer %zu, dropping it", i->first);
+ }
+ /*
+ * If we only have one layer, but we didn't emplace anything, we
+ * can run into trouble, as we might try to device composite a
+ * buffer we fake-imported, which can cause things to jamb up.
+ * So return an error in this case to ensure we force client
+ * compositing.
+ */
+ if (!layers_added && (initial_layers <= 1))
+ return -EINVAL;
+
+ return 0;
+ }
+};
+
+std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
std::unique_ptr<Planner> planner(new Planner);
- planner->AddStage<PlanStageGreedy>();
+ planner->AddStage<PlanStageHiSi>();
return planner;
}
-}
+} // namespace android
diff --git a/platformhisi.h b/platformhisi.h
index a098692..2b2d439 100644
--- a/platformhisi.h
+++ b/platformhisi.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_PLATFORM_HISI_H_
#define ANDROID_PLATFORM_HISI_H_
-#include "drmresources.h"
+#include "drmdevice.h"
#include "platform.h"
#include "platformdrmgeneric.h"
@@ -29,7 +29,7 @@
class HisiImporter : public DrmGenericImporter {
public:
- HisiImporter(DrmResources *drm);
+ HisiImporter(DrmDevice *drm);
~HisiImporter() override;
int Init();
@@ -37,11 +37,10 @@
int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
private:
-
- DrmResources *drm_;
+ DrmDevice *drm_;
const gralloc_module_t *gralloc_;
};
-}
+} // namespace android
#endif
diff --git a/platformminigbm.cpp b/platformminigbm.cpp
index 8e3cc65..2040768 100644
--- a/platformminigbm.cpp
+++ b/platformminigbm.cpp
@@ -16,16 +16,16 @@
#define LOG_TAG "hwc-platform-drm-minigbm"
+#include "platformminigbm.h"
#include "drmresources.h"
#include "platform.h"
-#include "platformminigbm.h"
#include <drm/drm_fourcc.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <log/log.h>
#include <hardware/gralloc.h>
+#include <log/log.h>
#include "cros_gralloc_handle.h"
@@ -45,7 +45,8 @@
return importer;
}
-DrmMinigbmImporter::DrmMinigbmImporter(DrmResources *drm) : DrmGenericImporter(drm), drm_(drm) {
+DrmMinigbmImporter::DrmMinigbmImporter(DrmResources *drm)
+ : DrmGenericImporter(drm), drm_(drm) {
}
DrmMinigbmImporter::~DrmMinigbmImporter() {
@@ -81,8 +82,10 @@
memset(bo, 0, sizeof(hwc_drm_bo_t));
bo->width = gr_handle->width;
bo->height = gr_handle->height;
+ bo->hal_format = gr_handle->droid_format;
bo->format = gr_handle->format;
bo->usage = gr_handle->usage;
+ bo->pixel_stride = gr_handle->pixel_stride;
bo->pitches[0] = gr_handle->strides[0];
bo->offsets[0] = gr_handle->offsets[0];
bo->gem_handles[0] = gem_handle;
@@ -103,4 +106,4 @@
return planner;
}
-}
+} // namespace android
diff --git a/platformminigbm.h b/platformminigbm.h
index f25bf7b..f5807b9 100644
--- a/platformminigbm.h
+++ b/platformminigbm.h
@@ -40,6 +40,6 @@
const gralloc_module_t *gralloc_;
};
-}
+} // namespace android
#endif
diff --git a/resourcemanager.cpp b/resourcemanager.cpp
new file mode 100644
index 0000000..6e23561
--- /dev/null
+++ b/resourcemanager.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "hwc-resource-manager"
+
+#include "resourcemanager.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+#include <sstream>
+#include <string>
+
+namespace android {
+
+ResourceManager::ResourceManager() : num_displays_(0), gralloc_(NULL) {
+}
+
+int ResourceManager::Init() {
+ char path_pattern[PROPERTY_VALUE_MAX];
+ // Could be a valid path or it can have at the end of it the wildcard %
+ // which means that it will try open all devices until an error is met.
+ int path_len = property_get("hwc.drm.device", path_pattern, "/dev/dri/card0");
+ int ret = 0;
+ if (path_pattern[path_len - 1] != '%') {
+ ret = AddDrmDevice(std::string(path_pattern));
+ } else {
+ path_pattern[path_len - 1] = '\0';
+ for (int idx = 0; !ret; ++idx) {
+ std::ostringstream path;
+ path << path_pattern << idx;
+ ret = AddDrmDevice(path.str());
+ }
+ }
+
+ if (!num_displays_) {
+ ALOGE("Failed to initialize any displays");
+ return ret ? -EINVAL : ret;
+ }
+
+ return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&gralloc_);
+}
+
+int ResourceManager::AddDrmDevice(std::string path) {
+ std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>();
+ int displays_added, ret;
+ std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_);
+ if (ret)
+ return ret;
+ std::shared_ptr<Importer> importer;
+ importer.reset(Importer::CreateInstance(drm.get()));
+ if (!importer) {
+ ALOGE("Failed to create importer instance");
+ return -ENODEV;
+ }
+ importers_.push_back(importer);
+ drms_.push_back(std::move(drm));
+ num_displays_ += displays_added;
+ return ret;
+}
+
+DrmConnector *ResourceManager::AvailableWritebackConnector(int display) {
+ DrmDevice *drm_device = GetDrmDevice(display);
+ DrmConnector *writeback_conn = NULL;
+ if (drm_device) {
+ writeback_conn = drm_device->AvailableWritebackConnector(display);
+ if (writeback_conn)
+ return writeback_conn;
+ }
+ for (auto &drm : drms_) {
+ if (drm.get() == drm_device)
+ continue;
+ writeback_conn = drm->AvailableWritebackConnector(display);
+ if (writeback_conn)
+ return writeback_conn;
+ }
+ return writeback_conn;
+}
+
+DrmDevice *ResourceManager::GetDrmDevice(int display) {
+ for (auto &drm : drms_) {
+ if (drm->HandlesDisplay(display))
+ return drm.get();
+ }
+ return NULL;
+}
+
+std::shared_ptr<Importer> ResourceManager::GetImporter(int display) {
+ for (unsigned int i = 0; i < drms_.size(); i++) {
+ if (drms_[i]->HandlesDisplay(display))
+ return importers_[i];
+ }
+ return NULL;
+}
+
+const gralloc_module_t *ResourceManager::gralloc() {
+ return gralloc_;
+}
+} // namespace android
diff --git a/resourcemanager.h b/resourcemanager.h
new file mode 100644
index 0000000..463739b
--- /dev/null
+++ b/resourcemanager.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RESOURCEMANAGER_H
+#define RESOURCEMANAGER_H
+
+#include "drmdevice.h"
+#include "platform.h"
+
+#include <string.h>
+
+namespace android {
+
+class ResourceManager {
+ public:
+ ResourceManager();
+ ResourceManager(const ResourceManager &) = delete;
+ ResourceManager &operator=(const ResourceManager &) = delete;
+ int Init();
+ DrmDevice *GetDrmDevice(int display);
+ std::shared_ptr<Importer> GetImporter(int display);
+ const gralloc_module_t *gralloc();
+ DrmConnector *AvailableWritebackConnector(int display);
+
+ private:
+ int AddDrmDevice(std::string path);
+
+ int num_displays_;
+ std::vector<std::unique_ptr<DrmDevice>> drms_;
+ std::vector<std::shared_ptr<Importer>> importers_;
+ const gralloc_module_t *gralloc_;
+};
+} // namespace android
+
+#endif // RESOURCEMANAGER_H
diff --git a/vsyncworker.cpp b/vsyncworker.cpp
index 6ac016d..d022887 100644
--- a/vsyncworker.cpp
+++ b/vsyncworker.cpp
@@ -16,18 +16,18 @@
#define LOG_TAG "hwc-vsync-worker"
-#include "drmresources.h"
#include "vsyncworker.h"
+#include "drmdevice.h"
#include "worker.h"
-#include <map>
#include <stdlib.h>
#include <time.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include <map>
-#include <log/log.h>
#include <hardware/hardware.h>
+#include <log/log.h>
namespace android {
@@ -42,7 +42,7 @@
VSyncWorker::~VSyncWorker() {
}
-int VSyncWorker::Init(DrmResources *drm, int display) {
+int VSyncWorker::Init(DrmDevice *drm, int display) {
drm_ = drm;
display_ = display;
@@ -99,8 +99,9 @@
ALOGW("Vsync worker active with conn=%p refresh=%f\n", conn,
conn ? conn->active_mode().v_refresh() : 0.0f);
- int64_t phased_timestamp = GetPhasedVSync(
- kOneSecondNs / refresh, vsync.tv_sec * kOneSecondNs + vsync.tv_nsec);
+ int64_t phased_timestamp = GetPhasedVSync(kOneSecondNs / refresh,
+ vsync.tv_sec * kOneSecondNs +
+ vsync.tv_nsec);
vsync.tv_sec = phased_timestamp / kOneSecondNs;
vsync.tv_nsec = phased_timestamp - (vsync.tv_sec * kOneSecondNs);
do {
@@ -172,4 +173,4 @@
callback->Callback(display, timestamp);
last_timestamp_ = timestamp;
}
-}
+} // namespace android
diff --git a/vsyncworker.h b/vsyncworker.h
index 787152e..b2bca9d 100644
--- a/vsyncworker.h
+++ b/vsyncworker.h
@@ -17,11 +17,11 @@
#ifndef ANDROID_EVENT_WORKER_H_
#define ANDROID_EVENT_WORKER_H_
-#include "drmresources.h"
+#include "drmdevice.h"
#include "worker.h"
-#include <map>
#include <stdint.h>
+#include <map>
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
@@ -40,7 +40,7 @@
VSyncWorker();
~VSyncWorker() override;
- int Init(DrmResources *drm, int display);
+ int Init(DrmDevice *drm, int display);
void RegisterCallback(std::shared_ptr<VsyncCallback> callback);
void VSyncControl(bool enabled);
@@ -52,7 +52,7 @@
int64_t GetPhasedVSync(int64_t frame_ns, int64_t current);
int SyntheticWaitVBlank(int64_t *timestamp);
- DrmResources *drm_;
+ DrmDevice *drm_;
// shared_ptr since we need to use this outside of the thread lock (to
// actually call the hook) and we don't want the memory freed until we're
@@ -63,6 +63,6 @@
bool enabled_;
int64_t last_timestamp_;
};
-}
+} // namespace android
#endif
diff --git a/worker.cpp b/worker.cpp
index da6c580..0dceb16 100644
--- a/worker.cpp
+++ b/worker.cpp
@@ -91,4 +91,4 @@
Routine();
}
}
-}
+} // namespace android
diff --git a/worker.h b/worker.h
index 8f6295b..7909038 100644
--- a/worker.h
+++ b/worker.h
@@ -77,5 +77,5 @@
bool exit_;
bool initialized_;
};
-}
+} // namespace android
#endif