summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authoralexst <alexst@chromium.org>2015-04-15 15:28:42 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-15 22:29:08 +0000
commitb47c9f5fb6b669b27e055ab8b305309170849732 (patch)
tree96ba5c801cf9e15efe057b17ff4b632c1486c9c3 /ui
parent3a725956aff76414de8ecec2dcaa773b21fc8fe5 (diff)
downloadchromium_src-b47c9f5fb6b669b27e055ab8b305309170849732.zip
chromium_src-b47c9f5fb6b669b27e055ab8b305309170849732.tar.gz
chromium_src-b47c9f5fb6b669b27e055ab8b305309170849732.tar.bz2
[ozone] Keep track of pending frames on drm_window when hardware display controller is disabled or when in headless mode.
When display controller is disabled, it used to stop tracking which buffer was the considered front. Surface would fast ack all incoming buffers without presenting them, which means that any one of them could be getting painted into while display controller is off. Upon wakeup, the controller would grab what it thought was the last front buffer, but in practice it was not because of the fast acks. Net result is that it may try to modeset with the buffer GL is painting into, making it hang on a fence in the driver. This patch removes all knowledge of front buffers from the display controller and explicitly sets it on the window, which tracks it while the controller is off. BUG=473831 Review URL: https://codereview.chromium.org/1078183003 Cr-Commit-Position: refs/heads/master@{#325326}
Diffstat (limited to 'ui')
-rw-r--r--ui/ozone/platform/drm/gbm_surface_factory.cc11
-rw-r--r--ui/ozone/platform/drm/gpu/drm_surface.cc11
-rw-r--r--ui/ozone/platform/drm/gpu/drm_window.cc28
-rw-r--r--ui/ozone/platform/drm/gpu/drm_window.h17
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_surface.cc3
-rw-r--r--ui/ozone/platform/drm/gpu/gbm_surfaceless.cc16
-rw-r--r--ui/ozone/platform/drm/gpu/hardware_display_controller.cc31
-rw-r--r--ui/ozone/platform/drm/gpu/hardware_display_controller.h9
-rw-r--r--ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc81
-rw-r--r--ui/ozone/platform/drm/gpu/screen_manager.cc29
-rw-r--r--ui/ozone/platform/drm/gpu/screen_manager.h6
-rw-r--r--ui/ozone/platform/drm/gpu/screen_manager_unittest.cc8
12 files changed, 149 insertions, 101 deletions
diff --git a/ui/ozone/platform/drm/gbm_surface_factory.cc b/ui/ozone/platform/drm/gbm_surface_factory.cc
index 4c836ee..8ecf724 100644
--- a/ui/ozone/platform/drm/gbm_surface_factory.cc
+++ b/ui/ozone/platform/drm/gbm_surface_factory.cc
@@ -191,14 +191,9 @@ bool GbmSurfaceFactory::ScheduleOverlayPlane(
LOG(ERROR) << "ScheduleOverlayPlane passed NULL buffer.";
return false;
}
- HardwareDisplayController* hdc =
- screen_manager_->GetWindow(widget)->GetController();
- if (!hdc)
- return true;
-
- hdc->QueueOverlayPlane(OverlayPlane(pixmap->buffer(), plane_z_order,
- plane_transform, display_bounds,
- crop_rect));
+ screen_manager_->GetWindow(widget)->QueueOverlayPlane(
+ OverlayPlane(pixmap->buffer(), plane_z_order, plane_transform,
+ display_bounds, crop_rect));
return true;
}
diff --git a/ui/ozone/platform/drm/gpu/drm_surface.cc b/ui/ozone/platform/drm/gpu/drm_surface.cc
index 466441e..0964c9e 100644
--- a/ui/ozone/platform/drm/gpu/drm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/drm_surface.cc
@@ -65,16 +65,13 @@ void DrmSurface::ResizeCanvas(const gfx::Size& viewport_size) {
void DrmSurface::PresentCanvas(const gfx::Rect& damage) {
DCHECK(base::MessageLoopForUI::IsCurrent());
- HardwareDisplayController* controller = window_delegate_->GetController();
- if (!controller)
- return;
-
DCHECK(buffers_[front_buffer_ ^ 1].get());
- controller->QueueOverlayPlane(OverlayPlane(buffers_[front_buffer_ ^ 1]));
+ window_delegate_->QueueOverlayPlane(
+ OverlayPlane(buffers_[front_buffer_ ^ 1]));
UpdateNativeSurface(damage);
- controller->SchedulePageFlip(false /* is_sync */,
- base::Bind(&base::DoNothing));
+ window_delegate_->SchedulePageFlip(false /* is_sync */,
+ base::Bind(&base::DoNothing));
// Update our front buffer pointer.
front_buffer_ ^= 1;
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc
index 7517f09..22a70f0 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -51,7 +51,8 @@ DrmWindow::DrmWindow(gfx::AcceleratedWidget widget,
controller_(NULL),
cursor_frontbuffer_(0),
cursor_frame_(0),
- cursor_frame_delay_ms_(0) {
+ cursor_frame_delay_ms_(0),
+ last_swap_sync_(false) {
}
DrmWindow::~DrmWindow() {
@@ -116,6 +117,31 @@ void DrmWindow::MoveCursor(const gfx::Point& location) {
controller_->MoveCursor(location);
}
+void DrmWindow::QueueOverlayPlane(const OverlayPlane& plane) {
+ pending_planes_.push_back(plane);
+}
+
+bool DrmWindow::SchedulePageFlip(bool is_sync, const base::Closure& callback) {
+ last_submitted_planes_.clear();
+ last_submitted_planes_.swap(pending_planes_);
+ last_swap_sync_ = is_sync;
+
+ if (controller_) {
+ return controller_->SchedulePageFlip(last_submitted_planes_, is_sync,
+ callback);
+ }
+
+ callback.Run();
+ return true;
+}
+
+bool DrmWindow::PrepareController(HardwareDisplayController* controller) {
+ const OverlayPlane* primary =
+ OverlayPlane::GetPrimaryPlane(last_submitted_planes_);
+
+ return controller->Modeset(*primary, controller->get_mode());
+}
+
void DrmWindow::ResetCursor(bool bitmap_only) {
if (!controller_)
return;
diff --git a/ui/ozone/platform/drm/gpu/drm_window.h b/ui/ozone/platform/drm/gpu/drm_window.h
index f655bbb..00f2cc0 100644
--- a/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/ui/ozone/platform/drm/gpu/drm_window.h
@@ -12,6 +12,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/ozone_export.h"
+#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
class SkBitmap;
@@ -73,6 +74,16 @@ class OZONE_EXPORT DrmWindow {
// Move the HW cursor to the specified location.
void MoveCursor(const gfx::Point& location);
+ // Queue overlay planes and page flips.
+ // If hardware display controller is available, forward the information
+ // immediately, otherwise queue up on the window and forward when the hardware
+ // is once again ready.
+ void QueueOverlayPlane(const OverlayPlane& plane);
+ bool SchedulePageFlip(bool is_sync, const base::Closure& callback);
+
+ // About to enable hardware display controller, aquire pending frames.
+ bool PrepareController(HardwareDisplayController* controller);
+
private:
// Draw the last set cursor & update the cursor plane.
void ResetCursor(bool bitmap_only);
@@ -106,6 +117,12 @@ class OZONE_EXPORT DrmWindow {
int cursor_frame_;
int cursor_frame_delay_ms_;
+ // Planes and flips currently being queued in the absence of hardware display
+ // controller.
+ OverlayPlaneList pending_planes_;
+ OverlayPlaneList last_submitted_planes_;
+ bool last_swap_sync_;
+
DISALLOW_COPY_AND_ASSIGN(DrmWindow);
};
diff --git a/ui/ozone/platform/drm/gpu/gbm_surface.cc b/ui/ozone/platform/drm/gpu/gbm_surface.cc
index 80c84f9..8b5b167 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surface.cc
@@ -150,8 +150,7 @@ bool GbmSurface::OnSwapBuffersAsync(const SwapCompletionCallback& callback) {
}
// The primary buffer is a special case.
- if (window_delegate_->GetController())
- window_delegate_->GetController()->QueueOverlayPlane(OverlayPlane(primary));
+ window_delegate_->QueueOverlayPlane(OverlayPlane(primary));
if (!GbmSurfaceless::OnSwapBuffersAsync(
base::Bind(&GbmSurface::OnSwapBuffersCallback,
diff --git a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index 138d207..c906cfd 100644
--- a/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -34,23 +34,13 @@ bool GbmSurfaceless::ResizeNativeWindow(const gfx::Size& viewport_size) {
}
bool GbmSurfaceless::OnSwapBuffers() {
- HardwareDisplayController* controller = window_delegate_->GetController();
- if (!controller)
- return true;
-
- return controller->SchedulePageFlip(true /* is_sync */,
- base::Bind(&base::DoNothing));
+ return window_delegate_->SchedulePageFlip(true /* is_sync */,
+ base::Bind(&base::DoNothing));
}
bool GbmSurfaceless::OnSwapBuffersAsync(
const SwapCompletionCallback& callback) {
- HardwareDisplayController* controller = window_delegate_->GetController();
- if (!controller) {
- callback.Run();
- return true;
- }
-
- return controller->SchedulePageFlip(false /* is_sync */, callback);
+ return window_delegate_->SchedulePageFlip(false /* is_sync */, callback);
}
scoped_ptr<gfx::VSyncProvider> GbmSurfaceless::CreateVSyncProvider() {
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
index f9f08ea..278dc15 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -67,45 +67,34 @@ bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
return status;
}
-bool HardwareDisplayController::Enable() {
- TRACE_EVENT0("drm", "HDC::Enable");
- DCHECK(!current_planes_.empty());
-
- const OverlayPlane* primary = nullptr;
- // Use the last scheduled buffer to modeset to preserve request order.
- if (!requests_.empty())
- primary = OverlayPlane::GetPrimaryPlane(requests_.back().planes);
- else
- primary = OverlayPlane::GetPrimaryPlane(current_planes_);
-
- return Modeset(*primary, mode_);
-}
-
void HardwareDisplayController::Disable() {
TRACE_EVENT0("drm", "HDC::Disable");
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
crtc_controllers_[i]->Disable();
- is_disabled_ = true;
-}
+ // Don't hold onto any requests because we don't track fron buffer while
+ // disabled.
+ while (requests_.size())
+ ProcessPageFlipRequest();
-void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) {
- pending_planes_.push_back(plane);
+ current_planes_.clear();
+
+ is_disabled_ = true;
}
bool HardwareDisplayController::SchedulePageFlip(
+ const OverlayPlaneList& plane_list,
bool is_sync,
const base::Closure& callback) {
TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
// Ignore requests with no planes to schedule.
- if (pending_planes_.empty()) {
+ if (plane_list.empty()) {
callback.Run();
return true;
}
- requests_.push_back(PageFlipRequest(pending_planes_, is_sync, callback));
- pending_planes_.clear();
+ requests_.push_back(PageFlipRequest(plane_list, is_sync, callback));
// A request is being serviced right now.
if (HasPendingPageFlips())
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
index 52095d5..196b2dd 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -98,14 +98,9 @@ class OZONE_EXPORT HardwareDisplayController
// framebuffer for |primary| with |mode|.
bool Modeset(const OverlayPlane& primary, drmModeModeInfo mode);
- // Reconfigures the CRTC with the current surface and mode.
- bool Enable();
-
// Disables the CRTC.
void Disable();
- void QueueOverlayPlane(const OverlayPlane& plane);
-
// Schedules the |overlays|' framebuffers to be displayed on the next vsync
// event. The event will be posted on the graphics card file descriptor |fd_|
// and it can be read and processed by |drmHandleEvent|. That function can
@@ -122,7 +117,9 @@ class OZONE_EXPORT HardwareDisplayController
// called again before the page flip occurrs.
//
// Returns true if the page flip was successfully registered, false otherwise.
- bool SchedulePageFlip(bool is_sync, const base::Closure& callback);
+ bool SchedulePageFlip(const OverlayPlaneList& plane_list,
+ bool is_sync,
+ const base::Closure& callback);
// Set the hardware cursor to show the contents of |surface|.
bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
index fb03519..c325f8b 100644
--- a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -101,10 +101,12 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
- controller_->QueueOverlayPlane(plane2);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane2);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_TRUE(plane1.buffer->HasOneRef());
EXPECT_FALSE(plane2.buffer->HasOneRef());
@@ -132,11 +134,14 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
- controller_->QueueOverlayPlane(plane2);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane2);
EXPECT_FALSE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
+ planes.clear();
EXPECT_FALSE(plane1.buffer->HasOneRef());
EXPECT_TRUE(plane2.buffer->HasOneRef());
@@ -150,18 +155,20 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) {
controller_->Disable();
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
- controller_->QueueOverlayPlane(plane2);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane2);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(0, drm_->get_page_flip_call_count());
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(1, drm_->get_page_flip_call_count());
}
@@ -176,12 +183,14 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane1);
- controller_->QueueOverlayPlane(plane2);
+ std::vector<ui::OverlayPlane> planes;
+ planes.push_back(plane1);
+ planes.push_back(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(1, drm_->get_page_flip_call_count());
EXPECT_EQ(1, drm_->get_overlay_flip_call_count());
@@ -198,10 +207,12 @@ TEST_F(HardwareDisplayControllerTest, PageflipMirroredControllers) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
- controller_->QueueOverlayPlane(plane2);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane2);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(2, drm_->get_page_flip_call_count());
EXPECT_EQ(1, page_flips_);
@@ -211,10 +222,12 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane1);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
drm_->RunCallbacks();
const ui::HardwareDisplayPlane* owned_plane = nullptr;
@@ -233,10 +246,12 @@ TEST_F(HardwareDisplayControllerTest, ModesetWhilePageFlipping) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane1);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
drm_->RunCallbacks();
@@ -247,10 +262,12 @@ TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane1);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
controller_->AddCrtc(scoped_ptr<ui::CrtcController>(
new ui::CrtcController(drm_.get(), kSecondaryCrtc, kSecondaryConnector)));
@@ -263,10 +280,12 @@ TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
- controller_->QueueOverlayPlane(plane1);
+ std::vector<ui::OverlayPlane> planes =
+ std::vector<ui::OverlayPlane>(1, plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
- false, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
- base::Unretained(this))));
+ planes, false,
+ base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this))));
controller_->RemoveCrtc(drm_, kPrimaryCrtc);
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc
index 5793572..19b6025 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -146,8 +146,7 @@ bool ScreenManager::ActualConfigureDisplayController(
}
// Just re-enable the controller to re-use the current state.
- bool enabled = controller->Enable();
- return enabled;
+ return EnableController(controller);
}
// Either the mode or the location of the display changed, so exit mirror
@@ -167,7 +166,7 @@ bool ScreenManager::ActualConfigureDisplayController(
if (mirror != controllers_.end() && it != mirror)
return HandleMirrorMode(it, mirror, drm, crtc, connector);
- return ModesetDisplayController(controller, origin, mode);
+ return ModesetDisplayController(controller, origin, mode, true);
}
bool ScreenManager::DisableDisplayController(
@@ -181,6 +180,9 @@ bool ScreenManager::DisableDisplayController(
controllers_.push_back(controller);
}
+ // Workaround for driver bug that does not release the buffer on null
+ // modeset.
+ ModesetDisplayController((*it), (*it)->origin(), (*it)->get_mode(), false);
(*it)->Disable();
UpdateControllerToWindowMapping();
return true;
@@ -252,7 +254,8 @@ ScreenManager::FindActiveDisplayControllerByLocation(const gfx::Rect& bounds) {
bool ScreenManager::ModesetDisplayController(
HardwareDisplayController* controller,
const gfx::Point& origin,
- const drmModeModeInfo& mode) {
+ const drmModeModeInfo& mode,
+ bool fill_modeset_buffer) {
DCHECK(!controller->crtc_controllers().empty());
scoped_refptr<DrmDevice> drm = controller->GetAllocationDrmDevice();
controller->set_origin(origin);
@@ -266,7 +269,8 @@ bool ScreenManager::ModesetDisplayController(
return false;
}
- FillModesetBuffer(drm, controller, buffer.get());
+ if (fill_modeset_buffer)
+ FillModesetBuffer(drm, controller, buffer.get());
if (!controller->Modeset(OverlayPlane(buffer), mode)) {
LOG(ERROR) << "Failed to modeset controller";
@@ -283,7 +287,7 @@ bool ScreenManager::HandleMirrorMode(
uint32_t crtc,
uint32_t connector) {
(*mirror)->AddCrtc((*original)->RemoveCrtc(drm, crtc));
- if ((*mirror)->Enable()) {
+ if (EnableController(*mirror)) {
controllers_.erase(original);
return true;
}
@@ -294,7 +298,7 @@ bool ScreenManager::HandleMirrorMode(
// it is expected that the configuration would not have changed if
// things fail.
(*original)->AddCrtc((*mirror)->RemoveCrtc(drm, crtc));
- (*original)->Enable();
+ EnableController(*original);
return false;
}
@@ -324,6 +328,17 @@ void ScreenManager::UpdateControllerToWindowMapping() {
}
}
+bool ScreenManager::EnableController(HardwareDisplayController* controller) {
+ DrmWindow* window =
+ FindWindowAt(gfx::Rect(controller->origin(), controller->GetModeSize()));
+ if (!window) {
+ return ModesetDisplayController(controller, controller->origin(),
+ controller->get_mode(), false);
+ }
+
+ return window->PrepareController(controller);
+}
+
DrmWindow* ScreenManager::FindWindowAt(const gfx::Rect& bounds) const {
for (auto pair : window_map_) {
if (pair.second->bounds() == bounds)
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.h b/ui/ozone/platform/drm/gpu/screen_manager.h
index 2732769..4e8123d 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager.h
+++ b/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -104,7 +104,8 @@ class OZONE_EXPORT ScreenManager {
// Perform modesetting in |controller| using |origin| and |mode|.
bool ModesetDisplayController(HardwareDisplayController* controller,
const gfx::Point& origin,
- const drmModeModeInfo& mode);
+ const drmModeModeInfo& mode,
+ bool fill_mode_set_buffer);
// Tries to set the controller identified by (|crtc|, |connector|) to mirror
// those in |mirror|. |original| is an iterator to the HDC where the
@@ -115,6 +116,9 @@ class OZONE_EXPORT ScreenManager {
uint32_t crtc,
uint32_t connector);
+ // Aquire pending frames from the time the controller was disabled.
+ bool EnableController(HardwareDisplayController* controller);
+
DrmWindow* FindWindowAt(const gfx::Rect& bounds) const;
ScanoutBufferGenerator* buffer_generator_; // Not owned.
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index bf0d211..444117b 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -121,8 +121,8 @@ TEST_F(ScreenManagerTest, CheckDuplicateConfiguration) {
drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
kDefaultMode);
- // Should reuse existing framebuffer.
- EXPECT_EQ(framebuffer, drm_->current_framebuffer());
+ // Should not hold onto buffers.
+ EXPECT_NE(framebuffer, drm_->current_framebuffer());
EXPECT_TRUE(screen_manager_->GetDisplayController(GetPrimaryBounds()));
EXPECT_FALSE(screen_manager_->GetDisplayController(GetSecondaryBounds()));
@@ -254,8 +254,8 @@ TEST_F(ScreenManagerTest, ReuseFramebufferIfDisabledThenReEnabled) {
drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
kDefaultMode);
- // Should reuse existing framebuffer.
- EXPECT_EQ(framebuffer, drm_->current_framebuffer());
+ // Buffers are released when disabled.
+ EXPECT_NE(framebuffer, drm_->current_framebuffer());
}
TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {