aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2020-02-03 19:03:14 +0000
committerJohn Stultz <john.stultz@linaro.org>2020-02-03 19:03:14 +0000
commita51ae292ee205dbbc76866fce29315f3f43400f3 (patch)
tree4c931e333e8b74d9ba90fa9e33e49ec30ec92641
parent68b94c0faebf0bf2d024fab7ed812e706589bbf1 (diff)
parentb2f2baeb9db0d0f4cbc0cac3184058d3fce85ea6 (diff)
downloaddrm_hwcomposer-a51ae292ee205dbbc76866fce29315f3f43400f3.tar.gz
Merge remote-tracking branch 'gitlab/master' into HEAD
* gitlab/master: drm_hwcomposer: Extract more BO data by Imagination importer drm_hwcomposer: Remove redundant hotplug call drm_hwcomposer: Add check to vsync routine to avoid crash on callback drm_hwcomposer: Add GetDisplayCapabilities and getDisplayIdentificationData drm_hwcomposer: Extract ConvertBoInfo() from ImportBuffer() method drm_hwcomposer: Choose client layer range to achieve minimal GPU load drm_hwcomposer: Add simplistic SetColorTransform implementation drm_hwcomposer: Add simplistic SetLayerColor implementation drm_hwcomposer: Add refcount for GEM handle drm_hwcomposer: Introduce dumpsys metrics Sync's AOSP with usptream master branch. Change-Id: Id98dea70b6236d4e0a1d8405b1cad157b495a892 Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r--drm/drmconnector.cpp9
-rw-r--r--drm/vsyncworker.cpp24
-rw-r--r--drmhwctwo.cpp225
-rw-r--r--include/drmconnector.h2
-rw-r--r--include/drmhwcgralloc.h3
-rw-r--r--include/drmhwctwo.h41
-rw-r--r--include/platform.h3
-rw-r--r--include/vsyncworker.h2
-rw-r--r--platform/platformdrmgeneric.cpp106
-rw-r--r--platform/platformdrmgeneric.h8
-rw-r--r--platform/platformhisi.cpp46
-rw-r--r--platform/platformhisi.h3
-rw-r--r--platform/platformimagination.cpp34
-rw-r--r--platform/platformimagination.h2
-rw-r--r--platform/platformmeson.cpp38
-rw-r--r--platform/platformmeson.h3
-rw-r--r--platform/platformminigbm.cpp22
-rw-r--r--platform/platformminigbm.h2
18 files changed, 406 insertions, 167 deletions
diff --git a/drm/drmconnector.cpp b/drm/drmconnector.cpp
index 7cde7cd..db3f9b6 100644
--- a/drm/drmconnector.cpp
+++ b/drm/drmconnector.cpp
@@ -58,6 +58,11 @@ int DrmConnector::Init() {
ALOGE("Could not get CRTC_ID property\n");
return ret;
}
+ ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_);
+ if (ret) {
+ ALOGE("Could not get EDID property\n");
+ return ret;
+ }
if (writeback()) {
ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
&writeback_pixel_formats_);
@@ -191,6 +196,10 @@ const DrmProperty &DrmConnector::crtc_id_property() const {
return crtc_id_property_;
}
+const DrmProperty &DrmConnector::edid_property() const {
+ return edid_property_;
+}
+
const DrmProperty &DrmConnector::writeback_pixel_formats() const {
return writeback_pixel_formats_;
}
diff --git a/drm/vsyncworker.cpp b/drm/vsyncworker.cpp
index d022887..08ab301 100644
--- a/drm/vsyncworker.cpp
+++ b/drm/vsyncworker.cpp
@@ -126,14 +126,10 @@ void VSyncWorker::Routine() {
}
}
- bool enabled = enabled_;
int display = display_;
std::shared_ptr<VsyncCallback> callback(callback_);
Unlock();
- if (!enabled)
- return;
-
DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
if (!crtc) {
ALOGE("Failed to get crtc for display");
@@ -161,6 +157,26 @@ void VSyncWorker::Routine() {
}
/*
+ * VSync could be disabled during routine execution so it could potentially
+ * lead to crash since callback's inner hook could be invalid anymore. We have
+ * no control over lifetime of this hook, therefore we can't rely that it'll
+ * be valid after vsync disabling.
+ *
+ * Blocking VSyncControl to wait until routine
+ * will finish execution is logically correct way to fix this issue, but it
+ * creates visible lags and stutters, so we have to resort to other ways of
+ * mitigating this issue.
+ *
+ * Doing check before attempt to invoke callback drastically shortens the
+ * window when such situation could happen and that allows us to practically
+ * avoid this issue.
+ *
+ * Please note that issue described below is different one and it is related
+ * to RegisterCallback, not to disabling vsync via VSyncControl.
+ */
+ if (!enabled_)
+ return;
+ /*
* There's a race here where a change in callback_ will not take effect until
* the next subsequent requested vsync. This is unavoidable since we can't
* call the vsync hook while holding the thread lock.
diff --git a/drmhwctwo.cpp b/drmhwctwo.cpp
index ffc5fcd..2b7f684 100644
--- a/drmhwctwo.cpp
+++ b/drmhwctwo.cpp
@@ -128,9 +128,58 @@ HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) {
return unsupported(__func__, display);
}
-void DrmHwcTwo::Dump(uint32_t *size, char *buffer) {
- // TODO: Implement dump
- unsupported(__func__, size, buffer);
+std::string DrmHwcTwo::HwcDisplay::DumpDelta(
+ DrmHwcTwo::HwcDisplay::Stats delta) {
+ if (delta.total_pixops_ == 0)
+ return "No stats yet";
+ double Ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
+
+ return (std::stringstream()
+ << " Total frames count: " << delta.total_frames_ << "\n"
+ << " Failed to test commit frames: " << delta.failed_kms_validate_
+ << "\n"
+ << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
+ << ((delta.failed_kms_present_ > 0)
+ ? " !!! Internal failure, FIX it please\n"
+ : "")
+ << " Pixel operations (free units)"
+ << " : [TOTAL: " << delta.total_pixops_
+ << " / GPU: " << delta.gpu_pixops_ << "]\n"
+ << " Composition efficiency: " << Ratio)
+ .str();
+}
+
+std::string DrmHwcTwo::HwcDisplay::Dump() {
+ auto out = (std::stringstream()
+ << "- Display on: " << connector_->name() << "\n"
+ << "Statistics since system boot:\n"
+ << DumpDelta(total_stats_) << "\n\n"
+ << "Statistics since last dumpsys request:\n"
+ << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n")
+ .str();
+
+ memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
+ return out;
+}
+
+void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
+ supported(__func__);
+
+ if (outBuffer != nullptr) {
+ auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+ *outSize = static_cast<uint32_t>(copiedBytes);
+ return;
+ }
+
+ std::stringstream output;
+
+ output << "-- drm_hwcomposer --\n\n";
+
+ for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &dp : displays_)
+ output << dp.second.Dump();
+
+ mDumpString = output.str();
+ *outSize = static_cast<uint32_t>(mDumpString.size());
}
uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() {
@@ -154,9 +203,6 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
switch (callback) {
case HWC2::Callback::Hotplug: {
- auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(function);
- hotplug(data, HWC_DISPLAY_PRIMARY,
- static_cast<int32_t>(HWC2::Connection::Connected));
auto &drmDevices = resource_manager_.getDrmDevices();
for (auto &device : drmDevices)
HandleInitialHotplugState(device.get());
@@ -182,8 +228,16 @@ DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
drm_(drm),
importer_(importer),
handle_(handle),
- type_(type) {
+ type_(type),
+ color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
supported(__func__);
+
+ // clang-format off
+ color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0};
+ // clang-format on
}
void DrmHwcTwo::HwcDisplay::ClearDisplay() {
@@ -657,7 +711,12 @@ HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) {
supported(__func__);
HWC2::Error ret;
+ ++total_stats_.total_frames_;
+
ret = CreateComposition(false);
+ if (ret != HWC2::Error::None)
+ ++total_stats_.failed_kms_present_;
+
if (ret == HWC2::Error::BadLayer) {
// Can we really have no client or device layers?
*present_fence = -1;
@@ -737,8 +796,18 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) {
HWC2::Error DrmHwcTwo::HwcDisplay::SetColorTransform(const float *matrix,
int32_t hint) {
supported(__func__);
- // TODO: Force client composition if we get this
- return unsupported(__func__, matrix, hint);
+ if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
+ hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
+ return HWC2::Error::BadParameter;
+
+ if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
+ return HWC2::Error::BadParameter;
+
+ color_transform_hint_ = static_cast<android_color_transform_t>(hint);
+ if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
+ std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin());
+
+ return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
@@ -785,6 +854,30 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetVsyncEnabled(int32_t enabled) {
return HWC2::Error::None;
}
+uint32_t DrmHwcTwo::HwcDisplay::CalcPixOps(
+ std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t first_z,
+ size_t size) {
+ uint32_t pixops = 0;
+ for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
+ if (l.first >= first_z && l.first < first_z + size) {
+ hwc_rect_t df = l.second->display_frame();
+ pixops += (df.right - df.left) * (df.bottom - df.top);
+ }
+ }
+ return pixops;
+}
+
+void DrmHwcTwo::HwcDisplay::MarkValidated(
+ std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t client_first_z,
+ size_t client_size) {
+ for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
+ if (l.first >= client_first_z && l.first < client_first_z + client_size)
+ l.second->set_validated_type(HWC2::Composition::Client);
+ else
+ l.second->set_validated_type(HWC2::Composition::Device);
+ }
+}
+
HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
uint32_t *num_requests) {
supported(__func__);
@@ -799,32 +892,104 @@ HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
if (avail_planes < layers_.size())
avail_planes--;
- std::map<uint32_t, DrmHwcTwo::HwcLayer *, std::greater<int>> z_map;
+ std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
- bool gpu_block = false;
+ uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0;
+
+ int client_start = -1, client_size = 0;
+
for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
- if (gpu_block || avail_planes == 0 ||
- !HardwareSupportsLayerType(l.second->sf_type()) ||
- !importer_->CanImportBuffer(l.second->buffer())) {
- gpu_block = true;
- ++*num_types;
+ if (!HardwareSupportsLayerType(l.second->sf_type()) ||
+ !importer_->CanImportBuffer(l.second->buffer()) ||
+ color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY) {
+ if (client_start < 0)
+ client_start = l.first;
+ client_size = (l.first - client_start) + 1;
+ }
+ }
+
+ int extra_client = (z_map.size() - client_size) - avail_planes;
+ if (extra_client > 0) {
+ int start = 0, steps;
+ if (client_size != 0) {
+ int prepend = std::min(client_start, extra_client);
+ int append = std::min(int(z_map.size() - (client_start + client_size)),
+ extra_client);
+ start = client_start - prepend;
+ client_size += extra_client;
+ steps = 1 + std::min(std::min(append, prepend),
+ int(z_map.size()) - (start + client_size));
} else {
- avail_planes--;
+ client_size = extra_client;
+ steps = 1 + z_map.size() - extra_client;
+ }
+
+ gpu_pixops = INT_MAX;
+ for (int i = 0; i < steps; i++) {
+ uint32_t po = CalcPixOps(z_map, start + i, client_size);
+ if (po < gpu_pixops) {
+ gpu_pixops = po;
+ client_start = start + i;
+ }
}
+ }
+
+ MarkValidated(z_map, client_start, client_size);
- l.second->set_validated_type(gpu_block ? HWC2::Composition::Client
- : HWC2::Composition::Device);
+ if (CreateComposition(true) != HWC2::Error::None) {
+ ++total_stats_.failed_kms_validate_;
+ gpu_pixops = total_pixops;
+ client_size = z_map.size();
+ MarkValidated(z_map, 0, client_size);
}
- if (CreateComposition(true) != HWC2::Error::None)
- for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
- l.second.set_validated_type(HWC2::Composition::Client);
+ *num_types = client_size;
+
+ total_stats_.gpu_pixops_ += gpu_pixops;
+ total_stats_.total_pixops_ += total_pixops;
return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
}
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData(
+ uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) {
+ supported(__func__);
+
+ drmModePropertyBlobPtr blob;
+ int ret;
+ uint64_t blob_id;
+
+ std::tie(ret, blob_id) = connector_->edid_property().value();
+ if (ret) {
+ ALOGE("Failed to get edid property value.");
+ return HWC2::Error::Unsupported;
+ }
+
+ blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
+
+ outData = static_cast<uint8_t *>(blob->data);
+
+ *outPort = connector_->id();
+ *outDataSize = blob->length;
+
+ return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities(
+ uint32_t *outNumCapabilities, uint32_t *outCapabilities) {
+ unsupported(__func__, outCapabilities);
+
+ if (outNumCapabilities == NULL) {
+ return HWC2::Error::BadParameter;
+ }
+
+ *outNumCapabilities = 0;
+
+ return HWC2::Error::None;
+}
+
HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
supported(__func__);
cursor_x_ = x;
@@ -855,8 +1020,10 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) {
- // TODO: Punt to client composition here?
- return unsupported(__func__, color);
+ // TODO: Put to client composition here?
+ supported(__func__);
+ layer_color_ = color;
+ return HWC2::Error::None;
}
HWC2::Error DrmHwcTwo::HwcLayer::SetLayerCompositionType(int32_t type) {
@@ -1145,6 +1312,16 @@ hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction(
return ToHook<HWC2_PFN_VALIDATE_DISPLAY>(
DisplayHook<decltype(&HwcDisplay::ValidateDisplay),
&HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>);
+ case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
+ return ToHook<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
+ DisplayHook<decltype(&HwcDisplay::GetDisplayIdentificationData),
+ &HwcDisplay::GetDisplayIdentificationData, uint8_t *,
+ uint32_t *, uint8_t *>);
+ case HWC2::FunctionDescriptor::GetDisplayCapabilities:
+ return ToHook<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
+ DisplayHook<decltype(&HwcDisplay::GetDisplayCapabilities),
+ &HwcDisplay::GetDisplayCapabilities, uint32_t *,
+ uint32_t *>);
// Layer functions
case HWC2::FunctionDescriptor::SetCursorPosition:
diff --git a/include/drmconnector.h b/include/drmconnector.h
index c9fd7ab..dc64b38 100644
--- a/include/drmconnector.h
+++ b/include/drmconnector.h
@@ -62,6 +62,7 @@ class DrmConnector {
const DrmProperty &dpms_property() const;
const DrmProperty &crtc_id_property() const;
+ const DrmProperty &edid_property() const;
const DrmProperty &writeback_pixel_formats() const;
const DrmProperty &writeback_fb_id() const;
const DrmProperty &writeback_out_fence() const;
@@ -100,6 +101,7 @@ class DrmConnector {
DrmProperty dpms_property_;
DrmProperty crtc_id_property_;
+ DrmProperty edid_property_;
DrmProperty writeback_pixel_formats_;
DrmProperty writeback_fb_id_;
DrmProperty writeback_out_fence_;
diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h
index 65a4007..b959714 100644
--- a/include/drmhwcgralloc.h
+++ b/include/drmhwcgralloc.h
@@ -29,8 +29,11 @@ typedef struct hwc_drm_bo {
uint32_t pixel_stride;
uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
+ uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
+ uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
uint32_t fb_id;
+ bool with_modifiers;
int acquire_fence_fd;
void *priv;
} hwc_drm_bo_t;
diff --git a/include/drmhwctwo.h b/include/drmhwctwo.h
index c6ce640..76e71b0 100644
--- a/include/drmhwctwo.h
+++ b/include/drmhwctwo.h
@@ -22,6 +22,7 @@
#include <hardware/hwcomposer2.h>
+#include <array>
#include <map>
namespace android {
@@ -86,6 +87,10 @@ class DrmHwcTwo : public hwc2_device_t {
return OutputFd(&release_fence_raw_);
}
+ hwc_rect_t display_frame() {
+ return display_frame_;
+ }
+
void PopulateDrmLayer(DrmHwcLayer *layer);
// Layer hooks
@@ -120,6 +125,7 @@ class DrmHwcTwo : public hwc2_device_t {
hwc_frect_t source_crop_;
int32_t cursor_x_;
int32_t cursor_y_;
+ hwc_color_t layer_color_;
HWC2::Transform transform_ = HWC2::Transform::None;
uint32_t z_order_ = 0;
android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
@@ -145,6 +151,8 @@ class DrmHwcTwo : public hwc2_device_t {
hwc2_function_pointer_t func);
void ClearDisplay();
+ std::string Dump();
+
// HWC Hooks
HWC2::Error AcceptDisplayChanges();
HWC2::Error CreateLayer(hwc2_layer_t *layer);
@@ -165,6 +173,11 @@ class DrmHwcTwo : public hwc2_device_t {
uint32_t *num_elements, hwc2_layer_t *layers,
int32_t *layer_requests);
HWC2::Error GetDisplayType(int32_t *type);
+ HWC2::Error GetDisplayIdentificationData(uint8_t *outPort,
+ uint32_t *outDataSize,
+ uint8_t *outData);
+ HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities,
+ uint32_t *outCapabilities);
HWC2::Error GetDozeSupport(int32_t *support);
HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
float *max_luminance,
@@ -194,6 +207,12 @@ class DrmHwcTwo : public hwc2_device_t {
HWC2::Error CreateComposition(bool test);
void AddFenceToPresentFence(int fd);
bool HardwareSupportsLayerType(HWC2::Composition comp_type);
+ uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
+ size_t first_z, size_t size);
+ void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
+ size_t client_first_z, size_t client_size);
+
+ constexpr static size_t MATRIX_SIZE = 16;
ResourceManager *resource_manager_;
DrmDevice *drm_;
@@ -214,8 +233,26 @@ class DrmHwcTwo : public hwc2_device_t {
HwcLayer client_layer_;
UniqueFd present_fence_;
int32_t color_mode_;
+ std::array<float, MATRIX_SIZE> color_transform_matrix_;
+ android_color_transform_t color_transform_hint_;
uint32_t frame_no_ = 0;
+ /* Statistics */
+ struct Stats {
+ Stats minus(Stats b) {
+ return {total_frames_ - b.total_frames_,
+ total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_,
+ failed_kms_validate_ - b.failed_kms_validate_,
+ failed_kms_present_ - b.failed_kms_present_};
+ }
+
+ uint32_t total_frames_ = 0;
+ uint64_t total_pixops_ = 0;
+ uint64_t gpu_pixops_ = 0;
+ uint32_t failed_kms_validate_ = 0;
+ uint32_t failed_kms_present_ = 0;
+ } total_stats_, prev_stats_;
+ std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
};
class DrmHotplugHandler : public DrmEventHandler {
@@ -289,7 +326,7 @@ class DrmHwcTwo : public hwc2_device_t {
HWC2::Error CreateVirtualDisplay(uint32_t width, uint32_t height,
int32_t *format, hwc2_display_t *display);
HWC2::Error DestroyVirtualDisplay(hwc2_display_t display);
- void Dump(uint32_t *size, char *buffer);
+ void Dump(uint32_t *outSize, char *outBuffer);
uint32_t GetMaxVirtualDisplayCount();
HWC2::Error RegisterCallback(int32_t descriptor, hwc2_callback_data_t data,
hwc2_function_pointer_t function);
@@ -300,5 +337,7 @@ class DrmHwcTwo : public hwc2_device_t {
ResourceManager resource_manager_;
std::map<hwc2_display_t, HwcDisplay> displays_;
std::map<HWC2::Callback, HwcCallback> callbacks_;
+
+ std::string mDumpString;
};
} // namespace android
diff --git a/include/platform.h b/include/platform.h
index 6fdece2..6775e29 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -52,6 +52,9 @@ class Importer {
// Checks if importer can import the buffer.
virtual bool CanImportBuffer(buffer_handle_t handle) = 0;
+
+ // Convert platform-dependent buffer format to drm_hwc internal format.
+ virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0;
};
class Planner {
diff --git a/include/vsyncworker.h b/include/vsyncworker.h
index b2bca9d..96f7432 100644
--- a/include/vsyncworker.h
+++ b/include/vsyncworker.h
@@ -60,7 +60,7 @@ class VSyncWorker : public Worker {
std::shared_ptr<VsyncCallback> callback_ = NULL;
int display_;
- bool enabled_;
+ std::atomic_bool enabled_;
int64_t last_timestamp_;
};
} // namespace android
diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp
index 0883b90..1aa8160 100644
--- a/platform/platformdrmgeneric.cpp
+++ b/platform/platformdrmgeneric.cpp
@@ -110,19 +110,12 @@ uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) {
}
}
-int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle,
+ hwc_drm_bo_t *bo) {
gralloc_handle_t *gr_handle = gralloc_handle(handle);
if (!gr_handle)
return -EINVAL;
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(drm_->fd(), gr_handle->prime_fd, &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", gr_handle->prime_fd, ret);
- return ret;
- }
-
- memset(bo, 0, sizeof(hwc_drm_bo_t));
bo->width = gr_handle->width;
bo->height = gr_handle->height;
bo->hal_format = gr_handle->format;
@@ -132,17 +125,55 @@ int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
bo->usage = gr_handle->usage;
bo->pixel_stride = (gr_handle->stride * 8) /
DrmFormatToBitsPerPixel(bo->format);
+ bo->prime_fds[0] = gr_handle->prime_fd;
bo->pitches[0] = gr_handle->stride;
- bo->gem_handles[0] = gem_handle;
bo->offsets[0] = 0;
- ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
- bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
+ return 0;
+}
+
+int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+ memset(bo, 0, sizeof(hwc_drm_bo_t));
+
+ int ret = ConvertBoInfo(handle, bo);
+ if (ret)
+ return ret;
+
+ ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]);
+ if (ret) {
+ ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret);
+ return ret;
+ }
+
+ for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
+ int fd = bo->prime_fds[i];
+ if (fd != 0) {
+ if (fd != bo->prime_fds[0]) {
+ ALOGE("Multiplanar FBs are not supported by this version of composer");
+ return -ENOTSUP;
+ }
+ bo->gem_handles[i] = bo->gem_handles[0];
+ }
+ }
+
+ if (!bo->with_modifiers)
+ ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
+ bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id,
+ 0);
+ else
+ ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
+ bo->format, bo->gem_handles, bo->pitches,
+ bo->offsets, bo->modifiers, &bo->fb_id,
+ bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS
+ : 0);
+
if (ret) {
ALOGE("could not create drm fb %d", ret);
return ret;
}
+ ImportHandle(bo->gem_handles[0]);
+
return ret;
}
@@ -151,17 +182,12 @@ int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
if (drmModeRmFB(drm_->fd(), bo->fb_id))
ALOGE("Failed to rm fb");
- struct drm_gem_close gem_close;
- memset(&gem_close, 0, sizeof(gem_close));
-
for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
if (!bo->gem_handles[i])
continue;
- gem_close.handle = bo->gem_handles[i];
- int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
- if (ret) {
- ALOGE("Failed to close gem handle %d %d", i, ret);
+ if (ReleaseHandle(bo->gem_handles[i])) {
+ ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
} else {
for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
if (bo->gem_handles[j] == bo->gem_handles[i])
@@ -173,13 +199,17 @@ int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
}
bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) {
- if (handle == NULL)
+ hwc_drm_bo_t bo;
+
+ int ret = ConvertBoInfo(handle, &bo);
+ if (ret)
return false;
- if (exclude_non_hwfb_) {
- gralloc_handle_t *hnd = gralloc_handle(handle);
- return hnd->usage & GRALLOC_USAGE_HW_FB;
- }
+ if (bo.prime_fds[0] == 0)
+ return false;
+
+ if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB))
+ return false;
return true;
}
@@ -191,4 +221,32 @@ std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
return planner;
}
#endif
+
+int DrmGenericImporter::ImportHandle(uint32_t gem_handle) {
+ gem_refcount_[gem_handle]++;
+
+ return 0;
+}
+
+int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) {
+ if (--gem_refcount_[gem_handle])
+ return 0;
+
+ gem_refcount_.erase(gem_handle);
+
+ return CloseHandle(gem_handle);
+}
+
+int DrmGenericImporter::CloseHandle(uint32_t gem_handle) {
+ struct drm_gem_close gem_close;
+
+ memset(&gem_close, 0, sizeof(gem_close));
+
+ gem_close.handle = gem_handle;
+ int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret)
+ ALOGE("Failed to close gem handle %d %d", gem_handle, ret);
+
+ return ret;
+}
}
diff --git a/platform/platformdrmgeneric.h b/platform/platformdrmgeneric.h
index 7bb2ea2..f9d923f 100644
--- a/platform/platformdrmgeneric.h
+++ b/platform/platformdrmgeneric.h
@@ -21,6 +21,7 @@
#include "platform.h"
#include <hardware/gralloc.h>
+#include <map>
#include <drm/drm_fourcc.h>
@@ -40,6 +41,10 @@ class DrmGenericImporter : public Importer {
int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
int ReleaseBuffer(hwc_drm_bo_t *bo) override;
bool CanImportBuffer(buffer_handle_t handle) override;
+ int ImportHandle(uint32_t gem_handle);
+ int ReleaseHandle(uint32_t gem_handle);
+
+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format);
@@ -50,6 +55,9 @@ class DrmGenericImporter : public Importer {
private:
const gralloc_module_t *gralloc_;
bool exclude_non_hwfb_;
+
+ int CloseHandle(uint32_t gem_handle);
+ std::map<uint32_t, int> gem_refcount_;
};
} // namespace android
diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp
index 2e6ac43..1f1478f 100644
--- a/platform/platformhisi.cpp
+++ b/platform/platformhisi.cpp
@@ -92,41 +92,29 @@ bool HisiImporter::IsDrmFormatRgb(uint32_t drm_format) {
case DRM_FORMAT_YVU420:
return false;
default:
- ALOGE("Unsupported format %u assuming rgb?", drm_format);
+ ALOGV("Unsupported format %u assuming rgb?", drm_format);
return true;
}
}
-int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+int HisiImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
bool is_rgb;
- uint64_t modifiers[4] = {0};
-
- 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.
- // These buffers should have been filtered out with CanImportBuffer()
if (!(hnd->usage & GRALLOC_USAGE_HW_FB))
return -EINVAL;
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(drm_->fd(), hnd->share_fd, &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", hnd->share_fd, ret);
- return ret;
- }
-
uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
if (fmt == DRM_FORMAT_INVALID)
return -EINVAL;
- is_rgb = IsDrmFormatRgb(fmt);
- modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format,
- is_rgb);
+ is_rgb = HisiImporter::IsDrmFormatRgb(fmt);
+ bo->modifiers[0] = HisiImporter::
+ ConvertGrallocFormatToDrmModifiers(hnd->internal_format, is_rgb);
bo->width = hnd->width;
bo->height = hnd->height;
@@ -135,7 +123,7 @@ int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
bo->usage = hnd->usage;
bo->pixel_stride = hnd->stride;
bo->pitches[0] = hnd->byte_stride;
- bo->gem_handles[0] = gem_handle;
+ bo->prime_fds[0] = hnd->share_fd;
bo->offsets[0] = 0;
switch (fmt) {
@@ -150,11 +138,11 @@ int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
int v_size = vu_stride * (adjusted_height / 2);
/* V plane*/
- bo->gem_handles[1] = gem_handle;
+ bo->prime_fds[1] = hnd->share_fd;
bo->pitches[1] = vu_stride;
bo->offsets[1] = y_size;
/* U plane */
- bo->gem_handles[2] = gem_handle;
+ bo->prime_fds[2] = hnd->share_fd;
bo->pitches[2] = vu_stride;
bo->offsets[2] = y_size + v_size;
break;
@@ -163,23 +151,9 @@ int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
break;
}
- ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
- bo->format, bo->gem_handles, bo->pitches,
- bo->offsets, modifiers, &bo->fb_id,
- modifiers[0] ? DRM_MODE_FB_MODIFIERS : 0);
-
- if (ret) {
- ALOGE("could not create drm fb %d", ret);
- return ret;
- }
-
- return ret;
-}
+ bo->with_modifiers = true;
-bool HisiImporter::CanImportBuffer(buffer_handle_t handle) {
- private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
- handle);
- return hnd && (hnd->usage & GRALLOC_USAGE_HW_FB);
+ return 0;
}
class PlanStageHiSi : public Planner::PlanStage {
diff --git a/platform/platformhisi.h b/platform/platformhisi.h
index 9dfea89..f127bdb 100644
--- a/platform/platformhisi.h
+++ b/platform/platformhisi.h
@@ -31,8 +31,7 @@ class HisiImporter : public DrmGenericImporter {
public:
using DrmGenericImporter::DrmGenericImporter;
- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
- bool CanImportBuffer(buffer_handle_t handle) override;
+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
private:
uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb);
diff --git a/platform/platformimagination.cpp b/platform/platformimagination.cpp
index 565e6ee..63d8130 100644
--- a/platform/platformimagination.cpp
+++ b/platform/platformimagination.cpp
@@ -22,31 +22,30 @@ Importer *Importer::CreateInstance(DrmDevice *drm) {
return importer;
}
-int ImaginationImporter::ImportBuffer(buffer_handle_t handle,
- hwc_drm_bo_t *bo) {
+int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle,
+ hwc_drm_bo_t *bo) {
IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle;
if (!hnd)
return -EINVAL;
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(drm_->fd(), hnd->fd[0], &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", hnd->fd[0], ret);
- return ret;
- }
-
/* Extra bits are responsible for buffer compression and memory layout */
if (hnd->iFormat & ~0x10f) {
- ALOGE("Special buffer formats are not supported");
+ ALOGV("Special buffer formats are not supported");
return -EINVAL;
}
- memset(bo, 0, sizeof(hwc_drm_bo_t));
bo->width = hnd->iWidth;
bo->height = hnd->iHeight;
bo->usage = hnd->usage;
- bo->gem_handles[0] = gem_handle;
- bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3;
+ bo->hal_format = hnd->iFormat;
+ bo->pixel_stride = hnd->aiStride[0];
+
+ int sub = std::min(hnd->iNumSubAllocs, HWC_DRM_BO_MAX_PLANES);
+ for (int i = 0; i < sub; i++) {
+ bo->prime_fds[i] = hnd->fd[i];
+ bo->offsets[i] = hnd->aulPlaneOffset[i];
+ bo->pitches[i] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3;
+ }
switch (hnd->iFormat) {
#ifdef HAL_PIXEL_FORMAT_BGRX_8888
@@ -57,18 +56,11 @@ int ImaginationImporter::ImportBuffer(buffer_handle_t handle,
default:
bo->format = ConvertHalFormatToDrm(hnd->iFormat & 0xf);
if (bo->format == DRM_FORMAT_INVALID) {
- ALOGE("Cannot convert hal format to drm format %u", hnd->iFormat);
+ ALOGV("Cannot convert hal format to drm format %u", hnd->iFormat);
return -EINVAL;
}
}
- ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
- bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
- if (ret) {
- ALOGE("could not create drm fb ret: %d", ret);
- return ret;
- }
-
return 0;
}
diff --git a/platform/platformimagination.h b/platform/platformimagination.h
index 85dfc45..f2a7cb7 100644
--- a/platform/platformimagination.h
+++ b/platform/platformimagination.h
@@ -15,7 +15,7 @@ class ImaginationImporter : public DrmGenericImporter {
public:
using DrmGenericImporter::DrmGenericImporter;
- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
};
} // namespace android
diff --git a/platform/platformmeson.cpp b/platform/platformmeson.cpp
index 5184972..ad3aff1 100644
--- a/platform/platformmeson.cpp
+++ b/platform/platformmeson.cpp
@@ -75,33 +75,21 @@ uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(
}
#endif
-int MesonImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
- uint64_t modifiers[4] = {0};
-
- memset(bo, 0, sizeof(hwc_drm_bo_t));
-
+int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
handle);
if (!hnd)
return -EINVAL;
- // We can't import these types of buffers.
- // These buffers should have been filtered out with CanImportBuffer()
if (!(hnd->usage & GRALLOC_USAGE_HW_FB))
return -EINVAL;
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(drm_->fd(), hnd->share_fd, &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", hnd->share_fd, ret);
- return ret;
- }
-
uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
if (fmt == DRM_FORMAT_INVALID)
return -EINVAL;
- modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format);
+ bo->modifiers[0] = MesonImporter::ConvertGrallocFormatToDrmModifiers(
+ hnd->internal_format);
bo->width = hnd->width;
bo->height = hnd->height;
@@ -109,27 +97,13 @@ int MesonImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
bo->format = fmt;
bo->usage = hnd->usage;
bo->pixel_stride = hnd->stride;
+ bo->prime_fds[0] = hnd->share_fd;
bo->pitches[0] = hnd->byte_stride;
- bo->gem_handles[0] = gem_handle;
bo->offsets[0] = 0;
- ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
- bo->format, bo->gem_handles, bo->pitches,
- bo->offsets, modifiers, &bo->fb_id,
- modifiers[0] ? DRM_MODE_FB_MODIFIERS : 0);
+ bo->with_modifiers = true;
- if (ret) {
- ALOGE("could not create drm fb %d", ret);
- return ret;
- }
-
- return ret;
-}
-
-bool MesonImporter::CanImportBuffer(buffer_handle_t handle) {
- private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
- handle);
- return hnd && (hnd->usage & GRALLOC_USAGE_HW_FB);
+ return 0;
}
std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
diff --git a/platform/platformmeson.h b/platform/platformmeson.h
index 7be7702..f29b796 100644
--- a/platform/platformmeson.h
+++ b/platform/platformmeson.h
@@ -31,8 +31,7 @@ class MesonImporter : public DrmGenericImporter {
public:
using DrmGenericImporter::DrmGenericImporter;
- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
- bool CanImportBuffer(buffer_handle_t handle) override;
+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
private:
uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags);
diff --git a/platform/platformminigbm.cpp b/platform/platformminigbm.cpp
index a65e196..df195d3 100644
--- a/platform/platformminigbm.cpp
+++ b/platform/platformminigbm.cpp
@@ -44,37 +44,23 @@ Importer *Importer::CreateInstance(DrmDevice *drm) {
return importer;
}
-int DrmMinigbmImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle,
+ hwc_drm_bo_t *bo) {
cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle;
if (!gr_handle)
return -EINVAL;
- uint32_t gem_handle;
- int ret = drmPrimeFDToHandle(drm_->fd(), gr_handle->fds[0], &gem_handle);
- if (ret) {
- ALOGE("failed to import prime fd %d ret=%d", gr_handle->fds[0], ret);
- return ret;
- }
-
- 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->prime_fds[0] = gr_handle->fds[0];
bo->pitches[0] = gr_handle->strides[0];
bo->offsets[0] = gr_handle->offsets[0];
- bo->gem_handles[0] = gem_handle;
-
- ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
- bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id, 0);
- if (ret) {
- ALOGE("could not create drm fb %d", ret);
- return ret;
- }
- return ret;
+ return 0;
}
std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
diff --git a/platform/platformminigbm.h b/platform/platformminigbm.h
index ff69f14..053b2aa 100644
--- a/platform/platformminigbm.h
+++ b/platform/platformminigbm.h
@@ -28,7 +28,7 @@ namespace android {
class DrmMinigbmImporter : public DrmGenericImporter {
public:
using DrmGenericImporter::DrmGenericImporter;
- int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
+ int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
};
} // namespace android