[go: up one dir, main page]

blob: efadce735e76d704b54ab683c2b88be3f1c29bae [file] [log] [blame]
// Copyright 2014 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.
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
#include <drm.h>
#include <string.h>
#include <xf86drm.h>
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "ui/ozone/public/native_pixmap.h"
namespace ui {
HardwareDisplayController::HardwareDisplayController(
scoped_ptr<CrtcController> controller,
const gfx::Point& origin)
: origin_(origin),
is_disabled_(controller->is_disabled()) {
AddCrtc(controller.Pass());
}
HardwareDisplayController::~HardwareDisplayController() {
// Reset the cursor.
UnsetCursor();
}
bool HardwareDisplayController::Modeset(const OverlayPlane& primary,
drmModeModeInfo mode) {
TRACE_EVENT0("drm", "HDC::Modeset");
DCHECK(primary.buffer.get());
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->Modeset(primary, mode);
is_disabled_ = false;
return status;
}
bool HardwareDisplayController::Enable(const OverlayPlane& primary) {
TRACE_EVENT0("drm", "HDC::Enable");
DCHECK(primary.buffer.get());
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i) {
status &=
crtc_controllers_[i]->Modeset(primary, crtc_controllers_[i]->mode());
}
is_disabled_ = false;
return status;
}
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;
}
bool HardwareDisplayController::SchedulePageFlip(
const OverlayPlaneList& plane_list,
bool is_sync,
bool test_only,
const PageFlipCallback& callback) {
TRACE_EVENT0("drm", "HDC::SchedulePageFlip");
DCHECK(!is_disabled_);
// Ignore requests with no planes to schedule.
if (plane_list.empty()) {
callback.Run(gfx::SwapResult::SWAP_ACK);
return true;
}
scoped_refptr<PageFlipRequest> page_flip_request =
new PageFlipRequest(crtc_controllers_.size(), callback);
OverlayPlaneList pending_planes = plane_list;
std::sort(pending_planes.begin(), pending_planes.end(),
[](const OverlayPlane& l, const OverlayPlane& r) {
return l.z_order < r.z_order;
});
if (pending_planes.front().z_order != 0)
return false;
for (const auto& planes : owned_hardware_planes_)
planes.first->plane_manager()->BeginFrame(planes.second);
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().get()),
pending_planes, test_only, page_flip_request);
}
for (const auto& planes : owned_hardware_planes_) {
if (!planes.first->plane_manager()->Commit(planes.second, is_sync,
test_only)) {
status = false;
}
}
return status;
}
bool HardwareDisplayController::SetCursor(
const scoped_refptr<ScanoutBuffer>& buffer) {
bool status = true;
if (is_disabled_)
return true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->SetCursor(buffer);
return status;
}
bool HardwareDisplayController::UnsetCursor() {
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->SetCursor(nullptr);
return status;
}
bool HardwareDisplayController::MoveCursor(const gfx::Point& location) {
if (is_disabled_)
return true;
bool status = true;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
status &= crtc_controllers_[i]->MoveCursor(location);
return status;
}
void HardwareDisplayController::AddCrtc(scoped_ptr<CrtcController> controller) {
owned_hardware_planes_.add(
controller->drm().get(),
scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList()));
crtc_controllers_.push_back(controller.Pass());
}
scoped_ptr<CrtcController> HardwareDisplayController::RemoveCrtc(
const scoped_refptr<DrmDevice>& drm,
uint32_t crtc) {
for (ScopedVector<CrtcController>::iterator it = crtc_controllers_.begin();
it != crtc_controllers_.end(); ++it) {
if ((*it)->drm() == drm && (*it)->crtc() == crtc) {
scoped_ptr<CrtcController> controller(*it);
crtc_controllers_.weak_erase(it);
// Remove entry from |owned_hardware_planes_| iff no other crtcs share it.
bool found = false;
for (ScopedVector<CrtcController>::iterator it =
crtc_controllers_.begin();
it != crtc_controllers_.end(); ++it) {
if ((*it)->drm() == controller->drm()) {
found = true;
break;
}
}
if (!found)
owned_hardware_planes_.erase(controller->drm().get());
return controller.Pass();
}
}
return nullptr;
}
bool HardwareDisplayController::HasCrtc(const scoped_refptr<DrmDevice>& drm,
uint32_t crtc) const {
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
if (crtc_controllers_[i]->drm() == drm &&
crtc_controllers_[i]->crtc() == crtc)
return true;
return false;
}
bool HardwareDisplayController::IsMirrored() const {
return crtc_controllers_.size() > 1;
}
bool HardwareDisplayController::IsDisabled() const {
return is_disabled_;
}
gfx::Size HardwareDisplayController::GetModeSize() const {
// If there are multiple CRTCs they should all have the same size.
return gfx::Size(crtc_controllers_[0]->mode().hdisplay,
crtc_controllers_[0]->mode().vdisplay);
}
uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
uint64_t time = 0;
for (size_t i = 0; i < crtc_controllers_.size(); ++i)
if (time < crtc_controllers_[i]->time_of_last_flip())
time = crtc_controllers_[i]->time_of_last_flip();
return time;
}
scoped_refptr<DrmDevice> HardwareDisplayController::GetAllocationDrmDevice()
const {
DCHECK(!crtc_controllers_.empty());
// TODO(dnicoara) When we support mirroring across DRM devices, figure out
// which device should be used for allocations.
return crtc_controllers_[0]->drm();
}
} // namespace ui