[go: nahoru, domu]

blob: f13bbd5fffd8a942bf689b4ea5faa4270296b949 [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// 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_DRM_DEVICE_H_
#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_DRM_DEVICE_H_
#include <drm_fourcc.h>
#include <drm_mode.h>
#include <stddef.h>
#include <stdint.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <cstdint>
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <tuple>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
namespace ui {
using ResolutionAndRefreshRate = std::pair<gfx::Size, uint32_t>;
template <class Object>
Object* DrmAllocator(size_t num_of_objects = 1) {
return static_cast<Object*>(drmMalloc(num_of_objects * sizeof(Object)));
}
// DRM Object Base IDs:
constexpr uint32_t kPlaneOffset = 100;
constexpr uint32_t kCrtcIdBase = 200;
constexpr uint32_t kConnectorIdBase = 300;
constexpr uint32_t kInFormatsBlobIdBase = 400;
constexpr uint32_t kEncoderIdBase = 500;
// Required Connector Property IDs:
constexpr uint32_t kCrtcIdPropId = 1000;
constexpr uint32_t kLinkStatusPropId = 1001;
constexpr uint32_t kEdidBlobPropId = 1002;
// Required CRTC Property IDs:
constexpr uint32_t kActivePropId = 2000;
constexpr uint32_t kModePropId = 2001;
// Optional CRTC Property IDs:
constexpr uint32_t kBackgroundColorPropId = 3000;
constexpr uint32_t kCtmPropId = 3001;
constexpr uint32_t kDegammaLutPropId = 3002;
constexpr uint32_t kDegammaLutSizePropId = 3003;
constexpr uint32_t kGammaLutPropId = 3004;
constexpr uint32_t kGammaLutSizePropId = 3005;
constexpr uint32_t kInFencePropId = 3006;
constexpr uint32_t kOutFencePtrPropId = 3007;
constexpr uint32_t kVrrEnabledPropId = 3008;
// Required Plane Property IDs:
constexpr uint32_t kCrtcH = 4001;
constexpr uint32_t kCrtcW = 4002;
constexpr uint32_t kCrtcX = 4003;
constexpr uint32_t kCrtcY = 4004;
constexpr uint32_t kPlaneCrtcId = 4005;
constexpr uint32_t kPlaneFbId = 4006;
constexpr uint32_t kSrcH = 4007;
constexpr uint32_t kSrcW = 4008;
constexpr uint32_t kSrcX = 4009;
constexpr uint32_t kSrcY = 4010;
// Optional Plane Property IDs:
constexpr uint32_t kTypePropId = 5000;
constexpr uint32_t kInFormatsPropId = 5001;
constexpr uint32_t kPlaneCtmId = 5002;
constexpr uint32_t kRotationPropId = 5003;
// Blob IDs:
constexpr uint32_t kBaseBlobId = 6000;
// The real DrmDevice makes actual DRM calls which we can't use in unit tests.
class MockDrmDevice : public DrmDevice {
public:
struct CrtcProperties {
CrtcProperties();
CrtcProperties(const CrtcProperties&);
~CrtcProperties();
uint32_t id;
std::vector<DrmWrapper::Property> properties;
};
struct ConnectorProperties {
ConnectorProperties();
ConnectorProperties(const ConnectorProperties&);
~ConnectorProperties();
uint32_t id;
bool connection;
std::vector<ResolutionAndRefreshRate> modes;
std::vector<uint32_t> encoders;
std::vector<uint8_t> edid_blob;
std::vector<DrmWrapper::Property> properties;
};
struct EncoderProperties {
EncoderProperties();
EncoderProperties(const EncoderProperties&);
~EncoderProperties();
uint32_t id;
uint32_t possible_crtcs;
};
struct PlaneProperties {
PlaneProperties();
PlaneProperties(const PlaneProperties&);
~PlaneProperties();
uint32_t type() const;
absl::optional<const DrmWrapper::Property*> GetProp(uint32_t prop_id) const;
void SetProp(uint32_t prop_id, uint32_t value);
uint32_t id;
uint32_t crtc_mask;
std::vector<DrmWrapper::Property> properties;
};
struct MockDrmState {
MockDrmState();
MockDrmState(const MockDrmState&);
~MockDrmState();
// Creates a totally empty |MockDrmState| with no properties configured and
// no property names set.
static MockDrmState CreateStateWithNoProperties();
// Creates a |MockDrmState| with all properties registered with their names
// in |property_names|, but no objects configured.
static MockDrmState CreateStateWithAllProperties();
// Creates a generic |MockDrmState|. Will create |crtc_count| different
// CRTCs and connectors with 1 primary plane, 1 cursor plane (since some
// tests expect them), and |planes_per_crtc| - 1 overlay planes for each
// CRTC.
static MockDrmState CreateStateWithDefaultObjects(
size_t crtc_count,
size_t planes_per_crtc,
size_t movable_planes = 0u);
ConnectorProperties& AddConnector();
EncoderProperties& AddEncoder();
CrtcProperties& AddCrtc();
std::pair<CrtcProperties&, ConnectorProperties&> AddCrtcAndConnector();
PlaneProperties& AddPlane(uint32_t crtc_id, uint32_t type);
PlaneProperties& AddPlane(const std::vector<uint32_t>& crtc_ids,
uint32_t type);
bool HasResources() const;
std::vector<CrtcProperties> crtc_properties;
std::vector<ConnectorProperties> connector_properties;
std::vector<EncoderProperties> encoder_properties;
std::vector<PlaneProperties> plane_properties;
std::vector<DrmWrapper::Property> blobs;
std::map<uint32_t, std::string> property_names;
};
explicit MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device);
explicit MockDrmDevice(const base::FilePath& path,
std::unique_ptr<GbmDevice> gbm_device,
bool is_primary_device);
MockDrmDevice(const MockDrmDevice&) = delete;
MockDrmDevice& operator=(const MockDrmDevice&) = delete;
static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob(
uint32_t id,
const std::vector<uint32_t>& supported_formats,
const std::vector<drm_format_modifier>& supported_format_modifiers);
int get_set_crtc_call_count() const { return set_crtc_call_count_; }
int get_add_framebuffer_call_count() const {
return add_framebuffer_call_count_;
}
int get_remove_framebuffer_call_count() const {
return remove_framebuffer_call_count_;
}
int get_page_flip_call_count() const { return page_flip_call_count_; }
int get_overlay_clear_call_count() const { return overlay_clear_call_count_; }
int get_test_modeset_count() const { return test_modeset_count_; }
int get_commit_modeset_count() const { return commit_modeset_count_; }
int get_seamless_modeset_count() const { return seamless_modeset_count_; }
int get_commit_count() const { return commit_count_; }
int get_set_object_property_count() const {
return set_object_property_count_;
}
int get_set_gamma_ramp_count() const { return set_gamma_ramp_count_; }
void set_set_crtc_expectation(bool state) { set_crtc_expectation_ = state; }
void set_page_flip_expectation(bool state) { page_flip_expectation_ = state; }
void set_add_framebuffer_expectation(bool state) {
add_framebuffer_expectation_ = state;
}
void set_create_dumb_buffer_expectation(bool state) {
create_dumb_buffer_expectation_ = state;
}
void set_legacy_gamma_ramp_expectation(bool state) {
legacy_gamma_ramp_expectation_ = state;
}
void set_commit_expectation(bool state) { commit_expectation_ = state; }
void set_overlay_modeset_expectation(bool state) {
modeset_with_overlays_expectation_ = state;
}
uint32_t current_framebuffer() const { return current_framebuffer_; }
const std::vector<sk_sp<SkSurface>> buffers() const { return buffers_; }
int last_planes_committed_count() const {
return last_planes_committed_count_;
}
int modeset_sequence_id() const override;
uint32_t get_cursor_handle_for_crtc(uint32_t crtc) const {
const auto it = crtc_cursor_map_.find(crtc);
return it != crtc_cursor_map_.end() ? it->second : 0;
}
void InitializeState(MockDrmState& state, bool use_atomic);
bool InitializeStateWithResult(MockDrmState& state, bool use_atomic);
// Runs all connector update utility functions on |state|.
void UpdateConnectors(MockDrmState& state);
// Update a connector's link status to bad if it has no modes (probably due
// to unsuccessful link-training.
void UpdateConnectorsLinkStatus(MockDrmState& state);
// Sets EDID blobs as property blobs so they can be fetched when needed via
// GetPropertyBlob().
void MaybeSetEdidBlobsForConnectors(MockDrmState& state);
void UpdateStateBesidesPlaneManager(const MockDrmState& state);
void RunCallbacks();
void SetPropertyBlob(ScopedDrmPropertyBlobPtr blob);
void SetModifiersOverhead(base::flat_map<uint64_t, int> modifiers_overhead);
void SetSystemLimitOfModifiers(uint64_t limit);
const CrtcProperties& crtc_property(size_t idx) const {
return drm_state_.crtc_properties[idx];
}
const ConnectorProperties& connector_property(size_t idx) const {
return drm_state_.connector_properties[idx];
}
const PlaneProperties& plane_property(size_t idx) const {
return drm_state_.plane_properties[idx];
}
const std::vector<CrtcProperties>& crtc_properties() const {
return drm_state_.crtc_properties;
}
const std::vector<ConnectorProperties>& connector_properties() const {
return drm_state_.connector_properties;
}
const std::vector<PlaneProperties>& plane_properties() const {
return drm_state_.plane_properties;
}
const std::map<uint32_t, std::string>& property_names() const {
return drm_state_.property_names;
}
// DrmDevice:
ScopedDrmResourcesPtr GetResources() const override;
ScopedDrmPlaneResPtr GetPlaneResources() const override;
ScopedDrmObjectPropertyPtr GetObjectProperties(
uint32_t object_id,
uint32_t object_type) const override;
ScopedDrmCrtcPtr GetCrtc(uint32_t crtc_id) const override;
bool SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
const drmModeModeInfo& mode) override;
bool DisableCrtc(uint32_t crtc_id) override;
ScopedDrmConnectorPtr GetConnector(uint32_t connector_id) const override;
ScopedDrmEncoderPtr GetEncoder(uint32_t encoder_id) const override;
bool AddFramebuffer2(uint32_t width,
uint32_t height,
uint32_t format,
uint32_t handles[4],
uint32_t strides[4],
uint32_t offsets[4],
uint64_t modifiers[4],
uint32_t* framebuffer,
uint32_t flags) override;
bool RemoveFramebuffer(uint32_t framebuffer) override;
ScopedDrmFramebufferPtr GetFramebuffer(uint32_t framebuffer) const override;
bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
scoped_refptr<PageFlipRequest> page_flip_request) override;
ScopedDrmPlanePtr GetPlane(uint32_t plane_id) const override;
ScopedDrmPropertyPtr GetProperty(drmModeConnector* connector,
const char* name) const override;
ScopedDrmPropertyPtr GetProperty(uint32_t id) const override;
bool SetProperty(uint32_t connector_id,
uint32_t property_id,
uint64_t value) override;
ScopedDrmPropertyBlob CreatePropertyBlob(const void* blob,
size_t size) override;
void DestroyPropertyBlob(uint32_t id) override;
bool GetCapability(uint64_t capability, uint64_t* value) const override;
ScopedDrmPropertyBlobPtr GetPropertyBlob(uint32_t property_id) const override;
ScopedDrmPropertyBlobPtr GetPropertyBlob(drmModeConnector* connector,
const char* name) const override;
bool SetObjectProperty(uint32_t object_id,
uint32_t object_type,
uint32_t property_id,
uint32_t property_value) override;
bool SetCursor(uint32_t crtc_id,
uint32_t handle,
const gfx::Size& size) override;
bool MoveCursor(uint32_t crtc_id, const gfx::Point& point) override;
bool CommitProperties(drmModeAtomicReq* request,
uint32_t flags,
uint32_t crtc_count,
scoped_refptr<PageFlipRequest> callback) override;
bool CreateDumbBuffer(const SkImageInfo& info,
uint32_t* handle,
uint32_t* stride) override;
bool DestroyDumbBuffer(uint32_t handle) override;
bool MapDumbBuffer(uint32_t handle, size_t size, void** pixels) override;
bool UnmapDumbBuffer(void* pixels, size_t size) override;
bool CloseBufferHandle(uint32_t handle) override;
bool SetGammaRamp(uint32_t crtc_id,
const display::GammaCurve& curve) override;
bool SetCapability(uint64_t capability, uint64_t value) override;
absl::optional<std::string> GetDriverName() const override;
void SetDriverName(absl::optional<std::string> name);
uint32_t GetFramebufferForCrtc(uint32_t crtc_id) const;
private:
// Properties of the plane associated with a fb.
struct FramebufferProps {
uint32_t width = 0;
uint32_t height = 0;
uint64_t modifier = 0;
};
~MockDrmDevice() override;
bool UpdateProperty(uint32_t id,
uint64_t value,
std::vector<DrmWrapper::Property>* properties);
bool UpdateProperty(uint32_t object_id, uint32_t property_id, uint64_t value);
bool ValidatePropertyValue(uint32_t id, uint64_t value);
int set_crtc_call_count_ = 0;
int add_framebuffer_call_count_ = 0;
int remove_framebuffer_call_count_ = 0;
int page_flip_call_count_ = 0;
int overlay_clear_call_count_ = 0;
int allocate_buffer_count_ = 0;
int test_modeset_count_ = 0;
int commit_modeset_count_ = 0;
int seamless_modeset_count_ = 0;
int commit_count_ = 0;
int set_object_property_count_ = 0;
int set_gamma_ramp_count_ = 0;
int last_planes_committed_count_ = 0;
int modeset_sequence_id_ = 0;
bool set_crtc_expectation_ = true;
bool add_framebuffer_expectation_ = true;
bool page_flip_expectation_ = true;
bool create_dumb_buffer_expectation_ = true;
bool legacy_gamma_ramp_expectation_ = false;
bool commit_expectation_ = true;
bool modeset_with_overlays_expectation_ = true;
uint32_t current_framebuffer_ = 0;
absl::optional<std::string> driver_name_ = "mock";
std::vector<sk_sp<SkSurface>> buffers_;
std::map<uint32_t, uint32_t> crtc_cursor_map_;
std::map<uint32_t, ScopedDrmPropertyBlobPtr> blob_property_map_;
std::set<uint32_t> framebuffer_ids_;
std::map<uint32_t, uint32_t> crtc_fb_;
std::map<uint64_t, uint64_t> capabilities_;
base::queue<PageFlipRequest::PageFlipCallback> callbacks_;
MockDrmState drm_state_;
std::set<uint32_t> allocated_property_blobs_;
// Props of the plane associated with the generated fb_id.
base::flat_map<uint32_t /*fb_id*/, FramebufferProps> fb_props_;
uint64_t system_watermark_limitations_ = std::numeric_limits<uint64_t>::max();
base::flat_map<uint64_t /*modifier*/, int /*overhead*/> modifiers_overhead_;
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_DRM_DEVICE_H_