Commit bb1059e5 authored by Michael Spang's avatar Michael Spang Committed by Commit Bot

ozone: drm: Clean up error handling around page flips

The page flip code mixes two error handling styles and in many cases
returns the same status (or in some cases, inconsistent statuses) through
the return value and also via the SwapCompletionCallback.

The page flip code also supports two modes: real page flips and test page
flips, which are used to validate configurations before use. Real page
flips crash the GPU process if the return value indicates failure, but
obviously this is not expected to occur so in practice those always
return success, and pass status information through the
SwapCompletionCallback. Test page flips are the opposite: they must
return their status in the return value, and pass a dummy completion
callback which ignores its arguments.

There are actually no asynchronous failure cases, despite a fair amount
of code trying to account for that possibility such as the coalescing of
SwapResults in PageFlipRequest. We can take advantage of this to avoid
passing the SwapCompletionCallback into most functions, and simply use
the return value as the only status return. The only complication is that
successful completion is always asynchronous, and may even require
tracking multiple underlying page flip events, as in hardware mirroring
scenarios.

This patch handles that issue by registering PageFlipCallbacks for all of
the individual page flip events as usual, but only passing ownership of
the SwapCompletionCallback into the PageFlipRequest at the last minute,
after all of the individual page flips have been submitted succesfully.

After hiding the SwapCompletionCallback from most of the DRM internals,
test page flips no longer need to construct a dummy
SwapCompletionCallback. They also don't need to construct any
PageFlipCallbacks, since they don't generate any page flip events - this
simplifies that logic as well by moving construction of each
PageFlipCallback to immediately after a successful page flip request.
Moving creation of those callbacks later also removes any requirement to
make manual calls to PageFlipRequest::Signal to fixup failure cases.

Since failures of real page flips triggered by SchedulePageFlip() simply
crash the process, there is no need for a return value. This patch moves
the CHECK() which cause these crashes inside of SchedulePageFlip(), and
removes the return value.

As a result, TestPageFlip() and all of the internal methods called via
ActualSchedulePageFlip() use return values exclusively for status
information, and never see the SwapCompletionCallback.
SchedulePageFlip(), on the other hand, receives the SwapCompletionCallack
and uses it exclusively for its status, and returns void.

Bug: 851997
Test: unit tests, various display configurations on cros

Change-Id: I87408275b0958281ef79a6b5086a38b2c3c08ee1
Reviewed-on: https://chromium-review.googlesource.com/1104859
Commit-Queue: Michael Spang <spang@chromium.org>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569973}
parent 0b43edaf
...@@ -34,13 +34,6 @@ CrtcController::~CrtcController() { ...@@ -34,13 +34,6 @@ CrtcController::~CrtcController() {
SetCursor(nullptr); SetCursor(nullptr);
drm_->DisableCrtc(crtc_); drm_->DisableCrtc(crtc_);
if (page_flip_request_) {
// The controller is being destroyed, so signal the pending page flip
// request with an empty presentation feedback which means the buffer
// is never presented on a screen.
SignalPageFlipRequest(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback::Failure());
}
} }
} }
...@@ -57,18 +50,8 @@ bool CrtcController::Modeset(const DrmOverlayPlane& plane, ...@@ -57,18 +50,8 @@ bool CrtcController::Modeset(const DrmOverlayPlane& plane,
} }
mode_ = mode; mode_ = mode;
pending_planes_.clear();
is_disabled_ = false; is_disabled_ = false;
// 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.
current_planes_.clear();
current_planes_.push_back(plane.Clone());
if (page_flip_request_.get())
pending_planes_ = DrmOverlayPlane::Clone(current_planes_);
ResetCursor(); ResetCursor();
return true; return true;
...@@ -82,12 +65,8 @@ bool CrtcController::Disable() { ...@@ -82,12 +65,8 @@ bool CrtcController::Disable() {
return drm_->DisableCrtc(crtc_); return drm_->DisableCrtc(crtc_);
} }
bool CrtcController::SchedulePageFlip( bool CrtcController::AssignOverlayPlanes(HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlaneList* plane_list, const DrmOverlayPlaneList& overlays) {
const DrmOverlayPlaneList& overlays,
bool test_only,
scoped_refptr<PageFlipRequest> page_flip_request) {
DCHECK(!page_flip_request_.get() || test_only);
DCHECK(!is_disabled_); DCHECK(!is_disabled_);
const DrmOverlayPlane* primary = DrmOverlayPlane::GetPrimaryPlane(overlays); const DrmOverlayPlane* primary = DrmOverlayPlane::GetPrimaryPlane(overlays);
...@@ -96,30 +75,15 @@ bool CrtcController::SchedulePageFlip( ...@@ -96,30 +75,15 @@ bool CrtcController::SchedulePageFlip(
<< mode_.hdisplay << "x" << mode_.vdisplay << " got " << mode_.hdisplay << "x" << mode_.vdisplay << " got "
<< primary->buffer->GetSize().ToString() << " for" << primary->buffer->GetSize().ToString() << " for"
<< " crtc=" << crtc_ << " connector=" << connector_; << " crtc=" << crtc_ << " connector=" << connector_;
page_flip_request->Signal(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback::Failure());
return true; return true;
} }
if (!drm_->plane_manager()->AssignOverlayPlanes(plane_list, overlays, crtc_, if (!drm_->plane_manager()->AssignOverlayPlanes(plane_list, overlays, crtc_,
this)) { this)) {
PLOG(ERROR) << "Failed to assign overlay planes for crtc " << crtc_; PLOG(ERROR) << "Failed to assign overlay planes for crtc " << crtc_;
page_flip_request->Signal(gfx::SwapResult::SWAP_FAILED,
gfx::PresentationFeedback::Failure());
return false; return false;
} }
if (test_only) {
// If |test_only| is true, we just verify overlay configuration and don't
// present anything on a screen, so signal the request with an empty
// presentation feedback.
page_flip_request->Signal(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback());
} else {
pending_planes_ = DrmOverlayPlane::Clone(overlays);
page_flip_request_ = page_flip_request;
}
return true; return true;
} }
...@@ -127,24 +91,6 @@ std::vector<uint64_t> CrtcController::GetFormatModifiers(uint32_t format) { ...@@ -127,24 +91,6 @@ std::vector<uint64_t> CrtcController::GetFormatModifiers(uint32_t format) {
return drm_->plane_manager()->GetFormatModifiers(crtc_, format); return drm_->plane_manager()->GetFormatModifiers(crtc_, format);
} }
void CrtcController::OnPageFlipEvent(unsigned int frame,
base::TimeTicks timestamp) {
time_of_last_flip_ = timestamp;
// For Ozone DRM, the page flip is aligned with VSYNC, and the timestamp is
// provided by kernel DRM driver (kHWClock) and the buffer has been presented
// on the screen (kHWCompletion).
const uint32_t kFlags = gfx::PresentationFeedback::Flags::kVSync |
gfx::PresentationFeedback::Flags::kHWClock |
gfx::PresentationFeedback::Flags::kHWCompletion;
SignalPageFlipRequest(
gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback(
time_of_last_flip_,
mode_.vrefresh ? base::TimeDelta::FromSeconds(1) / mode_.vrefresh
: base::TimeDelta(),
kFlags));
}
bool CrtcController::SetCursor(const scoped_refptr<ScanoutBuffer>& buffer) { bool CrtcController::SetCursor(const scoped_refptr<ScanoutBuffer>& buffer) {
DCHECK(!is_disabled_ || !buffer); DCHECK(!is_disabled_ || !buffer);
cursor_buffer_ = buffer; cursor_buffer_ = buffer;
...@@ -176,17 +122,4 @@ bool CrtcController::ResetCursor() { ...@@ -176,17 +122,4 @@ bool CrtcController::ResetCursor() {
return status; return status;
} }
void CrtcController::SignalPageFlipRequest(
gfx::SwapResult result,
const gfx::PresentationFeedback& feedback) {
if (result == gfx::SwapResult::SWAP_ACK)
current_planes_.swap(pending_planes_);
pending_planes_.clear();
scoped_refptr<PageFlipRequest> request;
request.swap(page_flip_request_);
request->Signal(result, feedback);
}
} // namespace ui } // namespace ui
...@@ -18,21 +18,16 @@ ...@@ -18,21 +18,16 @@
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h" #include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
namespace gfx {
struct PresentationFeedback;
} // namespace gfx
namespace ui { namespace ui {
class DrmDevice; class DrmDevice;
class PageFlipRequest;
// Wrapper around a CRTC. // Wrapper around a CRTC.
// //
// One CRTC can be paired up with one or more connectors. The simplest // One CRTC can be paired up with one or more connectors. The simplest
// configuration represents one CRTC driving one monitor, while pairing up a // configuration represents one CRTC driving one monitor, while pairing up a
// CRTC with multiple connectors results in hardware mirroring. // CRTC with multiple connectors results in hardware mirroring.
class CrtcController : public base::SupportsWeakPtr<CrtcController> { class CrtcController {
public: public:
CrtcController(const scoped_refptr<DrmDevice>& drm, CrtcController(const scoped_refptr<DrmDevice>& drm,
uint32_t crtc, uint32_t crtc,
...@@ -44,7 +39,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> { ...@@ -44,7 +39,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
uint32_t connector() const { return connector_; } uint32_t connector() const { return connector_; }
const scoped_refptr<DrmDevice>& drm() const { return drm_; } const scoped_refptr<DrmDevice>& drm() const { return drm_; }
bool is_disabled() const { return is_disabled_; } bool is_disabled() const { return is_disabled_; }
base::TimeTicks time_of_last_flip() const { return time_of_last_flip_; }
// Perform the initial modesetting operation using |plane| as the buffer for // Perform the initial modesetting operation using |plane| as the buffer for
// the primary plane. The CRTC configuration is specified by |mode|. // the primary plane. The CRTC configuration is specified by |mode|.
...@@ -53,11 +47,8 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> { ...@@ -53,11 +47,8 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
// Disables the controller. // Disables the controller.
bool Disable(); bool Disable();
// Schedule a page flip event and present the overlays in |planes|. bool AssignOverlayPlanes(HardwareDisplayPlaneList* plane_list,
bool SchedulePageFlip(HardwareDisplayPlaneList* plane_list, const DrmOverlayPlaneList& planes);
const DrmOverlayPlaneList& planes,
bool test_only,
scoped_refptr<PageFlipRequest> page_flip_request);
// Returns a vector of format modifiers for the given fourcc format // Returns a vector of format modifiers for the given fourcc format
// on this CRTCs primary plane. A format modifier describes the // on this CRTCs primary plane. A format modifier describes the
...@@ -69,16 +60,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> { ...@@ -69,16 +60,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
// gbm will pick a modifier as it allocates the bo. // gbm will pick a modifier as it allocates the bo.
std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format); std::vector<uint64_t> GetFormatModifiers(uint32_t fourcc_format);
// Called if the page flip event wasn't scheduled (ie: page flip fails). This
// will then signal the request such that the caller doesn't wait for the
// event forever.
void SignalPageFlipRequest(gfx::SwapResult result,
const gfx::PresentationFeedback& feedback);
// Called when the page flip event occurred. The event is provided by the
// kernel when a VBlank event finished. This allows the controller to
// update internal state and propagate the update to the surface.
void OnPageFlipEvent(unsigned int frame, base::TimeTicks timestamp);
bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer); bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
bool MoveCursor(const gfx::Point& location); bool MoveCursor(const gfx::Point& location);
...@@ -90,10 +71,7 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> { ...@@ -90,10 +71,7 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
// Buffers need to be declared first so that they are destroyed last. Needed // Buffers need to be declared first so that they are destroyed last. Needed
// since the controllers may reference the buffers. // since the controllers may reference the buffers.
DrmOverlayPlaneList current_planes_;
DrmOverlayPlaneList pending_planes_;
scoped_refptr<ScanoutBuffer> cursor_buffer_; scoped_refptr<ScanoutBuffer> cursor_buffer_;
scoped_refptr<PageFlipRequest> page_flip_request_;
uint32_t crtc_; uint32_t crtc_;
...@@ -106,9 +84,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> { ...@@ -106,9 +84,6 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
// is set to false. Otherwise it is true. // is set to false. Otherwise it is true.
bool is_disabled_ = true; bool is_disabled_ = true;
// The time of the last page flip event as reported by the kernel callback.
base::TimeTicks time_of_last_flip_;
DISALLOW_COPY_AND_ASSIGN(CrtcController); DISALLOW_COPY_AND_ASSIGN(CrtcController);
}; };
......
...@@ -363,7 +363,7 @@ bool DrmDevice::RemoveFramebuffer(uint32_t framebuffer) { ...@@ -363,7 +363,7 @@ bool DrmDevice::RemoveFramebuffer(uint32_t framebuffer) {
bool DrmDevice::PageFlip(uint32_t crtc_id, bool DrmDevice::PageFlip(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
PageFlipCallback callback) { scoped_refptr<PageFlipRequest> page_flip_request) {
DCHECK(file_.IsValid()); DCHECK(file_.IsValid());
TRACE_EVENT2("drm", "DrmDevice::PageFlip", "crtc", crtc_id, "framebuffer", TRACE_EVENT2("drm", "DrmDevice::PageFlip", "crtc", crtc_id, "framebuffer",
framebuffer); framebuffer);
...@@ -374,7 +374,8 @@ bool DrmDevice::PageFlip(uint32_t crtc_id, ...@@ -374,7 +374,8 @@ bool DrmDevice::PageFlip(uint32_t crtc_id,
if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer, if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer,
DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) { DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) {
// If successful the payload will be removed by a PageFlip event. // If successful the payload will be removed by a PageFlip event.
page_flip_manager_->RegisterCallback(id, 1, std::move(callback)); page_flip_manager_->RegisterCallback(id, 1,
page_flip_request->AddPageFlip());
return true; return true;
} }
...@@ -558,20 +559,23 @@ bool DrmDevice::CloseBufferHandle(uint32_t handle) { ...@@ -558,20 +559,23 @@ bool DrmDevice::CloseBufferHandle(uint32_t handle) {
&close_request); &close_request);
} }
bool DrmDevice::CommitProperties(drmModeAtomicReq* properties, bool DrmDevice::CommitProperties(
uint32_t flags, drmModeAtomicReq* properties,
uint32_t crtc_count, uint32_t flags,
PageFlipCallback callback) { uint32_t crtc_count,
scoped_refptr<PageFlipRequest> page_flip_request) {
uint64_t id = 0; uint64_t id = 0;
bool page_flip_event_requested = flags & DRM_MODE_PAGE_FLIP_EVENT; if (page_flip_request) {
flags |= DRM_MODE_PAGE_FLIP_EVENT;
if (page_flip_event_requested)
id = page_flip_manager_->GetNextId(); id = page_flip_manager_->GetNextId();
}
if (!drmModeAtomicCommit(file_.GetPlatformFile(), properties, flags, if (!drmModeAtomicCommit(file_.GetPlatformFile(), properties, flags,
reinterpret_cast<void*>(id))) { reinterpret_cast<void*>(id))) {
if (page_flip_event_requested) if (page_flip_request) {
page_flip_manager_->RegisterCallback(id, crtc_count, std::move(callback)); page_flip_manager_->RegisterCallback(id, crtc_count,
page_flip_request->AddPageFlip());
}
return true; return true;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ui/gfx/overlay_transform.h" #include "ui/gfx/overlay_transform.h"
#include "ui/ozone/common/linux/gbm_device_linux.h" #include "ui/ozone/common/linux/gbm_device_linux.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h" #include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
typedef struct _drmEventContext drmEventContext; typedef struct _drmEventContext drmEventContext;
typedef struct _drmModeModeInfo drmModeModeInfo; typedef struct _drmModeModeInfo drmModeModeInfo;
...@@ -139,9 +140,12 @@ class DrmDevice : public GbmDeviceLinux, ...@@ -139,9 +140,12 @@ class DrmDevice : public GbmDeviceLinux,
// immediately. Upon completion of the pageflip event, the CRTC will be // immediately. Upon completion of the pageflip event, the CRTC will be
// displaying the buffer with ID |framebuffer| and will have a DRM event // displaying the buffer with ID |framebuffer| and will have a DRM event
// queued on |fd_|. // queued on |fd_|.
//
// On success, true is returned and |page_flip_request| will receive a
// callback signalling completion of the flip.
virtual bool PageFlip(uint32_t crtc_id, virtual bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
PageFlipCallback callback); scoped_refptr<PageFlipRequest> page_flip_request);
// Schedule an overlay to be show during the page flip for CRTC |crtc_id|. // Schedule an overlay to be show during the page flip for CRTC |crtc_id|.
// |source| location from |framebuffer| will be shown on overlay // |source| location from |framebuffer| will be shown on overlay
...@@ -222,10 +226,13 @@ class DrmDevice : public GbmDeviceLinux, ...@@ -222,10 +226,13 @@ class DrmDevice : public GbmDeviceLinux,
virtual bool CloseBufferHandle(uint32_t handle); virtual bool CloseBufferHandle(uint32_t handle);
virtual bool CommitProperties(drmModeAtomicReq* properties, // On success, true is returned and |page_flip_request| will receive a
uint32_t flags, // callback signalling completion of the flip, if provided.
uint32_t crtc_count, virtual bool CommitProperties(
PageFlipCallback callback); drmModeAtomicReq* properties,
uint32_t flags,
uint32_t crtc_count,
scoped_refptr<PageFlipRequest> page_flip_request);
virtual bool SetCapability(uint64_t capability, uint64_t value); virtual bool SetCapability(uint64_t capability, uint64_t value);
......
...@@ -97,7 +97,7 @@ void DrmOverlayValidatorTest::SetUp() { ...@@ -97,7 +97,7 @@ void DrmOverlayValidatorTest::SetUp() {
last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED;
message_loop_.reset(new base::MessageLoopForUI); message_loop_.reset(new base::MessageLoopForUI);
drm_ = new ui::MockDrmDevice(false); drm_ = new ui::MockDrmDevice;
CrtcState crtc_state = {.planes = { CrtcState crtc_state = {.planes = {
{.formats = {DRM_FORMAT_XRGB8888}}, {.formats = {DRM_FORMAT_XRGB8888}},
......
...@@ -218,12 +218,10 @@ void DrmThread::OnPlanesReadyForPageFlip(gfx::AcceleratedWidget widget, ...@@ -218,12 +218,10 @@ void DrmThread::OnPlanesReadyForPageFlip(gfx::AcceleratedWidget widget,
std::vector<DrmOverlayPlane> planes) { std::vector<DrmOverlayPlane> planes) {
DrmWindow* window = screen_manager_->GetWindow(widget); DrmWindow* window = screen_manager_->GetWindow(widget);
if (window) { if (window) {
bool result = window->SchedulePageFlip(std::move(planes), std::move(callback));
window->SchedulePageFlip(std::move(planes), std::move(callback));
CHECK(result) << "DrmThread::SchedulePageFlip failed.";
} else { } else {
std::move(callback).Run(gfx::SwapResult::SWAP_ACK, std::move(callback).Run(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback()); gfx::PresentationFeedback::Failure());
} }
} }
......
...@@ -114,7 +114,7 @@ void DrmWindow::MoveCursor(const gfx::Point& location) { ...@@ -114,7 +114,7 @@ void DrmWindow::MoveCursor(const gfx::Point& location) {
controller_->MoveCursor(location); controller_->MoveCursor(location);
} }
bool DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes, void DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes,
SwapCompletionOnceCallback callback) { SwapCompletionOnceCallback callback) {
if (controller_) { if (controller_) {
const DrmDevice* drm = controller_->GetDrmDevice().get(); const DrmDevice* drm = controller_->GetDrmDevice().get();
...@@ -133,7 +133,7 @@ bool DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes, ...@@ -133,7 +133,7 @@ bool DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes,
force_buffer_reallocation_ = false; force_buffer_reallocation_ = false;
std::move(callback).Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS, std::move(callback).Run(gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS,
gfx::PresentationFeedback::Failure()); gfx::PresentationFeedback::Failure());
return true; return;
} }
last_submitted_planes_ = DrmOverlayPlane::Clone(planes); last_submitted_planes_ = DrmOverlayPlane::Clone(planes);
...@@ -141,10 +141,10 @@ bool DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes, ...@@ -141,10 +141,10 @@ bool DrmWindow::SchedulePageFlip(std::vector<DrmOverlayPlane> planes,
if (!controller_) { if (!controller_) {
std::move(callback).Run(gfx::SwapResult::SWAP_ACK, std::move(callback).Run(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback::Failure()); gfx::PresentationFeedback::Failure());
return true; return;
} }
return controller_->SchedulePageFlip(std::move(planes), std::move(callback)); controller_->SchedulePageFlip(std::move(planes), std::move(callback));
} }
std::vector<OverlayCheckReturn_Params> DrmWindow::TestPageFlip( std::vector<OverlayCheckReturn_Params> DrmWindow::TestPageFlip(
......
...@@ -85,7 +85,7 @@ class DrmWindow { ...@@ -85,7 +85,7 @@ class DrmWindow {
// Move the HW cursor to the specified location. // Move the HW cursor to the specified location.
void MoveCursor(const gfx::Point& location); void MoveCursor(const gfx::Point& location);
bool SchedulePageFlip(std::vector<DrmOverlayPlane> planes, void SchedulePageFlip(std::vector<DrmOverlayPlane> planes,
SwapCompletionOnceCallback callback); SwapCompletionOnceCallback callback);
std::vector<OverlayCheckReturn_Params> TestPageFlip( std::vector<OverlayCheckReturn_Params> TestPageFlip(
const std::vector<OverlayCheck_Params>& overlay_params); const std::vector<OverlayCheck_Params>& overlay_params);
......
...@@ -99,7 +99,7 @@ void DrmWindowTest::SetUp() { ...@@ -99,7 +99,7 @@ void DrmWindowTest::SetUp() {
last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED;
message_loop_.reset(new base::MessageLoopForUI); message_loop_.reset(new base::MessageLoopForUI);
drm_ = new ui::MockDrmDevice(false); drm_ = new ui::MockDrmDevice;
buffer_generator_.reset(new ui::MockDumbBufferGenerator()); buffer_generator_.reset(new ui::MockDumbBufferGenerator());
screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector); screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector);
...@@ -156,7 +156,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) { ...@@ -156,7 +156,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) {
gfx::Point(4, 2), 0); gfx::Point(4, 2), 0);
// Add another device. // Add another device.
scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice(false); scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice;
screen_manager_->AddDisplayController(drm, kDefaultCrtc, kDefaultConnector); screen_manager_->AddDisplayController(drm, kDefaultCrtc, kDefaultConnector);
screen_manager_->ConfigureDisplayController( screen_manager_->ConfigureDisplayController(
drm, kDefaultCrtc, kDefaultConnector, drm, kDefaultCrtc, kDefaultConnector,
...@@ -172,7 +172,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) { ...@@ -172,7 +172,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) {
EXPECT_NE(0u, drm->get_cursor_handle_for_crtc(kDefaultCrtc)); EXPECT_NE(0u, drm->get_cursor_handle_for_crtc(kDefaultCrtc));
} }
TEST_F(DrmWindowTest, CheckCallbackOnFailedSwap) { TEST_F(DrmWindowTest, CheckDeathOnFailedSwap) {
const gfx::Size window_size(6, 4); const gfx::Size window_size(6, 4);
ui::MockDumbBufferGenerator buffer_generator; ui::MockDumbBufferGenerator buffer_generator;
ui::DrmWindow* window = screen_manager_->GetWindow(kDefaultWidgetHandle); ui::DrmWindow* window = screen_manager_->GetWindow(kDefaultWidgetHandle);
...@@ -195,11 +195,9 @@ TEST_F(DrmWindowTest, CheckCallbackOnFailedSwap) { ...@@ -195,11 +195,9 @@ TEST_F(DrmWindowTest, CheckCallbackOnFailedSwap) {
EXPECT_EQ(static_cast<uint32_t>(gfx::PresentationFeedback::Flags::kFailure), EXPECT_EQ(static_cast<uint32_t>(gfx::PresentationFeedback::Flags::kFailure),
last_presentation_feedback_.flags); last_presentation_feedback_.flags);
window->SchedulePageFlip( EXPECT_DEATH_IF_SUPPORTED(
ui::DrmOverlayPlane::Clone(planes), window->SchedulePageFlip(ui::DrmOverlayPlane::Clone(planes),
base::BindOnce(&DrmWindowTest::OnSwapBuffers, base::Unretained(this))); base::BindOnce(&DrmWindowTest::OnSwapBuffers,
EXPECT_EQ(2, on_swap_buffers_count_); base::Unretained(this))),
EXPECT_EQ(gfx::SwapResult::SWAP_FAILED, last_swap_buffers_result_); "SchedulePageFlip failed");
EXPECT_EQ(static_cast<uint32_t>(gfx::PresentationFeedback::Flags::kFailure),
last_presentation_feedback_.flags);
} }
...@@ -28,15 +28,27 @@ namespace ui { ...@@ -28,15 +28,27 @@ namespace ui {
namespace { namespace {
void EmptyFlipCallback(gfx::SwapResult, void CompletePageFlip(
const gfx::PresentationFeedback& feedback) {} base::WeakPtr<HardwareDisplayController> hardware_display_controller_,
SwapCompletionOnceCallback callback,
DrmOverlayPlaneList plane_list,
gfx::SwapResult swap_result,
const gfx::PresentationFeedback& presentation_feedback) {
if (hardware_display_controller_) {
hardware_display_controller_->OnPageFlipComplete(std::move(plane_list),
presentation_feedback);
}
std::move(callback).Run(swap_result, presentation_feedback);
}
} // namespace } // namespace
HardwareDisplayController::HardwareDisplayController( HardwareDisplayController::HardwareDisplayController(
std::unique_ptr<CrtcController> controller, std::unique_ptr<CrtcController> controller,
const gfx::Point& origin) const gfx::Point& origin)
: origin_(origin), is_disabled_(controller->is_disabled()) { : origin_(origin),
is_disabled_(controller->is_disabled()),
weak_ptr_factory_(this) {
AddCrtc(std::move(controller)); AddCrtc(std::move(controller));
} }
...@@ -54,7 +66,7 @@ bool HardwareDisplayController::Modeset(const DrmOverlayPlane& primary, ...@@ -54,7 +66,7 @@ bool HardwareDisplayController::Modeset(const DrmOverlayPlane& primary,
status &= controller->Modeset(primary, mode); status &= controller->Modeset(primary, mode);
is_disabled_ = false; is_disabled_ = false;
OnModesetComplete(primary);
return status; return status;
} }
...@@ -66,7 +78,7 @@ bool HardwareDisplayController::Enable(const DrmOverlayPlane& primary) { ...@@ -66,7 +78,7 @@ bool HardwareDisplayController::Enable(const DrmOverlayPlane& primary) {
status &= controller->Modeset(primary, controller->mode()); status &= controller->Modeset(primary, controller->mode());
is_disabled_ = false; is_disabled_ = false;
OnModesetComplete(primary);
return status; return status;
} }
...@@ -82,54 +94,63 @@ void HardwareDisplayController::Disable() { ...@@ -82,54 +94,63 @@ void HardwareDisplayController::Disable() {
is_disabled_ = true; is_disabled_ = true;
} }
bool HardwareDisplayController::SchedulePageFlip( void HardwareDisplayController::SchedulePageFlip(
const DrmOverlayPlaneList& plane_list, DrmOverlayPlaneList plane_list,
SwapCompletionOnceCallback callback) { SwapCompletionOnceCallback callback) {
return ActualSchedulePageFlip(plane_list, false /* test_only */, DCHECK(!page_flip_request_);
std::move(callback)); scoped_refptr<PageFlipRequest> page_flip_request =
base::MakeRefCounted<PageFlipRequest>(GetRefreshInterval());
bool status = ScheduleOrTestPageFlip(plane_list, page_flip_request);
CHECK(status) << "SchedulePageFlip failed";
if (page_flip_request->page_flip_count() == 0) {
// Apparently, there was nothing to do. This probably should not be
// able to happen but both CrtcController::AssignOverlayPlanes and
// HardwareDisplayPlaneManagerLegacy::Commit appear to have cases
// where we ACK without actually scheduling a page flip.
std::move(callback).Run(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback::Failure());
return;
}
// Everything was submitted successfully, wait for asynchronous completion.
page_flip_request->TakeCallback(
base::BindOnce(&CompletePageFlip, weak_ptr_factory_.GetWeakPtr(),
base::Passed(&callback), base::Passed(&plane_list)));
page_flip_request_ = std::move(page_flip_request);
} }
bool HardwareDisplayController::TestPageFlip( bool HardwareDisplayController::TestPageFlip(
const DrmOverlayPlaneList& plane_list) { const DrmOverlayPlaneList& plane_list) {
return ActualSchedulePageFlip(plane_list, true /* test_only */, return ScheduleOrTestPageFlip(plane_list, nullptr);
base::BindOnce(&EmptyFlipCallback));
} }
bool HardwareDisplayController::ActualSchedulePageFlip( bool HardwareDisplayController::ScheduleOrTestPageFlip(
const DrmOverlayPlaneList& plane_list, const DrmOverlayPlaneList& plane_list,
bool test_only, scoped_refptr<PageFlipRequest> page_flip_request) {
SwapCompletionOnceCallback callback) {
TRACE_EVENT0("drm", "HDC::SchedulePageFlip"); TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
DCHECK(!is_disabled_); DCHECK(!is_disabled_);
// Ignore requests with no planes to schedule. // Ignore requests with no planes to schedule.
if (plane_list.empty()) { if (plane_list.empty())
std::move(callback).Run(gfx::SwapResult::SWAP_ACK,
gfx::PresentationFeedback());
return true; return true;
}
DrmOverlayPlaneList pending_planes = DrmOverlayPlane::Clone(plane_list); DrmOverlayPlaneList pending_planes = DrmOverlayPlane::Clone(plane_list);
std::sort(pending_planes.begin(), pending_planes.end(), std::sort(pending_planes.begin(), pending_planes.end(),
[](const DrmOverlayPlane& l, const DrmOverlayPlane& r) { [](const DrmOverlayPlane& l, const DrmOverlayPlane& r) {
return l.z_order < r.z_order; return l.z_order < r.z_order;
}); });
scoped_refptr<PageFlipRequest> page_flip_request =
new PageFlipRequest(crtc_controllers_.size(), std::move(callback));
GetDrmDevice()->plane_manager()->BeginFrame(&owned_hardware_planes_); GetDrmDevice()->plane_manager()->BeginFrame(&owned_hardware_planes_);
bool status = true; bool status = true;
for (const auto& controller : crtc_controllers_) { for (const auto& controller : crtc_controllers_) {
status &= controller->SchedulePageFlip( status &= controller->AssignOverlayPlanes(&owned_hardware_planes_,
&owned_hardware_planes_, pending_planes, test_only, page_flip_request); pending_planes);
} }
if (!GetDrmDevice()->plane_manager()->Commit(&owned_hardware_planes_, status &= GetDrmDevice()->plane_manager()->Commit(&owned_hardware_planes_,
test_only)) { page_flip_request);
status = false;
}
return status; return status;
} }
...@@ -284,14 +305,19 @@ gfx::Size HardwareDisplayController::GetModeSize() const { ...@@ -284,14 +305,19 @@ gfx::Size HardwareDisplayController::GetModeSize() const {
crtc_controllers_[0]->mode().vdisplay); crtc_controllers_[0]->mode().vdisplay);
} }
base::TimeTicks HardwareDisplayController::GetTimeOfLastFlip() const { uint32_t HardwareDisplayController::GetRefreshRate() const {
base::TimeTicks time; // If there are multiple CRTCs they should all have the same size.
for (const auto& controller : crtc_controllers_) { return crtc_controllers_[0]->mode().vrefresh;
if (time < controller->time_of_last_flip()) }
time = controller->time_of_last_flip();
}
return time; base::TimeDelta HardwareDisplayController::GetRefreshInterval() const {
uint32_t vrefresh = GetRefreshRate();
return vrefresh ? base::TimeDelta::FromSeconds(1) / vrefresh
: base::TimeDelta();
}
base::TimeTicks HardwareDisplayController::GetTimeOfLastFlip() const {
return time_of_last_flip_;
} }
scoped_refptr<DrmDevice> HardwareDisplayController::GetDrmDevice() const { scoped_refptr<DrmDevice> HardwareDisplayController::GetDrmDevice() const {
...@@ -301,4 +327,26 @@ scoped_refptr<DrmDevice> HardwareDisplayController::GetDrmDevice() const { ...@@ -301,4 +327,26 @@ scoped_refptr<DrmDevice> HardwareDisplayController::GetDrmDevice() const {
return crtc_controllers_[0]->drm(); return crtc_controllers_[0]->drm();
} }
void HardwareDisplayController::OnPageFlipComplete(
DrmOverlayPlaneList pending_planes,
const gfx::PresentationFeedback& presentation_feedback) {
if (!page_flip_request_)
return; // Modeset occured during this page flip.
time_of_last_flip_ = presentation_feedback.timestamp;
current_planes_ = std::move(pending_planes);
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.
page_flip_request_ = nullptr;
current_planes_.clear();
current_planes_.push_back(primary.Clone());
time_of_last_flip_ = base::TimeTicks::Now();
}
} // namespace ui } // namespace ui
...@@ -116,7 +116,7 @@ class HardwareDisplayController { ...@@ -116,7 +116,7 @@ class HardwareDisplayController {
// //
// Note that this function does not block. Also, this function should not be // Note that this function does not block. Also, this function should not be
// called again before the page flip occurrs. // called again before the page flip occurrs.
bool SchedulePageFlip(const DrmOverlayPlaneList& plane_list, void SchedulePageFlip(DrmOverlayPlaneList plane_list,
SwapCompletionOnceCallback callback); SwapCompletionOnceCallback callback);
// Returns true if the page flip with the |plane_list| would succeed. This // Returns true if the page flip with the |plane_list| would succeed. This
...@@ -155,6 +155,8 @@ class HardwareDisplayController { ...@@ -155,6 +155,8 @@ class HardwareDisplayController {
gfx::Point origin() const { return origin_; } gfx::Point origin() const { return origin_; }
void set_origin(const gfx::Point& origin) { origin_ = origin; } void set_origin(const gfx::Point& origin) { origin_ = origin; }
uint32_t GetRefreshRate() const;
base::TimeDelta GetRefreshInterval() const;
base::TimeTicks GetTimeOfLastFlip() const; base::TimeTicks GetTimeOfLastFlip() const;
const std::vector<std::unique_ptr<CrtcController>>& crtc_controllers() const { const std::vector<std::unique_ptr<CrtcController>>& crtc_controllers() const {
...@@ -163,10 +165,14 @@ class HardwareDisplayController { ...@@ -163,10 +165,14 @@ class HardwareDisplayController {
scoped_refptr<DrmDevice> GetDrmDevice() const; scoped_refptr<DrmDevice> GetDrmDevice() const;
void OnPageFlipComplete(
DrmOverlayPlaneList pending_planes,
const gfx::PresentationFeedback& presentation_feedback);
private: private:
bool ActualSchedulePageFlip(const DrmOverlayPlaneList& plane_list, void OnModesetComplete(const DrmOverlayPlane& primary);
bool test_only, bool ScheduleOrTestPageFlip(const DrmOverlayPlaneList& plane_list,
SwapCompletionOnceCallback callback); scoped_refptr<PageFlipRequest> page_flip_request);
HardwareDisplayPlaneList owned_hardware_planes_; HardwareDisplayPlaneList owned_hardware_planes_;
...@@ -177,8 +183,14 @@ class HardwareDisplayController { ...@@ -177,8 +183,14 @@ class HardwareDisplayController {
// Location of the controller on the screen. // Location of the controller on the screen.
gfx::Point origin_; gfx::Point origin_;
scoped_refptr<PageFlipRequest> page_flip_request_;
DrmOverlayPlaneList current_planes_;
base::TimeTicks time_of_last_flip_;
bool is_disabled_; bool is_disabled_;
base::WeakPtrFactory<HardwareDisplayController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController); DISALLOW_COPY_AND_ASSIGN(HardwareDisplayController);
}; };
......
...@@ -66,7 +66,7 @@ void HardwareDisplayControllerTest::SetUp() { ...@@ -66,7 +66,7 @@ void HardwareDisplayControllerTest::SetUp() {
page_flips_ = 0; page_flips_ = 0;
last_swap_result_ = gfx::SwapResult::SWAP_FAILED; last_swap_result_ = gfx::SwapResult::SWAP_FAILED;
drm_ = new ui::MockDrmDevice(false); drm_ = new ui::MockDrmDevice;
InitializeDrmDevice(/* use_atomic= */ false); InitializeDrmDevice(/* use_atomic= */ false);
controller_.reset(new ui::HardwareDisplayController( controller_.reset(new ui::HardwareDisplayController(
...@@ -208,14 +208,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) { ...@@ -208,14 +208,8 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
nullptr); nullptr);
std::vector<ui::DrmOverlayPlane> planes; std::vector<ui::DrmOverlayPlane> planes;
planes.push_back(plane2.Clone()); planes.push_back(plane2.Clone());
SchedulePageFlip(std::move(planes)); EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(planes)),
drm_->RunCallbacks(); "SchedulePageFlip failed");
planes.clear();
EXPECT_EQ(gfx::SwapResult::SWAP_FAILED, last_swap_result_);
EXPECT_EQ(1, page_flips_);
EXPECT_FALSE(plane1.buffer->HasOneRef());
EXPECT_TRUE(plane2.buffer->HasOneRef());
} }
TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) { TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
...@@ -469,11 +463,8 @@ TEST_F(HardwareDisplayControllerTest, FailPageFlipping) { ...@@ -469,11 +463,8 @@ TEST_F(HardwareDisplayControllerTest, FailPageFlipping) {
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode)); EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
std::vector<ui::DrmOverlayPlane> planes; std::vector<ui::DrmOverlayPlane> planes;
planes.push_back(plane1.Clone()); planes.push_back(plane1.Clone());
SchedulePageFlip(std::move(planes)); EXPECT_DEATH_IF_SUPPORTED(SchedulePageFlip(std::move(planes)),
"SchedulePageFlip failed");
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_FAILED, last_swap_result_);
EXPECT_EQ(1, page_flips_);
} }
TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlane) { TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlane) {
...@@ -520,7 +511,6 @@ TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) { ...@@ -520,7 +511,6 @@ TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
controller_->RemoveCrtc(drm_, kPrimaryCrtc); controller_->RemoveCrtc(drm_, kPrimaryCrtc);
EXPECT_EQ(1, page_flips_);
drm_->RunCallbacks(); drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_); EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_); EXPECT_EQ(1, page_flips_);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "ui/ozone/platform/drm/common/scoped_drm_types.h" #include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h" #include "ui/ozone/platform/drm/gpu/drm_overlay_plane.h"
#include "ui/ozone/public/swap_completion_callback.h"
namespace gfx { namespace gfx {
class Rect; class Rect;
...@@ -97,8 +98,11 @@ class HardwareDisplayPlaneManager { ...@@ -97,8 +98,11 @@ class HardwareDisplayPlaneManager {
CrtcController* crtc); CrtcController* crtc);
// Commit the plane states in |plane_list|. // Commit the plane states in |plane_list|.
//
// If |page_flip_request| is null, this tests the plane configuration without
// submitting it.
virtual bool Commit(HardwareDisplayPlaneList* plane_list, virtual bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) = 0; scoped_refptr<PageFlipRequest> page_flip_request) = 0;
// Disable all the overlay planes previously submitted and now stored in // Disable all the overlay planes previously submitted and now stored in
// plane_list->old_plane_list. // plane_list->old_plane_list.
......
...@@ -17,24 +17,11 @@ ...@@ -17,24 +17,11 @@
#include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h" #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
namespace ui { namespace ui {
namespace {
void AtomicPageFlipCallback(std::vector<base::WeakPtr<CrtcController>> crtcs,
unsigned int frame,
base::TimeTicks timestamp) {
for (auto& crtc : crtcs) {
auto* crtc_ptr = crtc.get();
if (crtc_ptr)
crtc_ptr->OnPageFlipEvent(frame, timestamp);
}
}
} // namespace
HardwareDisplayPlaneManagerAtomic::HardwareDisplayPlaneManagerAtomic() { HardwareDisplayPlaneManagerAtomic::HardwareDisplayPlaneManagerAtomic() {
} }
...@@ -43,7 +30,8 @@ HardwareDisplayPlaneManagerAtomic::~HardwareDisplayPlaneManagerAtomic() { ...@@ -43,7 +30,8 @@ HardwareDisplayPlaneManagerAtomic::~HardwareDisplayPlaneManagerAtomic() {
bool HardwareDisplayPlaneManagerAtomic::Commit( bool HardwareDisplayPlaneManagerAtomic::Commit(
HardwareDisplayPlaneList* plane_list, HardwareDisplayPlaneList* plane_list,
bool test_only) { scoped_refptr<PageFlipRequest> page_flip_request) {
bool test_only = !page_flip_request;
for (HardwareDisplayPlane* plane : plane_list->old_plane_list) { for (HardwareDisplayPlane* plane : plane_list->old_plane_list) {
if (!base::ContainsValue(plane_list->plane_list, plane)) { if (!base::ContainsValue(plane_list->plane_list, plane)) {
// This plane is being released, so we need to zero it. // This plane is being released, so we need to zero it.
...@@ -56,12 +44,12 @@ bool HardwareDisplayPlaneManagerAtomic::Commit( ...@@ -56,12 +44,12 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
} }
} }
std::vector<base::WeakPtr<CrtcController>> crtcs; std::vector<CrtcController*> crtcs;
for (HardwareDisplayPlane* plane : plane_list->plane_list) { for (HardwareDisplayPlane* plane : plane_list->plane_list) {
HardwareDisplayPlaneAtomic* atomic_plane = HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane); static_cast<HardwareDisplayPlaneAtomic*>(plane);
if (crtcs.empty() || crtcs.back().get() != atomic_plane->crtc()) if (crtcs.empty() || crtcs.back() != atomic_plane->crtc())
crtcs.push_back(atomic_plane->crtc()->AsWeakPtr()); crtcs.push_back(atomic_plane->crtc());
} }
if (test_only) { if (test_only) {
...@@ -76,12 +64,11 @@ bool HardwareDisplayPlaneManagerAtomic::Commit( ...@@ -76,12 +64,11 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
if (test_only) { if (test_only) {
flags = DRM_MODE_ATOMIC_TEST_ONLY; flags = DRM_MODE_ATOMIC_TEST_ONLY;
} else { } else {
flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK; flags = DRM_MODE_ATOMIC_NONBLOCK;
} }
if (!drm_->CommitProperties(plane_list->atomic_property_set.get(), flags, if (!drm_->CommitProperties(plane_list->atomic_property_set.get(), flags,
crtcs.size(), crtcs.size(), page_flip_request)) {
base::BindOnce(&AtomicPageFlipCallback, crtcs))) {
if (!test_only) { if (!test_only) {
PLOG(ERROR) << "Failed to commit properties for page flip."; PLOG(ERROR) << "Failed to commit properties for page flip.";
} else { } else {
...@@ -111,13 +98,8 @@ bool HardwareDisplayPlaneManagerAtomic::DisableOverlayPlanes( ...@@ -111,13 +98,8 @@ bool HardwareDisplayPlaneManagerAtomic::DisableOverlayPlanes(
plane_list->atomic_property_set.get(), 0, 0, gfx::Rect(), gfx::Rect(), plane_list->atomic_property_set.get(), 0, 0, gfx::Rect(), gfx::Rect(),
gfx::OVERLAY_TRANSFORM_NONE, base::kInvalidPlatformFile); gfx::OVERLAY_TRANSFORM_NONE, base::kInvalidPlatformFile);
} }
// The list of crtcs is only useful if flags contains DRM_MODE_PAGE_FLIP_EVENT bool ret = drm_->CommitProperties(plane_list->atomic_property_set.get(),
// to get the pageflip callback. In this case we don't need to be notified DRM_MODE_ATOMIC_NONBLOCK, 0, nullptr);
// at the next page flip, so the list of crtcs can be empty.
std::vector<base::WeakPtr<CrtcController>> crtcs;
bool ret = drm_->CommitProperties(
plane_list->atomic_property_set.get(), DRM_MODE_ATOMIC_NONBLOCK,
crtcs.size(), base::BindOnce(&AtomicPageFlipCallback, crtcs));
PLOG_IF(ERROR, !ret) << "Failed to commit properties for page flip."; PLOG_IF(ERROR, !ret) << "Failed to commit properties for page flip.";
plane_list->atomic_property_set.reset(drmModeAtomicAlloc()); plane_list->atomic_property_set.reset(drmModeAtomicAlloc());
...@@ -149,7 +131,7 @@ bool HardwareDisplayPlaneManagerAtomic::SetColorCorrectionOnAllCrtcPlanes( ...@@ -149,7 +131,7 @@ bool HardwareDisplayPlaneManagerAtomic::SetColorCorrectionOnAllCrtcPlanes(
} }
return drm_->CommitProperties(property_set.get(), DRM_MODE_ATOMIC_NONBLOCK, 0, return drm_->CommitProperties(property_set.get(), DRM_MODE_ATOMIC_NONBLOCK, 0,
DrmDevice::PageFlipCallback()); nullptr);
} }
bool HardwareDisplayPlaneManagerAtomic::ValidatePrimarySize( bool HardwareDisplayPlaneManagerAtomic::ValidatePrimarySize(
...@@ -222,8 +204,7 @@ bool HardwareDisplayPlaneManagerAtomic::CommitColorMatrix( ...@@ -222,8 +204,7 @@ bool HardwareDisplayPlaneManagerAtomic::CommitColorMatrix(
// API) to ensure the properties are applied. // API) to ensure the properties are applied.
// TODO(dnicoara): Should cache these values locally and aggregate them with // TODO(dnicoara): Should cache these values locally and aggregate them with
// the page flip event otherwise this "steals" a vsync to apply the property. // the page flip event otherwise this "steals" a vsync to apply the property.
return drm_->CommitProperties(property_set.get(), 0, 0, return drm_->CommitProperties(property_set.get(), 0, 0, nullptr);
DrmDevice::PageFlipCallback());
} }
bool HardwareDisplayPlaneManagerAtomic::CommitGammaCorrection( bool HardwareDisplayPlaneManagerAtomic::CommitGammaCorrection(
...@@ -258,8 +239,7 @@ bool HardwareDisplayPlaneManagerAtomic::CommitGammaCorrection( ...@@ -258,8 +239,7 @@ bool HardwareDisplayPlaneManagerAtomic::CommitGammaCorrection(
// API) to ensure the properties are applied. // API) to ensure the properties are applied.
// TODO(dnicoara): Should cache these values locally and aggregate them with // TODO(dnicoara): Should cache these values locally and aggregate them with
// the page flip event otherwise this "steals" a vsync to apply the property. // the page flip event otherwise this "steals" a vsync to apply the property.
return drm_->CommitProperties(property_set.get(), 0, 0, return drm_->CommitProperties(property_set.get(), 0, 0, nullptr);
DrmDevice::PageFlipCallback());
} }
} // namespace ui } // namespace ui
...@@ -19,7 +19,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager { ...@@ -19,7 +19,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
// HardwareDisplayPlaneManager: // HardwareDisplayPlaneManager:
bool Commit(HardwareDisplayPlaneList* plane_list, bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) override; scoped_refptr<PageFlipRequest> page_flip_request) override;
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override; bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetColorCorrectionOnAllCrtcPlanes( bool SetColorCorrectionOnAllCrtcPlanes(
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h" #include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
namespace ui { namespace ui {
...@@ -42,7 +43,8 @@ HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() { ...@@ -42,7 +43,8 @@ HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() {
bool HardwareDisplayPlaneManagerLegacy::Commit( bool HardwareDisplayPlaneManagerLegacy::Commit(
HardwareDisplayPlaneList* plane_list, HardwareDisplayPlaneList* plane_list,
bool test_only) { scoped_refptr<PageFlipRequest> page_flip_request) {
bool test_only = !page_flip_request;
if (test_only) { if (test_only) {
for (HardwareDisplayPlane* plane : plane_list->plane_list) { for (HardwareDisplayPlane* plane : plane_list->plane_list) {
plane->set_in_use(false); plane->set_in_use(false);
...@@ -69,14 +71,10 @@ bool HardwareDisplayPlaneManagerLegacy::Commit( ...@@ -69,14 +71,10 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(
PLOG(ERROR) << "Cannot display plane on overlay: crtc=" << flip.crtc PLOG(ERROR) << "Cannot display plane on overlay: crtc=" << flip.crtc
<< " plane=" << plane.plane; << " plane=" << plane.plane;
ret = false; ret = false;
flip.crtc->SignalPageFlipRequest(gfx::SwapResult::SWAP_FAILED,
gfx::PresentationFeedback::Failure());
break; break;
} }
} }
if (!drm_->PageFlip(flip.crtc_id, flip.framebuffer, if (!drm_->PageFlip(flip.crtc_id, flip.framebuffer, page_flip_request)) {
base::BindOnce(&CrtcController::OnPageFlipEvent,
flip.crtc->AsWeakPtr()))) {
// 1) Permission Denied is a legitimate error. // 1) Permission Denied is a legitimate error.
// 2) Device or resource busy is possible if we're page flipping a // 2) Device or resource busy is possible if we're page flipping a
// disconnected CRTC. Pretend we're fine since a hotplug event is supposed // disconnected CRTC. Pretend we're fine since a hotplug event is supposed
...@@ -90,9 +88,6 @@ bool HardwareDisplayPlaneManagerLegacy::Commit( ...@@ -90,9 +88,6 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(
<< " framebuffer=" << flip.framebuffer; << " framebuffer=" << flip.framebuffer;
ret = false; ret = false;
} }
flip.crtc->SignalPageFlipRequest(
ret ? gfx::SwapResult::SWAP_ACK : gfx::SwapResult::SWAP_FAILED,
gfx::PresentationFeedback::Failure());
} }
} }
// For each element in |old_plane_list|, if it hasn't been reclaimed (by // For each element in |old_plane_list|, if it hasn't been reclaimed (by
......
...@@ -19,7 +19,7 @@ class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager { ...@@ -19,7 +19,7 @@ class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
// HardwareDisplayPlaneManager: // HardwareDisplayPlaneManager:
bool Commit(HardwareDisplayPlaneList* plane_list, bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) override; scoped_refptr<PageFlipRequest> page_flip_request) override;
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override; bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetColorCorrectionOnAllCrtcPlanes( bool SetColorCorrectionOnAllCrtcPlanes(
......
...@@ -68,7 +68,7 @@ void HardwareDisplayPlaneManagerTest::SetUp() { ...@@ -68,7 +68,7 @@ void HardwareDisplayPlaneManagerTest::SetUp() {
use_atomic_ = GetParam(); use_atomic_ = GetParam();
fake_buffer_ = new ui::MockScanoutBuffer(kDefaultBufferSize); fake_buffer_ = new ui::MockScanoutBuffer(kDefaultBufferSize);
fake_drm_ = new ui::MockDrmDevice(/* use_sync_flips= */ false); fake_drm_ = new ui::MockDrmDevice;
fake_drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob( fake_drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {})); kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {}));
} }
...@@ -349,17 +349,20 @@ TEST_P(HardwareDisplayPlaneManagerLegacyTest, UnusedPlanesAreReleased) { ...@@ -349,17 +349,20 @@ TEST_P(HardwareDisplayPlaneManagerLegacyTest, UnusedPlanesAreReleased) {
assigns.push_back(ui::DrmOverlayPlane(overlay_buffer, nullptr)); assigns.push_back(ui::DrmOverlayPlane(overlay_buffer, nullptr));
ui::HardwareDisplayPlaneList hdpl; ui::HardwareDisplayPlaneList hdpl;
ui::CrtcController crtc(fake_drm_, crtc_properties_[0].id, 0); ui::CrtcController crtc(fake_drm_, crtc_properties_[0].id, 0);
scoped_refptr<ui::PageFlipRequest> page_flip_request =
base::MakeRefCounted<ui::PageFlipRequest>(base::TimeDelta());
fake_drm_->plane_manager()->BeginFrame(&hdpl); fake_drm_->plane_manager()->BeginFrame(&hdpl);
EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes( EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes(
&hdpl, assigns, crtc_properties_[0].id, &crtc)); &hdpl, assigns, crtc_properties_[0].id, &crtc));
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&hdpl, false)); EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&hdpl, page_flip_request));
assigns.clear(); assigns.clear();
assigns.push_back(ui::DrmOverlayPlane(primary_buffer, nullptr)); assigns.push_back(ui::DrmOverlayPlane(primary_buffer, nullptr));
fake_drm_->plane_manager()->BeginFrame(&hdpl); fake_drm_->plane_manager()->BeginFrame(&hdpl);
EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes( EXPECT_TRUE(fake_drm_->plane_manager()->AssignOverlayPlanes(
&hdpl, assigns, crtc_properties_[0].id, &crtc)); &hdpl, assigns, crtc_properties_[0].id, &crtc));
EXPECT_EQ(0, fake_drm_->get_overlay_clear_call_count()); EXPECT_EQ(0, fake_drm_->get_overlay_clear_call_count());
EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&hdpl, false)); EXPECT_TRUE(fake_drm_->plane_manager()->Commit(&hdpl, page_flip_request));
EXPECT_EQ(1, fake_drm_->get_overlay_clear_call_count()); EXPECT_EQ(1, fake_drm_->get_overlay_clear_call_count());
} }
......
...@@ -49,7 +49,7 @@ MockDrmDevice::PlaneProperties::PlaneProperties(const PlaneProperties&) = ...@@ -49,7 +49,7 @@ MockDrmDevice::PlaneProperties::PlaneProperties(const PlaneProperties&) =
default; default;
MockDrmDevice::PlaneProperties::~PlaneProperties() = default; MockDrmDevice::PlaneProperties::~PlaneProperties() = default;
MockDrmDevice::MockDrmDevice(bool use_sync_flips) MockDrmDevice::MockDrmDevice()
: DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */), : DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */),
get_crtc_call_count_(0), get_crtc_call_count_(0),
set_crtc_call_count_(0), set_crtc_call_count_(0),
...@@ -64,7 +64,6 @@ MockDrmDevice::MockDrmDevice(bool use_sync_flips) ...@@ -64,7 +64,6 @@ MockDrmDevice::MockDrmDevice(bool use_sync_flips)
add_framebuffer_expectation_(true), add_framebuffer_expectation_(true),
page_flip_expectation_(true), page_flip_expectation_(true),
create_dumb_buffer_expectation_(true), create_dumb_buffer_expectation_(true),
use_sync_flips_(use_sync_flips),
current_framebuffer_(0) { current_framebuffer_(0) {
plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
} }
...@@ -216,16 +215,12 @@ ScopedDrmFramebufferPtr MockDrmDevice::GetFramebuffer(uint32_t framebuffer) { ...@@ -216,16 +215,12 @@ ScopedDrmFramebufferPtr MockDrmDevice::GetFramebuffer(uint32_t framebuffer) {
bool MockDrmDevice::PageFlip(uint32_t crtc_id, bool MockDrmDevice::PageFlip(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
PageFlipCallback callback) { scoped_refptr<PageFlipRequest> page_flip_request) {
page_flip_call_count_++; page_flip_call_count_++;
DCHECK(page_flip_request);
current_framebuffer_ = framebuffer; current_framebuffer_ = framebuffer;
if (page_flip_expectation_) { if (page_flip_expectation_)
if (use_sync_flips_) callbacks_.push(page_flip_request->AddPageFlip());
std::move(callback).Run(0, base::TimeTicks());
else
callbacks_.push(std::move(callback));
}
return page_flip_expectation_; return page_flip_expectation_;
} }
...@@ -369,16 +364,15 @@ bool MockDrmDevice::CloseBufferHandle(uint32_t handle) { ...@@ -369,16 +364,15 @@ bool MockDrmDevice::CloseBufferHandle(uint32_t handle) {
return true; return true;
} }
bool MockDrmDevice::CommitProperties(drmModeAtomicReq* properties, bool MockDrmDevice::CommitProperties(
uint32_t flags, drmModeAtomicReq* properties,
uint32_t crtc_count, uint32_t flags,
PageFlipCallback callback) { uint32_t crtc_count,
if (use_sync_flips_) scoped_refptr<PageFlipRequest> page_flip_request) {
std::move(callback).Run(0, base::TimeTicks());
else
callbacks_.push(std::move(callback));
commit_count_++; commit_count_++;
if (page_flip_request) {
callbacks_.push(page_flip_request->AddPageFlip());
}
return true; return true;
} }
......
...@@ -43,7 +43,7 @@ class MockDrmDevice : public DrmDevice { ...@@ -43,7 +43,7 @@ class MockDrmDevice : public DrmDevice {
std::vector<DrmDevice::Property> properties; std::vector<DrmDevice::Property> properties;
}; };
explicit MockDrmDevice(bool use_sync_flips); MockDrmDevice();
static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob( static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob(
uint32_t id, uint32_t id,
...@@ -122,7 +122,7 @@ class MockDrmDevice : public DrmDevice { ...@@ -122,7 +122,7 @@ class MockDrmDevice : public DrmDevice {
ScopedDrmFramebufferPtr GetFramebuffer(uint32_t framebuffer) override; ScopedDrmFramebufferPtr GetFramebuffer(uint32_t framebuffer) override;
bool PageFlip(uint32_t crtc_id, bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
PageFlipCallback callback) override; scoped_refptr<PageFlipRequest> page_flip_request) override;
bool PageFlipOverlay(uint32_t crtc_id, bool PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer, uint32_t framebuffer,
const gfx::Rect& location, const gfx::Rect& location,
...@@ -159,7 +159,7 @@ class MockDrmDevice : public DrmDevice { ...@@ -159,7 +159,7 @@ class MockDrmDevice : public DrmDevice {
bool CommitProperties(drmModeAtomicReq* properties, bool CommitProperties(drmModeAtomicReq* properties,
uint32_t flags, uint32_t flags,
uint32_t crtc_count, uint32_t crtc_count,
PageFlipCallback callback) override; scoped_refptr<PageFlipRequest> callback) override;
bool SetGammaRamp( bool SetGammaRamp(
uint32_t crtc_id, uint32_t crtc_id,
const std::vector<display::GammaRampRGBEntry>& lut) override; const std::vector<display::GammaRampRGBEntry>& lut) override;
...@@ -186,8 +186,6 @@ class MockDrmDevice : public DrmDevice { ...@@ -186,8 +186,6 @@ class MockDrmDevice : public DrmDevice {
bool create_dumb_buffer_expectation_; bool create_dumb_buffer_expectation_;
bool legacy_gamma_ramp_expectation_ = false; bool legacy_gamma_ramp_expectation_ = false;
bool use_sync_flips_;
uint32_t current_framebuffer_; uint32_t current_framebuffer_;
std::vector<sk_sp<SkSurface>> buffers_; std::vector<sk_sp<SkSurface>> buffers_;
......
...@@ -4,24 +4,39 @@ ...@@ -4,24 +4,39 @@
#include "ui/ozone/platform/drm/gpu/page_flip_request.h" #include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "base/bind.h"
#include "ui/gfx/presentation_feedback.h"
namespace ui { namespace ui {
PageFlipRequest::PageFlipRequest(int crtc_count, PageFlipRequest::PageFlipRequest(const base::TimeDelta& refresh_interval)
SwapCompletionOnceCallback callback) : refresh_interval_(refresh_interval) {}
: callback_(std::move(callback)), crtc_count_(crtc_count) {}
PageFlipRequest::~PageFlipRequest() { PageFlipRequest::~PageFlipRequest() {
} }
void PageFlipRequest::Signal(gfx::SwapResult result, void PageFlipRequest::TakeCallback(SwapCompletionOnceCallback callback) {
const gfx::PresentationFeedback& feedback) { DCHECK(!callback_);
if (result == gfx::SwapResult::SWAP_FAILED) callback_ = std::move(callback);
result_ = gfx::SwapResult::SWAP_FAILED; }
else if (result != gfx::SwapResult::SWAP_ACK)
result_ = result; PageFlipRequest::PageFlipCallback PageFlipRequest::AddPageFlip() {
++page_flip_count_;
return base::BindOnce(&PageFlipRequest::Signal, this);
}
void PageFlipRequest::Signal(unsigned int frame, base::TimeTicks timestamp) {
if (--page_flip_count_ != 0 || callback_.is_null())
return;
if (!--crtc_count_) // For Ozone DRM, the page flip is aligned with VSYNC, and the timestamp is
std::move(callback_).Run(result_, feedback); // provided by kernel DRM driver (kHWClock) and the buffer has been presented
// on the screen (kHWCompletion).
const uint32_t kFlags = gfx::PresentationFeedback::Flags::kVSync |
gfx::PresentationFeedback::Flags::kHWClock |
gfx::PresentationFeedback::Flags::kHWCompletion;
gfx::PresentationFeedback feedback(timestamp, refresh_interval_, kFlags);
std::move(callback_).Run(gfx::SwapResult::SWAP_ACK, feedback);
} }
} // namespace ui } // namespace ui
...@@ -13,25 +13,39 @@ ...@@ -13,25 +13,39 @@
#include "ui/gfx/swap_result.h" #include "ui/gfx/swap_result.h"
#include "ui/ozone/public/swap_completion_callback.h" #include "ui/ozone/public/swap_completion_callback.h"
namespace gfx {
struct PresentationFeedback;
} // namespace gfx
namespace ui { namespace ui {
class PageFlipRequest : public base::RefCounted<PageFlipRequest> { class PageFlipRequest : public base::RefCounted<PageFlipRequest> {
public: public:
PageFlipRequest(int crtc_count, SwapCompletionOnceCallback callback); using PageFlipCallback =
base::OnceCallback<void(unsigned int /* frame */,
base::TimeTicks /* timestamp */)>;
PageFlipRequest(const base::TimeDelta& refresh_interval);
// Takes ownership of the swap completion callback to allow
// asynchronous notification of completion.
//
// This is only called once all of the individual flips have have been
// successfully submitted.
void TakeCallback(SwapCompletionOnceCallback callback);
void Signal(gfx::SwapResult result, // Add a page flip to this request. Once all page flips return, the
const gfx::PresentationFeedback& feedback); // overall callback is made with the timestamp from the page flip event
// that returned last.
PageFlipCallback AddPageFlip();
int page_flip_count() const { return page_flip_count_; }
private: private:
void Signal(unsigned int frame, base::TimeTicks timestamp);
friend class base::RefCounted<PageFlipRequest>; friend class base::RefCounted<PageFlipRequest>;
~PageFlipRequest(); ~PageFlipRequest();
SwapCompletionOnceCallback callback_; SwapCompletionOnceCallback callback_;
int crtc_count_; int page_flip_count_ = 0;
base::TimeDelta refresh_interval_;
gfx::SwapResult result_ = gfx::SwapResult::SWAP_ACK; gfx::SwapResult result_ = gfx::SwapResult::SWAP_ACK;
DISALLOW_COPY_AND_ASSIGN(PageFlipRequest); DISALLOW_COPY_AND_ASSIGN(PageFlipRequest);
......
...@@ -56,7 +56,7 @@ class ScreenManagerTest : public testing::Test { ...@@ -56,7 +56,7 @@ class ScreenManagerTest : public testing::Test {
} }
void SetUp() override { void SetUp() override {
drm_ = new ui::MockDrmDevice(false); drm_ = new ui::MockDrmDevice;
device_manager_.reset(new ui::DrmDeviceManager(nullptr)); device_manager_.reset(new ui::DrmDeviceManager(nullptr));
buffer_generator_.reset(new ui::MockScanoutBufferGenerator()); buffer_generator_.reset(new ui::MockScanoutBufferGenerator());
screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
...@@ -360,7 +360,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) { ...@@ -360,7 +360,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {
TEST_F(ScreenManagerTest, TEST_F(ScreenManagerTest,
CheckProperConfigurationWithDifferentDeviceAndSameCrtc) { CheckProperConfigurationWithDifferentDeviceAndSameCrtc) {
scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice(false); scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice;
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector); screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector); screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector);
...@@ -554,8 +554,8 @@ TEST_F(ScreenManagerTest, RejectBufferWithIncompatibleModifiers) { ...@@ -554,8 +554,8 @@ TEST_F(ScreenManagerTest, RejectBufferWithIncompatibleModifiers) {
} }
TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) { TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) {
auto drm_device1 = base::MakeRefCounted<MockDrmDevice>(false); auto drm_device1 = base::MakeRefCounted<MockDrmDevice>();
auto drm_device2 = base::MakeRefCounted<MockDrmDevice>(false); auto drm_device2 = base::MakeRefCounted<MockDrmDevice>();
DrmDeviceManager drm_device_manager(nullptr); DrmDeviceManager drm_device_manager(nullptr);
MockScanoutBufferGenerator buffer_generator; MockScanoutBufferGenerator buffer_generator;
ScreenManager screen_manager(&buffer_generator); ScreenManager screen_manager(&buffer_generator);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment