• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
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 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18 #define LOG_TAG "hwc-drm-two"
19 
20 #include "drmhwctwo.h"
21 #include "drmdisplaycomposition.h"
22 #include "drmhwcomposer.h"
23 #include "platform.h"
24 #include "vsyncworker.h"
25 
26 #include <inttypes.h>
27 #include <string>
28 
29 #include <cutils/properties.h>
30 #include <hardware/hardware.h>
31 #include <hardware/hwcomposer2.h>
32 #include <log/log.h>
33 
34 namespace android {
35 
36 class DrmVsyncCallback : public VsyncCallback {
37  public:
DrmVsyncCallback(hwc2_callback_data_t data,hwc2_function_pointer_t hook)38   DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook)
39       : data_(data), hook_(hook) {
40   }
41 
Callback(int display,int64_t timestamp)42   void Callback(int display, int64_t timestamp) {
43     auto hook = reinterpret_cast<HWC2_PFN_VSYNC>(hook_);
44     hook(data_, display, timestamp);
45   }
46 
47  private:
48   hwc2_callback_data_t data_;
49   hwc2_function_pointer_t hook_;
50 };
51 
DrmHwcTwo()52 DrmHwcTwo::DrmHwcTwo() {
53   common.tag = HARDWARE_DEVICE_TAG;
54   common.version = HWC_DEVICE_API_VERSION_2_0;
55   common.close = HookDevClose;
56   getCapabilities = HookDevGetCapabilities;
57   getFunction = HookDevGetFunction;
58 }
59 
CreateDisplay(hwc2_display_t displ,HWC2::DisplayType type)60 HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
61                                      HWC2::DisplayType type) {
62   DrmDevice *drm = resource_manager_.GetDrmDevice(displ);
63   std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ);
64   if (!drm || !importer) {
65     ALOGE("Failed to get a valid drmresource and importer");
66     return HWC2::Error::NoResources;
67   }
68   displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
69                     std::forward_as_tuple(&resource_manager_, drm, importer,
70                                           displ, type));
71 
72   DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
73   if (!crtc) {
74     ALOGE("Failed to get crtc for display %d", static_cast<int>(displ));
75     return HWC2::Error::BadDisplay;
76   }
77   std::vector<DrmPlane *> display_planes;
78   for (auto &plane : drm->planes()) {
79     if (plane->GetCrtcSupported(*crtc))
80       display_planes.push_back(plane.get());
81   }
82   displays_.at(displ).Init(&display_planes);
83   return HWC2::Error::None;
84 }
85 
Init()86 HWC2::Error DrmHwcTwo::Init() {
87   int rv = resource_manager_.Init();
88   if (rv) {
89     ALOGE("Can't initialize the resource manager %d", rv);
90     return HWC2::Error::NoResources;
91   }
92 
93   HWC2::Error ret = HWC2::Error::None;
94   for (int i = 0; i < resource_manager_.getDisplayCount(); i++) {
95     ret = CreateDisplay(i, HWC2::DisplayType::Physical);
96     if (ret != HWC2::Error::None) {
97       ALOGE("Failed to create display %d with error %d", i, ret);
98       return ret;
99     }
100   }
101 
102   auto &drmDevices = resource_manager_.getDrmDevices();
103   for (auto &device : drmDevices) {
104     device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get()));
105   }
106   return ret;
107 }
108 
109 template <typename... Args>
unsupported(char const * func,Args...)110 static inline HWC2::Error unsupported(char const *func, Args... /*args*/) {
111   ALOGV("Unsupported function: %s", func);
112   return HWC2::Error::Unsupported;
113 }
114 
supported(char const * func)115 static inline void supported(char const *func) {
116   ALOGV("Supported function: %s", func);
117 }
118 
CreateVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,hwc2_display_t * display)119 HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t width, uint32_t height,
120                                             int32_t *format,
121                                             hwc2_display_t *display) {
122   // TODO: Implement virtual display
123   return unsupported(__func__, width, height, format, display);
124 }
125 
DestroyVirtualDisplay(hwc2_display_t display)126 HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) {
127   // TODO: Implement virtual display
128   return unsupported(__func__, display);
129 }
130 
DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta)131 std::string DrmHwcTwo::HwcDisplay::DumpDelta(
132     DrmHwcTwo::HwcDisplay::Stats delta) {
133   if (delta.total_pixops_ == 0)
134     return "No stats yet";
135   double Ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
136 
137   return (std::stringstream()
138           << " Total frames count: " << delta.total_frames_ << "\n"
139           << " Failed to test commit frames: " << delta.failed_kms_validate_
140           << "\n"
141           << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
142           << ((delta.failed_kms_present_ > 0)
143                   ? " !!! Internal failure, FIX it please\n"
144                   : "")
145           << " Pixel operations (free units)"
146           << " : [TOTAL: " << delta.total_pixops_
147           << " / GPU: " << delta.gpu_pixops_ << "]\n"
148           << " Composition efficiency: " << Ratio)
149       .str();
150 }
151 
Dump()152 std::string DrmHwcTwo::HwcDisplay::Dump() {
153   auto out = (std::stringstream()
154               << "- Display on: " << connector_->name() << "\n"
155               << "Statistics since system boot:\n"
156               << DumpDelta(total_stats_) << "\n\n"
157               << "Statistics since last dumpsys request:\n"
158               << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n")
159                  .str();
160 
161   memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
162   return out;
163 }
164 
Dump(uint32_t * outSize,char * outBuffer)165 void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
166   supported(__func__);
167 
168   if (outBuffer != nullptr) {
169     auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
170     *outSize = static_cast<uint32_t>(copiedBytes);
171     return;
172   }
173 
174   std::stringstream output;
175 
176   output << "-- drm_hwcomposer --\n\n";
177 
178   for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &dp : displays_)
179     output << dp.second.Dump();
180 
181   mDumpString = output.str();
182   *outSize = static_cast<uint32_t>(mDumpString.size());
183 }
184 
GetMaxVirtualDisplayCount()185 uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() {
186   // TODO: Implement virtual display
187   unsupported(__func__);
188   return 0;
189 }
190 
RegisterCallback(int32_t descriptor,hwc2_callback_data_t data,hwc2_function_pointer_t function)191 HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
192                                         hwc2_callback_data_t data,
193                                         hwc2_function_pointer_t function) {
194   supported(__func__);
195   auto callback = static_cast<HWC2::Callback>(descriptor);
196 
197   if (!function) {
198     callbacks_.erase(callback);
199     return HWC2::Error::None;
200   }
201 
202   callbacks_.emplace(callback, HwcCallback(data, function));
203 
204   switch (callback) {
205     case HWC2::Callback::Hotplug: {
206       auto &drmDevices = resource_manager_.getDrmDevices();
207       for (auto &device : drmDevices)
208         HandleInitialHotplugState(device.get());
209       break;
210     }
211     case HWC2::Callback::Vsync: {
212       for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
213            displays_)
214         d.second.RegisterVsyncCallback(data, function);
215       break;
216     }
217     default:
218       break;
219   }
220   return HWC2::Error::None;
221 }
222 
HwcDisplay(ResourceManager * resource_manager,DrmDevice * drm,std::shared_ptr<Importer> importer,hwc2_display_t handle,HWC2::DisplayType type)223 DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
224                                   DrmDevice *drm,
225                                   std::shared_ptr<Importer> importer,
226                                   hwc2_display_t handle, HWC2::DisplayType type)
227     : resource_manager_(resource_manager),
228       drm_(drm),
229       importer_(importer),
230       handle_(handle),
231       type_(type),
232       color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
233   supported(__func__);
234 
235   // clang-format off
236   color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
237                              0.0, 1.0, 0.0, 0.0,
238                              0.0, 0.0, 1.0, 0.0,
239                              0.0, 0.0, 0.0, 1.0};
240   // clang-format on
241 }
242 
ClearDisplay()243 void DrmHwcTwo::HwcDisplay::ClearDisplay() {
244   compositor_.ClearDisplay();
245 }
246 
Init(std::vector<DrmPlane * > * planes)247 HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
248   supported(__func__);
249   planner_ = Planner::CreateInstance(drm_);
250   if (!planner_) {
251     ALOGE("Failed to create planner instance for composition");
252     return HWC2::Error::NoResources;
253   }
254 
255   int display = static_cast<int>(handle_);
256   int ret = compositor_.Init(resource_manager_, display);
257   if (ret) {
258     ALOGE("Failed display compositor init for display %d (%d)", display, ret);
259     return HWC2::Error::NoResources;
260   }
261 
262   // Split up the given display planes into primary and overlay to properly
263   // interface with the composition
264   char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
265   property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
266   bool use_overlay_planes = atoi(use_overlay_planes_prop);
267   for (auto &plane : *planes) {
268     if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
269       primary_planes_.push_back(plane);
270     else if (use_overlay_planes && (plane)->type() == DRM_PLANE_TYPE_OVERLAY)
271       overlay_planes_.push_back(plane);
272   }
273 
274   crtc_ = drm_->GetCrtcForDisplay(display);
275   if (!crtc_) {
276     ALOGE("Failed to get crtc for display %d", display);
277     return HWC2::Error::BadDisplay;
278   }
279 
280   connector_ = drm_->GetConnectorForDisplay(display);
281   if (!connector_) {
282     ALOGE("Failed to get connector for display %d", display);
283     return HWC2::Error::BadDisplay;
284   }
285 
286   ret = vsync_worker_.Init(drm_, display);
287   if (ret) {
288     ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
289     return HWC2::Error::BadDisplay;
290   }
291 
292   return ChosePreferredConfig();
293 }
294 
ChosePreferredConfig()295 HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() {
296   // Fetch the number of modes from the display
297   uint32_t num_configs;
298   HWC2::Error err = GetDisplayConfigs(&num_configs, NULL);
299   if (err != HWC2::Error::None || !num_configs)
300     return err;
301 
302   return SetActiveConfig(connector_->get_preferred_mode_id());
303 }
304 
RegisterVsyncCallback(hwc2_callback_data_t data,hwc2_function_pointer_t func)305 HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback(
306     hwc2_callback_data_t data, hwc2_function_pointer_t func) {
307   supported(__func__);
308   auto callback = std::make_shared<DrmVsyncCallback>(data, func);
309   vsync_worker_.RegisterCallback(std::move(callback));
310   return HWC2::Error::None;
311 }
312 
AcceptDisplayChanges()313 HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
314   supported(__func__);
315   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
316     l.second.accept_type_change();
317   return HWC2::Error::None;
318 }
319 
CreateLayer(hwc2_layer_t * layer)320 HWC2::Error DrmHwcTwo::HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
321   supported(__func__);
322   layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer());
323   *layer = static_cast<hwc2_layer_t>(layer_idx_);
324   ++layer_idx_;
325   return HWC2::Error::None;
326 }
327 
DestroyLayer(hwc2_layer_t layer)328 HWC2::Error DrmHwcTwo::HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
329   supported(__func__);
330   if (!get_layer(layer))
331     return HWC2::Error::BadLayer;
332 
333   layers_.erase(layer);
334   return HWC2::Error::None;
335 }
336 
GetActiveConfig(hwc2_config_t * config)337 HWC2::Error DrmHwcTwo::HwcDisplay::GetActiveConfig(hwc2_config_t *config) {
338   supported(__func__);
339   DrmMode const &mode = connector_->active_mode();
340   if (mode.id() == 0)
341     return HWC2::Error::BadConfig;
342 
343   *config = mode.id();
344   return HWC2::Error::None;
345 }
346 
GetChangedCompositionTypes(uint32_t * num_elements,hwc2_layer_t * layers,int32_t * types)347 HWC2::Error DrmHwcTwo::HwcDisplay::GetChangedCompositionTypes(
348     uint32_t *num_elements, hwc2_layer_t *layers, int32_t *types) {
349   supported(__func__);
350   uint32_t num_changes = 0;
351   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
352     if (l.second.type_changed()) {
353       if (layers && num_changes < *num_elements)
354         layers[num_changes] = l.first;
355       if (types && num_changes < *num_elements)
356         types[num_changes] = static_cast<int32_t>(l.second.validated_type());
357       ++num_changes;
358     }
359   }
360   if (!layers && !types)
361     *num_elements = num_changes;
362   return HWC2::Error::None;
363 }
364 
GetClientTargetSupport(uint32_t width,uint32_t height,int32_t,int32_t dataspace)365 HWC2::Error DrmHwcTwo::HwcDisplay::GetClientTargetSupport(uint32_t width,
366                                                           uint32_t height,
367                                                           int32_t /*format*/,
368                                                           int32_t dataspace) {
369   supported(__func__);
370   std::pair<uint32_t, uint32_t> min = drm_->min_resolution();
371   std::pair<uint32_t, uint32_t> max = drm_->max_resolution();
372 
373   if (width < min.first || height < min.second)
374     return HWC2::Error::Unsupported;
375 
376   if (width > max.first || height > max.second)
377     return HWC2::Error::Unsupported;
378 
379   if (dataspace != HAL_DATASPACE_UNKNOWN &&
380       dataspace != HAL_DATASPACE_STANDARD_UNSPECIFIED)
381     return HWC2::Error::Unsupported;
382 
383   // TODO: Validate format can be handled by either GL or planes
384   return HWC2::Error::None;
385 }
386 
GetColorModes(uint32_t * num_modes,int32_t * modes)387 HWC2::Error DrmHwcTwo::HwcDisplay::GetColorModes(uint32_t *num_modes,
388                                                  int32_t *modes) {
389   supported(__func__);
390   if (!modes)
391     *num_modes = 1;
392 
393   if (modes)
394     *modes = HAL_COLOR_MODE_NATIVE;
395 
396   return HWC2::Error::None;
397 }
398 
GetDisplayAttribute(hwc2_config_t config,int32_t attribute_in,int32_t * value)399 HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
400                                                        int32_t attribute_in,
401                                                        int32_t *value) {
402   supported(__func__);
403   auto mode = std::find_if(connector_->modes().begin(),
404                            connector_->modes().end(),
405                            [config](DrmMode const &m) {
406                              return m.id() == config;
407                            });
408   if (mode == connector_->modes().end()) {
409     ALOGE("Could not find active mode for %d", config);
410     return HWC2::Error::BadConfig;
411   }
412 
413   static const int32_t kUmPerInch = 25400;
414   uint32_t mm_width = connector_->mm_width();
415   uint32_t mm_height = connector_->mm_height();
416   auto attribute = static_cast<HWC2::Attribute>(attribute_in);
417   switch (attribute) {
418     case HWC2::Attribute::Width:
419       *value = mode->h_display();
420       break;
421     case HWC2::Attribute::Height:
422       *value = mode->v_display();
423       break;
424     case HWC2::Attribute::VsyncPeriod:
425       // in nanoseconds
426       *value = 1000 * 1000 * 1000 / mode->v_refresh();
427       break;
428     case HWC2::Attribute::DpiX:
429       // Dots per 1000 inches
430       *value = mm_width ? (mode->h_display() * kUmPerInch) / mm_width : -1;
431       break;
432     case HWC2::Attribute::DpiY:
433       // Dots per 1000 inches
434       *value = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1;
435       break;
436     default:
437       *value = -1;
438       return HWC2::Error::BadConfig;
439   }
440   return HWC2::Error::None;
441 }
442 
GetDisplayConfigs(uint32_t * num_configs,hwc2_config_t * configs)443 HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
444                                                      hwc2_config_t *configs) {
445   supported(__func__);
446   // Since this callback is normally invoked twice (once to get the count, and
447   // once to populate configs), we don't really want to read the edid
448   // redundantly. Instead, only update the modes on the first invocation. While
449   // it's possible this will result in stale modes, it'll all come out in the
450   // wash when we try to set the active config later.
451   if (!configs) {
452     int ret = connector_->UpdateModes();
453     if (ret) {
454       ALOGE("Failed to update display modes %d", ret);
455       return HWC2::Error::BadDisplay;
456     }
457   }
458 
459   // Since the upper layers only look at vactive/hactive/refresh, height and
460   // width, it doesn't differentiate interlaced from progressive and other
461   // similar modes. Depending on the order of modes we return to SF, it could
462   // end up choosing a suboptimal configuration and dropping the preferred
463   // mode. To workaround this, don't offer interlaced modes to SF if there is
464   // at least one non-interlaced alternative and only offer a single WxH@R
465   // mode with at least the prefered mode from in DrmConnector::UpdateModes()
466 
467   // TODO: Remove the following block of code until AOSP handles all modes
468   std::vector<DrmMode> sel_modes;
469 
470   // Add the preferred mode first to be sure it's not dropped
471   auto mode = std::find_if(connector_->modes().begin(),
472                            connector_->modes().end(), [&](DrmMode const &m) {
473                              return m.id() ==
474                                     connector_->get_preferred_mode_id();
475                            });
476   if (mode != connector_->modes().end())
477     sel_modes.push_back(*mode);
478 
479   // Add the active mode if different from preferred mode
480   if (connector_->active_mode().id() != connector_->get_preferred_mode_id())
481     sel_modes.push_back(connector_->active_mode());
482 
483   // Cycle over the modes and filter out "similar" modes, keeping only the
484   // first ones in the order given by DRM (from CEA ids and timings order)
485   for (const DrmMode &mode : connector_->modes()) {
486     // TODO: Remove this when 3D Attributes are in AOSP
487     if (mode.flags() & DRM_MODE_FLAG_3D_MASK)
488       continue;
489 
490     // TODO: Remove this when the Interlaced attribute is in AOSP
491     if (mode.flags() & DRM_MODE_FLAG_INTERLACE) {
492       auto m = std::find_if(connector_->modes().begin(),
493                             connector_->modes().end(),
494                             [&mode](DrmMode const &m) {
495                               return !(m.flags() & DRM_MODE_FLAG_INTERLACE) &&
496                                      m.h_display() == mode.h_display() &&
497                                      m.v_display() == mode.v_display();
498                             });
499       if (m == connector_->modes().end())
500         sel_modes.push_back(mode);
501 
502       continue;
503     }
504 
505     // Search for a similar WxH@R mode in the filtered list and drop it if
506     // another mode with the same WxH@R has already been selected
507     // TODO: Remove this when AOSP handles duplicates modes
508     auto m = std::find_if(sel_modes.begin(), sel_modes.end(),
509                           [&mode](DrmMode const &m) {
510                             return m.h_display() == mode.h_display() &&
511                                    m.v_display() == mode.v_display() &&
512                                    m.v_refresh() == mode.v_refresh();
513                           });
514     if (m == sel_modes.end())
515       sel_modes.push_back(mode);
516   }
517 
518   auto num_modes = static_cast<uint32_t>(sel_modes.size());
519   if (!configs) {
520     *num_configs = num_modes;
521     return HWC2::Error::None;
522   }
523 
524   uint32_t idx = 0;
525   for (const DrmMode &mode : sel_modes) {
526     if (idx >= *num_configs)
527       break;
528     configs[idx++] = mode.id();
529   }
530   *num_configs = idx;
531   return HWC2::Error::None;
532 }
533 
GetDisplayName(uint32_t * size,char * name)534 HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
535   supported(__func__);
536   std::ostringstream stream;
537   stream << "display-" << connector_->id();
538   std::string string = stream.str();
539   size_t length = string.length();
540   if (!name) {
541     *size = length;
542     return HWC2::Error::None;
543   }
544 
545   *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
546   strncpy(name, string.c_str(), *size);
547   return HWC2::Error::None;
548 }
549 
GetDisplayRequests(int32_t * display_requests,uint32_t * num_elements,hwc2_layer_t * layers,int32_t * layer_requests)550 HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayRequests(int32_t *display_requests,
551                                                       uint32_t *num_elements,
552                                                       hwc2_layer_t *layers,
553                                                       int32_t *layer_requests) {
554   supported(__func__);
555   // TODO: I think virtual display should request
556   //      HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
557   unsupported(__func__, display_requests, num_elements, layers, layer_requests);
558   *num_elements = 0;
559   return HWC2::Error::None;
560 }
561 
GetDisplayType(int32_t * type)562 HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayType(int32_t *type) {
563   supported(__func__);
564   *type = static_cast<int32_t>(type_);
565   return HWC2::Error::None;
566 }
567 
GetDozeSupport(int32_t * support)568 HWC2::Error DrmHwcTwo::HwcDisplay::GetDozeSupport(int32_t *support) {
569   supported(__func__);
570   *support = 0;
571   return HWC2::Error::None;
572 }
573 
GetHdrCapabilities(uint32_t * num_types,int32_t *,float *,float *,float *)574 HWC2::Error DrmHwcTwo::HwcDisplay::GetHdrCapabilities(
575     uint32_t *num_types, int32_t * /*types*/, float * /*max_luminance*/,
576     float * /*max_average_luminance*/, float * /*min_luminance*/) {
577   supported(__func__);
578   *num_types = 0;
579   return HWC2::Error::None;
580 }
581 
GetReleaseFences(uint32_t * num_elements,hwc2_layer_t * layers,int32_t * fences)582 HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements,
583                                                     hwc2_layer_t *layers,
584                                                     int32_t *fences) {
585   supported(__func__);
586   uint32_t num_layers = 0;
587 
588   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
589     ++num_layers;
590     if (layers == NULL || fences == NULL) {
591       continue;
592     } else if (num_layers > *num_elements) {
593       ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
594       return HWC2::Error::None;
595     }
596 
597     layers[num_layers - 1] = l.first;
598     fences[num_layers - 1] = l.second.take_release_fence();
599   }
600   *num_elements = num_layers;
601   return HWC2::Error::None;
602 }
603 
AddFenceToPresentFence(int fd)604 void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(int fd) {
605   if (fd < 0)
606     return;
607 
608   if (present_fence_.get() >= 0) {
609     int old_fence = present_fence_.get();
610     present_fence_.Set(sync_merge("dc_present", old_fence, fd));
611     close(fd);
612   } else {
613     present_fence_.Set(fd);
614   }
615 }
616 
HardwareSupportsLayerType(HWC2::Composition comp_type)617 bool DrmHwcTwo::HwcDisplay::HardwareSupportsLayerType(
618     HWC2::Composition comp_type) {
619   return comp_type == HWC2::Composition::Device ||
620          comp_type == HWC2::Composition::Cursor;
621 }
622 
CreateComposition(bool test)623 HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) {
624   std::vector<DrmCompositionDisplayLayersMap> layers_map;
625   layers_map.emplace_back();
626   DrmCompositionDisplayLayersMap &map = layers_map.back();
627 
628   map.display = static_cast<int>(handle_);
629   map.geometry_changed = true;  // TODO: Fix this
630 
631   // order the layers by z-order
632   bool use_client_layer = false;
633   uint32_t client_z_order = UINT32_MAX;
634   std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
635   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
636     switch (l.second.validated_type()) {
637       case HWC2::Composition::Device:
638         z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
639         break;
640       case HWC2::Composition::Client:
641         // Place it at the z_order of the lowest client layer
642         use_client_layer = true;
643         client_z_order = std::min(client_z_order, l.second.z_order());
644         break;
645       default:
646         continue;
647     }
648   }
649   if (use_client_layer)
650     z_map.emplace(std::make_pair(client_z_order, &client_layer_));
651 
652   if (z_map.empty())
653     return HWC2::Error::BadLayer;
654 
655   // now that they're ordered by z, add them to the composition
656   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
657     DrmHwcLayer layer;
658     l.second->PopulateDrmLayer(&layer);
659     int ret = layer.ImportBuffer(importer_.get());
660     if (ret) {
661       ALOGE("Failed to import layer, ret=%d", ret);
662       return HWC2::Error::NoResources;
663     }
664     map.layers.emplace_back(std::move(layer));
665   }
666 
667   std::unique_ptr<DrmDisplayComposition> composition = compositor_
668                                                            .CreateComposition();
669   composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
670 
671   // TODO: Don't always assume geometry changed
672   int ret = composition->SetLayers(map.layers.data(), map.layers.size(), true);
673   if (ret) {
674     ALOGE("Failed to set layers in the composition ret=%d", ret);
675     return HWC2::Error::BadLayer;
676   }
677 
678   std::vector<DrmPlane *> primary_planes(primary_planes_);
679   std::vector<DrmPlane *> overlay_planes(overlay_planes_);
680   ret = composition->Plan(&primary_planes, &overlay_planes);
681   if (ret) {
682     ALOGE("Failed to plan the composition ret=%d", ret);
683     return HWC2::Error::BadConfig;
684   }
685 
686   // Disable the planes we're not using
687   for (auto i = primary_planes.begin(); i != primary_planes.end();) {
688     composition->AddPlaneDisable(*i);
689     i = primary_planes.erase(i);
690   }
691   for (auto i = overlay_planes.begin(); i != overlay_planes.end();) {
692     composition->AddPlaneDisable(*i);
693     i = overlay_planes.erase(i);
694   }
695 
696   if (test) {
697     ret = compositor_.TestComposition(composition.get());
698   } else {
699     ret = compositor_.ApplyComposition(std::move(composition));
700     AddFenceToPresentFence(compositor_.TakeOutFence());
701   }
702   if (ret) {
703     if (!test)
704       ALOGE("Failed to apply the frame composition ret=%d", ret);
705     return HWC2::Error::BadParameter;
706   }
707   return HWC2::Error::None;
708 }
709 
PresentDisplay(int32_t * present_fence)710 HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) {
711   supported(__func__);
712   HWC2::Error ret;
713 
714   ++total_stats_.total_frames_;
715 
716   ret = CreateComposition(false);
717   if (ret != HWC2::Error::None)
718     ++total_stats_.failed_kms_present_;
719 
720   if (ret == HWC2::Error::BadLayer) {
721     // Can we really have no client or device layers?
722     *present_fence = -1;
723     return HWC2::Error::None;
724   }
725   if (ret != HWC2::Error::None)
726     return ret;
727 
728   *present_fence = present_fence_.Release();
729 
730   ++frame_no_;
731   return HWC2::Error::None;
732 }
733 
SetActiveConfig(hwc2_config_t config)734 HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) {
735   supported(__func__);
736   auto mode = std::find_if(connector_->modes().begin(),
737                            connector_->modes().end(),
738                            [config](DrmMode const &m) {
739                              return m.id() == config;
740                            });
741   if (mode == connector_->modes().end()) {
742     ALOGE("Could not find active mode for %d", config);
743     return HWC2::Error::BadConfig;
744   }
745 
746   std::unique_ptr<DrmDisplayComposition> composition = compositor_
747                                                            .CreateComposition();
748   composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
749   int ret = composition->SetDisplayMode(*mode);
750   ret = compositor_.ApplyComposition(std::move(composition));
751   if (ret) {
752     ALOGE("Failed to queue dpms composition on %d", ret);
753     return HWC2::Error::BadConfig;
754   }
755 
756   connector_->set_active_mode(*mode);
757 
758   // Setup the client layer's dimensions
759   hwc_rect_t display_frame = {.left = 0,
760                               .top = 0,
761                               .right = static_cast<int>(mode->h_display()),
762                               .bottom = static_cast<int>(mode->v_display())};
763   client_layer_.SetLayerDisplayFrame(display_frame);
764   hwc_frect_t source_crop = {.left = 0.0f,
765                              .top = 0.0f,
766                              .right = mode->h_display() + 0.0f,
767                              .bottom = mode->v_display() + 0.0f};
768   client_layer_.SetLayerSourceCrop(source_crop);
769 
770   return HWC2::Error::None;
771 }
772 
SetClientTarget(buffer_handle_t target,int32_t acquire_fence,int32_t dataspace,hwc_region_t)773 HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target,
774                                                    int32_t acquire_fence,
775                                                    int32_t dataspace,
776                                                    hwc_region_t /*damage*/) {
777   supported(__func__);
778   UniqueFd uf(acquire_fence);
779 
780   client_layer_.set_buffer(target);
781   client_layer_.set_acquire_fence(uf.get());
782   client_layer_.SetLayerDataspace(dataspace);
783   return HWC2::Error::None;
784 }
785 
SetColorMode(int32_t mode)786 HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) {
787   supported(__func__);
788 
789   if (mode != HAL_COLOR_MODE_NATIVE)
790     return HWC2::Error::BadParameter;
791 
792   color_mode_ = mode;
793   return HWC2::Error::None;
794 }
795 
SetColorTransform(const float * matrix,int32_t hint)796 HWC2::Error DrmHwcTwo::HwcDisplay::SetColorTransform(const float *matrix,
797                                                      int32_t hint) {
798   supported(__func__);
799   if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
800       hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
801     return HWC2::Error::BadParameter;
802 
803   if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
804     return HWC2::Error::BadParameter;
805 
806   color_transform_hint_ = static_cast<android_color_transform_t>(hint);
807   if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
808     std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin());
809 
810   return HWC2::Error::None;
811 }
812 
SetOutputBuffer(buffer_handle_t buffer,int32_t release_fence)813 HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
814                                                    int32_t release_fence) {
815   supported(__func__);
816   // TODO: Need virtual display support
817   return unsupported(__func__, buffer, release_fence);
818 }
819 
SetPowerMode(int32_t mode_in)820 HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) {
821   supported(__func__);
822   uint64_t dpms_value = 0;
823   auto mode = static_cast<HWC2::PowerMode>(mode_in);
824   switch (mode) {
825     case HWC2::PowerMode::Off:
826       dpms_value = DRM_MODE_DPMS_OFF;
827       break;
828     case HWC2::PowerMode::On:
829       dpms_value = DRM_MODE_DPMS_ON;
830       break;
831     case HWC2::PowerMode::Doze:
832     case HWC2::PowerMode::DozeSuspend:
833       return HWC2::Error::Unsupported;
834     default:
835       ALOGI("Power mode %d is unsupported\n", mode);
836       return HWC2::Error::BadParameter;
837   };
838 
839   std::unique_ptr<DrmDisplayComposition> composition = compositor_
840                                                            .CreateComposition();
841   composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
842   composition->SetDpmsMode(dpms_value);
843   int ret = compositor_.ApplyComposition(std::move(composition));
844   if (ret) {
845     ALOGE("Failed to apply the dpms composition ret=%d", ret);
846     return HWC2::Error::BadParameter;
847   }
848   return HWC2::Error::None;
849 }
850 
SetVsyncEnabled(int32_t enabled)851 HWC2::Error DrmHwcTwo::HwcDisplay::SetVsyncEnabled(int32_t enabled) {
852   supported(__func__);
853   vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled);
854   return HWC2::Error::None;
855 }
856 
CalcPixOps(std::map<uint32_t,DrmHwcTwo::HwcLayer * > & z_map,size_t first_z,size_t size)857 uint32_t DrmHwcTwo::HwcDisplay::CalcPixOps(
858     std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t first_z,
859     size_t size) {
860   uint32_t pixops = 0;
861   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
862     if (l.first >= first_z && l.first < first_z + size) {
863       hwc_rect_t df = l.second->display_frame();
864       pixops += (df.right - df.left) * (df.bottom - df.top);
865     }
866   }
867   return pixops;
868 }
869 
MarkValidated(std::map<uint32_t,DrmHwcTwo::HwcLayer * > & z_map,size_t client_first_z,size_t client_size)870 void DrmHwcTwo::HwcDisplay::MarkValidated(
871     std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t client_first_z,
872     size_t client_size) {
873   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
874     if (l.first >= client_first_z && l.first < client_first_z + client_size)
875       l.second->set_validated_type(HWC2::Composition::Client);
876     else
877       l.second->set_validated_type(HWC2::Composition::Device);
878   }
879 }
880 
ValidateDisplay(uint32_t * num_types,uint32_t * num_requests)881 HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
882                                                    uint32_t *num_requests) {
883   supported(__func__);
884   *num_types = 0;
885   *num_requests = 0;
886   size_t avail_planes = primary_planes_.size() + overlay_planes_.size();
887 
888   /*
889    * If more layers then planes, save one plane
890    * for client composited layers
891    */
892   if (avail_planes < layers_.size())
893     avail_planes--;
894 
895   std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
896   for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
897     z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
898 
899   uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0;
900 
901   int client_start = -1, client_size = 0;
902 
903   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
904     if (!HardwareSupportsLayerType(l.second->sf_type()) ||
905         !importer_->CanImportBuffer(l.second->buffer()) ||
906         color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY) {
907       if (client_start < 0)
908         client_start = l.first;
909       client_size = (l.first - client_start) + 1;
910     }
911   }
912 
913   int extra_client = (z_map.size() - client_size) - avail_planes;
914   if (extra_client > 0) {
915     int start = 0, steps;
916     if (client_size != 0) {
917       int prepend = std::min(client_start, extra_client);
918       int append = std::min(int(z_map.size() - (client_start + client_size)),
919                             extra_client);
920       start = client_start - prepend;
921       client_size += extra_client;
922       steps = 1 + std::min(std::min(append, prepend),
923                            int(z_map.size()) - (start + client_size));
924     } else {
925       client_size = extra_client;
926       steps = 1 + z_map.size() - extra_client;
927     }
928 
929     gpu_pixops = INT_MAX;
930     for (int i = 0; i < steps; i++) {
931       uint32_t po = CalcPixOps(z_map, start + i, client_size);
932       if (po < gpu_pixops) {
933         gpu_pixops = po;
934         client_start = start + i;
935       }
936     }
937   }
938 
939   MarkValidated(z_map, client_start, client_size);
940 
941   if (CreateComposition(true) != HWC2::Error::None) {
942     ++total_stats_.failed_kms_validate_;
943     gpu_pixops = total_pixops;
944     client_size = z_map.size();
945     MarkValidated(z_map, 0, client_size);
946   }
947 
948   *num_types = client_size;
949 
950   total_stats_.gpu_pixops_ += gpu_pixops;
951   total_stats_.total_pixops_ += total_pixops;
952 
953   return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
954 }
955 
SetCursorPosition(int32_t x,int32_t y)956 HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
957   supported(__func__);
958   cursor_x_ = x;
959   cursor_y_ = y;
960   return HWC2::Error::None;
961 }
962 
SetLayerBlendMode(int32_t mode)963 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) {
964   supported(__func__);
965   blending_ = static_cast<HWC2::BlendMode>(mode);
966   return HWC2::Error::None;
967 }
968 
SetLayerBuffer(buffer_handle_t buffer,int32_t acquire_fence)969 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
970                                                 int32_t acquire_fence) {
971   supported(__func__);
972   UniqueFd uf(acquire_fence);
973 
974   // The buffer and acquire_fence are handled elsewhere
975   if (sf_type_ == HWC2::Composition::Client ||
976       sf_type_ == HWC2::Composition::Sideband ||
977       sf_type_ == HWC2::Composition::SolidColor)
978     return HWC2::Error::None;
979 
980   set_buffer(buffer);
981   set_acquire_fence(uf.get());
982   return HWC2::Error::None;
983 }
984 
SetLayerColor(hwc_color_t color)985 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) {
986   // TODO: Put to client composition here?
987   supported(__func__);
988   layer_color_ = color;
989   return HWC2::Error::None;
990 }
991 
SetLayerCompositionType(int32_t type)992 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerCompositionType(int32_t type) {
993   sf_type_ = static_cast<HWC2::Composition>(type);
994   return HWC2::Error::None;
995 }
996 
SetLayerDataspace(int32_t dataspace)997 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDataspace(int32_t dataspace) {
998   supported(__func__);
999   dataspace_ = static_cast<android_dataspace_t>(dataspace);
1000   return HWC2::Error::None;
1001 }
1002 
SetLayerDisplayFrame(hwc_rect_t frame)1003 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
1004   supported(__func__);
1005   display_frame_ = frame;
1006   return HWC2::Error::None;
1007 }
1008 
SetLayerPlaneAlpha(float alpha)1009 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerPlaneAlpha(float alpha) {
1010   supported(__func__);
1011   alpha_ = alpha;
1012   return HWC2::Error::None;
1013 }
1014 
SetLayerSidebandStream(const native_handle_t * stream)1015 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSidebandStream(
1016     const native_handle_t *stream) {
1017   supported(__func__);
1018   // TODO: We don't support sideband
1019   return unsupported(__func__, stream);
1020 }
1021 
SetLayerSourceCrop(hwc_frect_t crop)1022 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) {
1023   supported(__func__);
1024   source_crop_ = crop;
1025   return HWC2::Error::None;
1026 }
1027 
SetLayerSurfaceDamage(hwc_region_t damage)1028 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
1029   supported(__func__);
1030   // TODO: We don't use surface damage, marking as unsupported
1031   unsupported(__func__, damage);
1032   return HWC2::Error::None;
1033 }
1034 
SetLayerTransform(int32_t transform)1035 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t transform) {
1036   supported(__func__);
1037   transform_ = static_cast<HWC2::Transform>(transform);
1038   return HWC2::Error::None;
1039 }
1040 
SetLayerVisibleRegion(hwc_region_t visible)1041 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerVisibleRegion(hwc_region_t visible) {
1042   supported(__func__);
1043   // TODO: We don't use this information, marking as unsupported
1044   unsupported(__func__, visible);
1045   return HWC2::Error::None;
1046 }
1047 
SetLayerZOrder(uint32_t order)1048 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerZOrder(uint32_t order) {
1049   supported(__func__);
1050   z_order_ = order;
1051   return HWC2::Error::None;
1052 }
1053 
PopulateDrmLayer(DrmHwcLayer * layer)1054 void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) {
1055   supported(__func__);
1056   switch (blending_) {
1057     case HWC2::BlendMode::None:
1058       layer->blending = DrmHwcBlending::kNone;
1059       break;
1060     case HWC2::BlendMode::Premultiplied:
1061       layer->blending = DrmHwcBlending::kPreMult;
1062       break;
1063     case HWC2::BlendMode::Coverage:
1064       layer->blending = DrmHwcBlending::kCoverage;
1065       break;
1066     default:
1067       ALOGE("Unknown blending mode b=%d", blending_);
1068       layer->blending = DrmHwcBlending::kNone;
1069       break;
1070   }
1071 
1072   OutputFd release_fence = release_fence_output();
1073 
1074   layer->sf_handle = buffer_;
1075   layer->acquire_fence = acquire_fence_.Release();
1076   layer->release_fence = std::move(release_fence);
1077   layer->SetDisplayFrame(display_frame_);
1078   layer->alpha = static_cast<uint16_t>(65535.0f * alpha_ + 0.5f);
1079   layer->SetSourceCrop(source_crop_);
1080   layer->SetTransform(static_cast<int32_t>(transform_));
1081 }
1082 
HandleDisplayHotplug(hwc2_display_t displayid,int state)1083 void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
1084   auto cb = callbacks_.find(HWC2::Callback::Hotplug);
1085   if (cb == callbacks_.end())
1086     return;
1087 
1088   auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(cb->second.func);
1089   hotplug(cb->second.data, displayid,
1090           (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
1091                                        : HWC2_CONNECTION_DISCONNECTED));
1092 }
1093 
HandleInitialHotplugState(DrmDevice * drmDevice)1094 void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
1095   for (auto &conn : drmDevice->connectors()) {
1096     if (conn->state() != DRM_MODE_CONNECTED)
1097       continue;
1098     HandleDisplayHotplug(conn->display(), conn->state());
1099   }
1100 }
1101 
HandleEvent(uint64_t timestamp_us)1102 void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) {
1103   for (auto &conn : drm_->connectors()) {
1104     drmModeConnection old_state = conn->state();
1105     drmModeConnection cur_state = conn->UpdateModes()
1106                                       ? DRM_MODE_UNKNOWNCONNECTION
1107                                       : conn->state();
1108 
1109     if (cur_state == old_state)
1110       continue;
1111 
1112     ALOGI("%s event @%" PRIu64 " for connector %u on display %d",
1113           cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
1114           conn->id(), conn->display());
1115 
1116     int display_id = conn->display();
1117     if (cur_state == DRM_MODE_CONNECTED) {
1118       auto &display = hwc2_->displays_.at(display_id);
1119       display.ChosePreferredConfig();
1120     } else {
1121       auto &display = hwc2_->displays_.at(display_id);
1122       display.ClearDisplay();
1123     }
1124 
1125     hwc2_->HandleDisplayHotplug(display_id, cur_state);
1126   }
1127 }
1128 
1129 // static
HookDevClose(hw_device_t *)1130 int DrmHwcTwo::HookDevClose(hw_device_t * /*dev*/) {
1131   unsupported(__func__);
1132   return 0;
1133 }
1134 
1135 // static
HookDevGetCapabilities(hwc2_device_t *,uint32_t * out_count,int32_t *)1136 void DrmHwcTwo::HookDevGetCapabilities(hwc2_device_t * /*dev*/,
1137                                        uint32_t *out_count,
1138                                        int32_t * /*out_capabilities*/) {
1139   supported(__func__);
1140   *out_count = 0;
1141 }
1142 
1143 // static
HookDevGetFunction(struct hwc2_device *,int32_t descriptor)1144 hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction(
1145     struct hwc2_device * /*dev*/, int32_t descriptor) {
1146   supported(__func__);
1147   auto func = static_cast<HWC2::FunctionDescriptor>(descriptor);
1148   switch (func) {
1149     // Device functions
1150     case HWC2::FunctionDescriptor::CreateVirtualDisplay:
1151       return ToHook<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
1152           DeviceHook<int32_t, decltype(&DrmHwcTwo::CreateVirtualDisplay),
1153                      &DrmHwcTwo::CreateVirtualDisplay, uint32_t, uint32_t,
1154                      int32_t *, hwc2_display_t *>);
1155     case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
1156       return ToHook<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
1157           DeviceHook<int32_t, decltype(&DrmHwcTwo::DestroyVirtualDisplay),
1158                      &DrmHwcTwo::DestroyVirtualDisplay, hwc2_display_t>);
1159     case HWC2::FunctionDescriptor::Dump:
1160       return ToHook<HWC2_PFN_DUMP>(
1161           DeviceHook<void, decltype(&DrmHwcTwo::Dump), &DrmHwcTwo::Dump,
1162                      uint32_t *, char *>);
1163     case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
1164       return ToHook<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
1165           DeviceHook<uint32_t, decltype(&DrmHwcTwo::GetMaxVirtualDisplayCount),
1166                      &DrmHwcTwo::GetMaxVirtualDisplayCount>);
1167     case HWC2::FunctionDescriptor::RegisterCallback:
1168       return ToHook<HWC2_PFN_REGISTER_CALLBACK>(
1169           DeviceHook<int32_t, decltype(&DrmHwcTwo::RegisterCallback),
1170                      &DrmHwcTwo::RegisterCallback, int32_t,
1171                      hwc2_callback_data_t, hwc2_function_pointer_t>);
1172 
1173     // Display functions
1174     case HWC2::FunctionDescriptor::AcceptDisplayChanges:
1175       return ToHook<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
1176           DisplayHook<decltype(&HwcDisplay::AcceptDisplayChanges),
1177                       &HwcDisplay::AcceptDisplayChanges>);
1178     case HWC2::FunctionDescriptor::CreateLayer:
1179       return ToHook<HWC2_PFN_CREATE_LAYER>(
1180           DisplayHook<decltype(&HwcDisplay::CreateLayer),
1181                       &HwcDisplay::CreateLayer, hwc2_layer_t *>);
1182     case HWC2::FunctionDescriptor::DestroyLayer:
1183       return ToHook<HWC2_PFN_DESTROY_LAYER>(
1184           DisplayHook<decltype(&HwcDisplay::DestroyLayer),
1185                       &HwcDisplay::DestroyLayer, hwc2_layer_t>);
1186     case HWC2::FunctionDescriptor::GetActiveConfig:
1187       return ToHook<HWC2_PFN_GET_ACTIVE_CONFIG>(
1188           DisplayHook<decltype(&HwcDisplay::GetActiveConfig),
1189                       &HwcDisplay::GetActiveConfig, hwc2_config_t *>);
1190     case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
1191       return ToHook<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
1192           DisplayHook<decltype(&HwcDisplay::GetChangedCompositionTypes),
1193                       &HwcDisplay::GetChangedCompositionTypes, uint32_t *,
1194                       hwc2_layer_t *, int32_t *>);
1195     case HWC2::FunctionDescriptor::GetClientTargetSupport:
1196       return ToHook<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
1197           DisplayHook<decltype(&HwcDisplay::GetClientTargetSupport),
1198                       &HwcDisplay::GetClientTargetSupport, uint32_t, uint32_t,
1199                       int32_t, int32_t>);
1200     case HWC2::FunctionDescriptor::GetColorModes:
1201       return ToHook<HWC2_PFN_GET_COLOR_MODES>(
1202           DisplayHook<decltype(&HwcDisplay::GetColorModes),
1203                       &HwcDisplay::GetColorModes, uint32_t *, int32_t *>);
1204     case HWC2::FunctionDescriptor::GetDisplayAttribute:
1205       return ToHook<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
1206           DisplayHook<decltype(&HwcDisplay::GetDisplayAttribute),
1207                       &HwcDisplay::GetDisplayAttribute, hwc2_config_t, int32_t,
1208                       int32_t *>);
1209     case HWC2::FunctionDescriptor::GetDisplayConfigs:
1210       return ToHook<HWC2_PFN_GET_DISPLAY_CONFIGS>(
1211           DisplayHook<decltype(&HwcDisplay::GetDisplayConfigs),
1212                       &HwcDisplay::GetDisplayConfigs, uint32_t *,
1213                       hwc2_config_t *>);
1214     case HWC2::FunctionDescriptor::GetDisplayName:
1215       return ToHook<HWC2_PFN_GET_DISPLAY_NAME>(
1216           DisplayHook<decltype(&HwcDisplay::GetDisplayName),
1217                       &HwcDisplay::GetDisplayName, uint32_t *, char *>);
1218     case HWC2::FunctionDescriptor::GetDisplayRequests:
1219       return ToHook<HWC2_PFN_GET_DISPLAY_REQUESTS>(
1220           DisplayHook<decltype(&HwcDisplay::GetDisplayRequests),
1221                       &HwcDisplay::GetDisplayRequests, int32_t *, uint32_t *,
1222                       hwc2_layer_t *, int32_t *>);
1223     case HWC2::FunctionDescriptor::GetDisplayType:
1224       return ToHook<HWC2_PFN_GET_DISPLAY_TYPE>(
1225           DisplayHook<decltype(&HwcDisplay::GetDisplayType),
1226                       &HwcDisplay::GetDisplayType, int32_t *>);
1227     case HWC2::FunctionDescriptor::GetDozeSupport:
1228       return ToHook<HWC2_PFN_GET_DOZE_SUPPORT>(
1229           DisplayHook<decltype(&HwcDisplay::GetDozeSupport),
1230                       &HwcDisplay::GetDozeSupport, int32_t *>);
1231     case HWC2::FunctionDescriptor::GetHdrCapabilities:
1232       return ToHook<HWC2_PFN_GET_HDR_CAPABILITIES>(
1233           DisplayHook<decltype(&HwcDisplay::GetHdrCapabilities),
1234                       &HwcDisplay::GetHdrCapabilities, uint32_t *, int32_t *,
1235                       float *, float *, float *>);
1236     case HWC2::FunctionDescriptor::GetReleaseFences:
1237       return ToHook<HWC2_PFN_GET_RELEASE_FENCES>(
1238           DisplayHook<decltype(&HwcDisplay::GetReleaseFences),
1239                       &HwcDisplay::GetReleaseFences, uint32_t *, hwc2_layer_t *,
1240                       int32_t *>);
1241     case HWC2::FunctionDescriptor::PresentDisplay:
1242       return ToHook<HWC2_PFN_PRESENT_DISPLAY>(
1243           DisplayHook<decltype(&HwcDisplay::PresentDisplay),
1244                       &HwcDisplay::PresentDisplay, int32_t *>);
1245     case HWC2::FunctionDescriptor::SetActiveConfig:
1246       return ToHook<HWC2_PFN_SET_ACTIVE_CONFIG>(
1247           DisplayHook<decltype(&HwcDisplay::SetActiveConfig),
1248                       &HwcDisplay::SetActiveConfig, hwc2_config_t>);
1249     case HWC2::FunctionDescriptor::SetClientTarget:
1250       return ToHook<HWC2_PFN_SET_CLIENT_TARGET>(
1251           DisplayHook<decltype(&HwcDisplay::SetClientTarget),
1252                       &HwcDisplay::SetClientTarget, buffer_handle_t, int32_t,
1253                       int32_t, hwc_region_t>);
1254     case HWC2::FunctionDescriptor::SetColorMode:
1255       return ToHook<HWC2_PFN_SET_COLOR_MODE>(
1256           DisplayHook<decltype(&HwcDisplay::SetColorMode),
1257                       &HwcDisplay::SetColorMode, int32_t>);
1258     case HWC2::FunctionDescriptor::SetColorTransform:
1259       return ToHook<HWC2_PFN_SET_COLOR_TRANSFORM>(
1260           DisplayHook<decltype(&HwcDisplay::SetColorTransform),
1261                       &HwcDisplay::SetColorTransform, const float *, int32_t>);
1262     case HWC2::FunctionDescriptor::SetOutputBuffer:
1263       return ToHook<HWC2_PFN_SET_OUTPUT_BUFFER>(
1264           DisplayHook<decltype(&HwcDisplay::SetOutputBuffer),
1265                       &HwcDisplay::SetOutputBuffer, buffer_handle_t, int32_t>);
1266     case HWC2::FunctionDescriptor::SetPowerMode:
1267       return ToHook<HWC2_PFN_SET_POWER_MODE>(
1268           DisplayHook<decltype(&HwcDisplay::SetPowerMode),
1269                       &HwcDisplay::SetPowerMode, int32_t>);
1270     case HWC2::FunctionDescriptor::SetVsyncEnabled:
1271       return ToHook<HWC2_PFN_SET_VSYNC_ENABLED>(
1272           DisplayHook<decltype(&HwcDisplay::SetVsyncEnabled),
1273                       &HwcDisplay::SetVsyncEnabled, int32_t>);
1274     case HWC2::FunctionDescriptor::ValidateDisplay:
1275       return ToHook<HWC2_PFN_VALIDATE_DISPLAY>(
1276           DisplayHook<decltype(&HwcDisplay::ValidateDisplay),
1277                       &HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>);
1278 
1279     // Layer functions
1280     case HWC2::FunctionDescriptor::SetCursorPosition:
1281       return ToHook<HWC2_PFN_SET_CURSOR_POSITION>(
1282           LayerHook<decltype(&HwcLayer::SetCursorPosition),
1283                     &HwcLayer::SetCursorPosition, int32_t, int32_t>);
1284     case HWC2::FunctionDescriptor::SetLayerBlendMode:
1285       return ToHook<HWC2_PFN_SET_LAYER_BLEND_MODE>(
1286           LayerHook<decltype(&HwcLayer::SetLayerBlendMode),
1287                     &HwcLayer::SetLayerBlendMode, int32_t>);
1288     case HWC2::FunctionDescriptor::SetLayerBuffer:
1289       return ToHook<HWC2_PFN_SET_LAYER_BUFFER>(
1290           LayerHook<decltype(&HwcLayer::SetLayerBuffer),
1291                     &HwcLayer::SetLayerBuffer, buffer_handle_t, int32_t>);
1292     case HWC2::FunctionDescriptor::SetLayerColor:
1293       return ToHook<HWC2_PFN_SET_LAYER_COLOR>(
1294           LayerHook<decltype(&HwcLayer::SetLayerColor),
1295                     &HwcLayer::SetLayerColor, hwc_color_t>);
1296     case HWC2::FunctionDescriptor::SetLayerCompositionType:
1297       return ToHook<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
1298           LayerHook<decltype(&HwcLayer::SetLayerCompositionType),
1299                     &HwcLayer::SetLayerCompositionType, int32_t>);
1300     case HWC2::FunctionDescriptor::SetLayerDataspace:
1301       return ToHook<HWC2_PFN_SET_LAYER_DATASPACE>(
1302           LayerHook<decltype(&HwcLayer::SetLayerDataspace),
1303                     &HwcLayer::SetLayerDataspace, int32_t>);
1304     case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
1305       return ToHook<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
1306           LayerHook<decltype(&HwcLayer::SetLayerDisplayFrame),
1307                     &HwcLayer::SetLayerDisplayFrame, hwc_rect_t>);
1308     case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
1309       return ToHook<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
1310           LayerHook<decltype(&HwcLayer::SetLayerPlaneAlpha),
1311                     &HwcLayer::SetLayerPlaneAlpha, float>);
1312     case HWC2::FunctionDescriptor::SetLayerSidebandStream:
1313       return ToHook<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
1314           LayerHook<decltype(&HwcLayer::SetLayerSidebandStream),
1315                     &HwcLayer::SetLayerSidebandStream,
1316                     const native_handle_t *>);
1317     case HWC2::FunctionDescriptor::SetLayerSourceCrop:
1318       return ToHook<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
1319           LayerHook<decltype(&HwcLayer::SetLayerSourceCrop),
1320                     &HwcLayer::SetLayerSourceCrop, hwc_frect_t>);
1321     case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
1322       return ToHook<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
1323           LayerHook<decltype(&HwcLayer::SetLayerSurfaceDamage),
1324                     &HwcLayer::SetLayerSurfaceDamage, hwc_region_t>);
1325     case HWC2::FunctionDescriptor::SetLayerTransform:
1326       return ToHook<HWC2_PFN_SET_LAYER_TRANSFORM>(
1327           LayerHook<decltype(&HwcLayer::SetLayerTransform),
1328                     &HwcLayer::SetLayerTransform, int32_t>);
1329     case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
1330       return ToHook<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
1331           LayerHook<decltype(&HwcLayer::SetLayerVisibleRegion),
1332                     &HwcLayer::SetLayerVisibleRegion, hwc_region_t>);
1333     case HWC2::FunctionDescriptor::SetLayerZOrder:
1334       return ToHook<HWC2_PFN_SET_LAYER_Z_ORDER>(
1335           LayerHook<decltype(&HwcLayer::SetLayerZOrder),
1336                     &HwcLayer::SetLayerZOrder, uint32_t>);
1337     case HWC2::FunctionDescriptor::Invalid:
1338     default:
1339       return NULL;
1340   }
1341 }
1342 
1343 // static
HookDevOpen(const struct hw_module_t * module,const char * name,struct hw_device_t ** dev)1344 int DrmHwcTwo::HookDevOpen(const struct hw_module_t *module, const char *name,
1345                            struct hw_device_t **dev) {
1346   supported(__func__);
1347   if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
1348     ALOGE("Invalid module name- %s", name);
1349     return -EINVAL;
1350   }
1351 
1352   std::unique_ptr<DrmHwcTwo> ctx(new DrmHwcTwo());
1353   if (!ctx) {
1354     ALOGE("Failed to allocate DrmHwcTwo");
1355     return -ENOMEM;
1356   }
1357 
1358   HWC2::Error err = ctx->Init();
1359   if (err != HWC2::Error::None) {
1360     ALOGE("Failed to initialize DrmHwcTwo err=%d\n", err);
1361     return -EINVAL;
1362   }
1363 
1364   ctx->common.module = const_cast<hw_module_t *>(module);
1365   *dev = &ctx->common;
1366   ctx.release();
1367   return 0;
1368 }
1369 }  // namespace android
1370 
1371 static struct hw_module_methods_t hwc2_module_methods = {
1372     .open = android::DrmHwcTwo::HookDevOpen,
1373 };
1374 
1375 hw_module_t HAL_MODULE_INFO_SYM = {
1376     .tag = HARDWARE_MODULE_TAG,
1377     .module_api_version = HARDWARE_MODULE_API_VERSION(2, 0),
1378     .id = HWC_HARDWARE_MODULE_ID,
1379     .name = "DrmHwcTwo module",
1380     .author = "The Android Open Source Project",
1381     .methods = &hwc2_module_methods,
1382     .dso = NULL,
1383     .reserved = {0},
1384 };
1385