Commit 47203105 authored by dnicoara's avatar dnicoara Committed by Commit bot

[Ozone-DRI] Listen for swap events

Rather than block until the swap event has been acknowledged, listen for page
flip events allowing the GPU main thread to continue execution while the
page flip is pending.

BUG=438389
NOTRY=true

Review URL: https://codereview.chromium.org/821023003

Cr-Commit-Position: refs/heads/master@{#310794}
parent be3f4399
......@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "base/time/time.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/page_flip_observer.h"
#include "ui/ozone/platform/dri/scanout_buffer.h"
namespace ui {
......@@ -41,11 +42,17 @@ bool CrtcController::Modeset(const OverlayPlane& plane, drmModeModeInfo mode) {
return false;
}
current_planes_ = std::vector<OverlayPlane>(1, plane);
mode_ = mode;
pending_planes_.clear();
is_disabled_ = false;
page_flip_pending_ = 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_ = std::vector<OverlayPlane>(1, plane);
if (page_flip_pending_)
pending_planes_ = current_planes_;
return true;
}
......@@ -55,7 +62,6 @@ bool CrtcController::Disable() {
return true;
is_disabled_ = true;
page_flip_pending_ = false;
return drm_->DisableCrtc(crtc_);
}
......@@ -66,6 +72,7 @@ bool CrtcController::SchedulePageFlip(HardwareDisplayPlaneList* plane_list,
const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(overlays);
if (!primary) {
LOG(ERROR) << "No primary plane to display on crtc " << crtc_;
FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent());
return true;
}
DCHECK(primary->buffer.get());
......@@ -75,6 +82,7 @@ bool CrtcController::SchedulePageFlip(HardwareDisplayPlaneList* plane_list,
<< mode_.hdisplay << "x" << mode_.vdisplay << " got "
<< primary->buffer->GetSize().ToString() << " for"
<< " crtc=" << crtc_ << " connector=" << connector_;
FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent());
return true;
}
......@@ -105,6 +113,8 @@ void CrtcController::OnPageFlipEvent(unsigned int frame,
current_planes_.clear();
current_planes_.swap(pending_planes_);
FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent());
}
bool CrtcController::SetCursor(const scoped_refptr<ScanoutBuffer>& buffer) {
......@@ -124,4 +134,12 @@ bool CrtcController::MoveCursor(const gfx::Point& location) {
return drm_->MoveCursor(crtc_, location);
}
void CrtcController::AddObserver(PageFlipObserver* observer) {
observers_.AddObserver(observer);
}
void CrtcController::RemoveObserver(PageFlipObserver* observer) {
observers_.RemoveObserver(observer);
}
} // namespace ui
......@@ -9,6 +9,8 @@
#include <stdint.h>
#include <xf86drmMode.h>
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "ui/ozone/platform/dri/hardware_display_plane_manager.h"
#include "ui/ozone/platform/dri/overlay_plane.h"
#include "ui/ozone/platform/dri/scoped_drm_types.h"
......@@ -16,13 +18,14 @@
namespace ui {
class DriWrapper;
class PageFlipObserver;
// Wrapper around a CRTC.
//
// One CRTC can be paired up with one or more connectors. The simplest
// configuration represents one CRTC driving one monitor, while pairing up a
// CRTC with multiple connectors results in hardware mirroring.
class CrtcController {
class CrtcController : public base::SupportsWeakPtr<CrtcController> {
public:
CrtcController(DriWrapper* drm, uint32_t crtc, uint32_t connector);
~CrtcController();
......@@ -64,6 +67,9 @@ class CrtcController {
bool UnsetCursor();
bool MoveCursor(const gfx::Point& location);
void AddObserver(PageFlipObserver* observer);
void RemoveObserver(PageFlipObserver* observer);
private:
DriWrapper* drm_; // Not owned.
......@@ -97,6 +103,8 @@ class CrtcController {
// The time of the last page flip event as reported by the kernel callback.
uint64_t time_of_last_flip_;
ObserverList<PageFlipObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(CrtcController);
};
......
......@@ -4,6 +4,7 @@
#include "ui/ozone/platform/dri/dri_surface.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "third_party/skia/include/core/SkCanvas.h"
......@@ -73,8 +74,7 @@ void DriSurface::PresentCanvas(const gfx::Rect& damage) {
controller->QueueOverlayPlane(OverlayPlane(buffers_[front_buffer_ ^ 1]));
UpdateNativeSurface(damage);
controller->SchedulePageFlip();
controller->WaitForPageFlipEvent();
controller->SchedulePageFlip(base::Bind(&base::DoNothing));
// Update our front buffer pointer.
front_buffer_ ^= 1;
......
......@@ -79,7 +79,7 @@ void DriSurfaceTest::SetUp() {
message_loop_.reset(new base::MessageLoopForUI);
std::vector<uint32_t> crtcs;
crtcs.push_back(kDefaultCrtc);
drm_.reset(new ui::MockDriWrapper(3, crtcs, kPlanesPerCrtc));
drm_.reset(new ui::MockDriWrapper(3, true, crtcs, kPlanesPerCrtc));
window_delegate_.reset(new MockDriWindowDelegate(drm_.get()));
surface_.reset(new ui::DriSurface(window_delegate_.get(), drm_.get()));
surface_->ResizeCanvas(gfx::Size(kDefaultMode.hdisplay,
......
......@@ -12,7 +12,10 @@
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "ui/ozone/platform/dri/dri_util.h"
#include "ui/ozone/platform/dri/hardware_display_plane_manager_legacy.h"
......@@ -21,6 +24,17 @@ namespace ui {
namespace {
struct PageFlipPayload {
PageFlipPayload(const scoped_refptr<base::TaskRunner>& task_runner,
const DriWrapper::PageFlipCallback& callback)
: task_runner(task_runner), callback(callback) {}
// Task runner for the thread scheduling the page flip event. This is used to
// run the callback on the same thread the callback was created on.
scoped_refptr<base::TaskRunner> task_runner;
DriWrapper::PageFlipCallback callback;
};
bool DrmCreateDumbBuffer(int fd,
const SkImageInfo& info,
uint32_t* handle,
......@@ -55,16 +69,95 @@ void DrmDestroyDumbBuffer(int fd, uint32_t handle) {
drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
}
void HandlePageFlipEventOnIO(int fd,
unsigned int frame,
unsigned int seconds,
unsigned int useconds,
void* data) {
scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
payload->task_runner->PostTask(
FROM_HERE, base::Bind(payload->callback, frame, seconds, useconds));
}
void HandlePageFlipEventOnUI(int fd,
unsigned int frame,
unsigned int seconds,
unsigned int useconds,
void* data) {
scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
payload->callback.Run(frame, seconds, useconds);
}
} // namespace
DriWrapper::DriWrapper(const char* device_path)
: fd_(-1), device_path_(device_path) {
class DriWrapper::IOWatcher
: public base::RefCountedThreadSafe<DriWrapper::IOWatcher>,
public base::MessagePumpLibevent::Watcher {
public:
IOWatcher(int fd,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: io_task_runner_(io_task_runner) {
io_task_runner_->PostTask(FROM_HERE,
base::Bind(&IOWatcher::RegisterOnIO, this, fd));
}
void Shutdown() {
io_task_runner_->PostTask(FROM_HERE,
base::Bind(&IOWatcher::UnregisterOnIO, this));
}
private:
friend class base::RefCountedThreadSafe<IOWatcher>;
~IOWatcher() override {}
void RegisterOnIO(int fd) {
DCHECK(base::MessageLoopForIO::IsCurrent());
base::MessageLoopForIO::current()->WatchFileDescriptor(
fd, true, base::MessageLoopForIO::WATCH_READ, &controller_, this);
}
void UnregisterOnIO() {
DCHECK(base::MessageLoopForIO::IsCurrent());
controller_.StopWatchingFileDescriptor();
}
// base::MessagePumpLibevent::Watcher overrides:
void OnFileCanReadWithoutBlocking(int fd) override {
DCHECK(base::MessageLoopForIO::IsCurrent());
TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd);
drmEventContext event;
event.version = DRM_EVENT_CONTEXT_VERSION;
event.page_flip_handler = HandlePageFlipEventOnIO;
event.vblank_handler = nullptr;
drmHandleEvent(fd, &event);
}
void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
base::MessagePumpLibevent::FileDescriptorWatcher controller_;
DISALLOW_COPY_AND_ASSIGN(IOWatcher);
};
DriWrapper::DriWrapper(const char* device_path, bool software_mode)
: fd_(-1),
software_mode_(software_mode),
device_path_(device_path),
io_thread_("DriIOThread") {
plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
}
DriWrapper::~DriWrapper() {
if (fd_ >= 0)
close(fd_);
if (watcher_)
watcher_->Shutdown();
}
void DriWrapper::Initialize() {
......@@ -75,6 +168,16 @@ void DriWrapper::Initialize() {
LOG(ERROR) << "Failed to initialize the plane manager";
}
void DriWrapper::InitializeIOWatcher() {
if (!software_mode_ && !watcher_) {
if (!io_thread_.StartWithOptions(
base::Thread::Options(base::MessageLoop::TYPE_IO, 0)))
LOG(FATAL) << "Failed to start the IO helper thread";
watcher_ = new IOWatcher(fd_, io_thread_.task_runner());
}
}
ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) {
DCHECK(fd_ >= 0);
return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id));
......@@ -161,16 +264,37 @@ bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) {
bool DriWrapper::PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
void* data) {
const PageFlipCallback& callback) {
DCHECK(fd_ >= 0);
TRACE_EVENT2("dri", "DriWrapper::PageFlip",
"crtc", crtc_id,
"framebuffer", framebuffer);
return !drmModePageFlip(fd_,
crtc_id,
framebuffer,
DRM_MODE_PAGE_FLIP_EVENT,
data);
// NOTE: Calling drmModeSetCrtc will immediately update the state, though
// callbacks to already scheduled page flips will be honored by the kernel.
scoped_ptr<PageFlipPayload> payload(
new PageFlipPayload(base::ThreadTaskRunnerHandle::Get(), callback));
if (!drmModePageFlip(fd_, crtc_id, framebuffer, DRM_MODE_PAGE_FLIP_EVENT,
payload.get())) {
// If successful the payload will be removed by a PageFlip event.
ignore_result(payload.release());
if (software_mode_) {
TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd_);
drmEventContext event;
event.version = DRM_EVENT_CONTEXT_VERSION;
event.page_flip_handler = HandlePageFlipEventOnUI;
event.vblank_handler = nullptr;
drmHandleEvent(fd_, &event);
} else {
InitializeIOWatcher();
}
return true;
}
return false;
}
bool DriWrapper::PageFlipOverlay(uint32_t crtc_id,
......@@ -257,12 +381,6 @@ bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) {
return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y());
}
void DriWrapper::HandleEvent(drmEventContext& event) {
DCHECK(fd_ >= 0);
TRACE_EVENT0("dri", "DriWrapper::HandleEvent");
drmHandleEvent(fd_, &event);
}
bool DriWrapper::CreateDumbBuffer(const SkImageInfo& info,
uint32_t* handle,
uint32_t* stride,
......
......@@ -9,7 +9,10 @@
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "base/threading/thread.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/overlay_transform.h"
......@@ -30,7 +33,11 @@ class HardwareDisplayPlaneManager;
// would be called. In unit tests this interface would be stubbed.
class DriWrapper {
public:
DriWrapper(const char* device_path);
typedef base::Callback<void(unsigned int /* frame */,
unsigned int /* seconds */,
unsigned int /* useconds */)> PageFlipCallback;
DriWrapper(const char* device_path, bool software_mode);
virtual ~DriWrapper();
// Open device.
......@@ -79,9 +86,10 @@ class DriWrapper {
// Schedules a pageflip for CRTC |crtc_id|. This function will return
// immediately. Upon completion of the pageflip event, the CRTC will be
// displaying the buffer with ID |framebuffer| and will have a DRM event
// queued on |fd_|. |data| is a generic pointer to some information the user
// will receive when processing the pageflip event.
virtual bool PageFlip(uint32_t crtc_id, uint32_t framebuffer, void* data);
// queued on |fd_|.
virtual bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
const PageFlipCallback& callback);
// Schedule an overlay to be show during the page flip for CRTC |crtc_id|.
// |source| location from |framebuffer| will be shown on overlay
......@@ -125,8 +133,6 @@ class DriWrapper {
// Move the cursor on CRTC |crtc_id| to (x, y);
virtual bool MoveCursor(uint32_t crtc_id, const gfx::Point& point);
virtual void HandleEvent(drmEventContext& event);
virtual bool CreateDumbBuffer(const SkImageInfo& info,
uint32_t* handle,
uint32_t* stride,
......@@ -146,16 +152,36 @@ class DriWrapper {
HardwareDisplayPlaneManager* plane_manager() { return plane_manager_.get(); }
protected:
// Responsible for late initialization of the IO thread. This needs to happen
// after the sandbox is up, thus the late initialization.
virtual void InitializeIOWatcher();
// The file descriptor associated with this wrapper. All DRM operations will
// be performed using this FD.
// TODO(dnicoara) Make this a base::File
int fd_;
scoped_ptr<HardwareDisplayPlaneManager> plane_manager_;
// If we're running in software mode this is true. In software mode we can't
// use the async page flip callbacks, so we need to block until the kernel
// responds to the page flip.
bool software_mode_;
private:
class IOWatcher;
// Path to DRM device.
const char* device_path_;
// Helper thread to perform IO listener operations.
// TODO(dnicoara) This should really be supported by the main thread.
// Alternatively we should have a way to access the IO thread's task runner.
base::Thread io_thread_;
// Watcher for |fd_| listening for page flip events.
scoped_refptr<IOWatcher> watcher_;
DISALLOW_COPY_AND_ASSIGN(DriWrapper);
};
......
......@@ -6,6 +6,7 @@
#include <gbm.h>
#include "base/bind.h"
#include "base/logging.h"
#include "ui/ozone/platform/dri/dri_buffer.h"
#include "ui/ozone/platform/dri/dri_window_delegate.h"
......@@ -82,7 +83,8 @@ GbmSurface::GbmSurface(DriWindowDelegate* window_delegate,
gbm_device_(device),
dri_(dri),
native_surface_(NULL),
current_buffer_(NULL) {
current_buffer_(NULL),
weak_factory_(this) {
}
GbmSurface::~GbmSurface() {
......@@ -130,6 +132,11 @@ bool GbmSurface::ResizeNativeWindow(const gfx::Size& viewport_size) {
}
bool GbmSurface::OnSwapBuffers() {
NOTREACHED();
return false;
}
bool GbmSurface::OnSwapBuffersAsync(const SwapCompletionCallback& callback) {
DCHECK(native_surface_);
gbm_bo* pending_buffer = gbm_surface_lock_front_buffer(native_surface_);
......@@ -139,6 +146,7 @@ bool GbmSurface::OnSwapBuffers() {
primary = GbmSurfaceBuffer::CreateBuffer(dri_, pending_buffer);
if (!primary.get()) {
LOG(ERROR) << "Failed to associate the buffer with the controller";
callback.Run();
return false;
}
}
......@@ -147,21 +155,24 @@ bool GbmSurface::OnSwapBuffers() {
if (window_delegate_->GetController())
window_delegate_->GetController()->QueueOverlayPlane(OverlayPlane(primary));
if (!GbmSurfaceless::OnSwapBuffers())
if (!GbmSurfaceless::OnSwapBuffersAsync(
base::Bind(&GbmSurface::OnSwapBuffersCallback,
weak_factory_.GetWeakPtr(), callback, pending_buffer))) {
callback.Run();
return false;
}
return true;
}
void GbmSurface::OnSwapBuffersCallback(const SwapCompletionCallback& callback,
gbm_bo* pending_buffer) {
// If there was a frontbuffer, it is no longer active. Release it back to GBM.
if (current_buffer_)
gbm_surface_release_buffer(native_surface_, current_buffer_);
current_buffer_ = pending_buffer;
return true;
}
bool GbmSurface::OnSwapBuffersAsync(const SwapCompletionCallback& callback) {
bool success = OnSwapBuffers();
callback.Run();
return success;
}
} // namespace ui
......@@ -6,6 +6,7 @@
#define UI_OZONE_PLATFORM_DRI_GBM_SURFACE_H_
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/dri/gbm_surfaceless.h"
#include "ui/ozone/public/surface_ozone_egl.h"
......@@ -40,6 +41,9 @@ class GbmSurface : public GbmSurfaceless {
bool OnSwapBuffersAsync(const SwapCompletionCallback& callback) override;
private:
void OnSwapBuffersCallback(const SwapCompletionCallback& callback,
gbm_bo* pending_buffer);
gbm_device* gbm_device_;
DriWrapper* dri_;
......@@ -52,6 +56,8 @@ class GbmSurface : public GbmSurfaceless {
gfx::Size size_;
base::WeakPtrFactory<GbmSurface> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(GbmSurface);
};
......
......@@ -28,21 +28,19 @@ bool GbmSurfaceless::ResizeNativeWindow(const gfx::Size& viewport_size) {
}
bool GbmSurfaceless::OnSwapBuffers() {
HardwareDisplayController* controller = window_delegate_->GetController();
if (!controller)
return true;
bool success = controller->SchedulePageFlip();
controller->WaitForPageFlipEvent();
return success;
NOTREACHED();
return false;
}
bool GbmSurfaceless::OnSwapBuffersAsync(
const SwapCompletionCallback& callback) {
bool success = OnSwapBuffers();
callback.Run();
return success;
HardwareDisplayController* controller = window_delegate_->GetController();
if (!controller) {
callback.Run();
return true;
}
return controller->SchedulePageFlip(callback);
}
scoped_ptr<gfx::VSyncProvider> GbmSurfaceless::CreateVSyncProvider() {
......
......@@ -22,28 +22,14 @@
namespace ui {
namespace {
// DRM callback on page flip events. This callback is triggered after the
// page flip has happened and the backbuffer is now the new frontbuffer
// The old frontbuffer is no longer used by the hardware and can be used for
// future draw operations.
//
// |device| will contain a reference to the |ScanoutSurface| object which
// the event belongs to.
//
// TODO(dnicoara) When we have a FD handler for the DRM calls in the message
// loop, we can move this function in the handler.
void HandlePageFlipEvent(int fd,
unsigned int frame,
unsigned int seconds,
unsigned int useconds,
void* controller) {
static_cast<CrtcController*>(controller)
->OnPageFlipEvent(frame, seconds, useconds);
}
} // namespace
HardwareDisplayController::PageFlipRequest::PageFlipRequest(
const OverlayPlaneList& planes,
const base::Closure& callback)
: planes(planes), callback(callback) {
}
HardwareDisplayController::PageFlipRequest::~PageFlipRequest() {
}
HardwareDisplayController::HardwareDisplayController(
scoped_ptr<CrtcController> controller)
......@@ -55,6 +41,7 @@ HardwareDisplayController::HardwareDisplayController(
HardwareDisplayController::~HardwareDisplayController() {
// Reset the cursor.
UnsetCursor();
ClearPendingRequests();
}
bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
......@@ -65,10 +52,19 @@ bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->Modeset(primary, mode);
current_planes_ = std::vector<OverlayPlane>(1, primary);
pending_planes_.clear();
is_disabled_ = false;
mode_ = mode;
current_planes_ = std::vector<OverlayPlane>(1, primary);
pending_planes_.clear();
ClearPendingRequests();
// Because a page flip is pending we need to leave some state for the
// callback. We use the modeset state since it is the only valid state.
if (HasPendingPageFlips())
requests_.push_back(
PageFlipRequest(current_planes_, base::Bind(&base::DoNothing)));
return status;
}
......@@ -92,59 +88,30 @@ void HardwareDisplayController::QueueOverlayPlane(const OverlayPlane& plane) {
pending_planes_.push_back(plane);
}
bool HardwareDisplayController::SchedulePageFlip() {
DCHECK(!pending_planes_.empty());
bool HardwareDisplayController::SchedulePageFlip(
const base::Closure& callback) {
TRACE_EVENT0("dri", "HDC::SchedulePageFlip");
if (is_disabled_)
// Ignore requests with no planes to schedule.
if (pending_planes_.empty()) {
callback.Run();
return true;
std::sort(pending_planes_.begin(), pending_planes_.end(),
[](const OverlayPlane& l, const OverlayPlane& r) {
return l.z_order < r.z_order;
});
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
status &= crtc_controllers_[i]->SchedulePageFlip(
owned_hardware_planes_.get(crtc_controllers_[i]->drm()),
pending_planes_);
}
for (const auto& planes : owned_hardware_planes_) {
if (!planes.first->plane_manager()->Commit(planes.second)) {
status = false;
}
}
return status;
}
void HardwareDisplayController::WaitForPageFlipEvent() {
TRACE_EVENT0("dri", "HDC::WaitForPageFlipEvent");
requests_.push_back(PageFlipRequest(pending_planes_, callback));
pending_planes_.clear();
drmEventContext drm_event;
drm_event.version = DRM_EVENT_CONTEXT_VERSION;
drm_event.page_flip_handler = HandlePageFlipEvent;
drm_event.vblank_handler = NULL;
// A request is being serviced right now.
if (HasPendingPageFlips())
return true;
bool has_pending_page_flips = false;
// Wait for the page-flips to complete.
for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
// In mirror mode the page flip callbacks can happen in different order than
// scheduled, so we need to make sure that the event for the current CRTC is
// processed before moving to the next CRTC.
while (crtc_controllers_[i]->page_flip_pending()) {
has_pending_page_flips = true;
crtc_controllers_[i]->drm()->HandleEvent(drm_event);
}
}
bool status = ActualSchedulePageFlip();
// In case there are no pending pageflips do not replace the current planes
// since they are still being used.
if (has_pending_page_flips)
current_planes_.swap(pending_planes_);
// No page flip event on failure so discard failed request.
if (!status)
requests_.pop_front();
pending_planes_.clear();
return status;
}
bool HardwareDisplayController::SetCursor(
......@@ -183,6 +150,7 @@ void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
owned_hardware_planes_.add(
controller->drm(),
scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList()));
controller->AddObserver(this);
crtc_controllers_.push_back(controller.release());
}
......@@ -193,9 +161,6 @@ scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
if ((*it)->crtc() == crtc) {
scoped_ptr<CrtcController> controller(*it);
crtc_controllers_.weak_erase(it);
// Release any planes this crtc might own.
HardwareDisplayPlaneManager::ResetPlanes(
owned_hardware_planes_.find(controller->drm())->second, crtc);
// Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
bool found = false;
for (ScopedVector<CrtcController>::iterator it =
......@@ -208,6 +173,14 @@ scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
}
if (!found)
owned_hardware_planes_.erase(controller->drm());
controller->RemoveObserver(this);
// If a display configuration happens mid page flip we want to make sure
// the HDC won't wait for an event from a CRTC that is no longer
// associated with it.
if (controller->page_flip_pending())
OnPageFlipEvent();
return controller.Pass();
}
}
......@@ -244,4 +217,98 @@ uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
return time;
}
void HardwareDisplayController::OnPageFlipEvent() {
TRACE_EVENT0("dri", "HDC::OnPageFlipEvent");
// OnPageFlipEvent() needs to handle 2 cases:
// 1) Normal page flips in which case:
// a) HasPendingPageFlips() may return false if we're in mirror mode and
// one of the CRTCs hasn't finished page flipping. In this case we want
// to wait for all the CRTCs.
// b) HasPendingPageFlips() returns true in which case all CRTCs are ready
// for the next request. In this case we expect that |requests_| isn't
// empty.
// 2) A CRTC was added while it was page flipping. In this case a modeset
// must be performed. Modesetting clears all pending requests, however the
// CRTCs will honor the scheduled page flip. Thus we need to handle page
// flip events with no requests.
if (HasPendingPageFlips())
return;
if (!requests_.empty())
ProcessPageFlipRequest();
// ProcessPageFlipRequest() consumes a request.
if (requests_.empty())
return;
// At this point we still have requests pending, so schedule the next request.
bool status = ActualSchedulePageFlip();
if (!status) {
PageFlipRequest request = requests_.front();
requests_.pop_front();
// Normally the caller would handle the error call, but because we're in a
// delayed schedule the initial SchedulePageFlip() already returned true,
// thus we need to run the callback.
request.callback.Run();
}
}
bool HardwareDisplayController::HasPendingPageFlips() const {
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
if (crtc_controllers_[i]->page_flip_pending())
return true;
return false;
}
bool HardwareDisplayController::ActualSchedulePageFlip() {
TRACE_EVENT0("dri", "HDC::ActualSchedulePageFlip");
DCHECK(!requests_.empty());
if (is_disabled_) {
ProcessPageFlipRequest();
return true;
}
OverlayPlaneList pending_planes = requests_.front().planes;
std::sort(pending_planes.begin(), pending_planes.end(),
[](const OverlayPlane& l, const OverlayPlane& r) {
return l.z_order < r.z_order;
});
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
status &= crtc_controllers_[i]->SchedulePageFlip(
owned_hardware_planes_.get(crtc_controllers_[i]->drm()),
pending_planes);
}
for (const auto& planes : owned_hardware_planes_) {
if (!planes.first->plane_manager()->Commit(planes.second)) {
status = false;
}
}
return status;
}
void HardwareDisplayController::ProcessPageFlipRequest() {
DCHECK(!requests_.empty());
PageFlipRequest request = requests_.front();
requests_.pop_front();
current_planes_.swap(request.planes);
request.callback.Run();
}
void HardwareDisplayController::ClearPendingRequests() {
while (!requests_.empty()) {
PageFlipRequest request = requests_.front();
requests_.pop_front();
request.callback.Run();
}
}
} // namespace ui
......@@ -8,16 +8,19 @@
#include <stddef.h>
#include <stdint.h>
#include <xf86drmMode.h>
#include <deque>
#include <map>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "ui/ozone/platform/dri/hardware_display_plane_manager.h"
#include "ui/ozone/platform/dri/overlay_plane.h"
#include "ui/ozone/platform/dri/page_flip_observer.h"
namespace gfx {
class Point;
......@@ -84,10 +87,11 @@ class DriWrapper;
// framebuffers. Though, in this case, it would be possible to have all
// connectors active if some use the same CRTC to mirror the display.
class HardwareDisplayController
: public base::SupportsWeakPtr<HardwareDisplayController> {
: public base::SupportsWeakPtr<HardwareDisplayController>,
public PageFlipObserver {
public:
explicit HardwareDisplayController(scoped_ptr<CrtcController> controller);
~HardwareDisplayController();
~HardwareDisplayController() override;
// Performs the initial CRTC configuration. If successful, it will display the
// framebuffer for |primary| with |mode|.
......@@ -118,11 +122,7 @@ class HardwareDisplayController
// called again before the page flip occurrs.
//
// Returns true if the page flip was successfully registered, false otherwise.
bool SchedulePageFlip();
// TODO(dnicoara) This should be on the MessageLoop when Ozone can have
// BeginFrame can be triggered explicitly by Ozone.
void WaitForPageFlipEvent();
bool SchedulePageFlip(const base::Closure& callback);
// Set the hardware cursor to show the contents of |surface|.
bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
......@@ -151,10 +151,32 @@ class HardwareDisplayController
}
private:
// Returns true if any of the CRTCs is waiting for a page flip.
bool HasPendingPageFlips() const;
bool ActualSchedulePageFlip();
void ProcessPageFlipRequest();
void ClearPendingRequests();
// PageFlipObserver:
void OnPageFlipEvent() override;
struct PageFlipRequest {
PageFlipRequest(const OverlayPlaneList& planes,
const base::Closure& callback);
~PageFlipRequest();
OverlayPlaneList planes;
base::Closure callback;
};
// Buffers need to be declared first so that they are destroyed last. Needed
// since the controllers may reference the buffers.
OverlayPlaneList current_planes_;
OverlayPlaneList pending_planes_;
std::deque<PageFlipRequest> requests_;
scoped_refptr<ScanoutBuffer> cursor_buffer_;
base::ScopedPtrHashMap<DriWrapper*, HardwareDisplayPlaneList>
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/bind.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/ozone/platform/dri/crtc_controller.h"
......@@ -47,16 +48,20 @@ class MockScanoutBuffer : public ui::ScanoutBuffer {
class HardwareDisplayControllerTest : public testing::Test {
public:
HardwareDisplayControllerTest() {}
HardwareDisplayControllerTest() : page_flips_(0) {}
~HardwareDisplayControllerTest() override {}
void SetUp() override;
void TearDown() override;
void PageFlipCallback();
protected:
scoped_ptr<ui::HardwareDisplayController> controller_;
scoped_ptr<ui::MockDriWrapper> drm_;
int page_flips_;
private:
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayControllerTest);
};
......@@ -65,7 +70,7 @@ void HardwareDisplayControllerTest::SetUp() {
std::vector<uint32_t> crtcs;
crtcs.push_back(kPrimaryCrtc);
crtcs.push_back(kSecondaryCrtc);
drm_.reset(new ui::MockDriWrapper(3, crtcs, kPlanesPerCrtc));
drm_.reset(new ui::MockDriWrapper(3, false, crtcs, kPlanesPerCrtc));
controller_.reset(new ui::HardwareDisplayController(
scoped_ptr<ui::CrtcController>(new ui::CrtcController(
drm_.get(), kPrimaryCrtc, kPrimaryConnector))));
......@@ -76,6 +81,10 @@ void HardwareDisplayControllerTest::TearDown() {
drm_.reset();
}
void HardwareDisplayControllerTest::PageFlipCallback() {
page_flips_++;
}
TEST_F(HardwareDisplayControllerTest, CheckModesettingResult) {
ui::OverlayPlane plane(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
......@@ -93,8 +102,10 @@ TEST_F(HardwareDisplayControllerTest, CheckStateAfterPageFlip) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip());
controller_->WaitForPageFlipEvent();
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_TRUE(plane1.buffer->HasOneRef());
EXPECT_FALSE(plane2.buffer->HasOneRef());
......@@ -122,11 +133,11 @@ TEST_F(HardwareDisplayControllerTest, CheckStateIfPageFlipFails) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
controller_->QueueOverlayPlane(plane2);
EXPECT_FALSE(controller_->SchedulePageFlip());
EXPECT_FALSE(plane1.buffer->HasOneRef());
EXPECT_FALSE(plane2.buffer->HasOneRef());
EXPECT_FALSE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
drm_->RunCallbacks();
controller_->WaitForPageFlipEvent();
EXPECT_FALSE(plane1.buffer->HasOneRef());
EXPECT_TRUE(plane2.buffer->HasOneRef());
}
......@@ -140,14 +151,18 @@ TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip());
controller_->WaitForPageFlipEvent();
EXPECT_TRUE(controller_->SchedulePageFlip(
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());
controller_->WaitForPageFlipEvent();
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(1, drm_->get_page_flip_call_count());
}
......@@ -166,8 +181,10 @@ TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) {
controller_->QueueOverlayPlane(plane1);
controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip());
controller_->WaitForPageFlipEvent();
EXPECT_TRUE(controller_->SchedulePageFlip(
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());
}
......@@ -184,42 +201,12 @@ TEST_F(HardwareDisplayControllerTest, PageflipMirroredControllers) {
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip());
EXPECT_EQ(2, drm_->get_page_flip_call_count());
controller_->WaitForPageFlipEvent();
EXPECT_EQ(2, drm_->get_handle_events_count());
}
TEST_F(HardwareDisplayControllerTest,
PageflipMirroredControllersWithInvertedCrtcOrder) {
scoped_ptr<ui::CrtcController> crtc1(
new ui::CrtcController(drm_.get(), kPrimaryCrtc, kPrimaryConnector));
scoped_ptr<ui::CrtcController> crtc2(
new ui::CrtcController(drm_.get(), kSecondaryCrtc, kSecondaryConnector));
// Make sure that if the order is reversed everything is still fine.
std::queue<ui::CrtcController*> crtc_queue;
crtc_queue.push(crtc2.get());
crtc_queue.push(crtc1.get());
controller_.reset(new ui::HardwareDisplayController(crtc1.Pass()));
controller_->AddCrtc(crtc2.Pass());
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
EXPECT_EQ(2, drm_->get_set_crtc_call_count());
ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
controller_->QueueOverlayPlane(plane2);
EXPECT_TRUE(controller_->SchedulePageFlip());
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
drm_->RunCallbacks();
EXPECT_EQ(2, drm_->get_page_flip_call_count());
drm_->set_controllers(crtc_queue);
controller_->WaitForPageFlipEvent();
EXPECT_EQ(2, drm_->get_handle_events_count());
EXPECT_EQ(1, page_flips_);
}
TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
......@@ -227,8 +214,10 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
controller_->QueueOverlayPlane(plane1);
EXPECT_TRUE(controller_->SchedulePageFlip());
controller_->WaitForPageFlipEvent();
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
drm_->RunCallbacks();
const ui::HardwareDisplayPlane* owned_plane = nullptr;
for (const auto& plane : drm_->plane_manager()->planes())
......@@ -240,3 +229,49 @@ TEST_F(HardwareDisplayControllerTest, PlaneStateAfterRemoveCrtc) {
scoped_ptr<ui::CrtcController> crtc = controller_->RemoveCrtc(kPrimaryCrtc);
EXPECT_FALSE(owned_plane->in_use());
}
TEST_F(HardwareDisplayControllerTest, ModesetWhilePageFlipping) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
controller_->QueueOverlayPlane(plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
drm_->RunCallbacks();
EXPECT_EQ(1, page_flips_);
}
TEST_F(HardwareDisplayControllerTest, AddCrtcMidPageFlip) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
controller_->QueueOverlayPlane(plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
controller_->AddCrtc(scoped_ptr<ui::CrtcController>(
new ui::CrtcController(drm_.get(), kSecondaryCrtc, kSecondaryConnector)));
drm_->RunCallbacks();
EXPECT_EQ(1, page_flips_);
}
TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new MockScanoutBuffer(kDefaultModeSize)));
EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
controller_->QueueOverlayPlane(plane1);
EXPECT_TRUE(controller_->SchedulePageFlip(
base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
base::Unretained(this))));
controller_->RemoveCrtc(kPrimaryCrtc);
EXPECT_EQ(1, page_flips_);
drm_->RunCallbacks();
EXPECT_EQ(1, page_flips_);
}
......@@ -4,6 +4,7 @@
#include "ui/ozone/platform/dri/hardware_display_plane_manager_legacy.h"
#include "base/bind.h"
#include "ui/ozone/platform/dri/crtc_controller.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/scanout_buffer.h"
......@@ -25,7 +26,9 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(
plane_list->plane_list.clear();
for (const auto& flip : plane_list->legacy_page_flips) {
// Permission Denied is a legitimate error
if (!drm_->PageFlip(flip.crtc_id, flip.framebuffer, flip.crtc)) {
if (!drm_->PageFlip(flip.crtc_id, flip.framebuffer,
base::Bind(&CrtcController::OnPageFlipEvent,
flip.crtc->AsWeakPtr()))) {
if (errno != EACCES) {
LOG(ERROR) << "Cannot page flip: error='" << strerror(errno) << "'"
<< " crtc=" << flip.crtc_id
......
......@@ -47,7 +47,7 @@ const char kDefaultGraphicsCardPath[] = "/dev/dri/card0";
class OzonePlatformDri : public OzonePlatform {
public:
OzonePlatformDri()
: dri_(new DriWrapper(kDefaultGraphicsCardPath)),
: dri_(new DriWrapper(kDefaultGraphicsCardPath, true)),
buffer_generator_(new DriBufferGenerator(dri_.get())),
screen_manager_(new ScreenManager(dri_.get(), buffer_generator_.get())),
device_manager_(CreateDeviceManager()) {
......
......@@ -148,7 +148,7 @@ class OzonePlatformGbm : public OzonePlatform {
}
void InitializeGPU() override {
dri_.reset(new DriWrapper(kDefaultGraphicsCardPath));
dri_.reset(new DriWrapper(kDefaultGraphicsCardPath, false));
dri_->Initialize();
buffer_generator_.reset(new GbmBufferGenerator(dri_.get()));
screen_manager_.reset(
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_OZONE_PLATFORM_DRI_PAGE_FLIP_OBSERVER_H_
#define UI_OZONE_PLATFORM_DRI_PAGE_FLIP_OBSERVER_H_
namespace ui {
class PageFlipObserver {
public:
virtual ~PageFlipObserver() {}
virtual void OnPageFlipEvent() = 0;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRI_PAGE_FLIP_OBSERVER_H_
......@@ -9,7 +9,6 @@
#include "base/logging.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/ozone/platform/dri/crtc_controller.h"
#include "ui/ozone/platform/dri/hardware_display_plane_manager_legacy.h"
namespace ui {
......@@ -41,7 +40,7 @@ class MockHardwareDisplayPlaneManager
} // namespace
MockDriWrapper::MockDriWrapper(int fd)
: DriWrapper(""),
: DriWrapper("", true),
get_crtc_call_count_(0),
set_crtc_call_count_(0),
restore_crtc_call_count_(0),
......@@ -49,7 +48,6 @@ MockDriWrapper::MockDriWrapper(int fd)
remove_framebuffer_call_count_(0),
page_flip_call_count_(0),
overlay_flip_call_count_(0),
handle_events_count_(0),
set_crtc_expectation_(true),
add_framebuffer_expectation_(true),
page_flip_expectation_(true),
......@@ -60,9 +58,10 @@ MockDriWrapper::MockDriWrapper(int fd)
}
MockDriWrapper::MockDriWrapper(int fd,
bool software_mode,
std::vector<uint32_t> crtcs,
size_t planes_per_crtc)
: DriWrapper(""),
: DriWrapper("", software_mode),
get_crtc_call_count_(0),
set_crtc_call_count_(0),
restore_crtc_call_count_(0),
......@@ -70,7 +69,6 @@ MockDriWrapper::MockDriWrapper(int fd,
remove_framebuffer_call_count_(0),
page_flip_call_count_(0),
overlay_flip_call_count_(0),
handle_events_count_(0),
set_crtc_expectation_(true),
add_framebuffer_expectation_(true),
page_flip_expectation_(true),
......@@ -137,10 +135,16 @@ ScopedDrmFramebufferPtr MockDriWrapper::GetFramebuffer(uint32_t framebuffer) {
bool MockDriWrapper::PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
void* data) {
const PageFlipCallback& callback) {
page_flip_call_count_++;
current_framebuffer_ = framebuffer;
controllers_.push(static_cast<ui::CrtcController*>(data));
if (page_flip_expectation_) {
if (software_mode_)
callback.Run(0, 0, 0);
else
callbacks_.push(callback);
}
return page_flip_expectation_;
}
......@@ -184,13 +188,6 @@ bool MockDriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) {
return true;
}
void MockDriWrapper::HandleEvent(drmEventContext& event) {
CHECK(!controllers_.empty());
controllers_.front()->OnPageFlipEvent(0, 0, 0);
controllers_.pop();
handle_events_count_++;
}
bool MockDriWrapper::CreateDumbBuffer(const SkImageInfo& info,
uint32_t* handle,
uint32_t* stride,
......@@ -215,4 +212,12 @@ void MockDriWrapper::DestroyDumbBuffer(const SkImageInfo& info,
delete[] static_cast<char*>(pixels);
}
void MockDriWrapper::RunCallbacks() {
while (!callbacks_.empty()) {
PageFlipCallback callback = callbacks_.front();
callbacks_.pop();
callback.Run(0, 0, 0);
}
}
} // namespace ui
......@@ -20,7 +20,10 @@ class CrtcController;
class MockDriWrapper : public ui::DriWrapper {
public:
MockDriWrapper(int fd);
MockDriWrapper(int fd, std::vector<uint32_t> crtcs, size_t planes_per_crtc);
MockDriWrapper(int fd,
bool software_mode,
std::vector<uint32_t> crtcs,
size_t planes_per_crtc);
~MockDriWrapper() override;
int get_get_crtc_call_count() const { return get_crtc_call_count_; }
......@@ -34,7 +37,6 @@ class MockDriWrapper : public ui::DriWrapper {
}
int get_page_flip_call_count() const { return page_flip_call_count_; }
int get_overlay_flip_call_count() const { return overlay_flip_call_count_; }
int get_handle_events_count() const { return handle_events_count_; }
void fail_init() { fd_ = -1; }
void set_set_crtc_expectation(bool state) { set_crtc_expectation_ = state; }
void set_page_flip_expectation(bool state) { page_flip_expectation_ = state; }
......@@ -51,10 +53,7 @@ class MockDriWrapper : public ui::DriWrapper {
return buffers_;
}
// Overwrite the list of controllers used when serving the PageFlip requests.
void set_controllers(const std::queue<CrtcController*>& controllers) {
controllers_ = controllers;
}
void RunCallbacks();
// DriWrapper:
ScopedDrmCrtcPtr GetCrtc(uint32_t crtc_id) override;
......@@ -74,7 +73,9 @@ class MockDriWrapper : public ui::DriWrapper {
uint32_t* framebuffer) override;
bool RemoveFramebuffer(uint32_t framebuffer) override;
ScopedDrmFramebufferPtr GetFramebuffer(uint32_t framebuffer) override;
bool PageFlip(uint32_t crtc_id, uint32_t framebuffer, void* data) override;
bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
const PageFlipCallback& callback) override;
bool PageFlipOverlay(uint32_t crtc_id,
uint32_t framebuffer,
const gfx::Rect& location,
......@@ -92,7 +93,6 @@ class MockDriWrapper : public ui::DriWrapper {
uint32_t handle,
const gfx::Size& size) override;
bool MoveCursor(uint32_t crtc_id, const gfx::Point& point) override;
void HandleEvent(drmEventContext& event) override;
bool CreateDumbBuffer(const SkImageInfo& info,
uint32_t* handle,
uint32_t* stride,
......@@ -110,7 +110,6 @@ class MockDriWrapper : public ui::DriWrapper {
int remove_framebuffer_call_count_;
int page_flip_call_count_;
int overlay_flip_call_count_;
int handle_events_count_;
bool set_crtc_expectation_;
bool add_framebuffer_expectation_;
......@@ -121,7 +120,7 @@ class MockDriWrapper : public ui::DriWrapper {
std::vector<skia::RefPtr<SkSurface> > buffers_;
std::queue<CrtcController*> controllers_;
std::queue<PageFlipCallback> callbacks_;
DISALLOW_COPY_AND_ASSIGN(MockDriWrapper);
};
......
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