2 // Copyright (c) 2016 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include "physicaldisplay.h"
29 #include "displayqueue.h"
30 #include "displayplanemanager.h"
32 #include "wsi_utils.h"
34 namespace hwcomposer {
36 PhysicalDisplay::PhysicalDisplay(uint32_t gpu_fd, uint32_t pipe_id)
44 PhysicalDisplay::~PhysicalDisplay() {
47 bool PhysicalDisplay::Initialize(NativeBufferHandler *buffer_handler) {
48 display_queue_.reset(new DisplayQueue(gpu_fd_, false, buffer_handler, this));
53 void PhysicalDisplay::MarkForDisconnect() {
54 SPIN_LOCK(modeset_lock_);
56 IHOTPLUGEVENTTRACE("PhysicalDisplay::MarkForDisconnect recieved.");
57 connection_state_ |= kDisconnectionInProgress;
58 display_state_ |= kRefreshClonedDisplays;
59 SPIN_UNLOCK(modeset_lock_);
62 void PhysicalDisplay::NotifyClientOfConnectedState() {
63 SPIN_LOCK(modeset_lock_);
64 bool refresh_needed = false;
65 if (hotplug_callback_ && (connection_state_ & kConnected) &&
66 (display_state_ & kNotifyClient)) {
68 "PhysicalDisplay Sent Hotplug even call back with connected value set "
69 "to true. %p hotplugdisplayid: %d \n",
70 this, hot_plug_display_id_);
71 hotplug_callback_->Callback(hot_plug_display_id_, true);
72 display_state_ &= ~kNotifyClient;
73 #ifdef ENABLE_ANDROID_WA
74 if (ordered_display_id_ == 0) {
75 refresh_needed = true;
79 SPIN_UNLOCK(modeset_lock_);
82 display_queue_->ForceRefresh();
86 void PhysicalDisplay::NotifyClientOfDisConnectedState() {
87 SPIN_LOCK(modeset_lock_);
89 if (hotplug_callback_ && !(connection_state_ & kConnected) &&
90 (display_state_ & kNotifyClient)) {
92 "PhysicalDisplay Sent Hotplug even call back with connected value set "
93 "to false. %p hotplugdisplayid: %d \n",
94 this, hot_plug_display_id_);
95 hotplug_callback_->Callback(hot_plug_display_id_, false);
96 display_state_ &= ~kNotifyClient;
98 SPIN_UNLOCK(modeset_lock_);
101 void PhysicalDisplay::DisConnect() {
102 SPIN_LOCK(modeset_lock_);
104 connection_state_ &= ~kDisconnectionInProgress;
106 if (!(connection_state_ & kConnected)) {
107 SPIN_UNLOCK(modeset_lock_);
112 "PhysicalDisplay DisConnect called for Display: %p hotplugdisplayid: %d "
114 this, hot_plug_display_id_);
115 display_state_ |= kNotifyClient;
117 if (power_mode_ != kOff) {
118 display_queue_->SetPowerMode(kOff);
121 connection_state_ &= ~kConnected;
122 display_state_ &= ~kUpdateDisplay;
123 SPIN_UNLOCK(modeset_lock_);
126 void PhysicalDisplay::Connect() {
127 SPIN_LOCK(modeset_lock_);
129 connection_state_ &= ~kDisconnectionInProgress;
130 if (connection_state_ & kConnected) {
131 SPIN_UNLOCK(modeset_lock_);
135 connection_state_ |= kConnected;
136 display_state_ &= ~kInitialized;
137 display_state_ |= kNotifyClient;
138 IHOTPLUGEVENTTRACE("PhysicalDisplay::Connect recieved. %p \n", this);
140 if (!display_queue_->Initialize(pipe_, width_, height_, this)) {
141 ETRACE("Failed to initialize Display Queue.");
143 display_state_ |= kInitialized;
146 if (display_state_ & kUpdateConfig) {
147 display_state_ &= ~kUpdateConfig;
148 display_queue_->DisplayConfigurationChanged();
149 UpdateDisplayConfig();
154 SPIN_UNLOCK(modeset_lock_);
157 bool PhysicalDisplay::IsConnected() const {
158 if (connection_state_ & kDisconnectionInProgress)
161 return connection_state_ & kConnected;
164 uint32_t PhysicalDisplay::PowerMode() const {
168 int PhysicalDisplay::GetDisplayPipe() {
172 bool PhysicalDisplay::SetActiveConfig(uint32_t config) {
173 // update the activeConfig
175 "SetActiveConfig: New config to be used %d pipe: %p display: %p", config,
178 display_state_ |= kNeedsModeset;
179 if (connection_state_ & kConnected) {
180 display_queue_->DisplayConfigurationChanged();
181 UpdateDisplayConfig();
183 display_state_ |= kUpdateConfig;
189 bool PhysicalDisplay::GetActiveConfig(uint32_t *config) {
193 "GetActiveConfig: Current config being used Config: %d pipe: %d display: "
195 config_, pipe_, this);
200 bool PhysicalDisplay::SetPowerMode(uint32_t power_mode) {
201 #ifndef DISABLE_HOTPLUG_NOTIFICATION
202 ScopedSpinLock lock(modeset_lock_);
205 if (power_mode_ == power_mode) {
209 power_mode_ = power_mode;
210 if (!(connection_state_ & kConnected)) {
212 "PhysicalDisplay is not connected, postponing power mode update.");
213 display_state_ |= kPendingPowerMode;
215 } else if (connection_state_ & kDisconnectionInProgress) {
217 "PhysicalDisplay diconnection in progress, postponing power mode "
219 // Don't update power mode in case disconnect is in
221 display_state_ |= kPendingPowerMode;
225 return UpdatePowerMode();
228 bool PhysicalDisplay::UpdatePowerMode() {
229 display_state_ &= ~kPendingPowerMode;
231 if (power_mode_ == kOn) {
232 display_state_ |= kNeedsModeset;
233 display_state_ |= kUpdateDisplay;
235 "UpdatePowerMode: Powering on Display: pipe: %d display: "
241 "UpdatePowerMode: Power mode is not kOn: pipe: %d display: "
244 display_state_ &= ~kUpdateDisplay;
247 if (!(display_state_ & kInitialized))
250 return display_queue_->SetPowerMode(power_mode_);
253 bool PhysicalDisplay::Present(std::vector<HwcLayer *> &source_layers,
254 int32_t *retire_fence, bool handle_constraints) {
256 SPIN_LOCK(modeset_lock_);
258 bool handle_hotplug_notifications = false;
259 if (display_state_ & kHandlePendingHotPlugNotifications) {
260 display_state_ &= ~kHandlePendingHotPlugNotifications;
261 handle_hotplug_notifications = true;
264 if (!(display_state_ & kUpdateDisplay)) {
266 if (power_mode_ != kDozeSuspend) {
267 ETRACE("Trying to update an Disconnected Display.%p \n", this);
270 SPIN_UNLOCK(modeset_lock_);
272 if (handle_hotplug_notifications) {
273 NotifyClientsOfDisplayChangeStatus();
279 if (source_display_) {
280 ETRACE("Trying to update display independently when in cloned mode.%p \n",
284 if (display_state_ & kRefreshClonedDisplays) {
288 SPIN_UNLOCK(modeset_lock_);
290 if (handle_hotplug_notifications) {
291 NotifyClientsOfDisplayChangeStatus();
292 IHOTPLUGEVENTTRACE("Handle_hoplug_notifications done. %p \n", this);
295 bool success = display_queue_->QueueUpdate(source_layers, retire_fence, false,
297 if (success && !clones_.empty()) {
298 HandleClonedDisplays(source_layers);
301 size_t size = source_layers.size();
302 for (size_t layer_index = 0; layer_index < size; layer_index++) {
303 HwcLayer *layer = source_layers.at(layer_index);
304 if (!layer->IsVisible())
313 bool PhysicalDisplay::PresentClone(std::vector<HwcLayer *> &source_layers,
314 int32_t *retire_fence, bool idle_frame) {
316 SPIN_LOCK(modeset_lock_);
318 if (display_state_ & kRefreshClonedDisplays) {
321 SPIN_UNLOCK(modeset_lock_);
323 bool success = display_queue_->QueueUpdate(source_layers, retire_fence,
325 HandleClonedDisplays(source_layers);
329 void PhysicalDisplay::HandleClonedDisplays(
330 std::vector<HwcLayer *> &source_layers) {
335 for (auto display : clones_) {
336 display->PresentClone(source_layers, &fence,
337 display_queue_->WasLastFrameIdleUpdate());
341 int PhysicalDisplay::RegisterVsyncCallback(
342 std::shared_ptr<VsyncCallback> callback, uint32_t display_id) {
343 return display_queue_->RegisterVsyncCallback(callback, display_id);
346 void PhysicalDisplay::RegisterRefreshCallback(
347 std::shared_ptr<RefreshCallback> callback, uint32_t display_id) {
348 return display_queue_->RegisterRefreshCallback(callback, display_id);
351 void PhysicalDisplay::RegisterHotPlugCallback(
352 std::shared_ptr<HotPlugCallback> callback, uint32_t display_id) {
353 SPIN_LOCK(modeset_lock_);
354 hot_plug_display_id_ = display_id;
355 hotplug_callback_ = callback;
356 #ifndef ENABLE_ANDROID_WA
357 bool connected = connection_state_ & kConnected;
359 SPIN_UNLOCK(modeset_lock_);
360 #ifdef ENABLE_ANDROID_WA
361 if (hotplug_callback_ && ordered_display_id_ == 0) {
362 display_state_ &= ~kNotifyClient;
363 display_state_ |= kHandlePendingHotPlugNotifications;
364 IHOTPLUGEVENTTRACE("RegisterHotPlugCallback: pipe: %d display: %p", pipe_,
366 hotplug_callback_->Callback(hot_plug_display_id_, true);
369 if (hotplug_callback_) {
371 hotplug_callback_->Callback(hot_plug_display_id_, true);
373 hotplug_callback_->Callback(hot_plug_display_id_, false);
379 void PhysicalDisplay::VSyncControl(bool enabled) {
380 display_queue_->VSyncControl(enabled);
383 bool PhysicalDisplay::CheckPlaneFormat(uint32_t format) {
384 return display_queue_->CheckPlaneFormat(format);
387 void PhysicalDisplay::SetGamma(float red, float green, float blue) {
388 display_queue_->SetGamma(red, green, blue);
391 void PhysicalDisplay::SetColorTransform(const float *matrix, HWCColorTransform hint) {
392 display_queue_->SetColorTransform(matrix, hint);
395 void PhysicalDisplay::SetContrast(uint32_t red, uint32_t green, uint32_t blue) {
396 display_queue_->SetContrast(red, green, blue);
399 void PhysicalDisplay::SetBrightness(uint32_t red, uint32_t green,
401 display_queue_->SetBrightness(red, green, blue);
404 void PhysicalDisplay::SetExplicitSyncSupport(bool disable_explicit_sync) {
405 display_queue_->SetExplicitSyncSupport(disable_explicit_sync);
408 void PhysicalDisplay::SetVideoScalingMode(uint32_t mode) {
409 display_queue_->SetVideoScalingMode(mode);
412 void PhysicalDisplay::SetVideoColor(HWCColorControl color, float value) {
413 display_queue_->SetVideoColor(color, value);
416 void PhysicalDisplay::GetVideoColor(HWCColorControl color,
417 float* value, float* start, float* end) {
418 display_queue_->GetVideoColor(color, value, start, end);
421 void PhysicalDisplay::RestoreVideoDefaultColor(HWCColorControl color) {
422 display_queue_->RestoreVideoDefaultColor(color);
425 void PhysicalDisplay::SetVideoDeinterlace(HWCDeinterlaceFlag flag,
426 HWCDeinterlaceControl mode) {
427 display_queue_->SetVideoDeinterlace(flag, mode);
430 void PhysicalDisplay::RestoreVideoDefaultDeinterlace() {
431 display_queue_->RestoreVideoDefaultDeinterlace();
434 bool PhysicalDisplay::PopulatePlanes(
435 std::vector<std::unique_ptr<DisplayPlane>> & /*overlay_planes*/) {
436 ETRACE("PopulatePlanes unimplemented in PhysicalDisplay.");
440 bool PhysicalDisplay::TestCommit(
441 const std::vector<OverlayPlane> & /*commit_planes*/) const {
442 ETRACE("TestCommit unimplemented in PhysicalDisplay.");
446 void PhysicalDisplay::UpdateScalingRatio(uint32_t primary_width,
447 uint32_t primary_height,
448 uint32_t display_width,
449 uint32_t display_height) {
450 display_queue_->UpdateScalingRatio(primary_width, primary_height,
451 display_width, display_height);
454 void PhysicalDisplay::CloneDisplay(NativeDisplay *source_display) {
455 if (source_display_) {
456 source_display_->DisOwnPresentation(this);
457 display_queue_->SetCloneMode(false);
458 source_display_ = NULL;
461 source_display_ = source_display;
462 if (source_display_) {
463 source_display_->OwnPresentation(this);
464 display_queue_->SetCloneMode(true);
468 void PhysicalDisplay::OwnPresentation(NativeDisplay *clone) {
469 cloned_displays_.emplace_back(clone);
470 display_state_ |= kRefreshClonedDisplays;
473 void PhysicalDisplay::DisOwnPresentation(NativeDisplay *clone) {
474 if (cloned_displays_.empty())
477 std::vector<NativeDisplay *> displays;
478 size_t size = cloned_displays_.size();
479 for (size_t i = 0; i < size; i++) {
480 NativeDisplay *display = cloned_displays_.at(i);
481 if (display == clone)
484 displays.emplace_back(display);
487 cloned_displays_.swap(displays);
488 display_state_ |= kRefreshClonedDisplays;
491 void PhysicalDisplay::SetDisplayOrder(uint32_t display_order) {
492 ordered_display_id_ = display_order;
495 void PhysicalDisplay::RotateDisplay(HWCRotation rotation) {
496 display_queue_->RotateDisplay(rotation);
499 void PhysicalDisplay::RefreshClones() {
500 display_state_ &= ~kRefreshClonedDisplays;
501 std::vector<NativeDisplay *>().swap(clones_);
502 if (cloned_displays_.empty())
505 size_t size = cloned_displays_.size();
506 for (size_t i = 0; i < size; i++) {
507 NativeDisplay *display = cloned_displays_.at(i);
508 if (!display->IsConnected())
511 clones_.emplace_back(display);
514 uint32_t primary_width = Width();
515 uint32_t primary_height = Height();
516 for (auto display : clones_) {
517 uint32_t display_width = display->Width();
518 uint32_t display_height = display->Height();
519 if ((primary_width == display_width) && (primary_height == display_height))
522 display->UpdateScalingRatio(primary_width, primary_height, display_width,
527 bool PhysicalDisplay::GetDisplayAttribute(uint32_t /*config*/,
528 HWCDisplayAttribute attribute,
530 // We always get the values from preferred mode config.
532 case HWCDisplayAttribute::kWidth:
535 case HWCDisplayAttribute::kHeight:
538 case HWCDisplayAttribute::kRefreshRate:
542 case HWCDisplayAttribute::kDpiX:
543 // Dots per 1000 inches
546 case HWCDisplayAttribute::kDpiY:
547 // Dots per 1000 inches
558 bool PhysicalDisplay::GetDisplayConfigs(uint32_t *num_configs,
567 bool PhysicalDisplay::GetDisplayName(uint32_t *size, char *name) {
568 std::ostringstream stream;
569 stream << "Headless";
570 std::string string = stream.str();
571 size_t length = string.length();
577 *size = std::min<uint32_t>(static_cast<uint32_t>(length + 1), *size);
578 strncpy(name, string.c_str(), *size);
581 } // namespace hwcomposer