#include "ui/ozone/platform/dri/chromeos/native_display_delegate_dri.h"
#include "base/bind.h"
-#include "ui/display/types/chromeos/native_display_observer.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/display/types/native_display_observer.h"
#include "ui/events/ozone/device/device_event.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/ozone/platform/dri/chromeos/display_mode_dri.h"
#include "ui/ozone/platform/dri/chromeos/display_snapshot_dri.h"
+#include "ui/ozone/platform/dri/dri_console_buffer.h"
#include "ui/ozone/platform/dri/dri_util.h"
#include "ui/ozone/platform/dri/dri_wrapper.h"
#include "ui/ozone/platform/dri/screen_manager.h"
namespace ui {
namespace {
+
const size_t kMaxDisplayCount = 2;
+
+const char kContentProtection[] = "Content Protection";
+
+struct ContentProtectionMapping {
+ const char* name;
+ HDCPState state;
+};
+
+const ContentProtectionMapping kContentProtectionStates[] = {
+ {"Undesired", HDCP_STATE_UNDESIRED},
+ {"Desired", HDCP_STATE_DESIRED},
+ {"Enabled", HDCP_STATE_ENABLED}};
+
+uint32_t GetContentProtectionValue(drmModePropertyRes* property,
+ HDCPState state) {
+ std::string name;
+ for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
+ if (kContentProtectionStates[i].state == state) {
+ name = kContentProtectionStates[i].name;
+ break;
+ }
+ }
+
+ for (int i = 0; i < property->count_enums; ++i)
+ if (name == property->enums[i].name)
+ return i;
+
+ NOTREACHED();
+ return 0;
+}
+
+class DisplaySnapshotComparator {
+ public:
+ DisplaySnapshotComparator(const DisplaySnapshotDri* snapshot)
+ : snapshot_(snapshot) {}
+
+ bool operator()(const DisplaySnapshotDri* other) const {
+ if (snapshot_->connector() == other->connector() &&
+ snapshot_->crtc() == other->crtc())
+ return true;
+
+ return false;
+ }
+
+ private:
+ const DisplaySnapshotDri* snapshot_;
+};
+
} // namespace
NativeDisplayDelegateDri::NativeDisplayDelegateDri(
: dri_(dri),
screen_manager_(screen_manager),
device_manager_(device_manager) {
+ // TODO(dnicoara): Remove when async display configuration is supported.
+ screen_manager_->ForceInitializationOfPrimaryDisplay();
}
NativeDisplayDelegateDri::~NativeDisplayDelegateDri() {
- device_manager_->RemoveObserver(this);
+ if (device_manager_)
+ device_manager_->RemoveObserver(this);
+}
+
+DisplaySnapshot* NativeDisplayDelegateDri::FindDisplaySnapshot(int64_t id) {
+ for (size_t i = 0; i < cached_displays_.size(); ++i)
+ if (cached_displays_[i]->display_id() == id)
+ return cached_displays_[i];
+
+ return NULL;
+}
+
+const DisplayMode* NativeDisplayDelegateDri::FindDisplayMode(
+ const gfx::Size& size,
+ bool is_interlaced,
+ float refresh_rate) {
+ for (size_t i = 0; i < cached_modes_.size(); ++i)
+ if (cached_modes_[i]->size() == size &&
+ cached_modes_[i]->is_interlaced() == is_interlaced &&
+ cached_modes_[i]->refresh_rate() == refresh_rate)
+ return cached_modes_[i];
+
+ return NULL;
}
void NativeDisplayDelegateDri::Initialize() {
- device_manager_->AddObserver(this);
+ if (device_manager_)
+ device_manager_->AddObserver(this);
+
+ ScopedVector<HardwareDisplayControllerInfo> displays =
+ GetAvailableDisplayControllerInfos(dri_->get_fd());
+
+ // By default all displays show the same console buffer.
+ console_buffer_.reset(
+ new DriConsoleBuffer(dri_, displays[0]->crtc()->buffer_id));
+ if (!console_buffer_->Initialize()) {
+ VLOG(1) << "Failed to initialize console buffer";
+ console_buffer_.reset();
+ } else {
+ // Clear the console buffer such that restarting Chrome will show a
+ // predetermined background.
+ //
+ // Black was chosen since Chrome's first buffer paints start with a black
+ // background.
+ console_buffer_->canvas()->clear(SK_ColorBLACK);
+ }
}
void NativeDisplayDelegateDri::GrabServer() {}
void NativeDisplayDelegateDri::SyncWithServer() {}
void NativeDisplayDelegateDri::SetBackgroundColor(uint32_t color_argb) {
- NOTIMPLEMENTED();
+ if (console_buffer_)
+ console_buffer_->canvas()->clear(color_argb);
}
void NativeDisplayDelegateDri::ForceDPMSOn() {
ScopedVector<DisplaySnapshotDri> old_displays(cached_displays_.Pass());
cached_modes_.clear();
- drmModeRes* resources = drmModeGetResources(dri_->get_fd());
- DCHECK(resources) << "Failed to get DRM resources";
ScopedVector<HardwareDisplayControllerInfo> displays =
- GetAvailableDisplayControllerInfos(dri_->get_fd(), resources);
+ GetAvailableDisplayControllerInfos(dri_->get_fd());
for (size_t i = 0;
i < displays.size() && cached_displays_.size() < kMaxDisplayCount; ++i) {
DisplaySnapshotDri* display = new DisplaySnapshotDri(
dri_, displays[i]->connector(), displays[i]->crtc(), i);
cached_displays_.push_back(display);
- // Modes can be shared between different displays, so we need to keep track
- // of them independently for cleanup.
cached_modes_.insert(cached_modes_.end(),
display->modes().begin(),
display->modes().end());
}
- drmModeFreeResources(resources);
-
NotifyScreenManager(cached_displays_.get(), old_displays.get());
std::vector<DisplaySnapshot*> generic_displays(cached_displays_.begin(),
if (!screen_manager_->ConfigureDisplayController(
dri_output.crtc(),
dri_output.connector(),
+ origin,
static_cast<const DisplayModeDri*>(mode)->mode_info())) {
VLOG(1) << "Failed to configure: crtc=" << dri_output.crtc()
<< " connector=" << dri_output.connector();
return false;
}
} else {
- if (!screen_manager_->DisableDisplayController(dri_output.crtc(),
- dri_output.connector())) {
+ if (!screen_manager_->DisableDisplayController(dri_output.crtc())) {
VLOG(1) << "Failed to disable crtc=" << dri_output.crtc();
return false;
}
bool NativeDisplayDelegateDri::GetHDCPState(const DisplaySnapshot& output,
HDCPState* state) {
- NOTIMPLEMENTED();
+ const DisplaySnapshotDri& dri_output =
+ static_cast<const DisplaySnapshotDri&>(output);
+
+ ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
+ if (!connector) {
+ LOG(ERROR) << "Failed to get connector " << dri_output.connector();
+ return false;
+ }
+
+ ScopedDrmPropertyPtr hdcp_property(
+ dri_->GetProperty(connector.get(), kContentProtection));
+ if (!hdcp_property) {
+ LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
+ return false;
+ }
+
+ DCHECK_LT(static_cast<int>(hdcp_property->prop_id), connector->count_props);
+ int hdcp_state_idx = connector->prop_values[hdcp_property->prop_id];
+ DCHECK_LT(hdcp_state_idx, hdcp_property->count_enums);
+
+ std::string name(hdcp_property->enums[hdcp_state_idx].name);
+ for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
+ if (name == kContentProtectionStates[i].name) {
+ *state = kContentProtectionStates[i].state;
+ VLOG(3) << "HDCP state: " << *state << " (" << name << ")";
+ return true;
+ }
+ }
+
+ LOG(ERROR) << "Unknown content protection value '" << name << "'";
return false;
}
bool NativeDisplayDelegateDri::SetHDCPState(const DisplaySnapshot& output,
HDCPState state) {
- NOTIMPLEMENTED();
- return false;
+ const DisplaySnapshotDri& dri_output =
+ static_cast<const DisplaySnapshotDri&>(output);
+
+ ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
+ if (!connector) {
+ LOG(ERROR) << "Failed to get connector " << dri_output.connector();
+ return false;
+ }
+
+ ScopedDrmPropertyPtr hdcp_property(
+ dri_->GetProperty(connector.get(), kContentProtection));
+ if (!hdcp_property) {
+ LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
+ return false;
+ }
+
+ return dri_->SetProperty(
+ dri_output.connector(),
+ hdcp_property->prop_id,
+ GetContentProtectionValue(hdcp_property.get(), state));
}
std::vector<ui::ColorCalibrationProfile>
const std::vector<DisplaySnapshotDri*>& new_displays,
const std::vector<DisplaySnapshotDri*>& old_displays) const {
for (size_t i = 0; i < old_displays.size(); ++i) {
- bool found = false;
- for (size_t j = 0; j < new_displays.size(); ++j) {
- if (old_displays[i]->connector() == new_displays[j]->connector() &&
- old_displays[i]->crtc() == new_displays[j]->crtc()) {
- found = true;
- break;
- }
- }
+ const std::vector<DisplaySnapshotDri*>::const_iterator it =
+ std::find_if(new_displays.begin(),
+ new_displays.end(),
+ DisplaySnapshotComparator(old_displays[i]));
+
+ if (it == new_displays.end())
+ screen_manager_->RemoveDisplayController(old_displays[i]->crtc());
+ }
+
+ for (size_t i = 0; i < new_displays.size(); ++i) {
+ const std::vector<DisplaySnapshotDri*>::const_iterator it =
+ std::find_if(old_displays.begin(),
+ old_displays.end(),
+ DisplaySnapshotComparator(new_displays[i]));
- if (!found)
- screen_manager_->RemoveDisplayController(old_displays[i]->crtc(),
- old_displays[i]->connector());
+ if (it == old_displays.end())
+ screen_manager_->AddDisplayController(new_displays[i]->crtc(),
+ new_displays[i]->connector());
}
}