diff options
author | John Stultz <john.stultz@linaro.org> | 2020-02-03 19:03:14 +0000 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2020-02-03 19:03:14 +0000 |
commit | a51ae292ee205dbbc76866fce29315f3f43400f3 (patch) | |
tree | 4c931e333e8b74d9ba90fa9e33e49ec30ec92641 | |
parent | 68b94c0faebf0bf2d024fab7ed812e706589bbf1 (diff) | |
parent | b2f2baeb9db0d0f4cbc0cac3184058d3fce85ea6 (diff) | |
download | drm_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.cpp | 9 | ||||
-rw-r--r-- | drm/vsyncworker.cpp | 24 | ||||
-rw-r--r-- | drmhwctwo.cpp | 225 | ||||
-rw-r--r-- | include/drmconnector.h | 2 | ||||
-rw-r--r-- | include/drmhwcgralloc.h | 3 | ||||
-rw-r--r-- | include/drmhwctwo.h | 41 | ||||
-rw-r--r-- | include/platform.h | 3 | ||||
-rw-r--r-- | include/vsyncworker.h | 2 | ||||
-rw-r--r-- | platform/platformdrmgeneric.cpp | 106 | ||||
-rw-r--r-- | platform/platformdrmgeneric.h | 8 | ||||
-rw-r--r-- | platform/platformhisi.cpp | 46 | ||||
-rw-r--r-- | platform/platformhisi.h | 3 | ||||
-rw-r--r-- | platform/platformimagination.cpp | 34 | ||||
-rw-r--r-- | platform/platformimagination.h | 2 | ||||
-rw-r--r-- | platform/platformmeson.cpp | 38 | ||||
-rw-r--r-- | platform/platformmeson.h | 3 | ||||
-rw-r--r-- | platform/platformminigbm.cpp | 22 | ||||
-rw-r--r-- | platform/platformminigbm.h | 2 |
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 |