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 "displayplanemanager.h"
30 #include "displayqueue.h"
32 #include "wsi_utils.h"
34 namespace hwcomposer {
36 PhysicalDisplay::PhysicalDisplay(uint32_t gpu_fd, uint32_t pipe_id)
40 custom_resolution_(false),
45 PhysicalDisplay::~PhysicalDisplay() {
48 bool PhysicalDisplay::Initialize(NativeBufferHandler *buffer_handler) {
49 display_queue_.reset(new DisplayQueue(gpu_fd_, false, buffer_handler, this));
54 const NativeBufferHandler *PhysicalDisplay::GetNativeBufferHandler() const {
56 return display_queue_->GetNativeBufferHandler();
62 void PhysicalDisplay::MarkForDisconnect() {
63 SPIN_LOCK(modeset_lock_);
65 IHOTPLUGEVENTTRACE("PhysicalDisplay::MarkForDisconnect recieved.");
66 connection_state_ |= kDisconnectionInProgress;
67 display_state_ |= kRefreshClonedDisplays;
68 SPIN_UNLOCK(modeset_lock_);
71 void PhysicalDisplay::NotifyClientOfConnectedState() {
72 SPIN_LOCK(modeset_lock_);
73 bool refresh_needed = false;
74 if (hotplug_callback_ && (connection_state_ & kConnected) &&
75 (display_state_ & kNotifyClient)) {
77 "PhysicalDisplay Sent Hotplug even call back with connected value set "
78 "to true. %p hotplugdisplayid: %d \n",
79 this, hot_plug_display_id_);
80 hotplug_callback_->Callback(hot_plug_display_id_, true);
81 display_state_ &= ~kNotifyClient;
82 #ifdef ENABLE_ANDROID_WA
83 if (ordered_display_id_ == 0) {
84 refresh_needed = true;
88 SPIN_UNLOCK(modeset_lock_);
91 if (!display_queue_->IsIgnoreUpdates()) {
92 display_queue_->ForceRefresh();
97 void PhysicalDisplay::NotifyClientOfDisConnectedState() {
98 SPIN_LOCK(modeset_lock_);
99 if (hotplug_callback_ && !(connection_state_ & kConnected) &&
100 (display_state_ & kNotifyClient)) {
102 "PhysicalDisplay Sent Hotplug even call back with connected value set "
103 "to false. %p hotplugdisplayid: %d \n",
104 this, hot_plug_display_id_);
105 hotplug_callback_->Callback(hot_plug_display_id_, false);
106 display_state_ &= ~kNotifyClient;
108 SPIN_UNLOCK(modeset_lock_);
111 void PhysicalDisplay::DisConnect() {
112 SPIN_LOCK(modeset_lock_);
114 connection_state_ &= ~kDisconnectionInProgress;
116 if (!(connection_state_ & kConnected)) {
117 SPIN_UNLOCK(modeset_lock_);
122 "PhysicalDisplay DisConnect called for Display: %p hotplugdisplayid: %d "
124 this, hot_plug_display_id_);
125 display_state_ |= kNotifyClient;
127 if (power_mode_ != kOff) {
128 display_queue_->SetPowerMode(kOff);
131 connection_state_ &= ~kConnected;
132 display_state_ &= ~kUpdateDisplay;
133 SPIN_UNLOCK(modeset_lock_);
136 void PhysicalDisplay::Connect() {
137 SPIN_LOCK(modeset_lock_);
139 connection_state_ &= ~kDisconnectionInProgress;
141 SPIN_UNLOCK(modeset_lock_);
143 if (source_display_) {
144 // Current display is a cloned display, set the source_display_'s
145 // k_RefreshClonedDisplays flag. This makes clone parent have a
146 // chance to update it's cloned display list
147 PhysicalDisplay *p_clone_parent = (PhysicalDisplay *)source_display_;
148 SPIN_LOCK(p_clone_parent->modeset_lock_);
149 p_clone_parent->display_state_ |= kRefreshClonedDisplays;
150 SPIN_UNLOCK(p_clone_parent->modeset_lock_);
153 SPIN_LOCK(modeset_lock_);
154 if (connection_state_ & kConnected) {
155 SPIN_UNLOCK(modeset_lock_);
159 connection_state_ |= kConnected;
160 display_state_ &= ~kInitialized;
161 display_state_ |= kNotifyClient;
162 IHOTPLUGEVENTTRACE("PhysicalDisplay::Connect recieved. %p \n", this);
164 if (!display_queue_->Initialize(pipe_, width_, height_, this)) {
165 ETRACE("Failed to initialize Display Queue.");
167 display_state_ |= kInitialized;
170 if (display_state_ & kUpdateConfig) {
171 display_state_ &= ~kUpdateConfig;
172 display_queue_->DisplayConfigurationChanged();
173 UpdateDisplayConfig();
178 SPIN_UNLOCK(modeset_lock_);
181 bool PhysicalDisplay::IsConnected() const {
182 if (connection_state_ & kDisconnectionInProgress)
185 return connection_state_ & kConnected;
188 uint32_t PhysicalDisplay::PowerMode() const {
192 int PhysicalDisplay::GetDisplayPipe() {
196 bool PhysicalDisplay::EnableDRMCommit(bool enable) {
197 display_queue_->ForceIgnoreUpdates(!enable);
199 return !display_queue_->IsIgnoreUpdates();
201 return display_queue_->IsIgnoreUpdates();
204 bool PhysicalDisplay::SetActiveConfig(uint32_t config) {
205 // update the activeConfig
207 "SetActiveConfig: New config to be used %d pipe: %p display: %p", config,
210 display_state_ |= kNeedsModeset;
211 if (connection_state_ & kConnected) {
212 display_queue_->DisplayConfigurationChanged();
213 UpdateDisplayConfig();
215 display_state_ |= kUpdateConfig;
221 bool PhysicalDisplay::GetActiveConfig(uint32_t *config) {
225 "GetActiveConfig: Current config being used Config: %d pipe: %d display: "
227 config_, pipe_, this);
232 bool PhysicalDisplay::SetPowerMode(uint32_t power_mode) {
233 #ifndef DISABLE_HOTPLUG_NOTIFICATION
234 ScopedSpinLock lock(modeset_lock_);
237 if (power_mode_ == power_mode) {
241 power_mode_ = power_mode;
242 if (!(connection_state_ & kConnected)) {
244 "PhysicalDisplay is not connected, postponing power mode update.");
245 display_state_ |= kPendingPowerMode;
247 } else if (connection_state_ & kDisconnectionInProgress) {
249 "PhysicalDisplay diconnection in progress, postponing power mode "
251 // Don't update power mode in case disconnect is in
253 display_state_ |= kPendingPowerMode;
257 return UpdatePowerMode();
260 bool PhysicalDisplay::UpdatePowerMode() {
261 display_state_ &= ~kPendingPowerMode;
263 if (power_mode_ == kOn) {
264 display_state_ |= kNeedsModeset;
265 display_state_ |= kUpdateDisplay;
267 "UpdatePowerMode: Powering on Display: pipe: %d display: "
273 "UpdatePowerMode: Power mode is not kOn: pipe: %d display: "
276 display_state_ &= ~kUpdateDisplay;
279 if (!(display_state_ & kInitialized))
282 return display_queue_->SetPowerMode(power_mode_);
285 bool PhysicalDisplay::Present(std::vector<HwcLayer *> &source_layers,
286 int32_t *retire_fence,
287 PixelUploaderCallback *call_back,
288 bool handle_constraints) {
290 SPIN_LOCK(modeset_lock_);
292 bool handle_hotplug_notifications = false;
293 if (display_state_ & kHandlePendingHotPlugNotifications) {
294 display_state_ &= ~kHandlePendingHotPlugNotifications;
295 handle_hotplug_notifications = true;
298 if (!(display_state_ & kUpdateDisplay)) {
300 if (power_mode_ != kDozeSuspend) {
301 ETRACE("Trying to update an Disconnected Display.%p \n", this);
304 SPIN_UNLOCK(modeset_lock_);
306 if (handle_hotplug_notifications) {
307 NotifyClientsOfDisplayChangeStatus();
313 if (source_display_) {
314 ETRACE("Trying to update display independently when in cloned mode.%p \n",
318 if (display_state_ & kRefreshClonedDisplays) {
322 SPIN_UNLOCK(modeset_lock_);
324 if (handle_hotplug_notifications) {
325 NotifyClientsOfDisplayChangeStatus();
326 IHOTPLUGEVENTTRACE("Handle_hoplug_notifications done. %p \n", this);
329 bool ignore_clone_update = false;
330 bool success = display_queue_->QueueUpdate(source_layers, retire_fence,
331 &ignore_clone_update, call_back,
333 if (success && !clones_.empty() && !ignore_clone_update) {
334 HandleClonedDisplays(this);
337 size_t size = source_layers.size();
338 for (size_t layer_index = 0; layer_index < size; layer_index++) {
339 HwcLayer *layer = source_layers.at(layer_index);
340 if (!layer->IsVisible())
349 bool PhysicalDisplay::PresentClone(NativeDisplay *display) {
351 SPIN_LOCK(modeset_lock_);
353 if (display_state_ & kRefreshClonedDisplays) {
356 SPIN_UNLOCK(modeset_lock_);
358 display_queue_->PresentClonedCommit(
359 static_cast<PhysicalDisplay *>(display)->display_queue_.get());
360 HandleClonedDisplays(display);
364 void PhysicalDisplay::HandleClonedDisplays(NativeDisplay *display) {
368 for (auto clone_display : clones_) {
369 clone_display->PresentClone(display);
373 int PhysicalDisplay::RegisterVsyncCallback(
374 std::shared_ptr<VsyncCallback> callback, uint32_t display_id) {
375 return display_queue_->RegisterVsyncCallback(callback, display_id);
378 void PhysicalDisplay::RegisterRefreshCallback(
379 std::shared_ptr<RefreshCallback> callback, uint32_t display_id) {
380 return display_queue_->RegisterRefreshCallback(callback, display_id);
383 void PhysicalDisplay::RegisterHotPlugCallback(
384 std::shared_ptr<HotPlugCallback> callback, uint32_t display_id) {
385 SPIN_LOCK(modeset_lock_);
386 hot_plug_display_id_ = display_id;
387 hotplug_callback_ = callback;
388 #ifndef ENABLE_ANDROID_WA
389 bool connected = connection_state_ & kConnected;
391 SPIN_UNLOCK(modeset_lock_);
392 #ifdef ENABLE_ANDROID_WA
393 if (hotplug_callback_ && ordered_display_id_ == 0) {
394 display_state_ &= ~kNotifyClient;
395 display_state_ |= kHandlePendingHotPlugNotifications;
396 IHOTPLUGEVENTTRACE("RegisterHotPlugCallback: pipe: %d display: %p", pipe_,
398 hotplug_callback_->Callback(hot_plug_display_id_, true);
401 if (hotplug_callback_) {
403 hotplug_callback_->Callback(hot_plug_display_id_, true);
405 hotplug_callback_->Callback(hot_plug_display_id_, false);
411 void PhysicalDisplay::VSyncControl(bool enabled) {
412 display_queue_->VSyncControl(enabled);
415 bool PhysicalDisplay::CheckPlaneFormat(uint32_t format) {
416 return display_queue_->CheckPlaneFormat(format);
419 void PhysicalDisplay::SetGamma(float red, float green, float blue) {
420 display_queue_->SetGamma(red, green, blue);
423 void PhysicalDisplay::SetColorTransform(const float *matrix,
424 HWCColorTransform hint) {
425 display_queue_->SetColorTransform(matrix, hint);
428 void PhysicalDisplay::SetContrast(uint32_t red, uint32_t green, uint32_t blue) {
429 display_queue_->SetContrast(red, green, blue);
432 void PhysicalDisplay::SetBrightness(uint32_t red, uint32_t green,
434 display_queue_->SetBrightness(red, green, blue);
437 void PhysicalDisplay::SetDisableExplicitSync(bool disable_explicit_sync) {
438 display_queue_->SetDisableExplicitSync(disable_explicit_sync);
441 void PhysicalDisplay::SetVideoScalingMode(uint32_t mode) {
442 display_queue_->SetVideoScalingMode(mode);
445 void PhysicalDisplay::SetVideoColor(HWCColorControl color, float value) {
446 display_queue_->SetVideoColor(color, value);
449 void PhysicalDisplay::GetVideoColor(HWCColorControl color, float *value,
450 float *start, float *end) {
451 display_queue_->GetVideoColor(color, value, start, end);
454 void PhysicalDisplay::RestoreVideoDefaultColor(HWCColorControl color) {
455 display_queue_->RestoreVideoDefaultColor(color);
458 void PhysicalDisplay::SetVideoDeinterlace(HWCDeinterlaceFlag flag,
459 HWCDeinterlaceControl mode) {
460 display_queue_->SetVideoDeinterlace(flag, mode);
463 void PhysicalDisplay::RestoreVideoDefaultDeinterlace() {
464 display_queue_->RestoreVideoDefaultDeinterlace();
467 void PhysicalDisplay::SetCanvasColor(uint16_t bpc, uint16_t red, uint16_t green,
468 uint16_t blue, uint16_t alpha) {
469 display_queue_->SetCanvasColor(bpc, red, green, blue, alpha);
472 void PhysicalDisplay::SetPAVPSessionStatus(bool enabled,
473 uint32_t pavp_session_id,
474 uint32_t pavp_instance_id) {
475 display_queue_->SetPAVPSessionStatus(enabled, pavp_session_id,
479 bool PhysicalDisplay::PopulatePlanes(
480 std::vector<std::unique_ptr<DisplayPlane>> & /*overlay_planes*/) {
481 ETRACE("PopulatePlanes unimplemented in PhysicalDisplay.");
485 bool PhysicalDisplay::TestCommit(
486 const std::vector<OverlayPlane> & /*commit_planes*/) const {
487 ETRACE("TestCommit unimplemented in PhysicalDisplay.");
491 void PhysicalDisplay::UpdateScalingRatio(uint32_t primary_width,
492 uint32_t primary_height,
493 uint32_t display_width,
494 uint32_t display_height) {
495 display_queue_->UpdateScalingRatio(primary_width, primary_height,
496 display_width, display_height);
499 void PhysicalDisplay::CloneDisplay(NativeDisplay *source_display) {
500 if (source_display_) {
501 source_display_->DisOwnPresentation(this);
502 display_queue_->SetCloneMode(false);
503 source_display_ = NULL;
506 source_display_ = source_display;
507 if (source_display_) {
508 source_display_->OwnPresentation(this);
509 display_queue_->SetCloneMode(true);
513 void PhysicalDisplay::OwnPresentation(NativeDisplay *clone) {
514 cloned_displays_.emplace_back(clone);
515 display_state_ |= kRefreshClonedDisplays;
518 void PhysicalDisplay::DisOwnPresentation(NativeDisplay *clone) {
519 if (cloned_displays_.empty())
522 std::vector<NativeDisplay *> displays;
523 size_t size = cloned_displays_.size();
524 for (size_t i = 0; i < size; i++) {
525 NativeDisplay *display = cloned_displays_.at(i);
526 if (display == clone)
529 displays.emplace_back(display);
532 cloned_displays_.swap(displays);
533 display_state_ |= kRefreshClonedDisplays;
536 void PhysicalDisplay::SetDisplayOrder(uint32_t display_order) {
537 ordered_display_id_ = display_order;
540 void PhysicalDisplay::RotateDisplay(HWCRotation rotation) {
541 display_queue_->RotateDisplay(rotation);
544 void PhysicalDisplay::RefreshClones() {
545 display_state_ &= ~kRefreshClonedDisplays;
546 std::vector<NativeDisplay *>().swap(clones_);
547 if (cloned_displays_.empty())
550 size_t size = cloned_displays_.size();
551 for (size_t i = 0; i < size; i++) {
552 NativeDisplay *display = cloned_displays_.at(i);
553 if (!display->IsConnected())
556 clones_.emplace_back(display);
559 uint32_t primary_width = Width();
560 uint32_t primary_height = Height();
561 for (auto display : clones_) {
562 uint32_t display_width = display->Width();
563 uint32_t display_height = display->Height();
564 if ((primary_width == display_width) && (primary_height == display_height))
567 display->UpdateScalingRatio(primary_width, primary_height, display_width,
572 bool PhysicalDisplay::GetDisplayAttribute(uint32_t /*config*/,
573 HWCDisplayAttribute attribute,
575 // We always get the values from preferred mode config.
577 case HWCDisplayAttribute::kWidth:
580 case HWCDisplayAttribute::kHeight:
583 case HWCDisplayAttribute::kRefreshRate:
587 case HWCDisplayAttribute::kDpiX:
588 // Dots per 1000 inches
591 case HWCDisplayAttribute::kDpiY:
592 // Dots per 1000 inches
603 /* Setting custom resolution instead of preferred as fetched from display */
604 bool PhysicalDisplay::SetCustomResolution(const HwcRect<int32_t> &rect) {
605 if ((rect.right - rect.left) && (rect.bottom - rect.top)) {
606 // Custom rectangle with valid width and height
607 rect_.left = rect.left;
608 rect_.top = rect.top;
609 rect_.right = rect.right;
610 rect_.bottom = rect.bottom;
611 custom_resolution_ = true;
614 "SetCustomResolution: custom width %d, height %d, bool %d",
615 rect_.right - rect_.left, rect_.bottom - rect_.top, custom_resolution_);
619 // Default display rectangle
620 custom_resolution_ = false;
625 bool PhysicalDisplay::GetDisplayConfigs(uint32_t *num_configs,
631 configs[0] = DEFAULT_CONFIG_ID;
633 connection_state_ |= kFakeConnected;
637 bool PhysicalDisplay::GetDisplayName(uint32_t *size, char *name) {
638 std::ostringstream stream;
639 stream << "Headless";
640 std::string string = stream.str();
641 size_t length = string.length();
647 *size = std::min<uint32_t>(static_cast<uint32_t>(length + 1), *size);
648 strncpy(name, string.c_str(), *size);
651 } // namespace hwcomposer