Commit 12dc8ef2 authored by Daniel Nicoara's avatar Daniel Nicoara Committed by Commit Bot

Reland "[Ozone-DRM] Refactor plane management and add tests"

This is a reland of ce767464

Original change's description:
> [Ozone-DRM] Refactor plane management and add tests
>
> * We use plane properties on legacy DRM to get some details (plane
> type, in_formats). Read the properties in HardwareDisplayPlane and
> check that the required properties are available in DRM atomic.
> * Split dummy plane into its own class to clean up code.
> * Remove test plane since we can now create the real objects via
> injected state in DrmDevice.
> * Cleanup plane initialization.
> * Remove MockHardwareDisplayPlaneManager and rely on MockDrmDevice to
> inject the necessary state.
>
> BUG=839487
> TEST=Ran unittests
>
> Change-Id: I03c91620557dcf7426629cf97bb989d8d7e83c68
> Reviewed-on: https://chromium-review.googlesource.com/1048585
> Commit-Queue: Daniel Nicoara <dnicoara@chromium.org>
> Reviewed-by: Daniele Castagna <dcastagna@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#561616}

Bug: 839487
Change-Id: Ifb74647dfe1f05ef3339261dd1f7c51c0c371622
Reviewed-on: https://chromium-review.googlesource.com/1073487Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Commit-Queue: Daniel Nicoara <dnicoara@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561949}
parent 6a25833c
......@@ -64,6 +64,8 @@ source_set("gbm") {
"gpu/hardware_display_plane.h",
"gpu/hardware_display_plane_atomic.cc",
"gpu/hardware_display_plane_atomic.h",
"gpu/hardware_display_plane_dummy.cc",
"gpu/hardware_display_plane_dummy.h",
"gpu/hardware_display_plane_manager.cc",
"gpu/hardware_display_plane_manager.h",
"gpu/hardware_display_plane_manager_atomic.cc",
......@@ -161,8 +163,6 @@ source_set("gbm_unittests") {
"gpu/mock_drm_device.h",
"gpu/mock_dumb_buffer_generator.cc",
"gpu/mock_dumb_buffer_generator.h",
"gpu/mock_hardware_display_plane_manager.cc",
"gpu/mock_hardware_display_plane_manager.h",
"gpu/mock_scanout_buffer.cc",
"gpu/mock_scanout_buffer.h",
"gpu/mock_scanout_buffer_generator.cc",
......
......@@ -8,6 +8,7 @@
#include "base/time/time.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
......
......@@ -393,6 +393,17 @@ ScopedDrmFramebufferPtr DrmDevice::GetFramebuffer(uint32_t framebuffer) {
drmModeGetFB(file_.GetPlatformFile(), framebuffer));
}
ScopedDrmPlanePtr DrmDevice::GetPlane(uint32_t plane_id) {
DCHECK(file_.IsValid());
return ScopedDrmPlanePtr(drmModeGetPlane(file_.GetPlatformFile(), plane_id));
}
ScopedDrmPlaneResPtr DrmDevice::GetPlaneResources() {
DCHECK(file_.IsValid());
return ScopedDrmPlaneResPtr(
drmModeGetPlaneResources(file_.GetPlatformFile()));
}
ScopedDrmPropertyPtr DrmDevice::GetProperty(drmModeConnector* connector,
const char* name) {
TRACE_EVENT2("drm", "DrmDevice::GetProperty", "connector",
......@@ -427,6 +438,12 @@ bool DrmDevice::GetCapability(uint64_t capability, uint64_t* value) {
return !drmGetCap(file_.GetPlatformFile(), capability, value);
}
ScopedDrmPropertyBlobPtr DrmDevice::GetPropertyBlob(uint32_t property_id) {
DCHECK(file_.IsValid());
return ScopedDrmPropertyBlobPtr(
drmModeGetPropertyBlob(file_.GetPlatformFile(), property_id));
}
ScopedDrmPropertyBlobPtr DrmDevice::GetPropertyBlob(drmModeConnector* connector,
const char* name) {
DCHECK(file_.IsValid());
......
......@@ -131,6 +131,12 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
const gfx::Rect& source,
int overlay_plane);
// Returns the list of all planes available on this DRM device.
virtual ScopedDrmPlaneResPtr GetPlaneResources();
// Returns the properties associated with plane with id |plane_id|.
virtual ScopedDrmPlanePtr GetPlane(uint32_t plane_id);
// Returns the property with name |name| associated with |connector|. Returns
// NULL if property not found. If the returned value is valid, it must be
// released using FreeProperty().
......@@ -145,17 +151,21 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
uint32_t property_id,
uint64_t value);
// Can be used to query device/driver |capability|. Sets the value of
// |capability to |value|. Returns true in case of a succesful query.
virtual bool GetCapability(uint64_t capability, uint64_t* value);
// Returns a binary blob associated with |property_id|. May be nullptr if the
// property couldn't be found.
virtual ScopedDrmPropertyBlobPtr GetPropertyBlob(uint32_t property_id);
// Return a binary blob associated with |connector|. The binary blob is
// Returns a binary blob associated with |connector|. The binary blob is
// associated with the property with name |name|. Return NULL if the property
// could not be found or if the property does not have a binary blob. If valid
// the returned object must be freed using FreePropertyBlob().
virtual ScopedDrmPropertyBlobPtr GetPropertyBlob(drmModeConnector* connector,
const char* name);
// Can be used to query device/driver |capability|. Sets the value of
// |capability| to |value|. Returns true in case of a succesful query.
virtual bool GetCapability(uint64_t capability, uint64_t* value);
// Set the cursor to be displayed in CRTC |crtc_id|. (width, height) is the
// cursor size pointed by |handle|.
virtual bool SetCursor(uint32_t crtc_id,
......
......@@ -97,7 +97,7 @@ void DrmWindowTest::SetUp() {
last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED;
message_loop_.reset(new base::MessageLoopForUI);
drm_ = new ui::MockDrmDevice();
drm_ = new ui::MockDrmDevice(false);
buffer_generator_.reset(new ui::MockDumbBufferGenerator());
screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector);
......@@ -154,7 +154,7 @@ TEST_F(DrmWindowTest, CheckCursorSurfaceAfterChangingDevice) {
gfx::Point(4, 2), 0);
// Add another device.
scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice();
scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice(false);
screen_manager_->AddDisplayController(drm, kDefaultCrtc, kDefaultConnector);
screen_manager_->ConfigureDisplayController(
drm, kDefaultCrtc, kDefaultConnector,
......
......@@ -20,6 +20,7 @@
#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/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
namespace ui {
......
......@@ -13,6 +13,7 @@
#include "ui/gfx/presentation_feedback.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/mock_drm_device.h"
#include "ui/ozone/platform/drm/gpu/mock_scanout_buffer.h"
......@@ -22,11 +23,11 @@ namespace {
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 size_t kPlanesPerCrtc = 2;
constexpr uint32_t kCrtcIdBase = 1;
constexpr uint32_t kPrimaryCrtc = kCrtcIdBase;
constexpr uint32_t kSecondaryCrtc = kCrtcIdBase + 1;
constexpr uint32_t kPrimaryConnector = 10;
constexpr uint32_t kSecondaryConnector = 11;
const gfx::Size kDefaultModeSize(kDefaultMode.hdisplay, kDefaultMode.vdisplay);
const gfx::Size kOverlaySize(kDefaultMode.hdisplay / 2,
......@@ -43,6 +44,7 @@ class HardwareDisplayControllerTest : public testing::Test {
void SetUp() override;
void TearDown() override;
void InitializeDrmDevice(bool use_atomic);
void PageFlipCallback(gfx::SwapResult result,
const gfx::PresentationFeedback& feedback);
......@@ -62,10 +64,9 @@ void HardwareDisplayControllerTest::SetUp() {
page_flips_ = 0;
last_swap_result_ = gfx::SwapResult::SWAP_FAILED;
std::vector<uint32_t> crtcs;
crtcs.push_back(kPrimaryCrtc);
crtcs.push_back(kSecondaryCrtc);
drm_ = new ui::MockDrmDevice(false, crtcs, kPlanesPerCrtc);
drm_ = new ui::MockDrmDevice(false);
InitializeDrmDevice(/* use_atomic= */ false);
controller_.reset(new ui::HardwareDisplayController(
std::unique_ptr<ui::CrtcController>(
new ui::CrtcController(drm_.get(), kPrimaryCrtc, kPrimaryConnector)),
......@@ -77,6 +78,60 @@ void HardwareDisplayControllerTest::TearDown() {
drm_ = nullptr;
}
void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) {
constexpr uint32_t kTypePropId = 300;
constexpr uint32_t kInFormatsPropId = 301;
constexpr uint32_t kInFormatsBlobPropId = 400;
std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties(2);
std::vector<ui::MockDrmDevice::PlaneProperties> plane_properties;
std::map<uint32_t, std::string> property_names = {
// Add all required properties.
{200, "CRTC_ID"},
{201, "CRTC_X"},
{202, "CRTC_Y"},
{203, "CRTC_W"},
{204, "CRTC_H"},
{205, "FB_ID"},
{206, "SRC_X"},
{207, "SRC_Y"},
{208, "SRC_W"},
{209, "SRC_H"},
// Add some optional properties we use for convenience.
{kTypePropId, "type"},
{kInFormatsPropId, "IN_FORMATS"},
};
for (size_t i = 0; i < crtc_properties.size(); ++i) {
crtc_properties[i].id = kCrtcIdBase + i;
for (size_t j = 0; j < 2; ++j) {
const uint32_t offset = plane_properties.size();
ui::MockDrmDevice::PlaneProperties plane;
plane.id = 100 + offset;
plane.crtc_mask = 1 << i;
for (const auto& pair : property_names) {
uint32_t value = 0;
if (pair.first == kTypePropId)
value = j == 0 ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
else if (pair.first == kInFormatsPropId)
value = kInFormatsBlobPropId;
plane.properties.push_back({.id = pair.first, .value = value});
};
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {}));
plane_properties.emplace_back(std::move(plane));
}
}
drm_->InitializeState(crtc_properties, plane_properties, property_names,
use_atomic);
}
void HardwareDisplayControllerTest::PageFlipCallback(
gfx::SwapResult result,
const gfx::PresentationFeedback& feedback) {
......@@ -480,6 +535,9 @@ TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
}
TEST_F(HardwareDisplayControllerTest, Disable) {
// Page flipping overlays is only supported on atomic configurations.
InitializeDrmDevice(/* use_atomic= */ true);
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new ui::MockScanoutBuffer(kDefaultModeSize)),
nullptr);
......@@ -497,7 +555,6 @@ TEST_F(HardwareDisplayControllerTest, Disable) {
base::Unretained(this)));
drm_->RunCallbacks();
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
controller_->Disable();
......
......@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_util.h"
#ifndef DRM_PLANE_TYPE_OVERLAY
#define DRM_PLANE_TYPE_OVERLAY 0
......@@ -26,7 +27,6 @@ namespace ui {
namespace {
const char* kTypePropName = "type";
HardwareDisplayPlane::Type GetPlaneType(int value) {
switch (value) {
case DRM_PLANE_TYPE_CURSOR:
......@@ -41,57 +41,63 @@ HardwareDisplayPlane::Type GetPlaneType(int value) {
}
}
void ParseSupportedFormatsAndModifiers(
drmModePropertyBlobPtr blob,
std::vector<uint32_t>* supported_formats,
std::vector<drm_format_modifier>* supported_format_modifiers) {
auto* data = static_cast<const uint8_t*>(blob->data);
auto* header = reinterpret_cast<const drm_format_modifier_blob*>(data);
auto* formats =
reinterpret_cast<const uint32_t*>(data + header->formats_offset);
auto* modifiers = reinterpret_cast<const drm_format_modifier*>(
data + header->modifiers_offset);
for (uint32_t k = 0; k < header->count_formats; k++)
supported_formats->push_back(formats[k]);
for (uint32_t k = 0; k < header->count_modifiers; k++)
supported_format_modifiers->push_back(modifiers[k]);
}
} // namespace
HardwareDisplayPlane::HardwareDisplayPlane(uint32_t plane_id,
uint32_t possible_crtcs)
: plane_id_(plane_id), possible_crtcs_(possible_crtcs) {
}
HardwareDisplayPlane::HardwareDisplayPlane(uint32_t id) : id_(id) {}
HardwareDisplayPlane::~HardwareDisplayPlane() {
}
HardwareDisplayPlane::~HardwareDisplayPlane() {}
bool HardwareDisplayPlane::CanUseForCrtc(uint32_t crtc_index) {
return possible_crtcs_ & (1 << crtc_index);
return crtc_mask_ & (1 << crtc_index);
}
bool HardwareDisplayPlane::Initialize(
DrmDevice* drm,
const std::vector<uint32_t>& formats,
const std::vector<drm_format_modifier>& format_modifiers,
bool is_dummy,
bool test_only) {
supported_formats_ = formats;
supported_format_modifiers_ = format_modifiers;
bool HardwareDisplayPlane::Initialize(DrmDevice* drm) {
InitializeProperties(drm);
if (test_only)
return true;
ScopedDrmPlanePtr drm_plane(drm->GetPlane(id_));
DCHECK(drm_plane);
if (is_dummy) {
type_ = kDummy;
supported_formats_.push_back(DRM_FORMAT_XRGB8888);
supported_formats_.push_back(DRM_FORMAT_XBGR8888);
return true;
crtc_mask_ = drm_plane->possible_crtcs;
if (properties_.in_formats.id) {
ScopedDrmPropertyBlobPtr blob(
drm->GetPropertyBlob(properties_.in_formats.value));
DCHECK(blob);
ParseSupportedFormatsAndModifiers(blob.get(), &supported_formats_,
&supported_format_modifiers_);
}
ScopedDrmObjectPropertyPtr plane_props(drmModeObjectGetProperties(
drm->get_fd(), plane_id_, DRM_MODE_OBJECT_PLANE));
if (!plane_props) {
PLOG(ERROR) << "Unable to get plane properties.";
return false;
if (supported_formats_.empty()) {
for (uint32_t i = 0; i < drm_plane->count_formats; ++i)
supported_formats_.push_back(drm_plane->formats[i]);
}
uint32_t count_props = plane_props->count_props;
for (uint32_t i = 0; i < count_props; i++) {
ScopedDrmPropertyPtr property(
drmModeGetProperty(drm->get_fd(), plane_props->props[i]));
if (property && !strcmp(property->name, kTypePropName)) {
type_ = GetPlaneType(plane_props->prop_values[i]);
break;
}
}
if (properties_.type.id)
type_ = GetPlaneType(properties_.type.value);
return InitializeProperties(drm, plane_props);
VLOG(3) << "Initialized plane=" << id_ << " crtc_mask=" << std::hex << "0x"
<< crtc_mask_ << std::dec
<< " supported_formats_count=" << supported_formats_.size()
<< " supported_modifiers_count="
<< supported_format_modifiers_.size();
return true;
}
bool HardwareDisplayPlane::IsSupportedFormat(uint32_t format) {
......@@ -141,10 +147,25 @@ std::vector<uint64_t> HardwareDisplayPlane::ModifiersForFormat(
return modifiers;
}
bool HardwareDisplayPlane::InitializeProperties(
DrmDevice* drm,
const ScopedDrmObjectPropertyPtr& plane_props) {
return true;
void HardwareDisplayPlane::InitializeProperties(DrmDevice* drm) {
ScopedDrmObjectPropertyPtr props =
drm->GetObjectProperties(id_, DRM_MODE_OBJECT_PLANE);
GetDrmPropertyForName(drm, props.get(), "CRTC_ID", &properties_.crtc_id);
GetDrmPropertyForName(drm, props.get(), "CRTC_X", &properties_.crtc_x);
GetDrmPropertyForName(drm, props.get(), "CRTC_Y", &properties_.crtc_y);
GetDrmPropertyForName(drm, props.get(), "CRTC_W", &properties_.crtc_w);
GetDrmPropertyForName(drm, props.get(), "CRTC_H", &properties_.crtc_h);
GetDrmPropertyForName(drm, props.get(), "FB_ID", &properties_.fb_id);
GetDrmPropertyForName(drm, props.get(), "SRC_X", &properties_.src_x);
GetDrmPropertyForName(drm, props.get(), "SRC_Y", &properties_.src_y);
GetDrmPropertyForName(drm, props.get(), "SRC_W", &properties_.src_w);
GetDrmPropertyForName(drm, props.get(), "SRC_H", &properties_.src_h);
GetDrmPropertyForName(drm, props.get(), "type", &properties_.type);
GetDrmPropertyForName(drm, props.get(), "rotation", &properties_.rotation);
GetDrmPropertyForName(drm, props.get(), "IN_FORMATS",
&properties_.in_formats);
GetDrmPropertyForName(drm, props.get(), "IN_FENCE_FD",
&properties_.in_fence_fd);
}
} // namespace ui
......@@ -14,24 +14,19 @@
#include "base/macros.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
namespace ui {
class DrmDevice;
class HardwareDisplayPlane {
public:
enum Type { kDummy, kPrimary, kOverlay, kCursor };
HardwareDisplayPlane(uint32_t plane_id, uint32_t possible_crtcs);
HardwareDisplayPlane(uint32_t id);
virtual ~HardwareDisplayPlane();
bool Initialize(DrmDevice* drm,
const std::vector<uint32_t>& formats,
const std::vector<drm_format_modifier>& format_info,
bool is_dummy,
bool test_only);
virtual bool Initialize(DrmDevice* drm);
bool IsSupportedFormat(uint32_t format);
......@@ -42,7 +37,7 @@ class HardwareDisplayPlane {
bool in_use() const { return in_use_; }
void set_in_use(bool in_use) { in_use_ = in_use; }
uint32_t plane_id() const { return plane_id_; }
uint32_t id() const { return id_; }
Type type() const { return type_; }
void set_type(const Type type) { type_ = type; }
......@@ -53,12 +48,32 @@ class HardwareDisplayPlane {
const std::vector<uint32_t>& supported_formats() const;
protected:
virtual bool InitializeProperties(
DrmDevice* drm,
const ScopedDrmObjectPropertyPtr& plane_props);
struct Properties {
// These properties are mandatory on DRM atomic. On legacy they may or may
// not be present.
DrmDevice::Property crtc_id;
DrmDevice::Property crtc_x;
DrmDevice::Property crtc_y;
DrmDevice::Property crtc_w;
DrmDevice::Property crtc_h;
DrmDevice::Property fb_id;
DrmDevice::Property src_x;
DrmDevice::Property src_y;
DrmDevice::Property src_w;
DrmDevice::Property src_h;
DrmDevice::Property type;
// Optional properties.
DrmDevice::Property rotation;
DrmDevice::Property in_formats;
DrmDevice::Property in_fence_fd;
};
uint32_t id_;
uint32_t crtc_mask_ = 0;
Properties properties_ = {};
uint32_t plane_id_ = 0;
uint32_t possible_crtcs_ = 0;
uint32_t owning_crtc_ = 0;
uint32_t last_used_format_ = 0;
bool in_use_ = false;
......@@ -66,6 +81,9 @@ class HardwareDisplayPlane {
std::vector<uint32_t> supported_formats_;
std::vector<drm_format_modifier> supported_format_modifiers_;
private:
void InitializeProperties(DrmDevice* drm);
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlane);
};
......
......@@ -9,19 +9,6 @@
namespace ui {
namespace {
const char* kCrtcPropName = "CRTC_ID";
const char* kFbPropName = "FB_ID";
const char* kCrtcXPropName = "CRTC_X";
const char* kCrtcYPropName = "CRTC_Y";
const char* kCrtcWPropName = "CRTC_W";
const char* kCrtcHPropName = "CRTC_H";
const char* kSrcXPropName = "SRC_X";
const char* kSrcYPropName = "SRC_Y";
const char* kSrcWPropName = "SRC_W";
const char* kSrcHPropName = "SRC_H";
const char* kRotationPropName = "rotation";
const char* kInFenceFdPropName = "IN_FENCE_FD";
// TODO(dcastagna): Remove the following defines once they're in libdrm headers.
#if !defined(DRM_ROTATE_0)
#define BIT(n) (1 << (n))
......@@ -54,31 +41,41 @@ uint32_t OverlayTransformToDrmRotationPropertyValue(
return 0;
}
} // namespace
bool AddProperty(drmModeAtomicReqPtr property_set,
uint32_t object_id,
const DrmDevice::Property& property) {
int ret = drmModeAtomicAddProperty(property_set, object_id, property.id,
property.value);
if (ret < 0) {
LOG(ERROR) << "Failed to set property object_id=" << object_id
<< " property_id=" << property.id
<< " property_value=" << property.value << " error=" << -ret;
return false;
}
HardwareDisplayPlaneAtomic::Property::Property() {
return true;
}
bool HardwareDisplayPlaneAtomic::Property::Initialize(
DrmDevice* drm,
const char* name,
const ScopedDrmObjectPropertyPtr& plane_props) {
for (uint32_t i = 0; i < plane_props->count_props; i++) {
ScopedDrmPropertyPtr property(
drmModeGetProperty(drm->get_fd(), plane_props->props[i]));
if (property && !strcmp(property->name, name)) {
id = property->prop_id;
break;
}
}
return !!id;
}
} // namespace
HardwareDisplayPlaneAtomic::HardwareDisplayPlaneAtomic(uint32_t plane_id,
uint32_t possible_crtcs)
: HardwareDisplayPlane(plane_id, possible_crtcs) {
}
HardwareDisplayPlaneAtomic::~HardwareDisplayPlaneAtomic() {
HardwareDisplayPlaneAtomic::HardwareDisplayPlaneAtomic(uint32_t id)
: HardwareDisplayPlane(id) {}
HardwareDisplayPlaneAtomic::~HardwareDisplayPlaneAtomic() {}
bool HardwareDisplayPlaneAtomic::Initialize(DrmDevice* drm) {
if (!HardwareDisplayPlane::Initialize(drm))
return false;
// Check that all the required properties have been found.
bool ret = properties_.crtc_id.id && properties_.crtc_x.id &&
properties_.crtc_y.id && properties_.crtc_w.id &&
properties_.crtc_h.id && properties_.fb_id.id &&
properties_.src_x.id && properties_.src_y.id &&
properties_.src_w.id && properties_.src_h.id;
LOG_IF(ERROR, !ret) << "Failed to find all required properties for plane="
<< id_;
return ret;
}
bool HardwareDisplayPlaneAtomic::SetPlaneData(
......@@ -89,72 +86,51 @@ bool HardwareDisplayPlaneAtomic::SetPlaneData(
const gfx::Rect& src_rect,
const gfx::OverlayTransform transform,
int in_fence_fd) {
if (transform != gfx::OVERLAY_TRANSFORM_NONE && !rotation_prop_.id)
if (transform != gfx::OVERLAY_TRANSFORM_NONE && !properties_.rotation.id)
return false;
int plane_set_succeeded =
drmModeAtomicAddProperty(property_set, plane_id_, crtc_prop_.id,
crtc_id) &&
drmModeAtomicAddProperty(property_set, plane_id_, fb_prop_.id,
framebuffer) &&
drmModeAtomicAddProperty(property_set, plane_id_, crtc_x_prop_.id,
crtc_rect.x()) &&
drmModeAtomicAddProperty(property_set, plane_id_, crtc_y_prop_.id,
crtc_rect.y()) &&
drmModeAtomicAddProperty(property_set, plane_id_, crtc_w_prop_.id,
crtc_rect.width()) &&
drmModeAtomicAddProperty(property_set, plane_id_, crtc_h_prop_.id,
crtc_rect.height()) &&
drmModeAtomicAddProperty(property_set, plane_id_, src_x_prop_.id,
src_rect.x()) &&
drmModeAtomicAddProperty(property_set, plane_id_, src_y_prop_.id,
src_rect.y()) &&
drmModeAtomicAddProperty(property_set, plane_id_, src_w_prop_.id,
src_rect.width()) &&
drmModeAtomicAddProperty(property_set, plane_id_, src_h_prop_.id,
src_rect.height());
if (rotation_prop_.id) {
plane_set_succeeded =
plane_set_succeeded &&
drmModeAtomicAddProperty(
property_set, plane_id_, rotation_prop_.id,
OverlayTransformToDrmRotationPropertyValue(transform));
properties_.crtc_id.value = crtc_id;
properties_.crtc_x.value = crtc_rect.x();
properties_.crtc_y.value = crtc_rect.y();
properties_.crtc_w.value = crtc_rect.width();
properties_.crtc_h.value = crtc_rect.height();
properties_.fb_id.value = framebuffer;
properties_.src_x.value = src_rect.x();
properties_.src_y.value = src_rect.y();
properties_.src_w.value = src_rect.width();
properties_.src_h.value = src_rect.height();
bool plane_set_succeeded =
AddProperty(property_set, id_, properties_.crtc_id) &&
AddProperty(property_set, id_, properties_.crtc_x) &&
AddProperty(property_set, id_, properties_.crtc_y) &&
AddProperty(property_set, id_, properties_.crtc_w) &&
AddProperty(property_set, id_, properties_.crtc_h) &&
AddProperty(property_set, id_, properties_.fb_id) &&
AddProperty(property_set, id_, properties_.src_x) &&
AddProperty(property_set, id_, properties_.src_y) &&
AddProperty(property_set, id_, properties_.src_w) &&
AddProperty(property_set, id_, properties_.src_h);
if (properties_.rotation.id) {
properties_.rotation.value =
OverlayTransformToDrmRotationPropertyValue(transform);
plane_set_succeeded = plane_set_succeeded &&
AddProperty(property_set, id_, properties_.rotation);
}
if (in_fence_fd_prop_.id && in_fence_fd >= 0) {
if (properties_.in_fence_fd.id && in_fence_fd >= 0) {
properties_.in_fence_fd.value = in_fence_fd;
plane_set_succeeded =
plane_set_succeeded &&
drmModeAtomicAddProperty(property_set, plane_id_, in_fence_fd_prop_.id,
in_fence_fd);
AddProperty(property_set, id_, properties_.in_fence_fd);
}
if (!plane_set_succeeded) {
PLOG(ERROR) << "Failed to set plane data";
LOG(ERROR) << "Failed to set plane data";
return false;
}
return true;
}
bool HardwareDisplayPlaneAtomic::InitializeProperties(
DrmDevice* drm,
const ScopedDrmObjectPropertyPtr& plane_props) {
bool props_init = crtc_prop_.Initialize(drm, kCrtcPropName, plane_props) &&
fb_prop_.Initialize(drm, kFbPropName, plane_props) &&
crtc_x_prop_.Initialize(drm, kCrtcXPropName, plane_props) &&
crtc_y_prop_.Initialize(drm, kCrtcYPropName, plane_props) &&
crtc_w_prop_.Initialize(drm, kCrtcWPropName, plane_props) &&
crtc_h_prop_.Initialize(drm, kCrtcHPropName, plane_props) &&
src_x_prop_.Initialize(drm, kSrcXPropName, plane_props) &&
src_y_prop_.Initialize(drm, kSrcYPropName, plane_props) &&
src_w_prop_.Initialize(drm, kSrcWPropName, plane_props) &&
src_h_prop_.Initialize(drm, kSrcHPropName, plane_props);
if (!props_init) {
LOG(ERROR) << "Unable to get plane properties.";
return false;
}
// The following properties are optional.
rotation_prop_.Initialize(drm, kRotationPropName, plane_props);
in_fence_fd_prop_.Initialize(drm, kInFenceFdPropName, plane_props);
return true;
}
......
......@@ -6,6 +6,7 @@
#define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_ATOMIC_H_
#include "ui/gfx/overlay_transform.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include <stdint.h>
......@@ -18,13 +19,14 @@ class Rect;
namespace ui {
class CrtcController;
class DrmDevice;
class HardwareDisplayPlaneAtomic : public HardwareDisplayPlane {
public:
HardwareDisplayPlaneAtomic(uint32_t plane_id, uint32_t possible_crtcs);
HardwareDisplayPlaneAtomic(uint32_t id);
~HardwareDisplayPlaneAtomic() override;
bool Initialize(DrmDevice* drm) override;
virtual bool SetPlaneData(drmModeAtomicReq* property_set,
uint32_t crtc_id,
uint32_t framebuffer,
......@@ -37,32 +39,9 @@ class HardwareDisplayPlaneAtomic : public HardwareDisplayPlane {
CrtcController* crtc() const { return crtc_; }
private:
bool InitializeProperties(
DrmDevice* drm,
const ScopedDrmObjectPropertyPtr& plane_props) override;
// TODO(dnicoara): Merge this with DrmDevice::Property.
struct Property {
Property();
bool Initialize(DrmDevice* drm,
const char* name,
const ScopedDrmObjectPropertyPtr& plane_properties);
uint32_t id = 0;
};
Property crtc_prop_;
Property fb_prop_;
Property crtc_x_prop_;
Property crtc_y_prop_;
Property crtc_w_prop_;
Property crtc_h_prop_;
Property src_x_prop_;
Property src_y_prop_;
Property src_w_prop_;
Property src_h_prop_;
Property rotation_prop_;
Property in_fence_fd_prop_;
CrtcController* crtc_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneAtomic);
};
} // namespace ui
......
// Copyright 2018 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_plane_dummy.h"
#include <drm_fourcc.h>
namespace ui {
HardwareDisplayPlaneDummy::HardwareDisplayPlaneDummy(uint32_t id,
uint32_t crtc_mask)
: HardwareDisplayPlane(id) {
crtc_mask_ = crtc_mask;
}
HardwareDisplayPlaneDummy::~HardwareDisplayPlaneDummy() {}
bool HardwareDisplayPlaneDummy::Initialize(DrmDevice* drm) {
type_ = kDummy;
supported_formats_.push_back(DRM_FORMAT_XRGB8888);
supported_formats_.push_back(DRM_FORMAT_XBGR8888);
return true;
}
} // namespace ui
// Copyright 2018 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_DRM_GPU_HARDWARE_DISPLAY_PLANE_DUMMY_H_
#define UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_DUMMY_H_
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
namespace ui {
// Fake plane used with DRM legacy when universal planes are not supported and
// the kernel doesn't report the primary plane.
class HardwareDisplayPlaneDummy : public HardwareDisplayPlane {
public:
HardwareDisplayPlaneDummy(uint32_t id, uint32_t crtc_mask);
~HardwareDisplayPlaneDummy() override;
bool Initialize(DrmDevice* drm) override;
private:
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneDummy);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRM_GPU_HARDWARE_DISPLAY_PLANE_DUMMY_H_
......@@ -16,12 +16,14 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/ozone/platform/drm/gpu/drm_device.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/hardware_display_plane_dummy.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
namespace ui {
namespace {
const float kFixedPointScaleValue = 65536.0f;
constexpr float kFixedPointScaleValue = 1 << 16;
ScopedDrmColorLutPtr CreateLutBlob(
const std::vector<display::GammaRampRGBEntry>& source) {
......@@ -169,82 +171,34 @@ HardwareDisplayPlaneManager::~HardwareDisplayPlaneManager() {
bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
drm_ = drm;
// Try to get all of the planes if possible, so we don't have to try to
// discover hidden primary planes.
bool has_universal_planes = false;
// Try to get all of the planes if possible, so we don't have to try to
// discover hidden primary planes.
#if defined(DRM_CLIENT_CAP_UNIVERSAL_PLANES)
has_universal_planes = drm->SetCapability(DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
#endif // defined(DRM_CLIENT_CAP_UNIVERSAL_PLANES)
has_universal_planes =
drm_->SetCapability(DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
#endif
if (!InitializeCrtcProperties(drm))
return false;
ScopedDrmPlaneResPtr plane_resources(drmModeGetPlaneResources(drm->get_fd()));
ScopedDrmPlaneResPtr plane_resources = drm->GetPlaneResources();
if (!plane_resources) {
PLOG(ERROR) << "Failed to get plane resources";
PLOG(ERROR) << "Failed to get plane resources.";
return false;
}
uint32_t num_planes = plane_resources->count_planes;
std::set<uint32_t> plane_ids;
for (uint32_t i = 0; i < num_planes; ++i) {
// TODO(hoegsberg) crbug.com/763760: We've rolled back the
// downstream, incompatible drmModeGetPlane2 ioctl for now while
// we update libdrm to the upstream per-plane IN_FORMATS property
// API. This drops support for compressed and tiled framebuffers
// in the interim, but once the buildroots and SDKs have pulled in
// the new libdrm we'll add it back by reading the property.
ScopedDrmPlanePtr drm_plane(
drmModeGetPlane(drm->get_fd(), plane_resources->planes[i]));
if (!drm_plane) {
PLOG(ERROR) << "Failed to get plane " << i;
return false;
}
ScopedDrmObjectPropertyPtr drm_plane_properties(drmModeObjectGetProperties(
drm->get_fd(), plane_resources->planes[i], DRM_MODE_OBJECT_PLANE));
std::vector<uint32_t> supported_formats;
std::vector<drm_format_modifier> supported_format_modifiers;
if (drm_plane_properties) {
for (uint32_t j = 0; j < drm_plane_properties->count_props; j++) {
ScopedDrmPropertyPtr property(
drmModeGetProperty(drm->get_fd(), drm_plane_properties->props[j]));
if (strcmp(property->name, "IN_FORMATS") == 0) {
ScopedDrmPropertyBlobPtr blob(drmModeGetPropertyBlob(
drm->get_fd(), drm_plane_properties->prop_values[j]));
auto* data = static_cast<const uint8_t*>(blob->data);
auto* header = reinterpret_cast<const drm_format_modifier_blob*>(data);
auto* formats =
reinterpret_cast<const uint32_t*>(data + header->formats_offset);
auto* modifiers = reinterpret_cast<const drm_format_modifier*>(
data + header->modifiers_offset);
for (uint32_t k = 0; k < header->count_formats; k++)
supported_formats.push_back(formats[k]);
for (uint32_t k = 0; k < header->count_modifiers; k++)
supported_format_modifiers.push_back(modifiers[k]);
}
}
}
if (supported_formats.empty()) {
uint32_t formats_size = drm_plane->count_formats;
for (uint32_t j = 0; j < formats_size; j++)
supported_formats.push_back(drm_plane->formats[j]);
}
plane_ids.insert(drm_plane->plane_id);
for (uint32_t i = 0; i < plane_resources->count_planes; ++i) {
plane_ids.insert(plane_resources->planes[i]);
std::unique_ptr<HardwareDisplayPlane> plane(
CreatePlane(drm_plane->plane_id, drm_plane->possible_crtcs));
CreatePlane(plane_resources->planes[i]));
if (plane->Initialize(drm, supported_formats, supported_format_modifiers,
false, false)) {
// CRTC controllers always assume they have a cursor plane and the cursor
// plane is updated via cursor specific DRM API. Hence, we dont keep
// track of Cursor plane here to avoid re-using it for any other purpose.
if (plane->Initialize(drm)) {
// CRTC controllers always assume they have a cursor plane and the
// cursor plane is updated via cursor specific DRM API. Hence, we don't
// keep track of cursor plane here to avoid re-using it for any other
// purpose.
if (plane->type() != HardwareDisplayPlane::kCursor)
planes_.push_back(std::move(plane));
}
......@@ -258,10 +212,8 @@ bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
for (size_t i = 0; i < crtc_properties_.size(); ++i) {
if (plane_ids.find(crtc_properties_[i].id - 1) == plane_ids.end()) {
std::unique_ptr<HardwareDisplayPlane> dummy_plane(
CreatePlane(crtc_properties_[i].id - 1, (1 << i)));
if (dummy_plane->Initialize(drm, std::vector<uint32_t>(),
std::vector<drm_format_modifier>(), true,
false)) {
new HardwareDisplayPlaneDummy(crtc_properties_[i].id - 1, 1 << i));
if (dummy_plane->Initialize(drm)) {
planes_.push_back(std::move(dummy_plane));
}
}
......@@ -271,7 +223,7 @@ bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
std::sort(planes_.begin(), planes_.end(),
[](const std::unique_ptr<HardwareDisplayPlane>& l,
const std::unique_ptr<HardwareDisplayPlane>& r) {
return l->plane_id() < r->plane_id();
return l->id() < r->id();
});
PopulateSupportedFormats();
......@@ -279,10 +231,8 @@ bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
}
std::unique_ptr<HardwareDisplayPlane> HardwareDisplayPlaneManager::CreatePlane(
uint32_t plane_id,
uint32_t possible_crtcs) {
return std::unique_ptr<HardwareDisplayPlane>(
new HardwareDisplayPlane(plane_id, possible_crtcs));
uint32_t id) {
return std::make_unique<HardwareDisplayPlane>(id);
}
HardwareDisplayPlane* HardwareDisplayPlaneManager::FindNextUnusedPlane(
......
......@@ -14,7 +14,6 @@
#include "ui/display/types/gamma_ramp_rgb_entry.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
namespace gfx {
......@@ -24,6 +23,7 @@ class Rect;
namespace ui {
class CrtcController;
class HardwareDisplayPlane;
// This contains the list of planes controlled by one HDC on a given DRM fd.
// It is owned by the HDC and filled by the CrtcController.
......@@ -150,9 +150,7 @@ class HardwareDisplayPlaneManager {
const gfx::Rect& src_rect,
CrtcController* crtc) = 0;
virtual std::unique_ptr<HardwareDisplayPlane> CreatePlane(
uint32_t plane_id,
uint32_t possible_crtcs);
virtual std::unique_ptr<HardwareDisplayPlane> CreatePlane(uint32_t plane_id);
// Finds the plane located at or after |*index| that is not in use and can
// be used with |crtc_index|.
......
......@@ -219,10 +219,8 @@ bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
}
std::unique_ptr<HardwareDisplayPlane>
HardwareDisplayPlaneManagerAtomic::CreatePlane(uint32_t plane_id,
uint32_t possible_crtcs) {
return std::unique_ptr<HardwareDisplayPlane>(
new HardwareDisplayPlaneAtomic(plane_id, possible_crtcs));
HardwareDisplayPlaneManagerAtomic::CreatePlane(uint32_t plane_id) {
return std::make_unique<HardwareDisplayPlaneAtomic>(plane_id);
}
} // namespace ui
......@@ -39,9 +39,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
CrtcController* crtc) override;
private:
std::unique_ptr<HardwareDisplayPlane> CreatePlane(
uint32_t plane_id,
uint32_t possible_crtcs) override;
std::unique_ptr<HardwareDisplayPlane> CreatePlane(uint32_t plane_id) override;
DISALLOW_COPY_AND_ASSIGN(HardwareDisplayPlaneManagerAtomic);
};
......
......@@ -14,6 +14,7 @@
#include "ui/gfx/presentation_feedback.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/scanout_buffer.h"
namespace ui {
......@@ -99,9 +100,9 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(
if (!plane->in_use() && (plane->type() != HardwareDisplayPlane::kDummy)) {
// This plane is being released, so we need to zero it.
if (!drm_->PageFlipOverlay(plane->owning_crtc(), 0, gfx::Rect(),
gfx::Rect(), plane->plane_id())) {
gfx::Rect(), plane->id())) {
PLOG(ERROR) << "Cannot free overlay: crtc=" << plane->owning_crtc()
<< " plane=" << plane->plane_id();
<< " plane=" << plane->id();
ret = false;
break;
}
......@@ -174,7 +175,7 @@ bool HardwareDisplayPlaneManagerLegacy::SetPlaneData(
} else {
plane_list->legacy_page_flips.back().planes.push_back(
HardwareDisplayPlaneList::PageFlipInfo::Plane(
hw_plane->plane_id(), overlay.buffer->GetOpaqueFramebufferId(),
hw_plane->id(), overlay.buffer->GetOpaqueFramebufferId(),
overlay.display_bounds, src_rect));
}
return true;
......
......@@ -9,7 +9,8 @@
#include "base/logging.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
namespace ui {
......@@ -20,9 +21,35 @@ Object* DrmAllocator() {
return static_cast<Object*>(drmMalloc(sizeof(Object)));
}
ScopedDrmObjectPropertyPtr CreatePropertyObject(
const std::vector<DrmDevice::Property>& properties) {
ScopedDrmObjectPropertyPtr drm_properties(
DrmAllocator<drmModeObjectProperties>());
drm_properties->count_props = properties.size();
drm_properties->props = static_cast<uint32_t*>(
drmMalloc(sizeof(uint32_t) * drm_properties->count_props));
drm_properties->prop_values = static_cast<uint64_t*>(
drmMalloc(sizeof(uint64_t) * drm_properties->count_props));
for (size_t i = 0; i < properties.size(); ++i) {
drm_properties->props[i] = properties[i].id;
drm_properties->prop_values[i] = properties[i].value;
}
return drm_properties;
}
} // namespace
MockDrmDevice::MockDrmDevice()
MockDrmDevice::CrtcProperties::CrtcProperties() = default;
MockDrmDevice::CrtcProperties::CrtcProperties(const CrtcProperties&) = default;
MockDrmDevice::CrtcProperties::~CrtcProperties() = default;
MockDrmDevice::PlaneProperties::PlaneProperties() = default;
MockDrmDevice::PlaneProperties::PlaneProperties(const PlaneProperties&) =
default;
MockDrmDevice::PlaneProperties::~PlaneProperties() = default;
MockDrmDevice::MockDrmDevice(bool use_sync_flips)
: DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */),
get_crtc_call_count_(0),
set_crtc_call_count_(0),
......@@ -37,44 +64,102 @@ MockDrmDevice::MockDrmDevice()
add_framebuffer_expectation_(true),
page_flip_expectation_(true),
create_dumb_buffer_expectation_(true),
use_sync_flips_(false),
use_sync_flips_(use_sync_flips),
current_framebuffer_(0) {
plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
}
MockDrmDevice::MockDrmDevice(bool use_sync_flips,
std::vector<uint32_t> crtcs,
size_t planes_per_crtc)
: DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */),
get_crtc_call_count_(0),
set_crtc_call_count_(0),
restore_crtc_call_count_(0),
add_framebuffer_call_count_(0),
remove_framebuffer_call_count_(0),
page_flip_call_count_(0),
overlay_flip_call_count_(0),
overlay_clear_call_count_(0),
allocate_buffer_count_(0),
set_crtc_expectation_(true),
add_framebuffer_expectation_(true),
page_flip_expectation_(true),
create_dumb_buffer_expectation_(true),
use_sync_flips_(use_sync_flips),
current_framebuffer_(0) {
plane_manager_.reset(
new MockHardwareDisplayPlaneManager(this, crtcs, planes_per_crtc));
// static
ScopedDrmPropertyBlobPtr MockDrmDevice::AllocateInFormatsBlob(
uint32_t id,
const std::vector<uint32_t>& supported_formats,
const std::vector<drm_format_modifier>& supported_format_modifiers) {
drm_format_modifier_blob header;
header.count_formats = supported_formats.size();
header.formats_offset = sizeof(header);
header.count_modifiers = supported_format_modifiers.size();
header.modifiers_offset =
header.formats_offset + sizeof(uint32_t) * header.count_formats;
ScopedDrmPropertyBlobPtr blob(DrmAllocator<drmModePropertyBlobRes>());
blob->id = id;
blob->length = header.modifiers_offset +
sizeof(drm_format_modifier) * header.count_modifiers;
blob->data = drmMalloc(blob->length);
memcpy(blob->data, &header, sizeof(header));
memcpy(static_cast<uint8_t*>(blob->data) + header.formats_offset,
supported_formats.data(), sizeof(uint32_t) * header.count_formats);
memcpy(static_cast<uint8_t*>(blob->data) + header.modifiers_offset,
supported_format_modifiers.data(),
sizeof(drm_format_modifier) * header.count_modifiers);
return blob;
}
void MockDrmDevice::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) {
crtc_properties_ = crtc_properties;
plane_properties_ = plane_properties;
property_names_ = property_names;
if (use_atomic) {
plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic());
} else {
plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
}
CHECK(plane_manager_->Initialize(this));
}
MockDrmDevice::~MockDrmDevice() {}
ScopedDrmResourcesPtr MockDrmDevice::GetResources() {
return ScopedDrmResourcesPtr(DrmAllocator<drmModeRes>());
ScopedDrmResourcesPtr resources(DrmAllocator<drmModeRes>());
resources->count_crtcs = crtc_properties_.size();
resources->crtcs = static_cast<uint32_t*>(
drmMalloc(sizeof(uint32_t) * resources->count_crtcs));
for (size_t i = 0; i < crtc_properties_.size(); ++i)
resources->crtcs[i] = crtc_properties_[i].id;
return resources;
}
ScopedDrmPlaneResPtr MockDrmDevice::GetPlaneResources() {
ScopedDrmPlaneResPtr resources(DrmAllocator<drmModePlaneRes>());
resources->count_planes = plane_properties_.size();
resources->planes = static_cast<uint32_t*>(
drmMalloc(sizeof(uint32_t) * resources->count_planes));
for (size_t i = 0; i < plane_properties_.size(); ++i)
resources->planes[i] = plane_properties_[i].id;
return resources;
}
ScopedDrmObjectPropertyPtr MockDrmDevice::GetObjectProperties(
uint32_t object_id,
uint32_t object_type) {
return ScopedDrmObjectPropertyPtr(DrmAllocator<drmModeObjectProperties>());
if (object_type == DRM_MODE_OBJECT_PLANE) {
auto it = std::find_if(
plane_properties_.begin(), plane_properties_.end(),
[object_id](const PlaneProperties& p) { return p.id == object_id; });
if (it == plane_properties_.end())
return nullptr;
return CreatePropertyObject(it->properties);
} else if (object_type == DRM_MODE_OBJECT_CRTC) {
auto it = std::find_if(
crtc_properties_.begin(), crtc_properties_.end(),
[object_id](const CrtcProperties& p) { return p.id == object_id; });
if (it == crtc_properties_.end())
return nullptr;
return CreatePropertyObject(it->properties);
}
return nullptr;
}
ScopedDrmCrtcPtr MockDrmDevice::GetCrtc(uint32_t crtc_id) {
......@@ -155,13 +240,33 @@ bool MockDrmDevice::PageFlipOverlay(uint32_t crtc_id,
return true;
}
ScopedDrmPlanePtr MockDrmDevice::GetPlane(uint32_t plane_id) {
auto it = std::find_if(plane_properties_.begin(), plane_properties_.end(),
[plane_id](const PlaneProperties& plane) {
return plane.id == plane_id;
});
if (it == plane_properties_.end())
return nullptr;
ScopedDrmPlanePtr plane(DrmAllocator<drmModePlane>());
plane->possible_crtcs = it->crtc_mask;
return plane;
}
ScopedDrmPropertyPtr MockDrmDevice::GetProperty(drmModeConnector* connector,
const char* name) {
return ScopedDrmPropertyPtr(DrmAllocator<drmModePropertyRes>());
}
ScopedDrmPropertyPtr MockDrmDevice::GetProperty(uint32_t id) {
return ScopedDrmPropertyPtr(DrmAllocator<drmModePropertyRes>());
auto it = property_names_.find(id);
if (it == property_names_.end())
return nullptr;
ScopedDrmPropertyPtr property(DrmAllocator<drmModePropertyRes>());
property->prop_id = id;
strcpy(property->name, it->second.c_str());
return property;
}
bool MockDrmDevice::SetProperty(uint32_t connector_id,
......@@ -174,6 +279,20 @@ bool MockDrmDevice::GetCapability(uint64_t capability, uint64_t* value) {
return true;
}
ScopedDrmPropertyBlobPtr MockDrmDevice::GetPropertyBlob(uint32_t property_id) {
auto it = blob_property_map_.find(property_id);
if (it == blob_property_map_.end())
return nullptr;
ScopedDrmPropertyBlobPtr blob(DrmAllocator<drmModePropertyBlobRes>());
blob->id = property_id;
blob->length = it->second->length;
blob->data = drmMalloc(blob->length);
memcpy(blob->data, it->second->data, blob->length);
return blob;
}
ScopedDrmPropertyBlobPtr MockDrmDevice::GetPropertyBlob(
drmModeConnector* connector,
const char* name) {
......@@ -236,7 +355,11 @@ bool MockDrmDevice::CommitProperties(drmModeAtomicReq* properties,
uint32_t flags,
uint32_t crtc_count,
PageFlipCallback callback) {
return false;
if (use_sync_flips_)
std::move(callback).Run(0, base::TimeTicks());
else
callbacks_.push(std::move(callback));
return true;
}
bool MockDrmDevice::SetGammaRamp(
......@@ -246,7 +369,7 @@ bool MockDrmDevice::SetGammaRamp(
}
bool MockDrmDevice::SetCapability(uint64_t capability, uint64_t value) {
return false;
return true;
}
void MockDrmDevice::RunCallbacks() {
......@@ -257,4 +380,8 @@ void MockDrmDevice::RunCallbacks() {
}
}
void MockDrmDevice::SetPropertyBlob(ScopedDrmPropertyBlobPtr blob) {
blob_property_map_[blob->id] = std::move(blob);
}
} // namespace ui
......@@ -5,6 +5,7 @@
#ifndef UI_OZONE_PLATFORM_DRM_GPU_MOCK_DRM_DEVICE_H_
#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_DRM_DEVICE_H_
#include <drm_mode.h>
#include <stddef.h>
#include <stdint.h>
......@@ -22,10 +23,32 @@ namespace ui {
// The real DrmDevice makes actual DRM calls which we can't use in unit tests.
class MockDrmDevice : public DrmDevice {
public:
MockDrmDevice();
MockDrmDevice(bool use_sync_flips,
std::vector<uint32_t> crtcs,
size_t planes_per_crtc);
struct CrtcProperties {
CrtcProperties();
CrtcProperties(const CrtcProperties&);
~CrtcProperties();
uint32_t id;
std::vector<DrmDevice::Property> properties;
};
struct PlaneProperties {
PlaneProperties();
PlaneProperties(const PlaneProperties&);
~PlaneProperties();
uint32_t id;
uint32_t crtc_mask;
std::vector<DrmDevice::Property> properties;
};
explicit MockDrmDevice(bool use_sync_flips);
static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob(
uint32_t id,
const std::vector<uint32_t>& supported_formats,
const std::vector<drm_format_modifier>& supported_format_modifiers);
int get_get_crtc_call_count() const { return get_crtc_call_count_; }
int get_set_crtc_call_count() const { return set_crtc_call_count_; }
......@@ -57,10 +80,18 @@ class MockDrmDevice : public DrmDevice {
return it != crtc_cursor_map_.end() ? it->second : 0;
}
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 RunCallbacks();
void SetPropertyBlob(ScopedDrmPropertyBlobPtr blob);
// DrmDevice:
ScopedDrmResourcesPtr GetResources() override;
ScopedDrmPlaneResPtr GetPlaneResources() override;
ScopedDrmObjectPropertyPtr GetObjectProperties(uint32_t object_id,
uint32_t object_type) override;
ScopedDrmCrtcPtr GetCrtc(uint32_t crtc_id) override;
......@@ -90,6 +121,7 @@ class MockDrmDevice : public DrmDevice {
const gfx::Rect& location,
const gfx::Rect& source,
int overlay_plane) override;
ScopedDrmPlanePtr GetPlane(uint32_t plane_id) override;
ScopedDrmPropertyPtr GetProperty(drmModeConnector* connector,
const char* name) override;
ScopedDrmPropertyPtr GetProperty(uint32_t id) override;
......@@ -97,6 +129,7 @@ class MockDrmDevice : public DrmDevice {
uint32_t property_id,
uint64_t value) override;
bool GetCapability(uint64_t capability, uint64_t* value) override;
ScopedDrmPropertyBlobPtr GetPropertyBlob(uint32_t property_id) override;
ScopedDrmPropertyBlobPtr GetPropertyBlob(drmModeConnector* connector,
const char* name) override;
bool SetCursor(uint32_t crtc_id,
......@@ -145,8 +178,16 @@ class MockDrmDevice : public DrmDevice {
std::map<uint32_t, uint32_t> crtc_cursor_map_;
std::map<uint32_t, ScopedDrmPropertyBlobPtr> blob_property_map_;
base::queue<PageFlipCallback> callbacks_;
std::vector<CrtcProperties> crtc_properties_;
std::vector<PlaneProperties> plane_properties_;
std::map<uint32_t, std::string> property_names_;
DISALLOW_COPY_AND_ASSIGN(MockDrmDevice);
};
......
// 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.
#include "ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h"
#include <drm_fourcc.h>
#include <utility>
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/ozone/platform/drm/gpu/fake_plane_info.h"
#include "ui/ozone/platform/drm/gpu/mock_scanout_buffer.h"
namespace ui {
MockHardwareDisplayPlaneManager::MockHardwareDisplayPlaneManager(
DrmDevice* drm,
const std::vector<uint32_t>& crtcs,
uint32_t planes_per_crtc) {
const int kPlaneBaseId = 50;
const struct drm_format_modifier linear_modifier { 0x1, DRM_FORMAT_MOD_NONE };
drm_ = drm;
for (size_t i = 0; i < crtcs.size(); ++i)
crtc_properties_.push_back({.id = crtcs[i]});
for (size_t crtc_idx = 0; crtc_idx < crtc_properties_.size(); crtc_idx++) {
for (size_t i = 0; i < planes_per_crtc; i++) {
std::unique_ptr<HardwareDisplayPlane> plane(
new HardwareDisplayPlane(kPlaneBaseId + i, 1 << crtc_idx));
plane->Initialize(drm, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888),
std::vector<drm_format_modifier>(1, linear_modifier),
false, true);
plane->set_type(i ? HardwareDisplayPlane::kOverlay
: HardwareDisplayPlane::kPrimary);
planes_.push_back(std::move(plane));
}
}
// The real HDPM uses sorted planes, so sort them for consistency.
std::sort(planes_.begin(), planes_.end(),
[](const std::unique_ptr<HardwareDisplayPlane>& l,
const std::unique_ptr<HardwareDisplayPlane>& r) {
return l->plane_id() < r->plane_id();
});
}
MockHardwareDisplayPlaneManager::MockHardwareDisplayPlaneManager(
DrmDevice* drm) {
drm_ = drm;
}
MockHardwareDisplayPlaneManager::~MockHardwareDisplayPlaneManager() {}
void MockHardwareDisplayPlaneManager::InitForTest(
const FakePlaneInfo* planes,
size_t count,
const std::vector<uint32_t>& crtcs) {
crtc_properties_.clear();
for (size_t i = 0; i < crtcs.size(); ++i)
crtc_properties_.push_back({.id = crtcs[i]});
planes_.clear();
for (size_t i = 0; i < count; i++) {
std::unique_ptr<HardwareDisplayPlane> plane(
new HardwareDisplayPlane(planes[i].id, planes[i].allowed_crtc_mask));
plane->Initialize(drm_, planes[i].allowed_formats,
std::vector<drm_format_modifier>(), // modifiers
false, true);
planes_.push_back(std::move(plane));
}
// The real HDPM uses sorted planes, so sort them for consistency.
std::sort(planes_.begin(), planes_.end(),
[](const std::unique_ptr<HardwareDisplayPlane>& l,
const std::unique_ptr<HardwareDisplayPlane>& r) {
return l->plane_id() < r->plane_id();
});
}
void MockHardwareDisplayPlaneManager::SetPlaneProperties(
const std::vector<FakePlaneInfo>& planes) {
planes_.clear();
uint32_t count = planes.size();
for (size_t i = 0; i < count; i++) {
std::unique_ptr<HardwareDisplayPlane> plane(
new HardwareDisplayPlane(planes[i].id, planes[i].allowed_crtc_mask));
plane->Initialize(drm_, planes[i].allowed_formats,
std::vector<drm_format_modifier>(), // modifiers
false, true);
planes_.push_back(std::move(plane));
}
// The real HDPM uses sorted planes, so sort them for consistency.
std::sort(planes_.begin(), planes_.end(),
[](const std::unique_ptr<HardwareDisplayPlane>& l,
const std::unique_ptr<HardwareDisplayPlane>& r) {
return l->plane_id() < r->plane_id();
});
ResetPlaneCount();
}
void MockHardwareDisplayPlaneManager::SetCrtcInfo(
const std::vector<uint32_t>& crtcs) {
crtc_properties_.clear();
for (size_t i = 0; i < crtcs.size(); ++i)
crtc_properties_.push_back({.id = crtcs[i]});
planes_.clear();
ResetPlaneCount();
}
bool MockHardwareDisplayPlaneManager::DisableOverlayPlanes(
HardwareDisplayPlaneList* plane_list) {
for (HardwareDisplayPlane* plane : plane_list->old_plane_list) {
if (plane->type() != HardwareDisplayPlane::kOverlay)
continue;
plane->set_in_use(false);
plane->set_owning_crtc(0);
}
return true;
}
bool MockHardwareDisplayPlaneManager::SetPlaneData(
HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
const OverlayPlane& overlay,
uint32_t crtc_id,
const gfx::Rect& src_rect,
CrtcController* crtc) {
// Check that the chosen plane is a legal choice for the crtc.
EXPECT_NE(-1, LookupCrtcIndex(crtc_id));
EXPECT_TRUE(hw_plane->CanUseForCrtc(LookupCrtcIndex(crtc_id)));
EXPECT_FALSE(hw_plane->in_use());
plane_count_++;
return HardwareDisplayPlaneManagerLegacy::SetPlaneData(
plane_list, hw_plane, overlay, crtc_id, src_rect, crtc);
}
int MockHardwareDisplayPlaneManager::plane_count() const {
return plane_count_;
}
void MockHardwareDisplayPlaneManager::ResetPlaneCount() {
plane_count_ = 0;
}
} // namespace ui
// 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_DRM_GPU_MOCK_HARDWARE_DISPLAY_PLANE_MANAGER_H_
#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_HARDWARE_DISPLAY_PLANE_MANAGER_H_
#include <stddef.h>
#include <stdint.h>
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
namespace ui {
struct FakePlaneInfo;
class MockHardwareDisplayPlaneManager
: public HardwareDisplayPlaneManagerLegacy {
public:
MockHardwareDisplayPlaneManager(DrmDevice* drm,
const std::vector<uint32_t>& crtcs,
uint32_t planes_per_crtc);
explicit MockHardwareDisplayPlaneManager(DrmDevice* drm);
~MockHardwareDisplayPlaneManager() override;
// Normally we'd use DRM to figure out the controller configuration. But we
// can't use DRM in unit tests, so we just create a fake configuration.
void InitForTest(const FakePlaneInfo* planes,
size_t count,
const std::vector<uint32_t>& crtcs);
void SetPlaneProperties(const std::vector<FakePlaneInfo>& planes);
void SetCrtcInfo(const std::vector<uint32_t>& crtcs);
bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
const OverlayPlane& overlay,
uint32_t crtc_id,
const gfx::Rect& src_rect,
CrtcController* crtc) override;
int plane_count() const;
void ResetPlaneCount();
private:
int plane_count_ = 0;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_HARDWARE_DISPLAY_PLANE_MANAGER_H_
......@@ -49,8 +49,7 @@ class ScreenManagerTest : public testing::Test {
}
void SetUp() override {
drm_ = new ui::MockDrmDevice(false, std::vector<uint32_t>(1, kPrimaryCrtc),
4 /* planes per crtc */);
drm_ = new ui::MockDrmDevice(false);
device_manager_.reset(new ui::DrmDeviceManager(nullptr));
buffer_generator_.reset(new ui::MockScanoutBufferGenerator());
screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
......@@ -354,7 +353,7 @@ TEST_F(ScreenManagerTest, CheckMirrorModeAfterBeginReEnabled) {
TEST_F(ScreenManagerTest,
CheckProperConfigurationWithDifferentDeviceAndSameCrtc) {
scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice();
scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice(false);
screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector);
......
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