OSDN Git Service

eb3ee3c790d2b4dcf1939cd77284dd486684c8d9
[android-x86/external-IA-Hardware-Composer.git] / wsi / physicaldisplay.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include "physicaldisplay.h"
18
19 #include <cmath>
20
21 #include <hwcdefs.h>
22 #include <hwclayer.h>
23 #include <hwctrace.h>
24
25 #include <algorithm>
26 #include <string>
27 #include <sstream>
28
29 #include "displayqueue.h"
30 #include "displayplanemanager.h"
31 #include "hwcutils.h"
32 #include "wsi_utils.h"
33
34 namespace hwcomposer {
35
36 PhysicalDisplay::PhysicalDisplay(uint32_t gpu_fd, uint32_t pipe_id)
37     : pipe_(pipe_id),
38       width_(0),
39       height_(0),
40       gpu_fd_(gpu_fd),
41       power_mode_(kOn) {
42 }
43
44 PhysicalDisplay::~PhysicalDisplay() {
45 }
46
47 bool PhysicalDisplay::Initialize(NativeBufferHandler *buffer_handler) {
48   display_queue_.reset(new DisplayQueue(gpu_fd_, false, buffer_handler, this));
49   InitializeDisplay();
50   return true;
51 }
52
53 void PhysicalDisplay::MarkForDisconnect() {
54   SPIN_LOCK(modeset_lock_);
55
56   IHOTPLUGEVENTTRACE("PhysicalDisplay::MarkForDisconnect recieved.");
57   connection_state_ |= kDisconnectionInProgress;
58   display_state_ |= kRefreshClonedDisplays;
59   SPIN_UNLOCK(modeset_lock_);
60 }
61
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)) {
67     IHOTPLUGEVENTTRACE(
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;
76     }
77 #endif
78   }
79   SPIN_UNLOCK(modeset_lock_);
80
81   if (refresh_needed) {
82     display_queue_->ForceRefresh();
83   }
84 }
85
86 void PhysicalDisplay::NotifyClientOfDisConnectedState() {
87   SPIN_LOCK(modeset_lock_);
88
89   if (hotplug_callback_ && !(connection_state_ & kConnected) &&
90       (display_state_ & kNotifyClient)) {
91     IHOTPLUGEVENTTRACE(
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;
97   }
98   SPIN_UNLOCK(modeset_lock_);
99 }
100
101 void PhysicalDisplay::DisConnect() {
102   SPIN_LOCK(modeset_lock_);
103
104   connection_state_ &= ~kDisconnectionInProgress;
105
106   if (!(connection_state_ & kConnected)) {
107     SPIN_UNLOCK(modeset_lock_);
108
109     return;
110   }
111   IHOTPLUGEVENTTRACE(
112       "PhysicalDisplay DisConnect called for Display: %p hotplugdisplayid: %d "
113       "\n",
114       this, hot_plug_display_id_);
115   display_state_ |= kNotifyClient;
116
117   if (power_mode_ != kOff) {
118     display_queue_->SetPowerMode(kOff);
119   }
120
121   connection_state_ &= ~kConnected;
122   display_state_ &= ~kUpdateDisplay;
123   SPIN_UNLOCK(modeset_lock_);
124 }
125
126 void PhysicalDisplay::Connect() {
127   SPIN_LOCK(modeset_lock_);
128
129   connection_state_ &= ~kDisconnectionInProgress;
130   if (connection_state_ & kConnected) {
131     SPIN_UNLOCK(modeset_lock_);
132     return;
133   }
134
135   connection_state_ |= kConnected;
136   display_state_ &= ~kInitialized;
137   display_state_ |= kNotifyClient;
138   IHOTPLUGEVENTTRACE("PhysicalDisplay::Connect recieved. %p \n", this);
139
140   if (!display_queue_->Initialize(pipe_, width_, height_, this)) {
141     ETRACE("Failed to initialize Display Queue.");
142   } else {
143     display_state_ |= kInitialized;
144   }
145
146   if (display_state_ & kUpdateConfig) {
147     display_state_ &= ~kUpdateConfig;
148     display_queue_->DisplayConfigurationChanged();
149     UpdateDisplayConfig();
150   }
151
152   UpdatePowerMode();
153
154   SPIN_UNLOCK(modeset_lock_);
155 }
156
157 bool PhysicalDisplay::IsConnected() const {
158   if (connection_state_ & kDisconnectionInProgress)
159     return false;
160
161   return connection_state_ & kConnected;
162 }
163
164 uint32_t PhysicalDisplay::PowerMode() const {
165   return power_mode_;
166 }
167
168 int PhysicalDisplay::GetDisplayPipe() {
169   return pipe_;
170 }
171
172 bool PhysicalDisplay::SetActiveConfig(uint32_t config) {
173   // update the activeConfig
174   IHOTPLUGEVENTTRACE(
175       "SetActiveConfig: New config to be used %d pipe: %p display: %p", config,
176       pipe_, this);
177   config_ = config;
178   display_state_ |= kNeedsModeset;
179   if (connection_state_ & kConnected) {
180     display_queue_->DisplayConfigurationChanged();
181     UpdateDisplayConfig();
182   } else {
183     display_state_ |= kUpdateConfig;
184   }
185
186   return true;
187 }
188
189 bool PhysicalDisplay::GetActiveConfig(uint32_t *config) {
190   if (!config)
191     return false;
192   IHOTPLUGEVENTTRACE(
193       "GetActiveConfig: Current config being used Config: %d pipe: %d display: "
194       "%p",
195       config_, pipe_, this);
196   *config = config_;
197   return true;
198 }
199
200 bool PhysicalDisplay::SetPowerMode(uint32_t power_mode) {
201 #ifndef DISABLE_HOTPLUG_NOTIFICATION
202   ScopedSpinLock lock(modeset_lock_);
203 #endif
204
205   if (power_mode_ == power_mode) {
206     return true;
207   }
208
209   power_mode_ = power_mode;
210   if (!(connection_state_ & kConnected)) {
211     IHOTPLUGEVENTTRACE(
212         "PhysicalDisplay is not connected, postponing power mode update.");
213     display_state_ |= kPendingPowerMode;
214     return true;
215   } else if (connection_state_ & kDisconnectionInProgress) {
216     IHOTPLUGEVENTTRACE(
217         "PhysicalDisplay diconnection in progress, postponing power mode "
218         "update.");
219     // Don't update power mode in case disconnect is in
220     // progress.
221     display_state_ |= kPendingPowerMode;
222     return true;
223   }
224
225   return UpdatePowerMode();
226 }
227
228 bool PhysicalDisplay::UpdatePowerMode() {
229   display_state_ &= ~kPendingPowerMode;
230
231   if (power_mode_ == kOn) {
232     display_state_ |= kNeedsModeset;
233     display_state_ |= kUpdateDisplay;
234     IHOTPLUGEVENTTRACE(
235         "UpdatePowerMode: Powering on Display: pipe: %d display: "
236         "%p",
237         pipe_, this);
238     PowerOn();
239   } else {
240     IHOTPLUGEVENTTRACE(
241         "UpdatePowerMode: Power mode is not kOn: pipe: %d display: "
242         "%p",
243         pipe_, this);
244     display_state_ &= ~kUpdateDisplay;
245   }
246
247   if (!(display_state_ & kInitialized))
248     return true;
249
250   return display_queue_->SetPowerMode(power_mode_);
251 }
252
253 bool PhysicalDisplay::Present(std::vector<HwcLayer *> &source_layers,
254                               int32_t *retire_fence, bool handle_constraints) {
255   CTRACE();
256   SPIN_LOCK(modeset_lock_);
257
258   bool handle_hotplug_notifications = false;
259   if (display_state_ & kHandlePendingHotPlugNotifications) {
260     display_state_ &= ~kHandlePendingHotPlugNotifications;
261     handle_hotplug_notifications = true;
262   }
263
264   if (!(display_state_ & kUpdateDisplay)) {
265     bool success = true;
266     if (power_mode_ != kDozeSuspend) {
267       ETRACE("Trying to update an Disconnected Display.%p \n", this);
268     }
269
270     SPIN_UNLOCK(modeset_lock_);
271
272     if (handle_hotplug_notifications) {
273       NotifyClientsOfDisplayChangeStatus();
274     }
275
276     return success;
277   }
278
279   if (source_display_) {
280     ETRACE("Trying to update display independently when in cloned mode.%p \n",
281            this);
282   }
283
284   if (display_state_ & kRefreshClonedDisplays) {
285     RefreshClones();
286   }
287
288   SPIN_UNLOCK(modeset_lock_);
289
290   if (handle_hotplug_notifications) {
291     NotifyClientsOfDisplayChangeStatus();
292     IHOTPLUGEVENTTRACE("Handle_hoplug_notifications done. %p \n", this);
293   }
294
295   bool success = display_queue_->QueueUpdate(source_layers, retire_fence, false,
296                                              handle_constraints);
297   if (success && !clones_.empty()) {
298     HandleClonedDisplays(source_layers);
299   }
300
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())
305       continue;
306
307     layer->Validate();
308   }
309
310   return success;
311 }
312
313 bool PhysicalDisplay::PresentClone(std::vector<HwcLayer *> &source_layers,
314                                    int32_t *retire_fence, bool idle_frame) {
315   CTRACE();
316   SPIN_LOCK(modeset_lock_);
317
318   if (display_state_ & kRefreshClonedDisplays) {
319     RefreshClones();
320   }
321   SPIN_UNLOCK(modeset_lock_);
322
323   bool success = display_queue_->QueueUpdate(source_layers, retire_fence,
324                                              idle_frame, false);
325   HandleClonedDisplays(source_layers);
326   return success;
327 }
328
329 void PhysicalDisplay::HandleClonedDisplays(
330     std::vector<HwcLayer *> &source_layers) {
331   if (clones_.empty())
332     return;
333
334   int32_t fence = -1;
335   for (auto display : clones_) {
336     display->PresentClone(source_layers, &fence,
337                           display_queue_->WasLastFrameIdleUpdate());
338   }
339 }
340
341 int PhysicalDisplay::RegisterVsyncCallback(
342     std::shared_ptr<VsyncCallback> callback, uint32_t display_id) {
343   return display_queue_->RegisterVsyncCallback(callback, display_id);
344 }
345
346 void PhysicalDisplay::RegisterRefreshCallback(
347     std::shared_ptr<RefreshCallback> callback, uint32_t display_id) {
348   return display_queue_->RegisterRefreshCallback(callback, display_id);
349 }
350
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;
358 #endif
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_,
365                        this);
366     hotplug_callback_->Callback(hot_plug_display_id_, true);
367   }
368 #else
369   if (hotplug_callback_) {
370     if (connected) {
371       hotplug_callback_->Callback(hot_plug_display_id_, true);
372     } else {
373       hotplug_callback_->Callback(hot_plug_display_id_, false);
374     }
375   }
376 #endif
377 }
378
379 void PhysicalDisplay::VSyncControl(bool enabled) {
380   display_queue_->VSyncControl(enabled);
381 }
382
383 bool PhysicalDisplay::CheckPlaneFormat(uint32_t format) {
384   return display_queue_->CheckPlaneFormat(format);
385 }
386
387 void PhysicalDisplay::SetGamma(float red, float green, float blue) {
388   display_queue_->SetGamma(red, green, blue);
389 }
390
391 void PhysicalDisplay::SetColorTransform(const float *matrix, HWCColorTransform hint) {
392   display_queue_->SetColorTransform(matrix, hint);
393 }
394
395 void PhysicalDisplay::SetContrast(uint32_t red, uint32_t green, uint32_t blue) {
396   display_queue_->SetContrast(red, green, blue);
397 }
398
399 void PhysicalDisplay::SetBrightness(uint32_t red, uint32_t green,
400                                     uint32_t blue) {
401   display_queue_->SetBrightness(red, green, blue);
402 }
403
404 void PhysicalDisplay::SetExplicitSyncSupport(bool disable_explicit_sync) {
405   display_queue_->SetExplicitSyncSupport(disable_explicit_sync);
406 }
407
408 void PhysicalDisplay::SetVideoScalingMode(uint32_t mode) {
409   display_queue_->SetVideoScalingMode(mode);
410 }
411
412 void PhysicalDisplay::SetVideoColor(HWCColorControl color, float value) {
413   display_queue_->SetVideoColor(color, value);
414 }
415
416 void PhysicalDisplay::GetVideoColor(HWCColorControl color,
417                                     float* value, float* start, float* end) {
418   display_queue_->GetVideoColor(color, value, start, end);
419 }
420
421 void PhysicalDisplay::RestoreVideoDefaultColor(HWCColorControl color) {
422   display_queue_->RestoreVideoDefaultColor(color);
423 }
424
425 void PhysicalDisplay::SetVideoDeinterlace(HWCDeinterlaceFlag flag,
426                                           HWCDeinterlaceControl mode) {
427   display_queue_->SetVideoDeinterlace(flag, mode);
428 }
429
430 void PhysicalDisplay::RestoreVideoDefaultDeinterlace() {
431   display_queue_->RestoreVideoDefaultDeinterlace();
432 }
433
434 bool PhysicalDisplay::PopulatePlanes(
435     std::vector<std::unique_ptr<DisplayPlane>> & /*overlay_planes*/) {
436   ETRACE("PopulatePlanes unimplemented in PhysicalDisplay.");
437   return false;
438 }
439
440 bool PhysicalDisplay::TestCommit(
441     const std::vector<OverlayPlane> & /*commit_planes*/) const {
442   ETRACE("TestCommit unimplemented in PhysicalDisplay.");
443   return false;
444 }
445
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);
452 }
453
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;
459   }
460
461   source_display_ = source_display;
462   if (source_display_) {
463     source_display_->OwnPresentation(this);
464     display_queue_->SetCloneMode(true);
465   }
466 }
467
468 void PhysicalDisplay::OwnPresentation(NativeDisplay *clone) {
469   cloned_displays_.emplace_back(clone);
470   display_state_ |= kRefreshClonedDisplays;
471 }
472
473 void PhysicalDisplay::DisOwnPresentation(NativeDisplay *clone) {
474   if (cloned_displays_.empty())
475     return;
476
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)
482       continue;
483
484     displays.emplace_back(display);
485   }
486
487   cloned_displays_.swap(displays);
488   display_state_ |= kRefreshClonedDisplays;
489 }
490
491 void PhysicalDisplay::SetDisplayOrder(uint32_t display_order) {
492   ordered_display_id_ = display_order;
493 }
494
495 void PhysicalDisplay::RotateDisplay(HWCRotation rotation) {
496   display_queue_->RotateDisplay(rotation);
497 }
498
499 void PhysicalDisplay::RefreshClones() {
500   display_state_ &= ~kRefreshClonedDisplays;
501   std::vector<NativeDisplay *>().swap(clones_);
502   if (cloned_displays_.empty())
503     return;
504
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())
509       continue;
510
511     clones_.emplace_back(display);
512   }
513
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))
520       return;
521
522     display->UpdateScalingRatio(primary_width, primary_height, display_width,
523                                 display_height);
524   }
525 }
526
527 bool PhysicalDisplay::GetDisplayAttribute(uint32_t /*config*/,
528                                           HWCDisplayAttribute attribute,
529                                           int32_t *value) {
530   // We always get the values from preferred mode config.
531   switch (attribute) {
532     case HWCDisplayAttribute::kWidth:
533       *value = 1920;
534       break;
535     case HWCDisplayAttribute::kHeight:
536       *value = 1080;
537       break;
538     case HWCDisplayAttribute::kRefreshRate:
539       // in nanoseconds
540       *value = 60;
541       break;
542     case HWCDisplayAttribute::kDpiX:
543       // Dots per 1000 inches
544       *value = 1;
545       break;
546     case HWCDisplayAttribute::kDpiY:
547       // Dots per 1000 inches
548       *value = 1;
549       break;
550     default:
551       *value = -1;
552       return false;
553   }
554
555   return true;
556 }
557
558 bool PhysicalDisplay::GetDisplayConfigs(uint32_t *num_configs,
559                                         uint32_t *configs) {
560   *num_configs = 1;
561   if (configs) {
562     configs[0] = 1;
563   }
564   return true;
565 }
566
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();
572   if (!name) {
573     *size = length;
574     return true;
575   }
576
577   *size = std::min<uint32_t>(static_cast<uint32_t>(length + 1), *size);
578   strncpy(name, string.c_str(), *size);
579   return true;
580 }
581
582 int PhysicalDisplay::InitializeLayerHashGenerator(int size) {
583   LayerIds_.clear();
584   for (int i = 0; i < size; i++) {
585     LayerIds_.push_back(i);
586   }
587
588   current_max_layer_ids_ = size;
589   return 0;
590 }
591
592 uint64_t PhysicalDisplay::AcquireId() {
593   if (LayerIds_.empty())
594     return ++current_max_layer_ids_;
595
596   uint64_t id = LayerIds_.back();
597   LayerIds_.pop_back();
598
599   return id;
600 }
601
602 void PhysicalDisplay::ReleaseId(uint64_t id) {
603   LayerIds_.push_back(id);
604 }
605
606 void PhysicalDisplay::ResetLayerHashGenerator() {
607   InitializeLayerHashGenerator(current_max_layer_ids_);
608 }
609 }  // namespace hwcomposer