summaryrefslogtreecommitdiff
path: root/chromium/ui/ozone/platform/drm/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/ozone/platform/drm/gpu')
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/DEPS1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.cc47
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.h22
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_display.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc42
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc13
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.cc10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc117
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h31
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc281
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.cc33
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc30
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc72
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc88
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h42
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/proxy_helpers.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/proxy_helpers.h31
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.cc350
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.h42
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc505
39 files changed, 1387 insertions, 481 deletions
diff --git a/chromium/ui/ozone/platform/drm/gpu/DEPS b/chromium/ui/ozone/platform/drm/gpu/DEPS
index 3fb5fa6f6a3..a4e9f0a5006 100644
--- a/chromium/ui/ozone/platform/drm/gpu/DEPS
+++ b/chromium/ui/ozone/platform/drm/gpu/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+media/media_buildflags.h",
"-ui/ozone/platform/drm",
"+ui/ozone/platform/drm/common",
"+ui/ozone/platform/drm/gpu",
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
index 8127e1633f2..6f4c17b6fa9 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.cc
@@ -9,6 +9,7 @@ namespace ui {
CrtcCommitRequest::CrtcCommitRequest(uint32_t crtc_id,
uint32_t connector_id,
drmModeModeInfo mode,
+ gfx::Point origin,
HardwareDisplayPlaneList* plane_list,
DrmOverlayPlaneList overlays,
bool should_enable)
@@ -16,8 +17,11 @@ CrtcCommitRequest::CrtcCommitRequest(uint32_t crtc_id,
crtc_id_(crtc_id),
connector_id_(connector_id),
mode_(mode),
+ origin_(origin),
plane_list_(plane_list),
overlays_(std::move(overlays)) {
+ // Verify that at least one overlay plane is a primary plane if we're enabling
+ // a CRTC.
DCHECK(!should_enable || DrmOverlayPlane::GetPrimaryPlane(overlays_));
}
@@ -28,6 +32,7 @@ CrtcCommitRequest::CrtcCommitRequest(const CrtcCommitRequest& other)
crtc_id_(other.crtc_id_),
connector_id_(other.connector_id_),
mode_(other.mode_),
+ origin_(other.origin_),
plane_list_(other.plane_list_),
overlays_(DrmOverlayPlane::Clone(other.overlays_)) {}
@@ -36,11 +41,12 @@ CrtcCommitRequest CrtcCommitRequest::EnableCrtcRequest(
uint32_t crtc_id,
uint32_t connector_id,
drmModeModeInfo mode,
+ gfx::Point origin,
HardwareDisplayPlaneList* plane_list,
DrmOverlayPlaneList overlays) {
DCHECK(plane_list && !overlays.empty());
- return CrtcCommitRequest(crtc_id, connector_id, mode, plane_list,
+ return CrtcCommitRequest(crtc_id, connector_id, mode, origin, plane_list,
std::move(overlays), /*should_enable=*/true);
}
@@ -49,7 +55,7 @@ CrtcCommitRequest CrtcCommitRequest::DisableCrtcRequest(
uint32_t crtc_id,
uint32_t connector_id,
HardwareDisplayPlaneList* plane_list) {
- return CrtcCommitRequest(crtc_id, connector_id, {}, plane_list,
+ return CrtcCommitRequest(crtc_id, connector_id, {}, gfx::Point(), plane_list,
DrmOverlayPlaneList(), /*should_enable=*/false);
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.h b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.h
index ad8eab84e7f..f3597f3bb31 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.h
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_commit_request.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include <xf86drmMode.h>
+#include "ui/gfx/geometry/point.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
@@ -31,6 +32,7 @@ class CrtcCommitRequest {
uint32_t crtc_id,
uint32_t connector_id,
drmModeModeInfo mode,
+ gfx::Point origin,
HardwareDisplayPlaneList* plane_list,
DrmOverlayPlaneList overlays);
@@ -43,6 +45,7 @@ class CrtcCommitRequest {
uint32_t crtc_id() const { return crtc_id_; }
uint32_t connector_id() const { return connector_id_; }
const drmModeModeInfo& mode() const { return mode_; }
+ const gfx::Point& origin() const { return origin_; }
HardwareDisplayPlaneList* plane_list() const { return plane_list_; }
const DrmOverlayPlaneList& overlays() const { return overlays_; }
@@ -50,6 +53,7 @@ class CrtcCommitRequest {
CrtcCommitRequest(uint32_t crtc_id,
uint32_t connector_id,
drmModeModeInfo mode,
+ gfx::Point origin,
HardwareDisplayPlaneList* plane_list,
DrmOverlayPlaneList overlays,
bool should_enable);
@@ -58,6 +62,7 @@ class CrtcCommitRequest {
const uint32_t crtc_id_ = 0;
const uint32_t connector_id_ = 0;
const drmModeModeInfo mode_ = {};
+ const gfx::Point origin_;
HardwareDisplayPlaneList* plane_list_ = nullptr;
const DrmOverlayPlaneList overlays_;
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
index cc5e8c5f213..6e262e27bbb 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -308,9 +308,15 @@ bool DrmDevice::SetCrtc(uint32_t crtc_id,
TRACE_EVENT2("drm", "DrmDevice::SetCrtc", "crtc", crtc_id, "size",
gfx::Size(mode.hdisplay, mode.vdisplay).ToString());
- return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, framebuffer, 0, 0,
- connectors.data(), connectors.size(),
- const_cast<drmModeModeInfo*>(&mode));
+
+ if (!drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, framebuffer, 0, 0,
+ connectors.data(), connectors.size(),
+ const_cast<drmModeModeInfo*>(&mode))) {
+ ++modeset_sequence_id_;
+ return true;
+ }
+
+ return false;
}
bool DrmDevice::DisableCrtc(uint32_t crtc_id) {
@@ -540,14 +546,45 @@ bool DrmDevice::CommitProperties(
uint32_t flags,
uint32_t crtc_count,
scoped_refptr<PageFlipRequest> page_flip_request) {
+ bool success = CommitPropertiesInternal(properties, flags, crtc_count,
+ page_flip_request);
+
+ if (success && flags == DRM_MODE_ATOMIC_ALLOW_MODESET)
+ ++modeset_sequence_id_;
+
+ return success;
+}
+
+bool DrmDevice::CommitPropertiesInternal(
+ drmModeAtomicReq* properties,
+ uint32_t flags,
+ uint32_t crtc_count,
+ scoped_refptr<PageFlipRequest> page_flip_request) {
uint64_t id = 0;
+
if (page_flip_request) {
flags |= DRM_MODE_PAGE_FLIP_EVENT;
id = page_flip_manager_->GetNextId();
}
- if (!drmModeAtomicCommit(file_.GetPlatformFile(), properties, flags,
- reinterpret_cast<void*>(id))) {
+ int result = drmModeAtomicCommit(file_.GetPlatformFile(), properties, flags,
+ reinterpret_cast<void*>(id));
+ if (result && errno == EBUSY && (flags & DRM_MODE_ATOMIC_NONBLOCK)) {
+ VLOG(1) << "Nonblocking atomic commit failed with EBUSY, retry without "
+ "nonblock";
+ // There have been cases where we get back EBUSY when attempting a
+ // non-blocking atomic commit. If we return false from here, that will cause
+ // the GPU process to CHECK itself. These are likely due to kernel bugs,
+ // which should be fixed, but rather than crashing we should retry the
+ // commit without the non-blocking flag and then it should work. This will
+ // cause a slight delay, but that should be imperceptible and better than
+ // crashing. We still do want the underlying driver bugs fixed, but this
+ // provide a better user experience.
+ flags &= ~DRM_MODE_ATOMIC_NONBLOCK;
+ result = drmModeAtomicCommit(file_.GetPlatformFile(), properties, flags,
+ reinterpret_cast<void*>(id));
+ }
+ if (!result) {
if (page_flip_request) {
page_flip_manager_->RegisterCallback(id, crtc_count,
page_flip_request->AddPageFlip());
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.h b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
index fdc7f2d0a38..400c9a80e66 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
@@ -215,11 +215,10 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
// On success, true is returned and |page_flip_request| will receive a
// callback signalling completion of the flip, if provided.
- virtual bool CommitProperties(
- drmModeAtomicReq* properties,
- uint32_t flags,
- uint32_t crtc_count,
- scoped_refptr<PageFlipRequest> page_flip_request);
+ bool CommitProperties(drmModeAtomicReq* properties,
+ uint32_t flags,
+ uint32_t crtc_count,
+ scoped_refptr<PageFlipRequest> page_flip_request);
virtual bool SetCapability(uint64_t capability, uint64_t value);
@@ -230,6 +229,8 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
virtual bool SetMaster();
virtual bool DropMaster();
+ int modeset_sequence_id() const { return modeset_sequence_id_; }
+
int get_fd() const { return file_.GetPlatformFile(); }
base::FilePath device_path() const { return device_path_; }
@@ -244,8 +245,19 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
virtual ~DrmDevice();
+ virtual bool CommitPropertiesInternal(
+ drmModeAtomicReq* properties,
+ uint32_t flags,
+ uint32_t crtc_count,
+ scoped_refptr<PageFlipRequest> page_flip_request);
+
std::unique_ptr<HardwareDisplayPlaneManager> plane_manager_;
+ // Sequence ID incremented at each modeset.
+ // Currently used by DRM Framebuffer to indicate when was the fb initialized
+ // wrt the preceding modeset.
+ int modeset_sequence_id_ = 0;
+
private:
class IOWatcher;
class PageFlipManager;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_display.cc b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
index 4f84ef488cf..b1ccd606e67 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_display.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
+#include "build/chromeos_buildflags.h"
#include "ui/display/display_features.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/gamma_ramp_rgb_entry.h"
@@ -156,7 +157,7 @@ std::unique_ptr<display::DisplaySnapshot> DrmDisplay::Update(
modes_ = GetDrmModeVector(info->connector());
is_hdr_capable_ =
params->bits_per_channel() > 8 && params->color_space().IsHDR();
-#if defined(OS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS_ASH)
is_hdr_capable_ =
is_hdr_capable_ &&
base::FeatureList::IsEnabled(display::features::kUseHDRTransferFunction);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.cc
index bdf7db0ec19..4eb71a4d0f7 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.cc
@@ -113,7 +113,8 @@ DrmFramebuffer::DrmFramebuffer(scoped_refptr<DrmDevice> drm_device,
opaque_framebuffer_pixel_format_(opaque_framebuffer_pixel_format),
format_modifier_(format_modifier),
preferred_modifiers_(modifiers),
- size_(size) {}
+ size_(size),
+ modeset_sequence_id_at_allocation_(drm_device_->modeset_sequence_id()) {}
DrmFramebuffer::~DrmFramebuffer() {
if (!drm_device_->RemoveFramebuffer(framebuffer_id_))
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
index 079297ac1a7..8dbfe7f2bd4 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
@@ -92,6 +92,10 @@ class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> {
// Device on which the buffer was created.
const scoped_refptr<DrmDevice>& drm_device() const { return drm_device_; }
+ int modeset_sequence_id_at_allocation() const {
+ return modeset_sequence_id_at_allocation_;
+ }
+
private:
~DrmFramebuffer();
@@ -110,6 +114,10 @@ class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> {
const std::vector<uint64_t> preferred_modifiers_;
const gfx::Size size_;
+ // The latest modeset sequence ID that was retrieved from DrmDevice when the
+ // buffer is initialized.
+ const int modeset_sequence_id_at_allocation_ = 0;
+
friend class base::RefCountedThreadSafe<DrmFramebuffer>;
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
index 8fdb11aba63..bd67bd3d60a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -166,9 +166,8 @@ void DrmGpuDisplayManager::RelinquishDisplayControl() {
drm->DropMaster();
}
-base::flat_map<int64_t, bool> DrmGpuDisplayManager::ConfigureDisplays(
+bool DrmGpuDisplayManager::ConfigureDisplays(
const std::vector<display::DisplayConfigurationParams>& config_requests) {
- base::flat_map<int64_t, bool> statuses;
ScreenManager::ControllerConfigsList controllers_to_configure;
for (const auto& config : config_requests) {
@@ -176,8 +175,7 @@ base::flat_map<int64_t, bool> DrmGpuDisplayManager::ConfigureDisplays(
DrmDisplay* display = FindDisplay(display_id);
if (!display) {
LOG(ERROR) << "There is no display with ID " << display_id;
- statuses.insert(std::make_pair(display_id, false));
- continue;
+ return false;
}
std::unique_ptr<drmModeModeInfo> mode_ptr =
@@ -185,8 +183,7 @@ base::flat_map<int64_t, bool> DrmGpuDisplayManager::ConfigureDisplays(
if (config.mode) {
if (!FindModeForDisplay(mode_ptr.get(), *config.mode.value(),
display->modes(), displays_)) {
- statuses.insert(std::make_pair(display_id, false));
- continue;
+ return false;
}
}
@@ -205,41 +202,30 @@ base::flat_map<int64_t, bool> DrmGpuDisplayManager::ConfigureDisplays(
controllers_to_configure.push_back(std::move(params));
}
- if (controllers_to_configure.empty())
- return statuses;
-
if (clear_overlay_cache_callback_)
clear_overlay_cache_callback_.Run();
- auto config_statuses =
+ bool config_success =
screen_manager_->ConfigureDisplayControllers(controllers_to_configure);
- for (const auto& status : config_statuses) {
- int64_t display_id = status.first;
- bool success = status.second;
- DrmDisplay* display = FindDisplay(display_id);
- auto config = std::find_if(
- config_requests.begin(), config_requests.end(),
- [display_id](const auto& request) { return request.id == display_id; });
- if (success) {
- display->SetOrigin(config->origin);
+ for (const auto& controller : controllers_to_configure) {
+ if (config_success) {
+ FindDisplay(controller.display_id)->SetOrigin(controller.origin);
} else {
- if (config->mode) {
+ if (controller.mode) {
VLOG(1) << "Failed to enable device="
- << display->drm()->device_path().value()
- << " crtc=" << display->crtc()
- << " connector=" << display->connector();
+ << controller.drm->device_path().value()
+ << " crtc=" << controller.crtc
+ << " connector=" << controller.connector;
} else {
VLOG(1) << "Failed to disable device="
- << display->drm()->device_path().value()
- << " crtc=" << display->crtc();
+ << controller.drm->device_path().value()
+ << " crtc=" << controller.crtc;
}
}
-
- statuses.insert(std::make_pair(display_id, success));
}
- return statuses;
+ return config_success;
}
bool DrmGpuDisplayManager::GetHDCPState(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index 2dbe2ba68a4..5bbdc84144e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -52,7 +52,7 @@ class DrmGpuDisplayManager {
bool TakeDisplayControl();
void RelinquishDisplayControl();
- base::flat_map<int64_t, bool> ConfigureDisplays(
+ bool ConfigureDisplays(
const std::vector<display::DisplayConfigurationParams>& config_requests);
bool GetHDCPState(int64_t display_id,
display::HDCPState* state,
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
index 231d1728494..928ad048588 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.cc
@@ -40,7 +40,10 @@ std::vector<OverlaySurfaceCandidate> ToCacheKey(
} // namespace
-DrmOverlayManager::DrmOverlayManager() {
+DrmOverlayManager::DrmOverlayManager(
+ bool allow_sync_and_real_buffer_page_flip_testing) {
+ allow_sync_and_real_buffer_page_flip_testing_ =
+ allow_sync_and_real_buffer_page_flip_testing;
DETACH_FROM_THREAD(thread_checker_);
}
@@ -79,7 +82,8 @@ void DrmOverlayManager::CheckOverlaySupport(
result_candidates.back().overlay_handled = can_handle;
}
- if (features::IsSynchronousPageFlipTestingEnabled()) {
+ if (allow_sync_and_real_buffer_page_flip_testing_ &&
+ features::IsSynchronousPageFlipTestingEnabled()) {
std::vector<OverlayStatus> status =
SendOverlayValidationRequestSync(result_candidates, widget);
size_t size = candidates->size();
@@ -145,6 +149,11 @@ bool DrmOverlayManager::CanHandleCandidate(
if (candidate.transform == gfx::OVERLAY_TRANSFORM_INVALID)
return false;
+ // The remaining checks are for ensuring consistency between GL compositing
+ // and overlays. If we must use an overlay, then skip the remaining checks.
+ if (candidate.requires_overlay)
+ return true;
+
// Reject candidates that don't fall on a pixel boundary.
if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f))
return false;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
index 87173fa824a..56112a3f508 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager.h
@@ -23,7 +23,8 @@ class OverlaySurfaceCandidate;
// of recent configurations.
class DrmOverlayManager : public OverlayManagerOzone {
public:
- DrmOverlayManager();
+ explicit DrmOverlayManager(
+ bool allow_sync_and_real_buffer_page_flip_testing = true);
~DrmOverlayManager() override;
// OverlayManagerOzone:
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
index 2137523fbd8..89c86a5f80e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.cc
@@ -8,13 +8,17 @@
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
+#include "ui/ozone/platform/drm/gpu/drm_overlay_manager.h"
#include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h"
#include "ui/ozone/public/overlay_surface_candidate.h"
namespace ui {
-DrmOverlayManagerGpu::DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy)
- : drm_thread_proxy_(drm_thread_proxy) {}
+DrmOverlayManagerGpu::DrmOverlayManagerGpu(
+ DrmThreadProxy* drm_thread_proxy,
+ bool allow_sync_and_real_buffer_page_flip_testing)
+ : DrmOverlayManager(allow_sync_and_real_buffer_page_flip_testing),
+ drm_thread_proxy_(drm_thread_proxy) {}
DrmOverlayManagerGpu::~DrmOverlayManagerGpu() = default;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
index 3931e02dac5..cb759538344 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_manager_gpu.h
@@ -18,7 +18,9 @@ class DrmThreadProxy;
// overlay validations requests to the DRM thread.
class DrmOverlayManagerGpu : public DrmOverlayManager {
public:
- explicit DrmOverlayManagerGpu(DrmThreadProxy* drm_thread_proxy);
+ explicit DrmOverlayManagerGpu(
+ DrmThreadProxy* drm_thread_proxy,
+ bool allow_sync_and_real_buffer_page_flip_testing);
~DrmOverlayManagerGpu() override;
private:
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
index 4c496547411..348cba77ec8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -46,7 +46,7 @@ scoped_refptr<DrmFramebuffer> GetBufferForPageFlipTest(
// flip commits.
std::vector<uint64_t> modifiers =
is_0th_plane
- ? drm_window->GetController()->GetFormatModifiers(fourcc_format)
+ ? drm_window->GetController()->GetSupportedModifiers(fourcc_format)
: std::vector<uint64_t>();
// Check if we can re-use existing buffers.
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
index 76577c6e485..f5938777c47 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -81,15 +81,16 @@ class DrmOverlayValidatorTest : public testing::Test {
bool ModesetController(ui::HardwareDisplayController* controller) {
ui::CommitRequest commit_request;
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
- controller->GetModesetProps(&commit_request, plane, kDefaultMode);
+ controller->GetModesetProps(&commit_request, modeset_planes, kDefaultMode);
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller->UpdateState(
- /*enable_requested=*/true,
- ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays()));
+
+ for (const ui::CrtcCommitRequest& crtc_request : commit_request)
+ controller->UpdateState(crtc_request);
return status;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index d77131c3dfc..115231c7d02 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -142,7 +142,7 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
std::vector<uint64_t> modifiers;
if (window && window->GetController() && !(flags & GBM_BO_USE_LINEAR) &&
!(client_flags & GbmPixmap::kFlagNoModifiers)) {
- modifiers = window->GetController()->GetFormatModifiers(fourcc_format);
+ modifiers = window->GetController()->GetSupportedModifiers(fourcc_format);
}
CreateBufferWithGbmFlags(drm, fourcc_format, size, framebuffer_size, flags,
@@ -328,13 +328,11 @@ void DrmThread::RefreshNativeDisplays(
void DrmThread::ConfigureNativeDisplays(
const std::vector<display::DisplayConfigurationParams>& config_requests,
- base::OnceCallback<void(const base::flat_map<int64_t, bool>&)> callback) {
+ base::OnceCallback<void(bool)> callback) {
TRACE_EVENT0("drm", "DrmThread::ConfigureNativeDisplays");
- base::flat_map<int64_t, bool> statuses =
- display_manager_->ConfigureDisplays(config_requests);
-
- std::move(callback).Run(statuses);
+ bool config_success = display_manager_->ConfigureDisplays(config_requests);
+ std::move(callback).Run(config_success);
}
void DrmThread::TakeDisplayControl(base::OnceCallback<void(bool)> callback) {
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index fa04ef64c35..f2774c1e4aa 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/linux/gbm_wrapper.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
index ec3aa6b951d..d83a4f53d8b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -31,11 +31,9 @@ DrmWindow::DrmWindow(gfx::AcceleratedWidget widget,
ScreenManager* screen_manager)
: widget_(widget),
device_manager_(device_manager),
- screen_manager_(screen_manager) {
-}
+ screen_manager_(screen_manager) {}
-DrmWindow::~DrmWindow() {
-}
+DrmWindow::~DrmWindow() {}
void DrmWindow::Initialize() {
TRACE_EVENT1("drm", "DrmWindow::Initialize", "widget", widget_);
@@ -133,10 +131,6 @@ OverlayStatusList DrmWindow::TestPageFlip(
last_submitted_planes_);
}
-const DrmOverlayPlane* DrmWindow::GetLastModesetBuffer() const {
- return DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes_);
-}
-
void DrmWindow::UpdateCursorImage() {
if (!controller_)
return;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.h b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
index ea2a2721408..ea1ef54b324 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
@@ -84,8 +84,9 @@ class DrmWindow {
OverlayStatusList TestPageFlip(
const OverlaySurfaceCandidateList& overlay_params);
- // Returns the last buffer associated with this window.
- const DrmOverlayPlane* GetLastModesetBuffer() const;
+ const DrmOverlayPlaneList& last_submitted_planes() const {
+ return last_submitted_planes_;
+ }
private:
// Draw next frame in an animated cursor.
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index 163a89f699c..2fdc72f9a49 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -12,6 +12,7 @@
#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "third_party/khronos/EGL/egl.h"
#include "ui/gfx/buffer_format_util.h"
@@ -20,6 +21,7 @@
#include "ui/gfx/linux/gbm_defines.h"
#include "ui/gfx/linux/scoped_gbm_device.h"
#include "ui/gfx/native_pixmap.h"
+#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/common/gl_ozone_egl.h"
@@ -275,8 +277,11 @@ GLOzone* GbmSurfaceFactory::GetGLOzone(gl::GLImplementation implementation) {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
-GbmSurfaceFactory::CreateVulkanImplementation(bool allow_protected_memory,
+GbmSurfaceFactory::CreateVulkanImplementation(bool use_swiftshader,
+ bool allow_protected_memory,
bool enforce_protected_memory) {
+ DCHECK(!use_swiftshader)
+ << "Vulkan Swiftshader is not supported on this platform.";
return std::make_unique<ui::VulkanImplementationGbm>();
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
index 4ac05739713..4aa40139d7d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
@@ -39,6 +39,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation(
+ bool use_swiftshader,
bool allow_protected_memory,
bool enforce_protected_memory) override;
scoped_refptr<gfx::NativePixmap> CreateNativePixmapForVulkan(
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 664381d52a2..67cb75493b6 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -15,12 +15,17 @@
#include "base/trace_event/trace_event.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/presentation_feedback.h"
+#include "ui/gl/gl_bindings.h"
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
+#if BUILDFLAG(USE_OPENGL_APITRACE)
+#include "ui/gl/gl_implementation.h"
+#endif
+
namespace ui {
namespace {
@@ -133,6 +138,10 @@ void GbmSurfaceless::SwapBuffersAsync(
glFlush();
}
+#if BUILDFLAG(USE_OPENGL_APITRACE)
+ gl::TerminateFrame(); // Notify end of frame at buffer swap request.
+#endif
+
unsubmitted_frames_.back()->Flush();
PendingFrame* frame = unsubmitted_frames_.back().get();
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index 47a684e7d22..ed387cbc7dc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -16,9 +16,11 @@
#include "base/trace_event/trace_event.h"
#include "third_party/libdrm/src/include/drm/drm_fourcc.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/linux/drm_util_linux.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
@@ -58,7 +60,7 @@ void DrawCursor(DrmDumbBuffer* cursor, const SkBitmap& image) {
// Clear to transparent in case |image| is smaller than the canvas.
SkCanvas* canvas = cursor->GetCanvas();
canvas->clear(SK_ColorTRANSPARENT);
- canvas->drawBitmapRect(image, damage, nullptr);
+ canvas->drawImageRect(image.asImage(), damage, SkSamplingOptions());
}
} // namespace
@@ -73,26 +75,26 @@ HardwareDisplayController::HardwareDisplayController(
HardwareDisplayController::~HardwareDisplayController() = default;
-void HardwareDisplayController::GetModesetProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
- const drmModeModeInfo& mode) {
- TRACE_EVENT0("drm", "HDC::GetModesetProps");
- GetModesetPropsForCrtcs(commit_request, primary,
+void HardwareDisplayController::GetModesetProps(
+ CommitRequest* commit_request,
+ const DrmOverlayPlaneList& modeset_planes,
+ const drmModeModeInfo& mode) {
+ GetModesetPropsForCrtcs(commit_request, modeset_planes,
/*use_current_crtc_mode=*/false, mode);
}
-void HardwareDisplayController::GetEnableProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary) {
- TRACE_EVENT0("drm", "HDC::GetEnableProps");
+void HardwareDisplayController::GetEnableProps(
+ CommitRequest* commit_request,
+ const DrmOverlayPlaneList& modeset_planes) {
// TODO(markyacoub): Simplify and remove the use of empty_mode.
drmModeModeInfo empty_mode = {};
- GetModesetPropsForCrtcs(commit_request, primary,
+ GetModesetPropsForCrtcs(commit_request, modeset_planes,
/*use_current_crtc_mode=*/true, empty_mode);
}
void HardwareDisplayController::GetModesetPropsForCrtcs(
CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
bool use_current_crtc_mode,
const drmModeModeInfo& mode) {
DCHECK(commit_request);
@@ -103,19 +105,16 @@ void HardwareDisplayController::GetModesetPropsForCrtcs(
drmModeModeInfo modeset_mode =
use_current_crtc_mode ? controller->mode() : mode;
- DrmOverlayPlaneList overlays;
- overlays.push_back(primary.Clone());
+ DrmOverlayPlaneList overlays = DrmOverlayPlane::Clone(modeset_planes);
CrtcCommitRequest request = CrtcCommitRequest::EnableCrtcRequest(
- controller->crtc(), controller->connector(), modeset_mode,
+ controller->crtc(), controller->connector(), modeset_mode, origin_,
&owned_hardware_planes_, std::move(overlays));
commit_request->push_back(std::move(request));
}
}
void HardwareDisplayController::GetDisableProps(CommitRequest* commit_request) {
- TRACE_EVENT0("drm", "HDC::GetDisableProps");
-
for (const auto& controller : crtc_controllers_) {
CrtcCommitRequest request = CrtcCommitRequest::DisableCrtcRequest(
controller->crtc(), controller->connector(), &owned_hardware_planes_);
@@ -124,14 +123,13 @@ void HardwareDisplayController::GetDisableProps(CommitRequest* commit_request) {
}
void HardwareDisplayController::UpdateState(
- bool enable_requested,
- const DrmOverlayPlane* primary_plane) {
+ const CrtcCommitRequest& crtc_request) {
// Verify that the current state matches the requested state.
- if (enable_requested && IsEnabled()) {
- DCHECK(primary_plane);
+ if (crtc_request.should_enable() && IsEnabled()) {
+ DCHECK(!crtc_request.overlays().empty());
// TODO(markyacoub): This should be absorbed in the commit request.
ResetCursor();
- OnModesetComplete(*primary_plane);
+ OnModesetComplete(crtc_request.overlays());
}
}
@@ -146,6 +144,24 @@ void HardwareDisplayController::SchedulePageFlip(
bool status =
ScheduleOrTestPageFlip(plane_list, page_flip_request, &out_fence);
+ if (!status) {
+ for (const auto& plane : plane_list) {
+ // If the page flip failed and we see that the buffer has been allocated
+ // before the latest modeset, it could mean it was an in-flight buffer
+ // carrying an obsolete configuration.
+ // Request a buffer reallocation to reflect the new change.
+ if (plane.buffer &&
+ plane.buffer->modeset_sequence_id_at_allocation() <
+ plane.buffer->drm_device()->modeset_sequence_id()) {
+ std::move(submission_callback)
+ .Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, nullptr);
+ std::move(presentation_callback)
+ .Run(gfx::PresentationFeedback::Failure());
+ return;
+ }
+ }
+ }
+
CHECK(status) << "SchedulePageFlip failed";
if (page_flip_request->page_flip_count() == 0) {
@@ -204,17 +220,16 @@ bool HardwareDisplayController::ScheduleOrTestPageFlip(
}
std::vector<uint64_t> HardwareDisplayController::GetFormatModifiers(
- uint32_t format) const {
- std::vector<uint64_t> modifiers;
-
+ uint32_t fourcc_format) const {
if (crtc_controllers_.empty())
- return modifiers;
+ return std::vector<uint64_t>();
- modifiers = crtc_controllers_[0]->GetFormatModifiers(format);
+ std::vector<uint64_t> modifiers =
+ crtc_controllers_[0]->GetFormatModifiers(fourcc_format);
for (size_t i = 1; i < crtc_controllers_.size(); ++i) {
std::vector<uint64_t> other =
- crtc_controllers_[i]->GetFormatModifiers(format);
+ crtc_controllers_[i]->GetFormatModifiers(fourcc_format);
std::vector<uint64_t> intersection;
std::set_intersection(modifiers.begin(), modifiers.end(), other.begin(),
@@ -225,11 +240,26 @@ std::vector<uint64_t> HardwareDisplayController::GetFormatModifiers(
return modifiers;
}
-std::vector<uint64_t>
-HardwareDisplayController::GetFormatModifiersForModesetting(
+std::vector<uint64_t> HardwareDisplayController::GetSupportedModifiers(
uint32_t fourcc_format) const {
- const auto& modifiers = GetFormatModifiers(fourcc_format);
+ if (preferred_format_modifier_.empty())
+ return std::vector<uint64_t>();
+
+ auto it = preferred_format_modifier_.find(fourcc_format);
+ if (it != preferred_format_modifier_.end())
+ return std::vector<uint64_t>{it->second};
+
+ return GetFormatModifiers(fourcc_format);
+}
+
+std::vector<uint64_t>
+HardwareDisplayController::GetFormatModifiersForTestModeset(
+ uint32_t fourcc_format) {
+ // If we're about to test, clear the current preferred modifier.
+ preferred_format_modifier_.clear();
+
std::vector<uint64_t> filtered_modifiers;
+ const auto& modifiers = GetFormatModifiers(fourcc_format);
for (auto modifier : modifiers) {
// AFBC for modeset buffers doesn't work correctly, as we can't fill it with
// a valid AFBC buffer. For now, don't use AFBC for modeset buffers.
@@ -242,6 +272,18 @@ HardwareDisplayController::GetFormatModifiersForModesetting(
return filtered_modifiers;
}
+void HardwareDisplayController::UpdatePreferredModiferForFormat(
+ gfx::BufferFormat buffer_format,
+ uint64_t modifier) {
+ uint32_t fourcc_format = GetFourCCFormatFromBufferFormat(buffer_format);
+ base::InsertOrAssign(preferred_format_modifier_, fourcc_format, modifier);
+
+ uint32_t opaque_fourcc_format =
+ GetFourCCFormatForOpaqueFramebuffer(buffer_format);
+ base::InsertOrAssign(preferred_format_modifier_, opaque_fourcc_format,
+ modifier);
+}
+
void HardwareDisplayController::MoveCursor(const gfx::Point& location) {
cursor_location_ = location;
UpdateCursorLocation();
@@ -368,22 +410,21 @@ void HardwareDisplayController::OnPageFlipComplete(
time_of_last_flip_ = presentation_feedback.timestamp;
current_planes_ = std::move(pending_planes);
for (const auto& controller : crtc_controllers_) {
- GetDrmDevice()->plane_manager()->ResetModesetBufferOfCrtc(
+ GetDrmDevice()->plane_manager()->ResetModesetStateForCrtc(
controller->crtc());
}
page_flip_request_ = nullptr;
}
void HardwareDisplayController::OnModesetComplete(
- const DrmOverlayPlane& primary) {
- // drmModeSetCrtc has an immediate effect, so we can assume that the current
- // planes have been updated. However if a page flip is still pending, set the
- // pending planes to the same values so that the callback keeps the correct
- // state.
+ const DrmOverlayPlaneList& modeset_planes) {
+ // Modesetting is blocking so it has an immediate effect. We can assume that
+ // the current planes have been updated. However, if a page flip is still
+ // pending, set the pending planes to the same values so that the callback
+ // keeps the correct state.
page_flip_request_ = nullptr;
owned_hardware_planes_.legacy_page_flips.clear();
- current_planes_.clear();
- current_planes_.push_back(primary.Clone());
+ current_planes_ = DrmOverlayPlane::Clone(modeset_planes);
time_of_last_flip_ = base::TimeTicks::Now();
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 17a917183ae..27e4dd4bcbf 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -14,9 +14,11 @@
#include <vector>
#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/buffer_types.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
@@ -96,15 +98,15 @@ class HardwareDisplayController {
// Gets the props required to modeset a CRTC with a |mode| onto
// |commit_request|.
void GetModesetProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
const drmModeModeInfo& mode);
// Gets the props required to enable/disable a CRTC onto |commit_request|.
void GetEnableProps(CommitRequest* commit_request,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
void GetDisableProps(CommitRequest* commit_request);
// Updates state of the controller after modeset/enable/disable is performed.
- void UpdateState(bool enable_requested, const DrmOverlayPlane* primary_plane);
+ void UpdateState(const CrtcCommitRequest& crtc_request);
// Schedules the |overlays|' framebuffers to be displayed on the next vsync
// event. The event will be posted on the graphics card file descriptor |fd_|
@@ -128,17 +130,19 @@ class HardwareDisplayController {
// doesn't change any state.
bool TestPageFlip(const DrmOverlayPlaneList& plane_list);
- // Return the supported modifiers for |fourcc_format| for this
- // controller.
- std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format) const;
+ // Return the supported modifiers for |fourcc_format| for this controller.
+ std::vector<uint64_t> GetSupportedModifiers(uint32_t fourcc_format) const;
// Return the supported modifiers for |fourcc_format| for this
// controller to be used for modeset buffers. Currently, this only exists
// because we can't provide valid AFBC buffers during modeset.
// See https://crbug.com/852675
// TODO: Remove this.
- std::vector<uint64_t> GetFormatModifiersForModesetting(
- uint32_t fourcc_format) const;
+ std::vector<uint64_t> GetFormatModifiersForTestModeset(
+ uint32_t fourcc_format);
+
+ void UpdatePreferredModiferForFormat(gfx::BufferFormat buffer_format,
+ uint64_t modifier);
// Moves the hardware cursor to |location|.
void MoveCursor(const gfx::Point& location);
@@ -175,10 +179,10 @@ class HardwareDisplayController {
// Loops over |crtc_controllers_| and save their props into |commit_request|
// to be enabled/modeset.
void GetModesetPropsForCrtcs(CommitRequest* commit_request,
- const DrmOverlayPlane& primary,
+ const DrmOverlayPlaneList& modeset_planes,
bool use_current_crtc_mode,
const drmModeModeInfo& mode);
- void OnModesetComplete(const DrmOverlayPlane& primary);
+ void OnModesetComplete(const DrmOverlayPlaneList& modeset_planes);
bool ScheduleOrTestPageFlip(const DrmOverlayPlaneList& plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence);
@@ -189,6 +193,8 @@ class HardwareDisplayController {
void ResetCursor();
void DisableCursor();
+ std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format) const;
+
HardwareDisplayPlaneList owned_hardware_planes_;
// Stores the CRTC configuration. This is used to identify monitors and
@@ -207,6 +213,11 @@ class HardwareDisplayController {
int cursor_frontbuffer_ = 0;
DrmDumbBuffer* current_cursor_ = nullptr;
+ // Maps each fourcc_format to its preferred modifier which was generated
+ // through modeset-test and updated in UpdatePreferredModifierForFormat().
+ base::flat_map<uint32_t /*fourcc_format*/, uint64_t /*preferred_modifier*/>
+ preferred_format_modifier_;
+
base::WeakPtrFactory<HardwareDisplayController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
index 739c8dd5d62..7cc0dddf155 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -123,7 +124,7 @@ class HardwareDisplayControllerTest : public testing::Test {
}
protected:
- bool ModesetWithPlane(const ui::DrmOverlayPlane& plane);
+ bool ModesetWithPlanes(const ui::DrmOverlayPlaneList& modeset_planes);
bool DisableController();
std::unique_ptr<ui::HardwareDisplayController> controller_;
@@ -242,16 +243,15 @@ void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) {
gfx::Point());
}
-bool HardwareDisplayControllerTest::ModesetWithPlane(
- const ui::DrmOverlayPlane& plane) {
+bool HardwareDisplayControllerTest::ModesetWithPlanes(
+ const ui::DrmOverlayPlaneList& modeset_planes) {
ui::CommitRequest commit_request;
- controller_->GetModesetProps(&commit_request, plane, kDefaultMode);
+ controller_->GetModesetProps(&commit_request, modeset_planes, kDefaultMode);
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller_->UpdateState(
- /*enable_requested=*/true,
- ui::DrmOverlayPlane::GetPrimaryPlane(request_for_update[0].overlays()));
+ for (const ui::CrtcCommitRequest& crtc_request : commit_request)
+ controller_->UpdateState(crtc_request);
return status;
}
@@ -262,7 +262,8 @@ bool HardwareDisplayControllerTest::DisableController() {
ui::CommitRequest request_for_update = commit_request;
bool status = drm_->plane_manager()->Commit(std::move(commit_request),
DRM_MODE_ATOMIC_ALLOW_MODESET);
- controller_->UpdateState(/*enable_requested=*/false, nullptr);
+ for (const ui::CrtcCommitRequest& crtc_request : commit_request)
+ controller_->UpdateState(crtc_request);
return status;
}
@@ -301,15 +302,18 @@ uint64_t HardwareDisplayControllerTest::GetPlanePropertyValue(
}
TEST_F(HardwareDisplayControllerTest, CheckModesettingResult) {
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane));
- EXPECT_FALSE(plane.buffer->HasOneRef());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
+ EXPECT_FALSE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->HasOneRef());
}
TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr crtc_props =
drm_->GetObjectProperties(kPrimaryCrtc, DRM_MODE_OBJECT_CRTC);
@@ -328,8 +332,9 @@ TEST_F(HardwareDisplayControllerTest, CrtcPropsAfterModeset) {
}
TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr connector_props =
drm_->GetObjectProperties(kConnectorIdBase, DRM_MODE_OBJECT_CONNECTOR);
@@ -343,11 +348,15 @@ TEST_F(HardwareDisplayControllerTest, ConnectorPropsAfterModeset) {
TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
const FakeFenceFD fake_fence_fd;
- ui::DrmOverlayPlane plane1(CreateBuffer(), fake_fence_fd.GetGpuFence());
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), fake_fence_fd.GetGpuFence());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
ui::ScopedDrmObjectPropertyPtr plane_props =
drm_->GetObjectProperties(kPlaneOffset, DRM_MODE_OBJECT_PLANE);
+ const ui::DrmOverlayPlane* primary_plane =
+ ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes);
+
{
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_ID", &prop);
@@ -358,13 +367,13 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_X", &prop);
EXPECT_EQ(kCrtcX, prop.id);
- EXPECT_EQ(plane1.display_bounds.x(), static_cast<int>(prop.value));
+ EXPECT_EQ(primary_plane->display_bounds.x(), static_cast<int>(prop.value));
}
{
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "CRTC_Y", &prop);
EXPECT_EQ(kCrtcY, prop.id);
- EXPECT_EQ(plane1.display_bounds.y(), static_cast<int>(prop.value));
+ EXPECT_EQ(primary_plane->display_bounds.y(), static_cast<int>(prop.value));
}
{
ui::DrmDevice::Property prop = {};
@@ -382,13 +391,13 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
ui::DrmDevice::Property prop = {};
ui::GetDrmPropertyForName(drm_.get(), plane_props.get(), "FB_ID", &prop);
EXPECT_EQ(kPlaneFbId, prop.id);
- EXPECT_EQ(plane1.buffer->opaque_framebuffer_id(),
+ EXPECT_EQ(primary_plane->buffer->opaque_framebuffer_id(),
static_cast<uint32_t>(prop.value));
}
- gfx::RectF crop_rectf = plane1.crop_rect;
- crop_rectf.Scale(plane1.buffer->size().width(),
- plane1.buffer->size().height());
+ gfx::RectF crop_rectf = primary_plane->crop_rect;
+ crop_rectf.Scale(primary_plane->buffer->size().width(),
+ primary_plane->buffer->size().height());
gfx::Rect crop_rect = gfx::ToNearestRect(crop_rectf);
gfx::Rect fixed_point_rect =
gfx::Rect(crop_rect.x() << 16, crop_rect.y() << 16,
@@ -427,8 +436,10 @@ TEST_F(HardwareDisplayControllerTest, PlanePropsAfterModeset) {
}
TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
+ modeset_planes.push_back(plane.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test invalid fence fd
{
@@ -443,9 +454,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
}
const FakeFenceFD fake_fence_fd;
- plane1.gpu_fence = fake_fence_fd.GetGpuFence();
+ plane.gpu_fence = fake_fence_fd.GetGpuFence();
std::vector<ui::DrmOverlayPlane> planes = {};
- planes.push_back(plane1.Clone());
+ planes.push_back(plane.Clone());
SchedulePageFlip(std::move(planes));
// Verify fence FD after a GPU Fence is added to the plane.
@@ -460,8 +471,10 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
static_cast<int>(fence_fd_prop.value));
}
- plane1.gpu_fence = nullptr;
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ plane.gpu_fence = nullptr;
+ modeset_planes.clear();
+ modeset_planes.push_back(plane.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test an invalid FD again after the fence is removed.
{
@@ -477,9 +490,9 @@ TEST_F(HardwareDisplayControllerTest, FenceFdValueChange) {
}
TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
-
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
// Test props values after disabling.
DisableController();
@@ -581,20 +594,21 @@ TEST_F(HardwareDisplayControllerTest, CheckDisableResetsProps) {
}
TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
-
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
EXPECT_EQ(1, drm_->get_commit_count());
- ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane2.Clone());
+ ui::DrmOverlayPlane page_flip_plane(CreateBuffer(), nullptr);
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.push_back(page_flip_plane.Clone());
- SchedulePageFlip(std::move(planes));
+ SchedulePageFlip(std::move(page_flip_planes));
drm_->RunCallbacks();
- EXPECT_TRUE(plane1.buffer->HasOneRef());
- EXPECT_FALSE(plane2.buffer->HasOneRef());
+ EXPECT_TRUE(ui::DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->HasOneRef());
+ EXPECT_FALSE(page_flip_plane.buffer->HasOneRef());
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
@@ -608,24 +622,21 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfModesetFails) {
InitializeDrmDevice(/* use_atomic */ false);
drm_->set_set_crtc_expectation(false);
- ui::DrmOverlayPlane plane(CreateBuffer(), nullptr);
-
- EXPECT_FALSE(ModesetWithPlane(plane));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_FALSE(ModesetWithPlanes(modeset_planes));
}
TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
-
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -637,18 +648,15 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
}
TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
-
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
EXPECT_EQ(2, drm_->get_commit_count());
// Verify both planes on the primary display have a valid framebuffer.
@@ -674,16 +682,13 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayTestMode) {
}
TEST_F(HardwareDisplayControllerTest, AcceptUnderlays) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- ui::DrmOverlayPlane plane2(CreateBuffer(), -1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kDefaultModeSize),
- gfx::RectF(kDefaultModeSizeF), true, nullptr);
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ planes.emplace_back(CreateBuffer(), -1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kDefaultModeSize),
+ gfx::RectF(kDefaultModeSizeF), true, nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
-
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
+ EXPECT_TRUE(ModesetWithPlanes(planes));
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
@@ -695,13 +700,12 @@ TEST_F(HardwareDisplayControllerTest, PageflipMirroredControllers) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+
+ EXPECT_TRUE(ModesetWithPlanes(planes));
EXPECT_EQ(1, drm_->get_commit_count());
- ui::DrmOverlayPlane plane2(CreateBuffer(), nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane2.Clone());
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -720,10 +724,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -762,10 +766,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
}
TEST_F(HardwareDisplayControllerTest, PlaneStateAfterDestroyingCrtc) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -790,10 +794,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) {
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
drm_.get(), kSecondaryCrtc, kConnectorIdBase + 1));
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -835,39 +839,52 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterAddCrtc) {
}
TEST_F(HardwareDisplayControllerTest, ModesetWhilePageFlipping) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- SchedulePageFlip(std::move(planes));
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes));
+
+ EXPECT_TRUE(ModesetWithPlanes(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
}
TEST_F(HardwareDisplayControllerTest, FailPageFlipping) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(modeset_planes));
+
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.emplace_back(CreateBuffer(), nullptr);
drm_->set_commit_expectation(false);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(planes)),
+ EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(page_flip_planes)),
"SchedulePageFlip failed");
}
-TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) {
- ui::DrmOverlayPlane modeset_primary_plane(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(modeset_primary_plane));
-
- ui::DrmOverlayPlane plane1(CreateBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kDefaultModeSize),
- gfx::RectF(0, 0, 1, 1), true, nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+TEST_F(HardwareDisplayControllerTest,
+ RecreateBuffersOnOldPlanesPageFlipFailure) {
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(planes));
+
+ drm_->set_commit_expectation(false);
SchedulePageFlip(std::move(planes));
+ EXPECT_EQ(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, last_swap_result_);
+}
+
+TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) {
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(modeset_planes));
+
+ std::vector<ui::DrmOverlayPlane> page_flip_planes;
+ page_flip_planes.emplace_back(CreateBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kDefaultModeSize),
+ gfx::RectF(0, 0, 1, 1), true, nullptr);
+ SchedulePageFlip(std::move(page_flip_planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -875,10 +892,10 @@ TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlaneOnFlip) {
}
TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
controller_->AddCrtc(std::make_unique<ui::CrtcController>(
@@ -890,10 +907,10 @@ TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
}
TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+
SchedulePageFlip(std::move(planes));
controller_->RemoveCrtc(drm_, kPrimaryCrtc);
@@ -907,16 +924,13 @@ TEST_F(HardwareDisplayControllerTest, Disable) {
// Page flipping overlays is only supported on atomic configurations.
InitializeDrmDevice(/* use_atomic= */ true);
- ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr);
- EXPECT_TRUE(ModesetWithPlane(plane1));
-
- ui::DrmOverlayPlane plane2(
- CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF), true, nullptr);
- std::vector<ui::DrmOverlayPlane> planes;
- planes.push_back(plane1.Clone());
- planes.push_back(plane2.Clone());
+ ui::DrmOverlayPlaneList planes;
+ planes.emplace_back(CreateBuffer(), nullptr);
+ EXPECT_TRUE(ModesetWithPlanes(planes));
+ planes.emplace_back(CreateOverlayBuffer(), 1, gfx::OVERLAY_TRANSFORM_NONE,
+ gfx::Rect(kOverlaySize), gfx::RectF(kDefaultModeSizeF),
+ true, nullptr);
SchedulePageFlip(std::move(planes));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
@@ -931,3 +945,20 @@ TEST_F(HardwareDisplayControllerTest, Disable) {
// No plane should be in use.
ASSERT_EQ(0, planes_in_use);
}
+
+TEST_F(HardwareDisplayControllerTest, MultiplePlanesModeset) {
+ ui::DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ modeset_planes.emplace_back(CreateBuffer(), nullptr);
+ ASSERT_TRUE(ModesetWithPlanes(modeset_planes));
+ EXPECT_EQ(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers.size(),
+ 2UL);
+ for (const auto& plane : modeset_planes) {
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ plane.buffer));
+ }
+}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.cc
index acff6ed2116..a24b5b83e70 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.cc
@@ -4,7 +4,10 @@
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h"
+#include <drm_fourcc.h>
+
#include "base/logging.h"
+#include "media/media_buildflags.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"
@@ -20,12 +23,15 @@ uint32_t OverlayTransformToDrmRotationPropertyValue(
return DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_0;
case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
return DRM_MODE_REFLECT_Y | DRM_MODE_ROTATE_0;
+ // Driver code swaps 90 and 270 to be compliant with how xrandr uses these
+ // values, so we need to invert them here as well to get them back to the
+ // proper value.
case gfx::OVERLAY_TRANSFORM_ROTATE_90:
- return DRM_MODE_ROTATE_90;
+ return DRM_MODE_ROTATE_270;
case gfx::OVERLAY_TRANSFORM_ROTATE_180:
return DRM_MODE_ROTATE_180;
case gfx::OVERLAY_TRANSFORM_ROTATE_270:
- return DRM_MODE_ROTATE_270;
+ return DRM_MODE_ROTATE_90;
default:
NOTREACHED();
}
@@ -35,8 +41,22 @@ uint32_t OverlayTransformToDrmRotationPropertyValue(
// Rotations are dependent on modifiers. Tiled formats can be rotated,
// linear formats cannot. Atomic tests currently ignore modifiers, so there
// isn't a way of determining if the rotation is supported.
-// TODO(https://crbug/880464): Remove this.
-bool IsRotationTransformSupported(gfx::OverlayTransform transform) {
+// TODO(https://b/172210707): Atomic tests should work if we are using
+// kUseRealBuffersForPageFlipTest, so this should be revisited and tested more
+// broadly with a condition on that.
+// NOTE: This is enabled for TGL+ and NV12/P010 formats for 90/270 rotation
+// currently since we always allocate those formats as Y-tiled and 90/270
+// rotation is supported by the HW in that case. This is needed for protected
+// content that requires overlays.
+bool IsRotationTransformSupported(gfx::OverlayTransform transform,
+ uint32_t format_fourcc) {
+#if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
+ if ((format_fourcc == DRM_FORMAT_NV12 || format_fourcc == DRM_FORMAT_P010) &&
+ (transform == gfx::OVERLAY_TRANSFORM_ROTATE_90 ||
+ transform == gfx::OVERLAY_TRANSFORM_ROTATE_270)) {
+ return true;
+ }
+#endif
if ((transform == gfx::OVERLAY_TRANSFORM_ROTATE_90) ||
(transform == gfx::OVERLAY_TRANSFORM_ROTATE_270) ||
(transform == gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL)) {
@@ -80,11 +100,12 @@ bool HardwareDisplayPlaneAtomic::AssignPlaneProps(
const gfx::Rect& crtc_rect,
const gfx::Rect& src_rect,
const gfx::OverlayTransform transform,
- int in_fence_fd) {
+ int in_fence_fd,
+ uint32_t format_fourcc) {
if (transform != gfx::OVERLAY_TRANSFORM_NONE && !properties_.rotation.id)
return false;
- if (!IsRotationTransformSupported(transform))
+ if (!IsRotationTransformSupported(transform, format_fourcc))
return false;
// Make a copy of properties to get the props IDs for the new intermediate
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h
index 5043b987468..ae8d07997ec 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h
@@ -31,7 +31,8 @@ class HardwareDisplayPlaneAtomic : public HardwareDisplayPlane {
const gfx::Rect& crtc_rect,
const gfx::Rect& src_rect,
const gfx::OverlayTransform transform,
- int in_fence_fd);
+ int in_fence_fd,
+ uint32_t format_fourcc);
// Sets the props on |property_set| for commit.
bool SetPlaneProps(drmModeAtomicReq* property_set);
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
index 634fb042481..448cfa9a14b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc
@@ -459,8 +459,10 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset(
if (is_enabled) {
crtc_state.mode = crtc_request.mode();
- crtc_state.modeset_framebuffer =
- DrmOverlayPlane::GetPrimaryPlane(crtc_request.overlays())->buffer;
+ crtc_state.modeset_framebuffers.clear();
+ for (const auto& overlay : crtc_request.overlays())
+ crtc_state.modeset_framebuffers.push_back(overlay.buffer);
+
} else {
if (crtc_request.plane_list())
disable_planes_lists.insert(crtc_request.plane_list());
@@ -483,9 +485,9 @@ void HardwareDisplayPlaneManager::UpdateCrtcAndPlaneStatesAfterModeset(
}
}
-void HardwareDisplayPlaneManager::ResetModesetBufferOfCrtc(uint32_t crtc_id) {
+void HardwareDisplayPlaneManager::ResetModesetStateForCrtc(uint32_t crtc_id) {
CrtcState& crtc_state = CrtcStateForCrtcId(crtc_id);
- crtc_state.modeset_framebuffer = nullptr;
+ crtc_state.modeset_framebuffers.clear();
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
index a4593292e8d..0cd18997ce8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h
@@ -82,7 +82,7 @@ class HardwareDisplayPlaneManager {
CrtcState(CrtcState&&);
drmModeModeInfo mode = {};
- scoped_refptr<DrmFramebuffer> modeset_framebuffer;
+ std::vector<scoped_refptr<DrmFramebuffer>> modeset_framebuffers;
CrtcProperties properties = {};
@@ -187,7 +187,7 @@ class HardwareDisplayPlaneManager {
// which resources needed to be tracked internally in
// HardwareDisplayPlaneManager and which should be taken care of by the
// caller.
- void ResetModesetBufferOfCrtc(uint32_t crtc_id);
+ void ResetModesetStateForCrtc(uint32_t crtc_id);
protected:
struct ConnectorProperties {
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
index db7e3cad473..2fae9fcc8ff 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc
@@ -11,10 +11,10 @@
#include <utility>
#include "base/bind.h"
+#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/files/platform_file.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_fence_handle.h"
@@ -142,8 +142,11 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(CommitRequest commit_request,
if (crtc_request.should_enable()) {
DCHECK(crtc_request.plane_list());
- status &= AssignOverlayPlanes(crtc_request.plane_list(),
- crtc_request.overlays(), crtc_id);
+ if (!AssignOverlayPlanes(crtc_request.plane_list(),
+ crtc_request.overlays(), crtc_id)) {
+ LOG_IF(ERROR, !is_testing) << "Failed to Assign Overlay Planes";
+ status = false;
+ }
enable_planes_lists.insert(crtc_request.plane_list());
}
}
@@ -204,9 +207,9 @@ void HardwareDisplayPlaneManagerAtomic::SetAtomicPropsForCommit(
plane->set_in_use(false);
HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane);
- atomic_plane->AssignPlaneProps(0, 0, gfx::Rect(), gfx::Rect(),
- gfx::OVERLAY_TRANSFORM_NONE,
- base::kInvalidPlatformFile);
+ atomic_plane->AssignPlaneProps(
+ 0, 0, gfx::Rect(), gfx::Rect(), gfx::OVERLAY_TRANSFORM_NONE,
+ base::kInvalidPlatformFile, DRM_FORMAT_INVALID);
atomic_plane->SetPlaneProps(atomic_request);
}
}
@@ -307,9 +310,9 @@ bool HardwareDisplayPlaneManagerAtomic::DisableOverlayPlanes(
HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane);
- atomic_plane->AssignPlaneProps(0, 0, gfx::Rect(), gfx::Rect(),
- gfx::OVERLAY_TRANSFORM_NONE,
- base::kInvalidPlatformFile);
+ atomic_plane->AssignPlaneProps(
+ 0, 0, gfx::Rect(), gfx::Rect(), gfx::OVERLAY_TRANSFORM_NONE,
+ base::kInvalidPlatformFile, DRM_FORMAT_INVALID);
atomic_plane->SetPlaneProps(plane_list->atomic_property_set.get());
}
ret = drm_->CommitProperties(plane_list->atomic_property_set.get(),
@@ -365,7 +368,7 @@ void HardwareDisplayPlaneManagerAtomic::RequestPlanesReadyCallback(
}
bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
- HardwareDisplayPlaneList* plane_list,
+ HardwareDisplayPlaneList*,
HardwareDisplayPlane* hw_plane,
const DrmOverlayPlane& overlay,
uint32_t crtc_id,
@@ -382,9 +385,10 @@ bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
fence_fd = gpu_fence_handle.owned_fd.get();
}
- if (!atomic_plane->AssignPlaneProps(crtc_id, framebuffer_id,
- overlay.display_bounds, src_rect,
- overlay.plane_transform, fence_fd)) {
+ if (!atomic_plane->AssignPlaneProps(
+ crtc_id, framebuffer_id, overlay.display_bounds, src_rect,
+ overlay.plane_transform, fence_fd,
+ overlay.buffer->framebuffer_pixel_format())) {
return false;
}
return true;
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index 6f73d1747a0..1f23be53932 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -288,7 +288,7 @@ TEST_P(HardwareDisplayPlaneManagerTest, ResettingConnectorCache) {
ui::CrtcCommitRequest request = ui::CrtcCommitRequest::EnableCrtcRequest(
crtc_properties_[i].id, connector_properties[i].id, kDefaultMode,
- &state, std::move(overlays));
+ gfx::Point(), &state, std::move(overlays));
commit_request.push_back(std::move(request));
}
@@ -309,22 +309,22 @@ TEST_P(HardwareDisplayPlaneManagerTest, ResettingConnectorCache) {
ui::DrmOverlayPlaneList overlays;
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[0].id, kConnectorIdBase, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[0].id, kConnectorIdBase, kDefaultMode, gfx::Point(),
+ &state, std::move(overlays)));
}
{
ui::DrmOverlayPlaneList overlays;
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[1].id, kConnectorIdBase + 1, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[1].id, kConnectorIdBase + 1, kDefaultMode,
+ gfx::Point(), &state, std::move(overlays)));
}
{
ui::DrmOverlayPlaneList overlays;
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[2].id, kConnectorIdBase + 3, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[2].id, kConnectorIdBase + 3, kDefaultMode,
+ gfx::Point(), &state, std::move(overlays)));
}
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(
@@ -332,6 +332,47 @@ TEST_P(HardwareDisplayPlaneManagerTest, ResettingConnectorCache) {
}
}
+TEST_P(HardwareDisplayPlaneManagerTest, SequenceIncrementOnModesetOnly) {
+ fake_drm_->InitializeState(crtc_properties_, connector_properties_,
+ plane_properties_, property_names_,
+ /*use_atomic=*/true);
+
+ // Modeset Test
+ {
+ int pre_test_sequence_id = fake_drm_->modeset_sequence_id();
+ ASSERT_TRUE(fake_drm_->plane_manager()->Commit(
+ ui::CommitRequest(),
+ DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET));
+ EXPECT_EQ(pre_test_sequence_id, fake_drm_->modeset_sequence_id());
+ }
+
+ // Successful Modeset
+ {
+ int pre_modeset_sequence_id = fake_drm_->modeset_sequence_id();
+ ASSERT_TRUE(fake_drm_->plane_manager()->Commit(
+ ui::CommitRequest(), DRM_MODE_ATOMIC_ALLOW_MODESET));
+ EXPECT_EQ(pre_modeset_sequence_id + 1, fake_drm_->modeset_sequence_id());
+ }
+
+ // Failed Modeset
+ {
+ int pre_modeset_sequence_id = fake_drm_->modeset_sequence_id();
+ fake_drm_->set_set_crtc_expectation(false);
+ ASSERT_FALSE(fake_drm_->plane_manager()->Commit(
+ ui::CommitRequest(), DRM_MODE_ATOMIC_ALLOW_MODESET));
+ fake_drm_->set_set_crtc_expectation(true);
+ EXPECT_EQ(pre_modeset_sequence_id, fake_drm_->modeset_sequence_id());
+ }
+
+ // Page Flip
+ {
+ int pre_flip_sequence_id = fake_drm_->modeset_sequence_id();
+ ASSERT_TRUE(fake_drm_->plane_manager()->Commit(ui::CommitRequest(),
+ DRM_MODE_ATOMIC_NONBLOCK));
+ EXPECT_EQ(pre_flip_sequence_id, fake_drm_->modeset_sequence_id());
+ }
+}
+
TEST_P(HardwareDisplayPlaneManagerLegacyTest, Modeset) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
fake_drm_->InitializeState(crtc_properties_, connector_properties_,
@@ -346,8 +387,8 @@ TEST_P(HardwareDisplayPlaneManagerLegacyTest, Modeset) {
ui::DrmOverlayPlaneList overlays;
overlays.push_back(plane.Clone());
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
+ gfx::Point(), &state, std::move(overlays)));
EXPECT_FALSE(fake_drm_->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET));
@@ -495,8 +536,8 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, Modeset) {
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
+ gfx::Point(), &state, std::move(overlays)));
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET));
@@ -530,8 +571,8 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, CheckPropsAfterModeset) {
ui::DrmOverlayPlaneList overlays;
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
- crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode, &state,
- std::move(overlays)));
+ crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
+ gfx::Point(), &state, std::move(overlays)));
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET));
@@ -570,7 +611,7 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, CheckPropsAfterDisable) {
overlays.push_back(ui::DrmOverlayPlane(fake_buffer_, nullptr));
commit_request.push_back(ui::CrtcCommitRequest::EnableCrtcRequest(
crtc_properties_[0].id, connector_properties_[0].id, kDefaultMode,
- &state, std::move(overlays)));
+ gfx::Point(), &state, std::move(overlays)));
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET));
}
@@ -1379,7 +1420,8 @@ class HardwareDisplayPlaneAtomicMock : public ui::HardwareDisplayPlaneAtomic {
const gfx::Rect& crtc_rect,
const gfx::Rect& src_rect,
const gfx::OverlayTransform transform,
- int in_fence_fd) override {
+ int in_fence_fd,
+ uint32_t format_fourcc) override {
framebuffer_ = framebuffer;
return true;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
index bf00ae93cfe..1ef0fe9f11f 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -9,7 +9,9 @@
#include <utility>
#include "base/check.h"
-#include "base/stl_util.h"
+#include "base/containers/contains.h"
+#include "base/containers/flat_map.h"
+#include "base/logging.h"
#include "skia/ext/legacy_display_globals.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -70,6 +72,13 @@ Type* FindObjectById(uint32_t id, std::vector<Type>& properties) {
return it != properties.end() ? &(*it) : nullptr;
}
+// TODO(dnicoara): Generate all IDs internal to MockDrmDevice.
+// For now generate something with a high enough ID to be unique in tests.
+uint32_t GetUniqueNumber() {
+ static uint32_t value_generator = 0xff000000;
+ return ++value_generator;
+}
+
} // namespace
MockDrmDevice::CrtcProperties::CrtcProperties() = default;
@@ -173,6 +182,34 @@ void MockDrmDevice::UpdateState(
connector_properties_ = connector_properties;
plane_properties_ = plane_properties;
property_names_ = property_names;
+
+ // Props IDs shouldn't change throughout a DRM state. Grab it once at
+ // UpdateState.
+ plane_crtc_id_prop_id_ = 0;
+ for (const PlaneProperties& plane_props : plane_properties) {
+ const std::vector<DrmDevice::Property>& props = plane_props.properties;
+ auto it = std::find_if(
+ props.begin(), props.end(),
+ [&names = property_names_](const DrmDevice::Property& prop) {
+ return names.at(prop.id) == "CRTC_ID";
+ });
+ if (it != props.end()) {
+ plane_crtc_id_prop_id_ = it->id;
+ // all planes should have the same prop ID for the name. Break right after
+ // the first one is found.
+ break;
+ }
+ }
+}
+
+void MockDrmDevice::SetModifiersOverhead(
+ base::flat_map<uint64_t /*modifier*/, int /*overhead*/>
+ modifiers_overhead) {
+ modifiers_overhead_ = modifiers_overhead;
+}
+
+void MockDrmDevice::SetSystemLimitOfModifiers(uint64_t limit) {
+ system_watermark_limitations_ = limit;
}
ScopedDrmResourcesPtr MockDrmDevice::GetResources() {
@@ -258,8 +295,9 @@ bool MockDrmDevice::AddFramebuffer2(uint32_t width,
uint32_t* framebuffer,
uint32_t flags) {
add_framebuffer_call_count_++;
- *framebuffer = add_framebuffer_call_count_;
+ *framebuffer = GetUniqueNumber();
framebuffer_ids_.insert(*framebuffer);
+ fb_props_[*framebuffer] = {width, height, modifiers[0]};
return add_framebuffer_expectation_;
}
@@ -269,6 +307,11 @@ bool MockDrmDevice::RemoveFramebuffer(uint32_t framebuffer) {
CHECK(it != framebuffer_ids_.end());
framebuffer_ids_.erase(it);
}
+ {
+ auto it = fb_props_.find(framebuffer);
+ CHECK(it != fb_props_.end());
+ fb_props_.erase(it);
+ }
remove_framebuffer_call_count_++;
std::vector<uint32_t> crtcs_to_clear;
for (auto crtc_fb : crtc_fb_) {
@@ -330,7 +373,7 @@ bool MockDrmDevice::SetProperty(uint32_t connector_id,
ScopedDrmPropertyBlob MockDrmDevice::CreatePropertyBlob(const void* blob,
size_t size) {
- uint32_t id = ++property_id_generator_;
+ uint32_t id = GetUniqueNumber();
allocated_property_blobs_.insert(id);
return std::make_unique<DrmPropertyBlobMetadata>(this, id);
}
@@ -427,25 +470,46 @@ bool MockDrmDevice::CloseBufferHandle(uint32_t handle) {
return true;
}
-bool MockDrmDevice::CommitProperties(
+bool MockDrmDevice::CommitPropertiesInternal(
drmModeAtomicReq* request,
uint32_t flags,
uint32_t crtc_count,
scoped_refptr<PageFlipRequest> page_flip_request) {
+ commit_count_++;
if (flags == kTestModesetFlags)
++test_modeset_count_;
else if (flags == kCommitModesetFlags)
++commit_modeset_count_;
- commit_count_++;
- if (!commit_expectation_)
+ if ((flags & kCommitModesetFlags && !set_crtc_expectation_) ||
+ (flags & DRM_MODE_ATOMIC_NONBLOCK && !commit_expectation_)) {
return false;
+ }
+
+ uint64_t requested_resources = 0;
+ base::flat_map<uint64_t, int> crtc_planes_counter;
for (uint32_t i = 0; i < request->cursor; ++i) {
- bool res = ValidatePropertyValue(request->items[i].property_id,
- request->items[i].value);
- if (!res)
+ const drmModeAtomicReqItem& item = request->items[i];
+ if (!ValidatePropertyValue(item.property_id, item.value))
return false;
+
+ if (fb_props_.find(item.value) != fb_props_.end()) {
+ const FramebufferProps& props = fb_props_[item.value];
+ requested_resources += modifiers_overhead_[props.modifier];
+ }
+
+ if (item.property_id == plane_crtc_id_prop_id_) {
+ if (++crtc_planes_counter[item.value] > 1 &&
+ !modeset_with_overlays_expectation_)
+ return false;
+ }
+ }
+
+ if (requested_resources > system_watermark_limitations_) {
+ LOG(ERROR) << "Requested display configuration exceeds system watermark "
+ "limitations";
+ return false;
}
if (page_flip_request)
@@ -463,6 +527,12 @@ bool MockDrmDevice::CommitProperties(
return false;
}
+ // Count all committed planes at the end just before returning true to reflect
+ // the number of planes that have successfully been committed.
+ last_planes_committed_count_ = 0;
+ for (const auto& planes_counter : crtc_planes_counter)
+ last_planes_committed_count_ += planes_counter.second;
+
return true;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
index 922d402147c..0c2d823f12a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -8,11 +8,13 @@
#include <drm_mode.h>
#include <stddef.h>
#include <stdint.h>
+#include <limits>
#include <map>
#include <memory>
#include <set>
#include <vector>
+#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -90,11 +92,18 @@ class MockDrmDevice : public DrmDevice {
legacy_gamma_ramp_expectation_ = state;
}
void set_commit_expectation(bool state) { commit_expectation_ = state; }
+ void set_overlay_modeset_expecation(bool state) {
+ modeset_with_overlays_expectation_ = state;
+ }
uint32_t current_framebuffer() const { return current_framebuffer_; }
const std::vector<sk_sp<SkSurface>> buffers() const { return buffers_; }
+ int last_planes_committed_count() const {
+ return last_planes_committed_count_;
+ }
+
uint32_t get_cursor_handle_for_crtc(uint32_t crtc) const {
const auto it = crtc_cursor_map_.find(crtc);
return it != crtc_cursor_map_.end() ? it->second : 0;
@@ -122,6 +131,9 @@ class MockDrmDevice : public DrmDevice {
void SetPropertyBlob(ScopedDrmPropertyBlobPtr blob);
+ void SetModifiersOverhead(base::flat_map<uint64_t, int> modifiers_overhead);
+ void SetSystemLimitOfModifiers(uint64_t limit);
+
// DrmDevice:
ScopedDrmResourcesPtr GetResources() override;
ScopedDrmPlaneResPtr GetPlaneResources() override;
@@ -177,10 +189,6 @@ class MockDrmDevice : public DrmDevice {
bool MapDumbBuffer(uint32_t handle, size_t size, void** pixels) override;
bool UnmapDumbBuffer(void* pixels, size_t size) override;
bool CloseBufferHandle(uint32_t handle) override;
- bool CommitProperties(drmModeAtomicReq* request,
- uint32_t flags,
- uint32_t crtc_count,
- scoped_refptr<PageFlipRequest> callback) override;
bool SetGammaRamp(
uint32_t crtc_id,
const std::vector<display::GammaRampRGBEntry>& lut) override;
@@ -188,8 +196,21 @@ class MockDrmDevice : public DrmDevice {
uint32_t GetFramebufferForCrtc(uint32_t crtc_id) const;
private:
+ // Properties of the plane associated with a fb.
+ struct FramebufferProps {
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint64_t modifier = 0;
+ };
+
~MockDrmDevice() override;
+ bool CommitPropertiesInternal(
+ drmModeAtomicReq* request,
+ uint32_t flags,
+ uint32_t crtc_count,
+ scoped_refptr<PageFlipRequest> callback) override;
+
bool UpdateProperty(uint32_t id,
uint64_t value,
std::vector<DrmDevice::Property>* properties);
@@ -210,6 +231,7 @@ class MockDrmDevice : public DrmDevice {
int commit_count_ = 0;
int set_object_property_count_ = 0;
int set_gamma_ramp_count_ = 0;
+ int last_planes_committed_count_ = 0;
bool set_crtc_expectation_;
bool add_framebuffer_expectation_;
@@ -217,8 +239,10 @@ class MockDrmDevice : public DrmDevice {
bool create_dumb_buffer_expectation_;
bool legacy_gamma_ramp_expectation_ = false;
bool commit_expectation_ = true;
+ bool modeset_with_overlays_expectation_ = true;
uint32_t current_framebuffer_;
+ uint32_t plane_crtc_id_prop_id_ = 0;
std::vector<sk_sp<SkSurface>> buffers_;
@@ -237,12 +261,14 @@ class MockDrmDevice : public DrmDevice {
std::map<uint32_t, std::string> property_names_;
- // TODO(dnicoara): Generate all IDs internal to MockDrmDevice.
- // For now generate something with a high enough ID to be unique in tests.
- uint32_t property_id_generator_ = 0xff000000;
-
std::set<uint32_t> allocated_property_blobs_;
+ // Props of the plane associated with the generated fb_id.
+ base::flat_map<uint32_t /*fb_id*/, FramebufferProps> fb_props_;
+
+ uint64_t system_watermark_limitations_ = std::numeric_limits<uint64_t>::max();
+ base::flat_map<uint64_t /*modifier*/, int /*overhead*/> modifiers_overhead_;
+
DISALLOW_COPY_AND_ASSIGN(MockDrmDevice);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.cc b/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.cc
index c65c5f6825c..af364e9c0e4 100644
--- a/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.cc
@@ -6,6 +6,8 @@
#include <utility>
+#include "base/bind.h"
+
namespace ui {
void PostSyncTask(
diff --git a/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.h b/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.h
index d5be9bd74e3..c488aea5a1d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.h
+++ b/chromium/ui/ozone/platform/drm/gpu/proxy_helpers.h
@@ -7,7 +7,7 @@
#include <utility>
-#include "base/bind.h"
+#include "base/bind_post_task.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/waitable_event.h"
@@ -15,19 +15,6 @@
namespace ui {
-namespace internal {
-
-template <typename... Args>
-void PostAsyncTask(
- const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- base::OnceCallback<void(Args...)> callback,
- Args... args) {
- auto closure = base::BindOnce(std::move(callback), std::move(args)...);
- task_runner->PostTask(FROM_HERE, std::move(closure));
-}
-
-} // namespace internal
-
// Posts a task to a different thread and blocks waiting for the task to finish
// executing.
void PostSyncTask(
@@ -40,10 +27,10 @@ void PostSyncTask(
// thread).
template <typename... Args>
base::RepeatingCallback<void(Args...)> CreateSafeRepeatingCallback(
- base::RepeatingCallback<void(Args...)> callback) {
- return base::BindRepeating(&internal::PostAsyncTask<Args...>,
- base::ThreadTaskRunnerHandle::Get(),
- std::move(callback));
+ base::RepeatingCallback<void(Args...)> callback,
+ const base::Location& location = FROM_HERE) {
+ return base::BindPostTask(base::ThreadTaskRunnerHandle::Get(),
+ std::move(callback), location);
}
// Creates a OnceCallback that will run |callback| on the calling thread. Useful
@@ -51,10 +38,10 @@ base::RepeatingCallback<void(Args...)> CreateSafeRepeatingCallback(
// task finished (and the callback needs to run on the original thread).
template <typename... Args>
base::OnceCallback<void(Args...)> CreateSafeOnceCallback(
- base::OnceCallback<void(Args...)> callback) {
- return base::BindOnce(&internal::PostAsyncTask<Args...>,
- base::ThreadTaskRunnerHandle::Get(),
- std::move(callback));
+ base::OnceCallback<void(Args...)> callback,
+ const base::Location& location = FROM_HERE) {
+ return base::BindPostTask(base::ThreadTaskRunnerHandle::Get(),
+ std::move(callback), location);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
index 5a8319fe9cd..127f4d87257 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -10,6 +10,7 @@
#include "base/files/platform_file.h"
#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/display/types/display_snapshot.h"
@@ -36,7 +37,7 @@ namespace {
bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
HardwareDisplayController* controller,
SkSurface* surface,
- uint32_t fourcc_format) {
+ const std::vector<uint64_t>& modifiers) {
DCHECK(!controller->crtc_controllers().empty());
CrtcController* first_crtc = controller->crtc_controllers()[0].get();
ScopedDrmCrtcPtr saved_crtc(drm->GetCrtc(first_crtc->crtc()));
@@ -45,7 +46,6 @@ bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
return false;
}
- const auto& modifiers = controller->GetFormatModifiers(fourcc_format);
for (const uint64_t modifier : modifiers) {
// A value of 0 means DRM_FORMAT_MOD_NONE. If the CRTC has any other
// modifier (tiling, compression, etc.) we can't read the fb and assume it's
@@ -77,7 +77,7 @@ bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
// Copy the source buffer. Do not perform any blending.
paint.setBlendMode(SkBlendMode::kSrc);
surface->getCanvas()->drawImage(saved_buffer.surface()->makeImageSnapshot(),
- 0, 0, &paint);
+ 0, 0, SkSamplingOptions(), &paint);
return true;
}
@@ -93,19 +93,6 @@ CrtcController* GetCrtcController(HardwareDisplayController* controller,
return nullptr;
}
-std::vector<uint64_t> GetModifiersForPrimaryFormat(
- HardwareDisplayController* controller) {
- gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
- uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(format);
- return controller->GetFormatModifiersForModesetting(fourcc_format);
-}
-
-bool AreAllStatusesTrue(base::flat_map<int64_t, bool>& display_statuses) {
- auto it = find_if(display_statuses.begin(), display_statuses.end(),
- [](const auto status) { return status.second == false; });
- return (it == display_statuses.end());
-}
-
} // namespace
ScreenManager::ScreenManager() = default;
@@ -175,6 +162,9 @@ void ScreenManager::AddDisplayController(const scoped_refptr<DrmDevice>& drm,
void ScreenManager::RemoveDisplayControllers(
const CrtcsWithDrmList& controllers_to_remove) {
+ TRACE_EVENT1("drm", "ScreenManager::RemoveDisplayControllers",
+ "display_count", controllers_to_remove.size());
+
// Split them to different lists unique to each DRM Device.
base::flat_map<scoped_refptr<DrmDevice>, CrtcsWithDrmList>
controllers_for_drm_devices;
@@ -223,8 +213,10 @@ void ScreenManager::RemoveDisplayControllers(
UpdateControllerToWindowMapping();
}
-base::flat_map<int64_t, bool> ScreenManager::ConfigureDisplayControllers(
+bool ScreenManager::ConfigureDisplayControllers(
const ControllerConfigsList& controllers_params) {
+ TRACE_EVENT0("drm", "ScreenManager::ConfigureDisplayControllers");
+
// Split them to different lists unique to each DRM Device.
base::flat_map<scoped_refptr<DrmDevice>, ControllerConfigsList>
displays_for_drm_devices;
@@ -238,33 +230,81 @@ base::flat_map<int64_t, bool> ScreenManager::ConfigureDisplayControllers(
displays_for_drm_devices[params.drm].emplace_back(params);
}
- base::flat_map<int64_t, bool> statuses;
+ bool config_success = true;
// Perform display configurations together for the same DRM only.
for (const auto& configs_on_drm : displays_for_drm_devices) {
- auto display_statuses = TestAndModeset(configs_on_drm.second);
- statuses.insert(display_statuses.begin(), display_statuses.end());
+ const ControllerConfigsList& controllers_params = configs_on_drm.second;
+ bool test_modeset = TestAndSetPreferredModifiers(controllers_params) ||
+ TestAndSetLinearModifier(controllers_params);
+ config_success &= test_modeset;
+ if (!test_modeset)
+ continue;
+ bool can_modeset_with_overlays =
+ TestModesetWithOverlays(controllers_params);
+ config_success &= Modeset(controllers_params, can_modeset_with_overlays);
}
- if (AreAllStatusesTrue(statuses))
+ if (config_success)
UpdateControllerToWindowMapping();
- return statuses;
+ return config_success;
}
-base::flat_map<int64_t, bool> ScreenManager::TestAndModeset(
+bool ScreenManager::TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params) {
- if (!TestModeset(controllers_params)) {
- base::flat_map<int64_t, bool> statuses;
- for (const auto& params : controllers_params)
- statuses.insert(std::make_pair(params.display_id, false));
- return statuses;
+ TRACE_EVENT1("drm", "ScreenManager::TestAndSetPreferredModifiers",
+ "display_count", controllers_params.size());
+
+ CrtcPreferredModifierMap crtcs_preferred_modifier;
+ CommitRequest commit_request;
+ auto drm = controllers_params[0].drm;
+
+ for (const auto& params : controllers_params) {
+ auto it = FindDisplayController(params.drm, params.crtc);
+ DCHECK(controllers_.end() != it);
+ HardwareDisplayController* controller = it->get();
+
+ if (params.mode) {
+ uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetFormatModifiersForTestModeset(fourcc_format);
+ // Test with no overlays to go for a lower bandwidth usage.
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
+ controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
+ modifiers, /*include_overlays=*/false, /*is_testing=*/true);
+ if (modeset_planes.empty())
+ return false;
+
+ uint64_t primary_modifier =
+ DrmOverlayPlane::GetPrimaryPlane(modeset_planes)
+ ->buffer->format_modifier();
+ crtcs_preferred_modifier[params.crtc] =
+ std::make_pair(modifiers.empty(), primary_modifier);
+
+ GetModesetControllerProps(&commit_request, controller, params.origin,
+ *params.mode, modeset_planes);
+ } else {
+ controller->GetDisableProps(&commit_request);
+ }
+ }
+
+ if (!drm->plane_manager()->Commit(
+ std::move(commit_request),
+ DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET)) {
+ return false;
}
- return Modeset(controllers_params);
+ SetPreferredModifiers(controllers_params, crtcs_preferred_modifier);
+ return true;
}
-bool ScreenManager::TestModeset(
+bool ScreenManager::TestAndSetLinearModifier(
const ControllerConfigsList& controllers_params) {
+ TRACE_EVENT1("drm", "ScreenManager::TestAndSetLinearModifier",
+ "display_count", controllers_params.size());
+
+ CrtcPreferredModifierMap crtcs_preferred_modifier;
CommitRequest commit_request;
auto drm = controllers_params[0].drm;
@@ -273,65 +313,151 @@ bool ScreenManager::TestModeset(
DCHECK(controllers_.end() != it);
HardwareDisplayController* controller = it->get();
+ uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetFormatModifiersForTestModeset(fourcc_format);
+ // Test with an empty list if no preferred modifiers are advertised.
+ // Platforms might not support gbm_bo_create_with_modifiers(). If the
+ // platform doesn't expose modifiers, do not attempt to explicitly request
+ // LINEAR otherwise we might CHECK() when trying to allocate buffers.
+ if (!modifiers.empty())
+ modifiers = std::vector<uint64_t>{DRM_FORMAT_MOD_LINEAR};
+ crtcs_preferred_modifier[params.crtc] =
+ std::make_pair(modifiers.empty(), DRM_FORMAT_MOD_LINEAR);
+
if (params.mode) {
- DrmOverlayPlane primary_plane = GetModesetBuffer(
+ // Test with no overlays to go for a lower bandwidth usage.
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
- GetModifiersForPrimaryFormat(controller));
- if (!primary_plane.buffer)
+ modifiers, /*include_overlays=*/false, /*is_testing=*/true);
+ if (modeset_planes.empty())
return false;
GetModesetControllerProps(&commit_request, controller, params.origin,
- *params.mode, primary_plane);
+ *params.mode, modeset_planes);
+ } else {
+ controller->GetDisableProps(&commit_request);
+ }
+ }
+
+ if (!drm->plane_manager()->Commit(
+ std::move(commit_request),
+ DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET)) {
+ return false;
+ }
+
+ SetPreferredModifiers(controllers_params, crtcs_preferred_modifier);
+ return true;
+}
+
+void ScreenManager::SetPreferredModifiers(
+ const ControllerConfigsList& controllers_params,
+ const CrtcPreferredModifierMap& crtcs_preferred_modifier) {
+ for (const auto& params : controllers_params) {
+ if (params.mode) {
+ bool was_modifiers_list_empty =
+ crtcs_preferred_modifier.at(params.crtc).first;
+ // No preferred modifiers should be saved as some platforms might not have
+ // bo_create_with_modifiers implemented, this will send the preferred
+ // modifiers list as an empty list.
+ if (!was_modifiers_list_empty) {
+ uint64_t picked_modifier =
+ crtcs_preferred_modifier.at(params.crtc).second;
+ auto it = FindDisplayController(params.drm, params.crtc);
+ DCHECK(*it);
+ it->get()->UpdatePreferredModiferForFormat(
+ display::DisplaySnapshot::PrimaryFormat(), picked_modifier);
+ }
+ }
+ }
+}
+
+bool ScreenManager::TestModesetWithOverlays(
+ const ControllerConfigsList& controllers_params) {
+ TRACE_EVENT1("drm", "ScreenManager::TestModesetWithOverlays", "display_count",
+ controllers_params.size());
+
+ bool does_an_overlay_exist = false;
+
+ CommitRequest commit_request;
+ auto drm = controllers_params[0].drm;
+ for (const auto& params : controllers_params) {
+ auto it = FindDisplayController(params.drm, params.crtc);
+ DCHECK(controllers_.end() != it);
+ HardwareDisplayController* controller = it->get();
+
+ if (params.mode) {
+ uint32_t fourcc_format = GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetSupportedModifiers(fourcc_format);
+
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
+ controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
+ modifiers, /*include_overlays=*/true, /*is_testing=*/true);
+ DCHECK(!modeset_planes.empty());
+ does_an_overlay_exist |= modeset_planes.size() > 1;
+
+ GetModesetControllerProps(&commit_request, controller, params.origin,
+ *params.mode, modeset_planes);
} else {
controller->GetDisableProps(&commit_request);
}
}
+ // If we have no overlays, report not modesetting with overlays as we haven't
+ // tested with overlays.
+ if (!does_an_overlay_exist)
+ return false;
return drm->plane_manager()->Commit(
std::move(commit_request),
DRM_MODE_ATOMIC_TEST_ONLY | DRM_MODE_ATOMIC_ALLOW_MODESET);
}
-base::flat_map<int64_t, bool> ScreenManager::Modeset(
- const ControllerConfigsList& controllers_params) {
- base::flat_map<int64_t, bool> statuses;
+bool ScreenManager::Modeset(const ControllerConfigsList& controllers_params,
+ bool can_modeset_with_overlays) {
+ TRACE_EVENT2("drm", "ScreenManager::Modeset", "display_count",
+ controllers_params.size(), "modeset_with_overlays",
+ can_modeset_with_overlays);
+
+ CommitRequest commit_request;
+ auto drm = controllers_params[0].drm;
for (const auto& params : controllers_params) {
- // Commit one controller at a time.
- CommitRequest commit_request;
- bool status = true;
if (params.mode) {
auto it = FindDisplayController(params.drm, params.crtc);
DCHECK(controllers_.end() != it);
HardwareDisplayController* controller = it->get();
- DrmOverlayPlane primary_plane = GetModesetBuffer(
- controller, gfx::Rect(params.origin, ModeSize(*params.mode)),
- GetModifiersForPrimaryFormat(controller));
- if (primary_plane.buffer) {
- SetDisplayControllerForEnableAndGetProps(
- &commit_request, params.drm, params.crtc, params.connector,
- params.origin, *params.mode, primary_plane);
- } else {
- status = false;
- }
+ uint32_t fourcc_format = GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetSupportedModifiers(fourcc_format);
+
+ gfx::Rect bounds = gfx::Rect(params.origin, ModeSize(*params.mode));
+ DrmOverlayPlaneList modeset_planes =
+ GetModesetPlanes(controller, bounds, modifiers,
+ can_modeset_with_overlays, /*is_testing=*/false);
+
+ SetDisplayControllerForEnableAndGetProps(
+ &commit_request, params.drm, params.crtc, params.connector,
+ params.origin, *params.mode, modeset_planes);
} else {
- status = SetDisableDisplayControllerForDisableAndGetProps(
+ bool disable_set = SetDisableDisplayControllerForDisableAndGetProps(
&commit_request, params.drm, params.crtc);
+ if (!disable_set)
+ return false;
}
+ }
- CommitRequest request_for_update = commit_request;
- if (status) {
- status &= params.drm->plane_manager()->Commit(
- std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET);
- UpdateControllerStateAfterModeset(params, request_for_update, status);
- }
+ bool commit_status = drm->plane_manager()->Commit(
+ commit_request, DRM_MODE_ATOMIC_ALLOW_MODESET);
- statuses.insert(std::make_pair(params.display_id, status));
- }
+ UpdateControllerStateAfterModeset(drm, commit_request, commit_status);
- return statuses;
+ return commit_status;
}
void ScreenManager::SetDisplayControllerForEnableAndGetProps(
@@ -341,7 +467,7 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
uint32_t connector,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
HardwareDisplayControllers::iterator it = FindDisplayController(drm, crtc);
DCHECK(controllers_.end() != it)
<< "Display controller (crtc=" << crtc << ") doesn't exist.";
@@ -358,10 +484,10 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
// Otherwise it could apply a mode with the same resolution and refresh
// rate but with different timings to the other CRTC.
GetModesetControllerProps(commit_request, controller,
- controller->origin(), mode, primary);
+ controller->origin(), mode, modeset_planes);
} else {
// Just get props to re-enable the controller re-using the current state.
- GetEnableControllerProps(commit_request, controller, primary);
+ GetEnableControllerProps(commit_request, controller, modeset_planes);
}
return;
}
@@ -377,7 +503,8 @@ void ScreenManager::SetDisplayControllerForEnableAndGetProps(
controller = it->get();
}
- GetModesetControllerProps(commit_request, controller, origin, mode, primary);
+ GetModesetControllerProps(commit_request, controller, origin, mode,
+ modeset_planes);
}
bool ScreenManager::SetDisableDisplayControllerForDisableAndGetProps(
@@ -402,31 +529,32 @@ bool ScreenManager::SetDisableDisplayControllerForDisableAndGetProps(
}
void ScreenManager::UpdateControllerStateAfterModeset(
- const ControllerConfigParams& config,
+ const scoped_refptr<DrmDevice>& drm,
const CommitRequest& commit_request,
bool did_succeed) {
- for (auto& crtc_request : commit_request) {
+ for (const CrtcCommitRequest& crtc_request : commit_request) {
bool was_enabled = (crtc_request.should_enable());
HardwareDisplayControllers::iterator it =
- FindDisplayController(config.drm, crtc_request.crtc_id());
+ FindDisplayController(drm, crtc_request.crtc_id());
if (it != controllers_.end()) {
- it->get()->UpdateState(was_enabled, DrmOverlayPlane::GetPrimaryPlane(
- crtc_request.overlays()));
+ it->get()->UpdateState(crtc_request);
// If the CRTC is mirrored, move it to the mirror controller.
if (did_succeed && was_enabled)
- HandleMirrorIfExists(config, it);
+ HandleMirrorIfExists(drm, crtc_request, it);
}
}
}
void ScreenManager::HandleMirrorIfExists(
- const ControllerConfigParams& config,
+ const scoped_refptr<DrmDevice>& drm,
+ const CrtcCommitRequest& crtc_request,
const HardwareDisplayControllers::iterator& controller) {
- gfx::Rect modeset_bounds(config.origin, ModeSize(*config.mode));
+ gfx::Rect modeset_bounds(crtc_request.origin(),
+ ModeSize(crtc_request.mode()));
HardwareDisplayControllers::iterator mirror =
- FindActiveDisplayControllerByLocation(config.drm, modeset_bounds);
+ FindActiveDisplayControllerByLocation(drm, modeset_bounds);
// TODO(dnicoara): This is hacky, instead the DrmDisplay and
// CrtcController should be merged and picking the mode should be done
// properly within HardwareDisplayController.
@@ -434,7 +562,7 @@ void ScreenManager::HandleMirrorIfExists(
// TODO(markyacoub): RemoveCrtc makes a blocking commit to
// DisableOverlayPlanes. This should be redesigned and included as part of
// the Modeset commit.
- (*mirror)->AddCrtc((*controller)->RemoveCrtc(config.drm, config.crtc));
+ (*mirror)->AddCrtc((*controller)->RemoveCrtc(drm, crtc_request.crtc_id()));
controllers_.erase(controller);
}
}
@@ -541,24 +669,30 @@ void ScreenManager::UpdateControllerToWindowMapping() {
// otherwise the controller may be waiting for a page flip while the window
// tries to schedule another buffer.
if (should_enable) {
- DrmOverlayPlane primary_plane = GetModesetBuffer(
+ uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
+ display::DisplaySnapshot::PrimaryFormat());
+ std::vector<uint64_t> modifiers =
+ controller->GetSupportedModifiers(fourcc_format);
+ DrmOverlayPlaneList modeset_planes = GetModesetPlanes(
controller,
- gfx::Rect(controller->origin(), controller->GetModeSize()),
- GetModifiersForPrimaryFormat(controller));
- DCHECK(primary_plane.buffer);
+ gfx::Rect(controller->origin(), controller->GetModeSize()), modifiers,
+ /*include_overlays=*/true, /*is_testing=*/false);
+ DCHECK(!modeset_planes.empty());
CommitRequest commit_request;
- GetEnableControllerProps(&commit_request, controller, primary_plane);
+ GetEnableControllerProps(&commit_request, controller, modeset_planes);
controller->GetDrmDevice()->plane_manager()->Commit(
std::move(commit_request), DRM_MODE_ATOMIC_ALLOW_MODESET);
}
}
}
-DrmOverlayPlane ScreenManager::GetModesetBuffer(
+DrmOverlayPlaneList ScreenManager::GetModesetPlanes(
HardwareDisplayController* controller,
const gfx::Rect& bounds,
- const std::vector<uint64_t>& modifiers) {
+ const std::vector<uint64_t>& modifiers,
+ bool include_overlays,
+ bool is_testing) {
scoped_refptr<DrmDevice> drm = controller->GetDrmDevice();
uint32_t fourcc_format = ui::GetFourCCFormatForOpaqueFramebuffer(
display::DisplaySnapshot::PrimaryFormat());
@@ -569,19 +703,27 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
fourcc_format, bounds.size(), GBM_BO_USE_SCANOUT, modifiers);
if (!buffer) {
LOG(ERROR) << "Failed to create scanout buffer";
- return DrmOverlayPlane::Error();
+ return DrmOverlayPlaneList();
}
// If the current primary plane matches what we need for the next page flip,
- // we can clone it.
+ // clone all last_submitted_planes (matching primary + overlays).
DrmWindow* window = FindWindowAt(bounds);
if (window) {
- const DrmOverlayPlane* primary = window->GetLastModesetBuffer();
- const DrmDevice* drm = controller->GetDrmDevice().get();
+ const DrmOverlayPlaneList& last_submitted_planes =
+ window->last_submitted_planes();
+ const DrmOverlayPlane* primary =
+ DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes);
if (primary && primary->buffer->size() == bounds.size() &&
- primary->buffer->drm_device() == drm) {
- if (primary->buffer->format_modifier() == buffer->GetFormatModifier())
- return primary->Clone();
+ primary->buffer->drm_device() == controller->GetDrmDevice().get() &&
+ primary->buffer->format_modifier() == buffer->GetFormatModifier()) {
+ if (include_overlays) {
+ return DrmOverlayPlane::Clone(last_submitted_planes);
+ } else {
+ DrmOverlayPlaneList modeset_plane;
+ modeset_plane.push_back(primary->Clone());
+ return modeset_plane;
+ }
}
}
@@ -589,28 +731,32 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
drm, buffer.get(), buffer->GetSize(), modifiers);
if (!framebuffer) {
LOG(ERROR) << "Failed to add framebuffer for scanout buffer";
- return DrmOverlayPlane::Error();
+ return DrmOverlayPlaneList();
}
- sk_sp<SkSurface> surface = buffer->GetSurface();
- if (!surface) {
- VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer.";
- } else if (!FillModesetBuffer(drm, controller, surface.get(),
- buffer->GetFormat())) {
- // If we fail to fill the modeset buffer, clear it black to avoid displaying
- // an uninitialized framebuffer.
- surface->getCanvas()->clear(SK_ColorBLACK);
+ if (!is_testing) {
+ sk_sp<SkSurface> surface = buffer->GetSurface();
+ if (!surface) {
+ VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer.";
+ } else if (!FillModesetBuffer(drm, controller, surface.get(), modifiers)) {
+ // If we fail to fill the modeset buffer, clear it black to avoid
+ // displaying an uninitialized framebuffer.
+ surface->getCanvas()->clear(SK_ColorBLACK);
+ }
}
- return DrmOverlayPlane(framebuffer, nullptr);
+
+ DrmOverlayPlaneList modeset_planes;
+ modeset_planes.emplace_back(framebuffer, nullptr);
+ return modeset_planes;
}
void ScreenManager::GetEnableControllerProps(
CommitRequest* commit_request,
HardwareDisplayController* controller,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
DCHECK(!controller->crtc_controllers().empty());
- controller->GetEnableProps(commit_request, primary);
+ controller->GetEnableProps(commit_request, modeset_planes);
}
void ScreenManager::GetModesetControllerProps(
@@ -618,11 +764,11 @@ void ScreenManager::GetModesetControllerProps(
HardwareDisplayController* controller,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary) {
+ const DrmOverlayPlaneList& modeset_planes) {
DCHECK(!controller->crtc_controllers().empty());
controller->set_origin(origin);
- controller->GetModesetProps(commit_request, primary, mode);
+ controller->GetModesetProps(commit_request, modeset_planes, mode);
}
DrmWindow* ScreenManager::FindWindowAt(const gfx::Rect& bounds) const {
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
index d7ac2810b53..c102c52525d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -68,7 +68,7 @@ class ScreenManager {
void RemoveDisplayControllers(const CrtcsWithDrmList& controllers_to_remove);
// Enables/Disables the display controller based on if a mode exists.
- base::flat_map<int64_t, bool> ConfigureDisplayControllers(
+ bool ConfigureDisplayControllers(
const ControllerConfigsList& controllers_params);
// Returns a reference to the display controller configured to display within
@@ -98,6 +98,9 @@ class ScreenManager {
std::vector<std::unique_ptr<HardwareDisplayController>>;
using WidgetToWindowMap =
std::unordered_map<gfx::AcceleratedWidget, std::unique_ptr<DrmWindow>>;
+ using CrtcPreferredModifierMap = base::flat_map<
+ uint32_t /*crtc_is*/,
+ std::pair<bool /*modifiers_list.empty()*/, uint64_t /*picked_modifier*/>>;
// Returns an iterator into |controllers_| for the controller identified by
// (|crtc|, |connector|).
@@ -105,13 +108,21 @@ class ScreenManager {
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc);
- base::flat_map<int64_t, bool> TestAndModeset(
+ bool TestAndSetPreferredModifiers(
const ControllerConfigsList& controllers_params);
-
- bool TestModeset(const ControllerConfigsList& controllers_params);
-
- base::flat_map<int64_t, bool> Modeset(
+ bool TestAndSetLinearModifier(
const ControllerConfigsList& controllers_params);
+ // Setting the Preferred modifiers that passed from one of the Modeset Test
+ // functions. The preferred modifiers are used in Modeset.
+ void SetPreferredModifiers(
+ const ControllerConfigsList& controllers_params,
+ const CrtcPreferredModifierMap& crtcs_preferred_modifier);
+ // The planes used for modesetting can have overlays beside the primary, test
+ // if we can modeset with them. If not, return false to indicate that we must
+ // only use the primary plane.
+ bool TestModesetWithOverlays(const ControllerConfigsList& controllers_params);
+ bool Modeset(const ControllerConfigsList& controllers_params,
+ bool can_modeset_with_overlays);
// Configures a display controller to be enabled. The display controller is
// identified by (|crtc|, |connector|) and the controller is to be modeset
@@ -123,7 +134,7 @@ class ScreenManager {
uint32_t connector,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
// Configures a display controller to be disabled. The display controller is
// identified by |crtc|. Controller modeset props are added into
@@ -135,12 +146,13 @@ class ScreenManager {
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc);
- void UpdateControllerStateAfterModeset(const ControllerConfigParams& config,
+ void UpdateControllerStateAfterModeset(const scoped_refptr<DrmDevice>& drm,
const CommitRequest& commit_request,
bool did_succeed);
void HandleMirrorIfExists(
- const ControllerConfigParams& config,
+ const scoped_refptr<DrmDevice>& drm,
+ const CrtcCommitRequest& crtc_request,
const HardwareDisplayControllers::iterator& controller);
// Returns an iterator into |controllers_| for the controller located at
@@ -154,19 +166,21 @@ class ScreenManager {
const scoped_refptr<DrmDevice>& drm,
const gfx::Rect& bounds);
- DrmOverlayPlane GetModesetBuffer(HardwareDisplayController* controller,
- const gfx::Rect& bounds,
- const std::vector<uint64_t>& modifiers);
+ DrmOverlayPlaneList GetModesetPlanes(HardwareDisplayController* controller,
+ const gfx::Rect& bounds,
+ const std::vector<uint64_t>& modifiers,
+ bool include_overlays,
+ bool is_testing);
// Gets props for modesetting the |controller| using |origin| and |mode|.
void GetModesetControllerProps(CommitRequest* commit_request,
HardwareDisplayController* controller,
const gfx::Point& origin,
const drmModeModeInfo& mode,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
void GetEnableControllerProps(CommitRequest* commit_request,
HardwareDisplayController* controller,
- const DrmOverlayPlane& primary);
+ const DrmOverlayPlaneList& modeset_planes);
DrmWindow* FindWindowAt(const gfx::Rect& bounds) const;
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index d4a1a691a1e..a98d358da52 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -47,6 +47,7 @@ constexpr uint32_t kSecondaryConnector = kConnectorIdBase + 1;
constexpr uint32_t kPlaneIdBase = 300;
constexpr uint32_t kInFormatsBlobPropIdBase = 400;
+constexpr uint32_t kFbIdPropId = 3005;
constexpr uint32_t kTypePropId = 3010;
constexpr uint32_t kInFormatsPropId = 3011;
@@ -81,7 +82,8 @@ class ScreenManagerTest : public testing::Test {
void InitializeDrmState(ui::MockDrmDevice* drm,
const std::vector<CrtcState>& crtc_states,
- bool is_atomic = true) {
+ bool is_atomic,
+ bool use_modifiers_list = false) {
std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(
crtc_states.size());
std::map<uint32_t, std::string> crtc_property_names = {
@@ -109,7 +111,7 @@ class ScreenManagerTest : public testing::Test {
{3002, "CRTC_Y"},
{3003, "CRTC_W"},
{3004, "CRTC_H"},
- {3005, "FB_ID"},
+ {kFbIdPropId, "FB_ID"},
{3006, "SRC_X"},
{3007, "SRC_Y"},
{3008, "SRC_W"},
@@ -143,9 +145,17 @@ class ScreenManagerTest : public testing::Test {
: DRM_PLANE_TYPE_OVERLAY;
} else if (pair.first == kInFormatsPropId) {
value = property_id++;
+ std::vector<drm_format_modifier> drm_format_modifiers;
+ if (use_modifiers_list) {
+ for (const auto modifier : supported_modifiers_) {
+ drm_format_modifiers.push_back(
+ {/*formats=*/1, /*offset=*/0, /*pad=*/0, modifier});
+ }
+ }
+
drm->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
value, crtc_states[crtc_idx].planes[plane_idx].formats,
- std::vector<drm_format_modifier>()));
+ std::move(drm_format_modifiers)));
}
crtc_plane_properties[plane_idx].properties.push_back(
@@ -165,12 +175,15 @@ class ScreenManagerTest : public testing::Test {
connector_property_names.end());
property_names.insert(plane_property_names.begin(),
plane_property_names.end());
+
+ drm->SetModifiersOverhead(modifiers_overhead_);
drm->InitializeState(crtc_properties, connector_properties,
plane_properties, property_names, is_atomic);
}
void InitializeDrmStateWithDefault(ui::MockDrmDevice* drm,
- bool is_atomic = true) {
+ bool is_atomic,
+ bool use_modifiers_list = false) {
// A Sample of CRTC states.
std::vector<CrtcState> crtc_states = {
{/* .planes = */
@@ -182,11 +195,12 @@ class ScreenManagerTest : public testing::Test {
{/* .formats = */ {DRM_FORMAT_XRGB8888}},
}},
};
- InitializeDrmState(drm, crtc_states, is_atomic);
+ InitializeDrmState(drm, crtc_states, is_atomic, use_modifiers_list);
}
void SetUp() override {
auto gbm = std::make_unique<ui::MockGbmDevice>();
+ supported_modifiers_ = gbm->GetSupportedModifiers();
drm_ = new ui::MockDrmDevice(std::move(gbm));
device_manager_ = std::make_unique<ui::DrmDeviceManager>(nullptr);
screen_manager_ = std::make_unique<ui::ScreenManager>();
@@ -218,6 +232,10 @@ class ScreenManagerTest : public testing::Test {
scoped_refptr<ui::MockDrmDevice> drm_;
std::unique_ptr<ui::DrmDeviceManager> device_manager_;
std::unique_ptr<ui::ScreenManager> screen_manager_;
+ std::vector<uint64_t> supported_modifiers_;
+ base::flat_map<uint64_t /*modifier*/, int /*overhead*/> modifiers_overhead_{
+ {DRM_FORMAT_MOD_LINEAR, 1},
+ {I915_FORMAT_MOD_Yf_TILED_CCS, 100}};
private:
DISALLOW_COPY_AND_ASSIGN(ScreenManagerTest);
@@ -231,7 +249,7 @@ TEST_F(ScreenManagerTest, CheckWithNoControllers) {
}
TEST_F(ScreenManagerTest, CheckWithValidController) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
@@ -252,7 +270,7 @@ TEST_F(ScreenManagerTest, CheckWithValidController) {
}
TEST_F(ScreenManagerTest, CheckWithInvalidBounds) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
@@ -268,7 +286,7 @@ TEST_F(ScreenManagerTest, CheckWithInvalidBounds) {
}
TEST_F(ScreenManagerTest, CheckForSecondValidController) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -287,14 +305,104 @@ TEST_F(ScreenManagerTest, CheckForSecondValidController) {
screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
EXPECT_EQ(drm_->get_test_modeset_count(), 1);
- EXPECT_EQ(drm_->get_commit_modeset_count(), 2);
+ EXPECT_EQ(drm_->get_commit_modeset_count(), 1);
EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
EXPECT_TRUE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
}
+TEST_F(ScreenManagerTest, CheckMultipleDisplaysWithinModifiersLimit) {
+ int max_supported_displays_with_modifier = 2;
+ drm_->SetSystemLimitOfModifiers(
+ modifiers_overhead_[I915_FORMAT_MOD_Yf_TILED_CCS] *
+ max_supported_displays_with_modifier);
+
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true,
+ /*use_modifiers_list=*/true);
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
+ kSecondaryConnector);
+
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ drmModeModeInfo secondary_mode = kDefaultMode;
+ controllers_to_enable.emplace_back(
+ kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
+ GetSecondaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(secondary_mode));
+ EXPECT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 1);
+ EXPECT_EQ(drm_->get_commit_modeset_count(), 1);
+}
+
+TEST_F(ScreenManagerTest, CheckMultipleDisplaysOutsideModifiersLimit) {
+ int max_supported_displays_with_modifier = 2;
+ drm_->SetSystemLimitOfModifiers(modifiers_overhead_[DRM_FORMAT_MOD_LINEAR] *
+ max_supported_displays_with_modifier);
+
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true,
+ /*use_modifiers_list=*/true);
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
+ kSecondaryConnector);
+
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ drmModeModeInfo secondary_mode = kDefaultMode;
+ controllers_to_enable.emplace_back(
+ kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
+ GetSecondaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(secondary_mode));
+ EXPECT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ // Testing for a failed test-modeset with modifiers + a fallback to Linear
+ // Modifier and a modeset commit.
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->get_commit_modeset_count(), 1);
+}
+
+TEST_F(ScreenManagerTest, CheckDisplaysWith0Limit) {
+ drm_->SetSystemLimitOfModifiers(0);
+
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true,
+ /*use_modifiers_list=*/true);
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
+ kSecondaryConnector);
+
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ drmModeModeInfo secondary_mode = kDefaultMode;
+ controllers_to_enable.emplace_back(
+ kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
+ GetSecondaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(secondary_mode));
+ EXPECT_FALSE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ // Testing for a failed test-modeset with modifiers + failed test-modeset with
+ // Linear Modifier and no modeset due to failed tests.
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->get_commit_modeset_count(), 0);
+}
+
TEST_F(ScreenManagerTest, CheckControllerAfterItIsRemoved) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
@@ -314,7 +422,7 @@ TEST_F(ScreenManagerTest, CheckControllerAfterItIsRemoved) {
}
TEST_F(ScreenManagerTest, CheckControllerAfterDisabled) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
// Enable
@@ -344,7 +452,7 @@ TEST_F(ScreenManagerTest, CheckControllerAfterDisabled) {
}
TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingRemoved) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -375,7 +483,7 @@ TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingRemoved) {
}
TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingDisabled) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
kSecondaryConnector);
@@ -407,7 +515,7 @@ TEST_F(ScreenManagerTest, CheckMultipleControllersAfterBeingDisabled) {
EXPECT_EQ(drm_->get_test_modeset_count(),
test_modeset_count_before_disable + 1);
EXPECT_EQ(drm_->get_commit_modeset_count(),
- commit_modeset_count_before_disable + 2);
+ commit_modeset_count_before_disable + 1);
EXPECT_FALSE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
@@ -442,7 +550,7 @@ TEST_F(ScreenManagerTest, CheckDuplicateConfiguration) {
}
TEST_F(ScreenManagerTest, CheckChangingMode) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
@@ -478,7 +586,7 @@ TEST_F(ScreenManagerTest, CheckChangingMode) {
}
TEST_F(ScreenManagerTest, CheckForControllersInMirroredMode) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -517,7 +625,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeTransitions) {
},
},
};
- InitializeDrmState(drm_.get(), crtc_states);
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -574,7 +682,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeTransitions) {
// Make sure we're using each display's mode when doing mirror mode otherwise
// the timings may be off.
TEST_F(ScreenManagerTest, CheckMirrorModeModesettingWithDisplaysMode) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -609,7 +717,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeModesettingWithDisplaysMode) {
}
TEST_F(ScreenManagerTest, MonitorGoneInMirrorMode) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -641,23 +749,29 @@ TEST_F(ScreenManagerTest, MonitorGoneInMirrorMode) {
}
TEST_F(ScreenManagerTest, MonitorDisabledInMirrorMode) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
kSecondaryConnector);
- ScreenManager::ControllerConfigsList controllers_to_enable;
- controllers_to_enable.emplace_back(
- kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
- GetPrimaryBounds().origin(),
- std::make_unique<drmModeModeInfo>(kDefaultMode));
- drmModeModeInfo secondary_mode = kDefaultMode;
- controllers_to_enable.emplace_back(
- kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
- GetPrimaryBounds().origin(),
- std::make_unique<drmModeModeInfo>(secondary_mode));
+ // Enable in Mirror Mode.
+ {
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ drmModeModeInfo secondary_mode = kDefaultMode;
+ controllers_to_enable.emplace_back(
+ kSecondaryDisplayId, drm_, kSecondaryCrtc, kSecondaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(secondary_mode));
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
+ }
+
// Disable display Controller.
+ ScreenManager::ControllerConfigsList controllers_to_enable;
controllers_to_enable.emplace_back(0, drm_, kSecondaryCrtc, 0, gfx::Point(),
nullptr);
screen_manager_->ConfigureDisplayControllers(controllers_to_enable);
@@ -672,7 +786,7 @@ TEST_F(ScreenManagerTest, MonitorDisabledInMirrorMode) {
}
TEST_F(ScreenManagerTest, DoNotEnterMirrorModeUnlessSameBounds) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -741,7 +855,7 @@ TEST_F(ScreenManagerTest, ReuseFramebufferIfDisabledThenReEnabled) {
}
TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm_, kSecondaryCrtc,
@@ -839,8 +953,8 @@ TEST_F(ScreenManagerTest,
scoped_refptr<ui::MockDrmDevice> drm2 =
new ui::MockDrmDevice(std::move(gbm_device));
- InitializeDrmStateWithDefault(drm_.get());
- InitializeDrmStateWithDefault(drm2.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+ InitializeDrmStateWithDefault(drm2.get(), /*is_atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector);
@@ -868,7 +982,7 @@ TEST_F(ScreenManagerTest,
}
TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithSameBounds) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
std::unique_ptr<ui::DrmWindow> window(
new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
@@ -891,7 +1005,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithSameBounds) {
}
TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
std::unique_ptr<ui::DrmWindow> window(
new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
@@ -917,7 +1031,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) {
TEST_F(ScreenManagerTest,
CheckControllerToWindowMappingWithOverlappingWindows) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
const size_t kWindowCount = 2;
for (size_t i = 1; i < kWindowCount + 1; ++i) {
@@ -948,7 +1062,7 @@ TEST_F(ScreenManagerTest,
}
TEST_F(ScreenManagerTest, ShouldDissociateWindowOnControllerRemoval) {
- InitializeDrmStateWithDefault(drm_.get());
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
gfx::AcceleratedWidget window_id = 1;
std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow(
@@ -1105,12 +1219,12 @@ TEST_F(ScreenManagerTest, ShouldNotHardwareMirrorDifferentDrmDevices) {
auto gbm_device1 = std::make_unique<MockGbmDevice>();
auto drm_device1 =
base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device1));
- InitializeDrmStateWithDefault(drm_device1.get());
+ InitializeDrmStateWithDefault(drm_device1.get(), /*is_atomic=*/true);
auto gbm_device2 = std::make_unique<MockGbmDevice>();
auto drm_device2 =
base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device2));
- InitializeDrmStateWithDefault(drm_device2.get());
+ InitializeDrmStateWithDefault(drm_device2.get(), /*is_atomic=*/true);
DrmDeviceManager drm_device_manager(nullptr);
ScreenManager screen_manager;
@@ -1310,4 +1424,315 @@ TEST_F(ScreenManagerTest, ShouldNotUnbindFramebufferOnJoiningMirror) {
screen_manager.RemoveWindow(1)->Shutdown();
}
+TEST_F(ScreenManagerTest, DrmFramebufferSequenceIdIncrementingAtModeset) {
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+
+ scoped_refptr<DrmFramebuffer> pre_modeset_buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ CHECK_EQ(pre_modeset_buffer->modeset_sequence_id_at_allocation(), 0);
+
+ // Successful modeset
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ {
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+ }
+
+ scoped_refptr<DrmFramebuffer> first_post_modeset_buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ CHECK_EQ(first_post_modeset_buffer->modeset_sequence_id_at_allocation(), 1);
+ CHECK_EQ(pre_modeset_buffer->modeset_sequence_id_at_allocation(), 0);
+
+ // Unsuccessful modeset
+ {
+ drm_->set_set_crtc_expectation(false);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetSecondaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_FALSE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+ }
+
+ scoped_refptr<DrmFramebuffer> second_post_modeset_buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ CHECK_EQ(second_post_modeset_buffer->modeset_sequence_id_at_allocation(), 1);
+ CHECK_EQ(first_post_modeset_buffer->modeset_sequence_id_at_allocation(), 1);
+ CHECK_EQ(pre_modeset_buffer->modeset_sequence_id_at_allocation(), 0);
+}
+
+TEST_F(ScreenManagerTest, CloningPlanesOnModeset) {
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ buffer));
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, CloningMultiplePlanesOnModeset) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesNoOverlays) {
+ InitializeDrmStateWithDefault(drm_.get(), /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> buffer =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(buffer, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+ ASSERT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ buffer));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 1);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesWithOverlaySucceeding) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 2);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithClonedPlanesWithOverlayFailing) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true);
+
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ drm_->set_overlay_modeset_expecation(false);
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ EXPECT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_TRUE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ EXPECT_EQ(drm_->get_test_modeset_count(), 2);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
+TEST_F(ScreenManagerTest, ModesetWithNewBuffersOnModifiersChange) {
+ std::vector<CrtcState> crtc_states = {{
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
+ }};
+ InitializeDrmState(drm_.get(), crtc_states, /*is_atomic=*/true,
+ /*use_modifiers_list=*/true);
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+
+ scoped_refptr<DrmFramebuffer> primary =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ scoped_refptr<DrmFramebuffer> overlay =
+ CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size());
+ ui::DrmOverlayPlaneList planes;
+ planes.push_back(ui::DrmOverlayPlane(primary, nullptr));
+ planes.push_back(ui::DrmOverlayPlane(overlay, nullptr));
+ window->SchedulePageFlip(std::move(planes), base::DoNothing(),
+ base::DoNothing());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ ScreenManager::ControllerConfigsList controllers_to_enable;
+ controllers_to_enable.emplace_back(
+ kPrimaryDisplayId, drm_, kPrimaryCrtc, kPrimaryConnector,
+ GetPrimaryBounds().origin(),
+ std::make_unique<drmModeModeInfo>(kDefaultMode));
+ ASSERT_TRUE(
+ screen_manager_->ConfigureDisplayControllers(controllers_to_enable));
+
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ primary));
+ EXPECT_FALSE(base::Contains(drm_->plane_manager()
+ ->GetCrtcStateForCrtcId(kPrimaryCrtc)
+ .modeset_framebuffers,
+ overlay));
+
+ // Testing test modifiers only, no linear or overlays test.
+ EXPECT_EQ(drm_->get_test_modeset_count(), 1);
+ EXPECT_EQ(drm_->last_planes_committed_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
} // namespace ui