Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(696)

Unified Diff: ui/ozone/platform/drm/common/drm_util.cc

Issue 2420083003: ozone: Pick CRTCs with majority of planes. (Closed)
Patch Set: Prefer already set crtc. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/ozone/platform/drm/common/drm_util.cc
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc
index 8deaa6eb1af81e5f2b231cadf30193b5f1e6f5cc..8f395af46c58c1e5cef00586910740e7809291be 100644
--- a/ui/ozone/platform/drm/common/drm_util.cc
+++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -10,8 +10,10 @@
#include <sys/mman.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
+#include <algorithm>
#include <utility>
+#include "base/containers/small_map.h"
#include "ui/display/util/edid_parser.h"
#if !defined(DRM_FORMAT_YV12)
@@ -36,16 +38,21 @@ bool IsCrtcInUse(uint32_t crtc,
return false;
}
+// Return a CRTC compatible with |connector| and not already used in |displays|.
+// If there are multiple compatible CRTCs, the one that supports the majority of
+// planes will be returned.
uint32_t GetCrtc(int fd,
drmModeConnector* connector,
drmModeRes* resources,
const ScopedVector<HardwareDisplayControllerInfo>& displays) {
- // If the connector already has an encoder try to re-use.
- if (connector->encoder_id) {
- ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoder_id));
- if (encoder && encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays))
- return encoder->crtc_id;
- }
+ ScopedDrmPlaneResPtr plane_resources(drmModeGetPlaneResources(fd));
+ std::vector<ScopedDrmPlanePtr> planes;
+ for (uint32_t i = 0; i < plane_resources->count_planes; i++)
+ planes.emplace_back(drmModeGetPlane(fd, plane_resources->planes[i]));
+
+ DCHECK_GE(32, resources->count_crtcs);
+ uint32_t best_crtc = 0;
+ int best_crtc_planes = 0;
// Try to find an encoder for the connector.
for (int i = 0; i < connector->count_encoders; ++i) {
@@ -55,15 +62,29 @@ uint32_t GetCrtc(int fd,
for (int j = 0; j < resources->count_crtcs; ++j) {
// Check if the encoder is compatible with this CRTC
- if (!(encoder->possible_crtcs & (1 << j)) ||
+ int crtc_bit = 1 << j;
+ if (!(encoder->possible_crtcs & crtc_bit) ||
IsCrtcInUse(resources->crtcs[j], displays))
continue;
- return resources->crtcs[j];
+ int supported_planes = std::count_if(
+ planes.begin(), planes.end(), [crtc_bit](const ScopedDrmPlanePtr& p) {
+ return p->possible_crtcs & crtc_bit;
+ });
+
+ uint32_t assigned_crtc = 0;
Daniele Castagna 2017/01/10 01:11:45 Added logic to prefer an already set crtc in case
+ if (connector->encoder_id == encoder->encoder_id)
+ assigned_crtc = encoder->crtc_id;
+ if (supported_planes > best_crtc_planes ||
+ (supported_planes == best_crtc_planes &&
+ assigned_crtc == resources->crtcs[j])) {
+ best_crtc_planes = supported_planes;
+ best_crtc = resources->crtcs[j];
+ }
}
}
- return 0;
+ return best_crtc;
}
// Computes the refresh rate for the specific mode. If we have enough
@@ -206,21 +227,54 @@ ScopedVector<HardwareDisplayControllerInfo> GetAvailableDisplayControllerInfos(
DCHECK(resources) << "Failed to get DRM resources";
ScopedVector<HardwareDisplayControllerInfo> displays;
+ std::vector<ScopedDrmConnectorPtr> available_connectors;
+ std::vector<ScopedDrmConnectorPtr::element_type*> connectors;
for (int i = 0; i < resources->count_connectors; ++i) {
ScopedDrmConnectorPtr connector(
drmModeGetConnector(fd, resources->connectors[i]));
+ connectors.push_back(connector.get());
- if (!connector || connector->connection != DRM_MODE_CONNECTED ||
- connector->count_modes == 0)
- continue;
+ if (connector && connector->connection == DRM_MODE_CONNECTED &&
+ connector->count_modes != 0)
+ available_connectors.push_back(std::move(connector));
+ }
- uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays);
+ base::SmallMap<std::map<ScopedDrmConnectorPtr::element_type*, int>>
+ connector_crtcs;
+ for (auto& c : available_connectors) {
+ uint32_t possible_crtcs = 0;
+ for (int i = 0; i < c->count_encoders; ++i) {
+ ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, c->encoders[i]));
+ if (!encoder)
+ continue;
+ possible_crtcs |= encoder->possible_crtcs;
+ }
+ connector_crtcs[c.get()] = possible_crtcs;
+ }
+ // Make sure to start assigning a crtc to the connector that supports the
+ // fewest crtcs first.
+ std::stable_sort(available_connectors.begin(), available_connectors.end(),
+ [&connector_crtcs](const ScopedDrmConnectorPtr& c1,
+ const ScopedDrmConnectorPtr& c2) {
+ // When c1 supports a proper subset of the crtcs of c2, we
+ // should process c1 first (return true).
+ int c1_crtcs = connector_crtcs[c1.get()];
+ int c2_crtcs = connector_crtcs[c2.get()];
+ return (c1_crtcs & c2_crtcs) == c1_crtcs &&
+ c1_crtcs != c2_crtcs;
+ });
+
+ for (auto& c : available_connectors) {
+ uint32_t crtc_id = GetCrtc(fd, c.get(), resources.get(), displays);
if (!crtc_id)
continue;
ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
- displays.push_back(new HardwareDisplayControllerInfo(std::move(connector),
- std::move(crtc), i));
+ size_t index = std::find(connectors.begin(), connectors.end(), c.get()) -
+ connectors.begin();
+ DCHECK_LT(index, connectors.size());
+ displays.push_back(new HardwareDisplayControllerInfo(
+ std::move(c), std::move(crtc), index));
}
return displays;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698