Commit bb8e99d0 authored by Mark Yacoub's avatar Mark Yacoub Committed by Commit Bot

Replace drmModeSetCrtc by Atomic APIs

If the device supports atomic APIs, use drmModeAtomicCommit to modeset
and disable instead of drmModeSetCrtc.
Abstracted Modeset and Disabled code to HDPM to handle both atomic and
legacy call.
Updated tests to support Connector and CRTC props.

BUG=987274
TEST=HardwareDisplayControllerTest.CheckModesettingSetsProps,
HardwareDisplayPlaneManagerLegacyTest.Modeset,
HardwareDisplayPlaneManagerLegacyTest.DisableModeset,
HardwareDisplayPlaneManagerAtomicTest.DisableModeset, Tested on
Nautilus(Intel), Grunt(AMD) and Cave(Legacy).

Change-Id: Ic307c04df4e22d1696abb31ebcd820f6bdcb542a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1715751
Commit-Queue: Mark Yacoub <markyacoub@google.com>
Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735013}
parent 04d0e026
......@@ -14,6 +14,7 @@
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
......@@ -40,14 +41,16 @@ CrtcController::~CrtcController() {
}
DisableCursor();
drm_->DisableCrtc(crtc_);
drm_->plane_manager()->DisableModeset(crtc_, connector_);
}
}
bool CrtcController::Modeset(const DrmOverlayPlane& plane,
drmModeModeInfo mode) {
if (!drm_->SetCrtc(crtc_, plane.buffer->opaque_framebuffer_id(),
std::vector<uint32_t>(1, connector_), &mode)) {
const drmModeModeInfo& mode,
const ui::HardwareDisplayPlaneList& plane_list) {
if (!drm_->plane_manager()->Modeset(crtc_,
plane.buffer->opaque_framebuffer_id(),
connector_, mode, plane_list)) {
PLOG(ERROR) << "Failed to modeset: crtc=" << crtc_
<< " connector=" << connector_
<< " framebuffer_id=" << plane.buffer->opaque_framebuffer_id()
......@@ -74,12 +77,15 @@ bool CrtcController::Disable() {
is_disabled_ = true;
DisableCursor();
return drm_->DisableCrtc(crtc_);
return drm_->plane_manager()->DisableModeset(crtc_, connector_);
}
bool CrtcController::AssignOverlayPlanes(HardwareDisplayPlaneList* plane_list,
const DrmOverlayPlaneList& overlays) {
DCHECK(!is_disabled_);
const DrmOverlayPlaneList& overlays,
bool is_modesetting) {
// If we're in the process of modesetting, the CRTC is still disabled.
// Once the modeset is done, we expect it to be enabled.
DCHECK(is_modesetting || !is_disabled_);
const DrmOverlayPlane* primary = DrmOverlayPlane::GetPrimaryPlane(overlays);
if (primary && !drm_->plane_manager()->ValidatePrimarySize(*primary, mode_)) {
......
......@@ -40,15 +40,19 @@ class CrtcController {
const scoped_refptr<DrmDevice>& drm() const { return drm_; }
bool is_disabled() const { return is_disabled_; }
// Perform the initial modesetting operation using |plane| as the buffer for
// the primary plane. The CRTC configuration is specified by |mode|.
bool Modeset(const DrmOverlayPlane& plane, drmModeModeInfo mode);
// Sets up all props used in atomic modesets and performs the initial
// modesetting operation using |plane| as the buffer for the primary plane
// with the CRTC configuration is specified by |mode|.
bool Modeset(const DrmOverlayPlane& plane,
const drmModeModeInfo& mode,
const ui::HardwareDisplayPlaneList& plane_list);
// Disables the controller.
bool Disable();
bool AssignOverlayPlanes(HardwareDisplayPlaneList* plane_list,
const DrmOverlayPlaneList& planes);
const DrmOverlayPlaneList& planes,
bool is_modesetting);
// Returns a vector of format modifiers for the given fourcc format
// on this CRTCs primary plane. A format modifier describes the
......
......@@ -9,6 +9,7 @@
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <memory>
#include <utility>
......@@ -146,7 +147,7 @@ DrmPropertyBlobMetadata::~DrmPropertyBlobMetadata() {
class DrmDevice::PageFlipManager {
public:
PageFlipManager() : next_id_(0) {}
~PageFlipManager() {}
~PageFlipManager() = default;
void OnPageFlip(uint32_t frame, base::TimeTicks timestamp, uint64_t id) {
auto it =
......@@ -248,7 +249,7 @@ DrmDevice::DrmDevice(const base::FilePath& device_path,
is_primary_device_(is_primary_device),
gbm_(std::move(gbm)) {}
DrmDevice::~DrmDevice() {}
DrmDevice::~DrmDevice() = default;
bool DrmDevice::Initialize() {
// Ignore devices that cannot perform modesetting.
......@@ -302,36 +303,21 @@ ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) {
bool DrmDevice::SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
drmModeModeInfo* mode) {
drmModeModeInfo mode) {
DCHECK(file_.IsValid());
DCHECK(!connectors.empty());
DCHECK(mode);
TRACE_EVENT2("drm", "DrmDevice::SetCrtc", "crtc", crtc_id, "size",
gfx::Size(mode->hdisplay, mode->vdisplay).ToString());
gfx::Size(mode.hdisplay, mode.vdisplay).ToString());
return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, framebuffer, 0, 0,
connectors.data(), connectors.size(), mode);
}
bool DrmDevice::SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors) {
DCHECK(file_.IsValid());
// If there's no buffer then the CRTC was disabled.
if (!crtc->buffer_id)
return DisableCrtc(crtc->crtc_id);
DCHECK(!connectors.empty());
TRACE_EVENT1("drm", "DrmDevice::RestoreCrtc", "crtc", crtc->crtc_id);
return !drmModeSetCrtc(file_.GetPlatformFile(), crtc->crtc_id,
crtc->buffer_id, crtc->x, crtc->y, connectors.data(),
connectors.size(), &crtc->mode);
connectors.data(), connectors.size(), &mode);
}
bool DrmDevice::DisableCrtc(uint32_t crtc_id) {
DCHECK(file_.IsValid());
TRACE_EVENT1("drm", "DrmDevice::DisableCrtc", "crtc", crtc_id);
return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, 0, 0, 0, NULL, 0,
NULL);
return !drmModeSetCrtc(file_.GetPlatformFile(), crtc_id, 0, 0, 0, nullptr, 0,
nullptr);
}
ScopedDrmConnectorPtr DrmDevice::GetConnector(uint32_t connector_id) {
......@@ -432,7 +418,8 @@ bool DrmDevice::SetProperty(uint32_t connector_id,
property_id, value);
}
ScopedDrmPropertyBlob DrmDevice::CreatePropertyBlob(void* blob, size_t size) {
ScopedDrmPropertyBlob DrmDevice::CreatePropertyBlob(const void* blob,
size_t size) {
uint32_t id = 0;
int ret = drmModeCreatePropertyBlob(file_.GetPlatformFile(), blob, size, &id);
DCHECK(!ret && id);
......
......@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <vector>
......@@ -106,12 +107,7 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
virtual bool SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
drmModeModeInfo* mode);
// Used to set a specific configuration to the CRTC. Normally this function
// would be called with a CRTC saved state (from |GetCrtc|) to restore it to
// its original configuration.
virtual bool SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors);
drmModeModeInfo mode);
virtual bool DisableCrtc(uint32_t crtc_id);
......@@ -168,7 +164,8 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
uint64_t value);
// Creates a property blob with data |blob| of size |size|.
virtual ScopedDrmPropertyBlob CreatePropertyBlob(void* blob, size_t size);
virtual ScopedDrmPropertyBlob CreatePropertyBlob(const void* blob,
size_t size);
virtual void DestroyPropertyBlob(uint32_t id);
......
......@@ -40,14 +40,14 @@ constexpr uint32_t kConnectorIdBase = 100;
constexpr uint32_t kPlaneIdBase = 200;
constexpr uint32_t kInFormatsBlobPropIdBase = 400;
constexpr uint32_t kTypePropId = 300;
constexpr uint32_t kInFormatsPropId = 301;
constexpr uint32_t kTypePropId = 3010;
constexpr uint32_t kInFormatsPropId = 3011;
} // namespace
class DrmOverlayValidatorTest : public testing::Test {
public:
DrmOverlayValidatorTest() {}
DrmOverlayValidatorTest() = default;
void SetUp() override;
void TearDown() override;
......@@ -166,29 +166,51 @@ void DrmOverlayValidatorTest::InitializeDrmState(
const std::vector<CrtcState>& crtc_states) {
std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(
crtc_states.size());
std::map<uint32_t, std::string> crtc_property_names = {
{1000, "ACTIVE"},
{1001, "MODE_ID"},
};
std::vector<ui::MockDrmDevice::ConnectorProperties> connector_properties(
crtc_states.size());
std::map<uint32_t, std::string> connector_property_names = {
{2000, "CRTC_ID"},
};
std::vector<ui::MockDrmDevice::PlaneProperties> plane_properties;
std::map<uint32_t, std::string> property_names = {
constexpr uint32_t kPlaneCrtcidId = 3000;
std::map<uint32_t, std::string> plane_property_names = {
// Add all required properties.
{1000, "CRTC_ID"},
{1001, "CRTC_X"},
{1002, "CRTC_Y"},
{1003, "CRTC_W"},
{1004, "CRTC_H"},
{1005, "FB_ID"},
{1006, "SRC_X"},
{1007, "SRC_Y"},
{1008, "SRC_W"},
{1009, "SRC_H"},
{kPlaneCrtcidId, "CRTC_ID"},
{3001, "CRTC_X"},
{3002, "CRTC_Y"},
{3003, "CRTC_W"},
{3004, "CRTC_H"},
{3005, "FB_ID"},
{3006, "SRC_X"},
{3007, "SRC_Y"},
{3008, "SRC_W"},
{3009, "SRC_H"},
// Defines some optional properties we use for convenience.
{kTypePropId, "type"},
{kInFormatsPropId, "IN_FORMATS"},
};
{kInFormatsPropId, "IN_FORMATS"}};
uint32_t plane_id = kPlaneIdBase;
uint32_t property_id = kInFormatsBlobPropIdBase;
for (size_t crtc_idx = 0; crtc_idx < crtc_states.size(); ++crtc_idx) {
crtc_properties[crtc_idx].id = kCrtcIdBase + crtc_idx;
for (const auto& pair : crtc_property_names) {
crtc_properties[crtc_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ 0});
}
connector_properties[crtc_idx].id = kConnectorIdBase + crtc_idx;
for (const auto& pair : connector_property_names) {
connector_properties[crtc_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ 0});
}
std::vector<ui::MockDrmDevice::PlaneProperties> crtc_plane_properties(
crtc_states[crtc_idx].planes.size());
......@@ -197,29 +219,45 @@ void DrmOverlayValidatorTest::InitializeDrmState(
crtc_plane_properties[plane_idx].id = plane_id++;
crtc_plane_properties[plane_idx].crtc_mask = 1 << crtc_idx;
for (const auto& pair : property_names) {
for (const auto& pair : plane_property_names) {
uint64_t value = 0;
if (pair.first == kTypePropId) {
value =
plane_idx == 0 ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
} else if (pair.first == kInFormatsPropId) {
value = property_id++;
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
value, crtc_states[crtc_idx].planes[plane_idx].formats,
std::vector<drm_format_modifier>()));
switch (pair.first) {
case kTypePropId:
value = plane_idx == 0 ? DRM_PLANE_TYPE_PRIMARY
: DRM_PLANE_TYPE_OVERLAY;
break;
case kInFormatsPropId:
value = property_id++;
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
value, crtc_states[crtc_idx].planes[plane_idx].formats,
std::vector<drm_format_modifier>()));
break;
case kPlaneCrtcidId:
value = crtc_properties[crtc_idx].id;
break;
default:
break;
}
crtc_plane_properties[plane_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ value});
}
}
plane_properties.insert(plane_properties.end(),
crtc_plane_properties.begin(),
crtc_plane_properties.end());
plane_properties.insert(plane_properties.end(),
crtc_plane_properties.begin(),
crtc_plane_properties.end());
}
}
drm_->InitializeState(crtc_properties, plane_properties, property_names,
std::map<uint32_t, std::string> property_names;
property_names.insert(crtc_property_names.begin(), crtc_property_names.end());
property_names.insert(connector_property_names.begin(),
connector_property_names.end());
property_names.insert(plane_property_names.begin(),
plane_property_names.end());
drm_->InitializeState(crtc_properties, connector_properties, plane_properties,
property_names,
/* use_atomic= */ true);
}
......
......@@ -7,6 +7,7 @@
#include <drm.h>
#include <string.h>
#include <xf86drm.h>
#include <memory>
#include <utility>
......@@ -65,29 +66,39 @@ HardwareDisplayController::HardwareDisplayController(
AllocateCursorBuffers();
}
HardwareDisplayController::~HardwareDisplayController() {
}
HardwareDisplayController::~HardwareDisplayController() = default;
bool HardwareDisplayController::Modeset(const DrmOverlayPlane& primary,
drmModeModeInfo mode) {
const drmModeModeInfo& mode) {
TRACE_EVENT0("drm", "HDC::Modeset");
DCHECK(primary.buffer.get());
bool status = true;
for (const auto& controller : crtc_controllers_)
status &= controller->Modeset(primary, mode);
is_disabled_ = false;
ResetCursor();
OnModesetComplete(primary);
return status;
return ModesetCrtc(primary, /*use_current_crtc_mode=*/false, mode);
}
bool HardwareDisplayController::Enable(const DrmOverlayPlane& primary) {
TRACE_EVENT0("drm", "HDC::Enable");
drmModeModeInfo empty_mode = {};
return ModesetCrtc(primary, /*use_current_crtc_mode=*/true, empty_mode);
}
bool HardwareDisplayController::ModesetCrtc(const DrmOverlayPlane& primary,
bool use_current_crtc_mode,
const drmModeModeInfo& mode) {
DCHECK(primary.buffer.get());
bool status = true;
for (const auto& controller : crtc_controllers_)
status &= controller->Modeset(primary, controller->mode());
HardwareDisplayPlaneList hardware_planes;
hardware_planes.old_plane_list = GetAllOwnedPlanes();
GetDrmDevice()->plane_manager()->BeginFrame(hardware_planes);
DrmOverlayPlaneList plane_list;
plane_list.push_back(primary.Clone());
for (const auto& controller : crtc_controllers_) {
status &= controller->AssignOverlayPlanes(&hardware_planes, plane_list,
/*is_modesetting=*/true);
drmModeModeInfo modeset_mode =
use_current_crtc_mode ? controller->mode() : mode;
status &= controller->Modeset(primary, modeset_mode, hardware_planes);
}
is_disabled_ = false;
ResetCursor();
......@@ -99,6 +110,10 @@ void HardwareDisplayController::Disable() {
TRACE_EVENT0("drm", "HDC::Disable");
for (const auto& controller : crtc_controllers_)
// TODO(crbug.com/1015104): Modeset and Disable operations should go
// together. The current split is due to how the legacy/atomic split
// evolved. It should be cleaned up under the more generic
// HardwareDisplayPlaneManager{Legacy,Atomic} calls.
controller->Disable();
bool ret = GetDrmDevice()->plane_manager()->DisableOverlayPlanes(
......@@ -170,11 +185,12 @@ bool HardwareDisplayController::ScheduleOrTestPageFlip(
bool status = true;
for (const auto& controller : crtc_controllers_) {
status &= controller->AssignOverlayPlanes(&hardware_planes, pending_planes);
status &= controller->AssignOverlayPlanes(&hardware_planes, pending_planes,
/*is_modesetting=*/false);
}
status &= GetDrmDevice()->plane_manager()->Commit(
hardware_planes, page_flip_request, out_fence);
hardware_planes, /*modeset=*/false, page_flip_request, out_fence);
return status;
}
......
......@@ -95,7 +95,7 @@ class HardwareDisplayController {
// Performs the initial CRTC configuration. If successful, it will display the
// framebuffer for |primary| with |mode|.
bool Modeset(const DrmOverlayPlane& primary, drmModeModeInfo mode);
bool Modeset(const DrmOverlayPlane& primary, const drmModeModeInfo& mode);
// Performs a CRTC configuration re-using the modes from the CRTCs.
bool Enable(const DrmOverlayPlane& primary);
......@@ -169,6 +169,10 @@ class HardwareDisplayController {
const gfx::PresentationFeedback& presentation_feedback);
private:
bool ModesetCrtc(const DrmOverlayPlane& primary,
bool use_current_mode,
const drmModeModeInfo& mode);
void OnModesetComplete(const DrmOverlayPlane& primary);
bool ScheduleOrTestPageFlip(const DrmOverlayPlaneList& plane_list,
scoped_refptr<PageFlipRequest> page_flip_request,
......
......@@ -28,8 +28,7 @@ HardwareDisplayPlaneList::HardwareDisplayPlaneList() {
atomic_property_set.reset(drmModeAtomicAlloc());
}
HardwareDisplayPlaneList::~HardwareDisplayPlaneList() {
}
HardwareDisplayPlaneList::~HardwareDisplayPlaneList() = default;
HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(uint32_t crtc_id,
uint32_t framebuffer)
......@@ -38,8 +37,7 @@ HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(uint32_t crtc_id,
HardwareDisplayPlaneList::PageFlipInfo::PageFlipInfo(
const PageFlipInfo& other) = default;
HardwareDisplayPlaneList::PageFlipInfo::~PageFlipInfo() {
}
HardwareDisplayPlaneList::PageFlipInfo::~PageFlipInfo() = default;
HardwareDisplayPlaneManager::CrtcState::CrtcState() = default;
......@@ -50,8 +48,7 @@ HardwareDisplayPlaneManager::CrtcState::CrtcState(CrtcState&&) = default;
HardwareDisplayPlaneManager::HardwareDisplayPlaneManager(DrmDevice* drm)
: drm_(drm) {}
HardwareDisplayPlaneManager::~HardwareDisplayPlaneManager() {
}
HardwareDisplayPlaneManager::~HardwareDisplayPlaneManager() = default;
bool HardwareDisplayPlaneManager::Initialize() {
// Try to get all of the planes if possible, so we don't have to try to
......@@ -97,9 +94,19 @@ HardwareDisplayPlane* HardwareDisplayPlaneManager::FindNextUnusedPlane(
}
int HardwareDisplayPlaneManager::LookupCrtcIndex(uint32_t crtc_id) const {
for (size_t i = 0; i < crtc_state_.size(); ++i)
for (size_t i = 0; i < crtc_state_.size(); ++i) {
if (crtc_state_[i].properties.id == crtc_id)
return i;
}
return -1;
}
int HardwareDisplayPlaneManager::LookupConnectorIndex(
uint32_t connector_id) const {
for (size_t i = 0; i < connectors_props_.size(); ++i) {
if (connectors_props_[i].id == connector_id)
return i;
}
return -1;
}
......@@ -178,8 +185,9 @@ bool HardwareDisplayPlaneManager::AssignOverlayPlanes(
// This returns a number in 16.16 fixed point, required by the DRM overlay
// APIs.
auto to_fixed_point =
[](double v) -> uint32_t { return v * kFixedPointScaleValue; };
auto to_fixed_point = [](double v) -> uint32_t {
return v * kFixedPointScaleValue;
};
fixed_point_rect = gfx::Rect(to_fixed_point(crop_rect.x()),
to_fixed_point(crop_rect.y()),
to_fixed_point(crop_rect.width()),
......@@ -324,6 +332,23 @@ bool HardwareDisplayPlaneManager::InitializeCrtcState() {
return false;
}
for (int i = 0; i < resources->count_connectors; ++i) {
ConnectorProperties state_props;
state_props.id = resources->connectors[i];
ScopedDrmObjectPropertyPtr props(drm_->GetObjectProperties(
resources->connectors[i], DRM_MODE_OBJECT_CONNECTOR));
if (!props) {
PLOG(ERROR) << "Failed to get Connector properties for connector="
<< state_props.id;
continue;
}
GetDrmPropertyForName(drm_, props.get(), "CRTC_ID", &state_props.crtc_id);
DCHECK(state_props.crtc_id.id);
connectors_props_.emplace_back(std::move(state_props));
}
unsigned int num_crtcs_with_out_fence_ptr = 0;
for (int i = 0; i < resources->count_crtcs; ++i) {
......@@ -338,6 +363,13 @@ bool HardwareDisplayPlaneManager::InitializeCrtcState() {
continue;
}
GetDrmPropertyForName(drm_, props.get(), "ACTIVE",
&state.properties.active);
DCHECK(state.properties.active.id);
GetDrmPropertyForName(drm_, props.get(), "MODE_ID",
&state.properties.mode_id);
DCHECK(state.properties.mode_id.id);
// These properties are optional. If they don't exist we can tell by the
// invalid ID.
GetDrmPropertyForName(drm_, props.get(), "CTM", &state.properties.ctm);
......
......@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
#include <xf86drmMode.h>
#include <memory>
#include <vector>
......@@ -56,13 +57,22 @@ struct HardwareDisplayPlaneList {
class HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManager(DrmDevice* drm);
explicit HardwareDisplayPlaneManager(DrmDevice* drm);
virtual ~HardwareDisplayPlaneManager();
// This parses information from the drm driver, adding any new planes
// or crtcs found.
bool Initialize();
// Performs modesetting, either atomic or legacy, depending on the device.
virtual bool Modeset(uint32_t crtc_id,
uint32_t framebuffer_id,
uint32_t connector_id,
const drmModeModeInfo& mode,
const HardwareDisplayPlaneList& plane_list) = 0;
virtual bool DisableModeset(uint32_t crtc_id, uint32_t connector) = 0;
// Clears old frame state out. Must be called before any AssignOverlayPlanes
// calls.
void BeginFrame(const HardwareDisplayPlaneList& plane_list);
......@@ -88,7 +98,7 @@ class HardwareDisplayPlaneManager {
uint32_t crtc_id);
// Commit the plane states in |plane_list|.
//
// if |should_modeset| is set, it only modesets without page flipping.
// If |page_flip_request| is null, this tests the plane configuration without
// submitting it.
// The fence returned in |out_fence| will signal when the currently scanned
......@@ -96,6 +106,7 @@ class HardwareDisplayPlaneManager {
// |page_flip_request|. Note that the returned fence may be a nullptr
// if the system doesn't support out fences.
virtual bool Commit(const HardwareDisplayPlaneList& plane_list,
bool should_modeset,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence) = 0;
......@@ -136,10 +147,16 @@ class HardwareDisplayPlaneManager {
const std::vector<uint32_t>& crtcs);
protected:
struct ConnectorProperties {
uint32_t id;
DrmDevice::Property crtc_id;
};
struct CrtcProperties {
// Unique identifier for the CRTC. This must be greater than 0 to be valid.
uint32_t id;
DrmDevice::Property active;
DrmDevice::Property mode_id;
// Optional properties.
DrmDevice::Property ctm;
DrmDevice::Property gamma_lut;
......@@ -185,8 +202,10 @@ class HardwareDisplayPlaneManager {
uint32_t crtc_index,
const DrmOverlayPlane& overlay) const;
// Convert |crtc_id| into an index, returning -1 if the ID couldn't be found.
// Convert |crtc/connector_id| into an index, returning -1 if the ID couldn't
// be found.
int LookupCrtcIndex(uint32_t crtc_id) const;
int LookupConnectorIndex(uint32_t connector_idx) const;
// Returns true if |plane| can support |overlay| and compatible with
// |crtc_index|.
......@@ -211,6 +230,8 @@ class HardwareDisplayPlaneManager {
std::vector<std::unique_ptr<HardwareDisplayPlane>> planes_;
std::vector<CrtcState> crtc_state_;
std::vector<ConnectorProperties> connectors_props_;
std::vector<uint32_t> supported_formats_;
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneManager);
......
......@@ -7,6 +7,7 @@
#include <sync/sync.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <memory>
#include <utility>
......@@ -57,28 +58,92 @@ HardwareDisplayPlaneManagerAtomic::HardwareDisplayPlaneManagerAtomic(
DrmDevice* drm)
: HardwareDisplayPlaneManager(drm) {}
HardwareDisplayPlaneManagerAtomic::~HardwareDisplayPlaneManagerAtomic() {
HardwareDisplayPlaneManagerAtomic::~HardwareDisplayPlaneManagerAtomic() =
default;
bool HardwareDisplayPlaneManagerAtomic::Modeset(
uint32_t crtc_id,
uint32_t framebuffer_id,
uint32_t connector_id,
const drmModeModeInfo& mode,
const HardwareDisplayPlaneList& plane_list) {
const int connector_idx = LookupConnectorIndex(connector_id);
DCHECK_GE(connector_idx, 0);
connectors_props_[connector_idx].crtc_id.value = crtc_id;
bool res =
AddPropertyIfValid(plane_list.atomic_property_set.get(), connector_id,
connectors_props_[connector_idx].crtc_id);
const int crtc_idx = LookupCrtcIndex(crtc_id);
DCHECK_GE(crtc_idx, 0);
crtc_state_[crtc_idx].properties.active.value = 1UL;
ScopedDrmPropertyBlob mode_blob =
drm_->CreatePropertyBlob(&mode, sizeof(mode));
crtc_state_[crtc_idx].properties.mode_id.value =
mode_blob ? mode_blob->id() : 0;
res &= AddPropertyIfValid(plane_list.atomic_property_set.get(), crtc_id,
crtc_state_[crtc_idx].properties.active);
res &= AddPropertyIfValid(plane_list.atomic_property_set.get(), crtc_id,
crtc_state_[crtc_idx].properties.mode_id);
DCHECK(res);
return Commit(plane_list, /*should_modeset=*/true,
/*page_flip_request=*/nullptr,
/*out_fence=*/nullptr);
}
bool HardwareDisplayPlaneManagerAtomic::DisableModeset(uint32_t crtc,
uint32_t connector) {
ScopedDrmAtomicReqPtr property_set(drmModeAtomicAlloc());
const int connector_idx = LookupConnectorIndex(connector);
DCHECK_GE(connector_idx, 0);
connectors_props_[connector_idx].crtc_id.value = 0UL;
bool res = AddPropertyIfValid(property_set.get(), connector,
connectors_props_[connector_idx].crtc_id);
const int crtc_idx = LookupCrtcIndex(crtc);
DCHECK_GE(crtc_idx, 0);
crtc_state_[crtc_idx].properties.active.value = 0UL;
crtc_state_[crtc_idx].properties.mode_id.value = 0UL;
res &= AddPropertyIfValid(property_set.get(), crtc,
crtc_state_[crtc_idx].properties.active);
res &= AddPropertyIfValid(property_set.get(), crtc,
crtc_state_[crtc_idx].properties.mode_id);
DCHECK(res);
return drm_->CommitProperties(property_set.get(),
DRM_MODE_ATOMIC_ALLOW_MODESET, 1, nullptr);
}
bool HardwareDisplayPlaneManagerAtomic::Commit(
const HardwareDisplayPlaneList& plane_list,
bool should_modeset,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence) {
bool test_only = !page_flip_request;
bool test_only = !should_modeset && !page_flip_request;
for (HardwareDisplayPlane* plane : plane_list.old_plane_list) {
if (!base::Contains(plane_list.plane_list, plane)) {
// This plane is being released, so we need to zero it.
plane->set_in_use(false);
HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane);
atomic_plane->SetPlaneData(
plane_list.atomic_property_set.get(), 0, 0, gfx::Rect(), gfx::Rect(),
gfx::OVERLAY_TRANSFORM_NONE, base::kInvalidPlatformFile);
if (plane->in_use()) {
// This plane is being released, so we need to zero it.
plane->set_in_use(false);
HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane);
atomic_plane->SetPlaneData(plane_list.atomic_property_set.get(), 0, 0,
gfx::Rect(), gfx::Rect(),
gfx::OVERLAY_TRANSFORM_NONE,
base::kInvalidPlatformFile);
}
}
}
std::vector<uint32_t> crtcs;
for (HardwareDisplayPlane* plane : plane_list.plane_list) {
if (!plane->in_use())
continue;
HardwareDisplayPlaneAtomic* atomic_plane =
static_cast<HardwareDisplayPlaneAtomic*>(plane);
if (crtcs.empty() || crtcs.back() != atomic_plane->crtc_id())
......@@ -110,11 +175,10 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
}
uint32_t flags = 0;
if (test_only) {
flags = DRM_MODE_ATOMIC_TEST_ONLY;
} else {
flags = DRM_MODE_ATOMIC_NONBLOCK;
}
if (should_modeset)
flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
else
flags = test_only ? DRM_MODE_ATOMIC_TEST_ONLY : DRM_MODE_ATOMIC_NONBLOCK;
// After we perform the atomic commit, and if the caller has requested an
// out-fence, the out_fence_fds vector will contain any provided out-fence
......
......@@ -6,6 +6,7 @@
#define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_MANAGER_ATOMIC_H_
#include <stdint.h>
#include <memory>
#include "base/macros.h"
......@@ -15,11 +16,18 @@ namespace ui {
class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManagerAtomic(DrmDevice* drm);
explicit HardwareDisplayPlaneManagerAtomic(DrmDevice* drm);
~HardwareDisplayPlaneManagerAtomic() override;
// HardwareDisplayPlaneManager:
bool Modeset(uint32_t crtc_id,
uint32_t framebuffer_id,
uint32_t connector_id,
const drmModeModeInfo& mode,
const HardwareDisplayPlaneList& plane_list) override;
bool DisableModeset(uint32_t crtc, uint32_t connector) override;
bool Commit(const HardwareDisplayPlaneList& plane_list,
bool should_modeset,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence) override;
bool DisableOverlayPlanes(
......
......@@ -6,6 +6,7 @@
#include <errno.h>
#include <sync/sync.h>
#include <memory>
#include <utility>
......@@ -42,13 +43,31 @@ HardwareDisplayPlaneManagerLegacy::HardwareDisplayPlaneManagerLegacy(
DrmDevice* drm)
: HardwareDisplayPlaneManager(drm) {}
HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() {
HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() =
default;
bool HardwareDisplayPlaneManagerLegacy::Modeset(
uint32_t crtc_id,
uint32_t framebuffer_id,
uint32_t connector_id,
const drmModeModeInfo& mode,
const HardwareDisplayPlaneList&) {
return drm_->SetCrtc(crtc_id, framebuffer_id,
std::vector<uint32_t>(1, connector_id), mode);
}
bool HardwareDisplayPlaneManagerLegacy::DisableModeset(uint32_t crtc_id,
uint32_t connector) {
return drm_->DisableCrtc(crtc_id);
}
bool HardwareDisplayPlaneManagerLegacy::Commit(
const HardwareDisplayPlaneList& plane_list,
bool should_modeset,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence) {
DCHECK(!should_modeset);
bool test_only = !page_flip_request;
if (test_only) {
for (HardwareDisplayPlane* plane : plane_list.plane_list) {
......
......@@ -6,6 +6,7 @@
#define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_MANAGER_LEGACY_H_
#include <stdint.h>
#include <memory>
#include "base/macros.h"
......@@ -15,11 +16,18 @@ namespace ui {
class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
public:
HardwareDisplayPlaneManagerLegacy(DrmDevice* device);
explicit HardwareDisplayPlaneManagerLegacy(DrmDevice* device);
~HardwareDisplayPlaneManagerLegacy() override;
// HardwareDisplayPlaneManager:
bool Modeset(uint32_t crtc_id,
uint32_t framebuffer_id,
uint32_t connector_id,
const drmModeModeInfo& mode,
const HardwareDisplayPlaneList&) override;
bool DisableModeset(uint32_t crtc_id, uint32_t connector) override;
bool Commit(const HardwareDisplayPlaneList& plane_list,
bool should_modeset,
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence) override;
bool DisableOverlayPlanes(
......
......@@ -70,6 +70,11 @@ MockDrmDevice::CrtcProperties::CrtcProperties() = default;
MockDrmDevice::CrtcProperties::CrtcProperties(const CrtcProperties&) = default;
MockDrmDevice::CrtcProperties::~CrtcProperties() = default;
MockDrmDevice::ConnectorProperties::ConnectorProperties() = default;
MockDrmDevice::ConnectorProperties::ConnectorProperties(
const ConnectorProperties&) = default;
MockDrmDevice::ConnectorProperties::~ConnectorProperties() = default;
MockDrmDevice::PlaneProperties::PlaneProperties() = default;
MockDrmDevice::PlaneProperties::PlaneProperties(const PlaneProperties&) =
default;
......@@ -126,19 +131,23 @@ ScopedDrmPropertyBlobPtr MockDrmDevice::AllocateInFormatsBlob(
void MockDrmDevice::InitializeState(
const std::vector<CrtcProperties>& crtc_properties,
const std::vector<ConnectorProperties>& connector_properties,
const std::vector<PlaneProperties>& plane_properties,
const std::map<uint32_t, std::string>& property_names,
bool use_atomic) {
CHECK(InitializeStateWithResult(crtc_properties, plane_properties,
property_names, use_atomic));
CHECK(InitializeStateWithResult(crtc_properties, connector_properties,
plane_properties, property_names,
use_atomic));
}
bool MockDrmDevice::InitializeStateWithResult(
const std::vector<CrtcProperties>& crtc_properties,
const std::vector<ConnectorProperties>& connector_properties,
const std::vector<PlaneProperties>& plane_properties,
const std::map<uint32_t, std::string>& property_names,
bool use_atomic) {
crtc_properties_ = crtc_properties;
connector_properties_ = connector_properties;
plane_properties_ = plane_properties;
property_names_ = property_names;
if (use_atomic) {
......@@ -150,7 +159,7 @@ bool MockDrmDevice::InitializeStateWithResult(
return plane_manager_->Initialize();
}
MockDrmDevice::~MockDrmDevice() {}
MockDrmDevice::~MockDrmDevice() = default;
ScopedDrmResourcesPtr MockDrmDevice::GetResources() {
ScopedDrmResourcesPtr resources(DrmAllocator<drmModeRes>());
......@@ -160,6 +169,12 @@ ScopedDrmResourcesPtr MockDrmDevice::GetResources() {
for (size_t i = 0; i < crtc_properties_.size(); ++i)
resources->crtcs[i] = crtc_properties_[i].id;
resources->count_connectors = connector_properties_.size();
resources->connectors = static_cast<uint32_t*>(
drmMalloc(sizeof(uint32_t) * resources->count_connectors));
for (size_t i = 0; i < connector_properties_.size(); ++i)
resources->connectors[i] = connector_properties_[i].id;
return resources;
}
......@@ -185,6 +200,11 @@ ScopedDrmObjectPropertyPtr MockDrmDevice::GetObjectProperties(
CrtcProperties* properties = FindObjectById(object_id, crtc_properties_);
if (properties)
return CreatePropertyObject(properties->properties);
} else if (object_type == DRM_MODE_OBJECT_CONNECTOR) {
ConnectorProperties* properties =
FindObjectById(object_id, connector_properties_);
if (properties)
return CreatePropertyObject(properties->properties);
}
return nullptr;
......@@ -198,19 +218,13 @@ ScopedDrmCrtcPtr MockDrmDevice::GetCrtc(uint32_t crtc_id) {
bool MockDrmDevice::SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
drmModeModeInfo* mode) {
drmModeModeInfo mode) {
crtc_fb_[crtc_id] = framebuffer;
current_framebuffer_ = framebuffer;
set_crtc_call_count_++;
return set_crtc_expectation_;
}
bool MockDrmDevice::SetCrtc(drmModeCrtc* crtc,
std::vector<uint32_t> connectors) {
restore_crtc_call_count_++;
return true;
}
bool MockDrmDevice::DisableCrtc(uint32_t crtc_id) {
current_framebuffer_ = 0;
return true;
......@@ -304,7 +318,7 @@ bool MockDrmDevice::SetProperty(uint32_t connector_id,
return true;
}
ScopedDrmPropertyBlob MockDrmDevice::CreatePropertyBlob(void* blob,
ScopedDrmPropertyBlob MockDrmDevice::CreatePropertyBlob(const void* blob,
size_t size) {
uint32_t id = ++property_id_generator_;
allocated_property_blobs_.insert(id);
......@@ -484,6 +498,12 @@ bool MockDrmDevice::UpdateProperty(uint32_t object_id,
if (crtc_properties)
return UpdateProperty(property_id, value, &crtc_properties->properties);
ConnectorProperties* connector_properties =
FindObjectById(object_id, connector_properties_);
if (connector_properties)
return UpdateProperty(property_id, value,
&connector_properties->properties);
return false;
}
......
......@@ -34,6 +34,16 @@ class MockDrmDevice : public DrmDevice {
std::vector<DrmDevice::Property> properties;
};
struct ConnectorProperties {
ConnectorProperties();
ConnectorProperties(const ConnectorProperties&);
~ConnectorProperties();
uint32_t id;
std::vector<DrmDevice::Property> properties;
};
struct PlaneProperties {
PlaneProperties();
PlaneProperties(const PlaneProperties&);
......@@ -44,7 +54,7 @@ class MockDrmDevice : public DrmDevice {
std::vector<DrmDevice::Property> properties;
};
MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device);
explicit MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device);
static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob(
uint32_t id,
......@@ -91,12 +101,15 @@ class MockDrmDevice : public DrmDevice {
void set_connector_type(uint32_t type) { connector_type_ = type; }
void InitializeState(const std::vector<CrtcProperties>& crtc_properties,
const std::vector<PlaneProperties>& plane_properties,
const std::map<uint32_t, std::string>& property_names,
bool use_atomic);
void InitializeState(
const std::vector<CrtcProperties>& crtc_properties,
const std::vector<ConnectorProperties>& connector_properties,
const std::vector<PlaneProperties>& plane_properties,
const std::map<uint32_t, std::string>& property_names,
bool use_atomic);
bool InitializeStateWithResult(
const std::vector<CrtcProperties>& crtc_properties,
const std::vector<ConnectorProperties>& connector_properties,
const std::vector<PlaneProperties>& plane_properties,
const std::map<uint32_t, std::string>& property_names,
bool use_atomic);
......@@ -114,8 +127,7 @@ class MockDrmDevice : public DrmDevice {
bool SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
drmModeModeInfo* mode) override;
bool SetCrtc(drmModeCrtc* crtc, std::vector<uint32_t> connectors) override;
drmModeModeInfo mode) override;
bool DisableCrtc(uint32_t crtc_id) override;
ScopedDrmConnectorPtr GetConnector(uint32_t connector_id) override;
bool AddFramebuffer2(uint32_t width,
......@@ -139,7 +151,8 @@ class MockDrmDevice : public DrmDevice {
bool SetProperty(uint32_t connector_id,
uint32_t property_id,
uint64_t value) override;
ScopedDrmPropertyBlob CreatePropertyBlob(void* blob, size_t size) override;
ScopedDrmPropertyBlob CreatePropertyBlob(const void* blob,
size_t size) override;
void DestroyPropertyBlob(uint32_t id) override;
bool GetCapability(uint64_t capability, uint64_t* value) override;
ScopedDrmPropertyBlobPtr GetPropertyBlob(uint32_t property_id) override;
......@@ -215,6 +228,8 @@ class MockDrmDevice : public DrmDevice {
std::vector<CrtcProperties> crtc_properties_;
std::vector<ConnectorProperties> connector_properties_;
std::vector<PlaneProperties> plane_properties_;
std::map<uint32_t, std::string> property_names_;
......
......@@ -32,9 +32,14 @@ const drmModeModeInfo kDefaultMode = {0, 6, 0, 0, 0, 0, 4, 0,
0, 0, 0, 0, 0, 0, {'\0'}};
const uint32_t kPrimaryCrtc = 1;
const uint32_t kPrimaryConnector = 2;
const uint32_t kSecondaryCrtc = 3;
const uint32_t kSecondaryConnector = 4;
const uint32_t kPrimaryConnector = 100;
const uint32_t kSecondaryCrtc = kPrimaryCrtc + 1;
const uint32_t kSecondaryConnector = kPrimaryConnector + 1;
constexpr uint32_t kPlaneIdBase = 200;
constexpr uint32_t kTypePropId = 3010;
constexpr uint32_t kInFormatsPropId = 3011;
constexpr uint32_t kInFormatsBlobPropIdBase = 400;
drmModeModeInfo Mode(uint16_t hdisplay, uint16_t vdisplay) {
return {0, hdisplay, 0, 0, 0, 0, vdisplay, 0, 0, 0, 0, 0, 0, 0, {'\0'}};
......@@ -44,8 +49,117 @@ drmModeModeInfo Mode(uint16_t hdisplay, uint16_t vdisplay) {
class ScreenManagerTest : public testing::Test {
public:
ScreenManagerTest() {}
~ScreenManagerTest() override {}
ScreenManagerTest() = default;
~ScreenManagerTest() override = default;
struct PlaneState {
std::vector<uint32_t> formats;
};
struct CrtcState {
std::vector<PlaneState> planes;
};
void InitializeDrmState(const std::vector<CrtcState>& crtc_states,
bool atomic) {
std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(
crtc_states.size());
std::map<uint32_t, std::string> crtc_property_names = {
{1000, "ACTIVE"},
{1001, "MODE_ID"},
};
std::vector<ui::MockDrmDevice::ConnectorProperties> connector_properties(
crtc_states.size());
std::map<uint32_t, std::string> connector_property_names = {
{2000, "CRTC_ID"},
};
std::vector<ui::MockDrmDevice::PlaneProperties> plane_properties;
constexpr uint32_t kPlaneCrtcidId = 3000;
std::map<uint32_t, std::string> plane_property_names = {
// Add all required properties.
{kPlaneCrtcidId, "CRTC_ID"},
{3001, "CRTC_X"},
{3002, "CRTC_Y"},
{3003, "CRTC_W"},
{3004, "CRTC_H"},
{3005, "FB_ID"},
{3006, "SRC_X"},
{3007, "SRC_Y"},
{3008, "SRC_W"},
{3009, "SRC_H"},
// Defines some optional properties we use for convenience.
{kTypePropId, "type"},
{kInFormatsPropId, "IN_FORMATS"}};
uint32_t plane_id = kPlaneIdBase;
uint32_t property_id = kInFormatsBlobPropIdBase;
for (size_t crtc_idx = 0; crtc_idx < crtc_states.size(); ++crtc_idx) {
crtc_properties[crtc_idx].id = kPrimaryCrtc + crtc_idx;
for (const auto& pair : crtc_property_names) {
crtc_properties[crtc_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ 0});
}
connector_properties[crtc_idx].id = kPrimaryConnector + crtc_idx;
for (const auto& pair : connector_property_names) {
connector_properties[crtc_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ 0});
}
std::vector<ui::MockDrmDevice::PlaneProperties> crtc_plane_properties(
crtc_states[crtc_idx].planes.size());
for (size_t plane_idx = 0;
plane_idx < crtc_states[crtc_idx].planes.size(); ++plane_idx) {
crtc_plane_properties[plane_idx].id = plane_id++;
crtc_plane_properties[plane_idx].crtc_mask = 1 << crtc_idx;
for (const auto& pair : plane_property_names) {
uint64_t value = 0;
switch (pair.first) {
case kTypePropId:
value = plane_idx == 0 ? DRM_PLANE_TYPE_PRIMARY
: DRM_PLANE_TYPE_OVERLAY;
break;
case kInFormatsPropId:
value = property_id++;
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
value, crtc_states[crtc_idx].planes[plane_idx].formats,
std::vector<drm_format_modifier>()));
break;
case kPlaneCrtcidId:
value = crtc_properties[crtc_idx].id;
break;
default:
break;
}
crtc_plane_properties[plane_idx].properties.push_back(
{/* .id = */ pair.first, /* .value = */ value});
}
plane_properties.insert(plane_properties.end(),
crtc_plane_properties.begin(),
crtc_plane_properties.end());
}
}
std::map<uint32_t, std::string> property_names;
property_names.insert(crtc_property_names.begin(),
crtc_property_names.end());
property_names.insert(connector_property_names.begin(),
connector_property_names.end());
property_names.insert(plane_property_names.begin(),
plane_property_names.end());
drm_->InitializeState(crtc_properties, connector_properties,
plane_properties, property_names,
/* use_atomic= */ true);
}
gfx::Rect GetPrimaryBounds() const {
return gfx::Rect(0, 0, kDefaultMode.hdisplay, kDefaultMode.vdisplay);
......@@ -63,6 +177,7 @@ class ScreenManagerTest : public testing::Test {
device_manager_ = std::make_unique<ui::DrmDeviceManager>(nullptr);
screen_manager_ = std::make_unique<ui::ScreenManager>();
}
void TearDown() override {
screen_manager_.reset();
drm_ = nullptr;
......@@ -201,6 +316,24 @@ TEST_F(ScreenManagerTest, CheckForControllersInMirroredMode) {
}
TEST_F(ScreenManagerTest, CheckMirrorModeTransitions) {
std::vector<CrtcState> crtc_states = {
{
/* .planes = */
{
{/* .formats = */ {DRM_FORMAT_XRGB8888}},
{/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
},
},
{
/* .planes = */
{
{/* .formats = */ {DRM_FORMAT_XRGB8888}},
{/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
},
},
};
InitializeDrmState(crtc_states, /*atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->ConfigureDisplayController(
drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
......@@ -352,6 +485,24 @@ TEST_F(ScreenManagerTest, ReuseFramebufferIfDisabledThenReEnabled) {
}
TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {
std::vector<CrtcState> crtc_states = {
{
/* .planes = */
{
{/* .formats = */ {DRM_FORMAT_XRGB8888}},
{/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
},
},
{
/* .planes = */
{
{/* .formats = */ {DRM_FORMAT_XRGB8888}},
{/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_NV12}},
},
},
};
InitializeDrmState(crtc_states, /*atomic=*/true);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->ConfigureDisplayController(
drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
......
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