blob: 15fa324ea3624f4011695a28a6094cbe2eb76af0 [file] [log] [blame]
Sean Pauled2ec4b2016-03-10 15:35:40 -05001/*
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
Roman Stratiienko13cc3662020-08-29 21:35:39 +030020#include "DrmHwcTwo.h"
Sean Pauled2ec4b2016-03-10 15:35:40 -050021
Sean Paulac874152016-03-10 16:00:26 -050022#include <cutils/properties.h>
23#include <hardware/hardware.h>
Sean Pauled2ec4b2016-03-10 15:35:40 -050024#include <hardware/hwcomposer2.h>
Roman Stratiienkoaa3cd542020-08-29 11:26:16 +030025#include <inttypes.h>
Sean Paulf72cccd2018-08-27 13:59:08 -040026#include <log/log.h>
Sean Pauled2ec4b2016-03-10 15:35:40 -050027
Roman Stratiienkoaa3cd542020-08-29 11:26:16 +030028#include <string>
29
Roman Stratiienko13cc3662020-08-29 21:35:39 +030030#include "backend/BackendManager.h"
31#include "compositor/DrmDisplayComposition.h"
Roman Stratiienkoaa3cd542020-08-29 11:26:16 +030032
Sean Pauled2ec4b2016-03-10 15:35:40 -050033namespace android {
34
Sean Paulac874152016-03-10 16:00:26 -050035class DrmVsyncCallback : public VsyncCallback {
36 public:
37 DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook)
38 : data_(data), hook_(hook) {
39 }
40
41 void Callback(int display, int64_t timestamp) {
42 auto hook = reinterpret_cast<HWC2_PFN_VSYNC>(hook_);
43 hook(data_, display, timestamp);
44 }
45
46 private:
47 hwc2_callback_data_t data_;
48 hwc2_function_pointer_t hook_;
49};
50
Sean Pauled2ec4b2016-03-10 15:35:40 -050051DrmHwcTwo::DrmHwcTwo() {
Sean Paulac874152016-03-10 16:00:26 -050052 common.tag = HARDWARE_DEVICE_TAG;
53 common.version = HWC_DEVICE_API_VERSION_2_0;
Sean Pauled2ec4b2016-03-10 15:35:40 -050054 common.close = HookDevClose;
55 getCapabilities = HookDevGetCapabilities;
56 getFunction = HookDevGetFunction;
57}
58
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030059HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
60 HWC2::DisplayType type) {
61 DrmDevice *drm = resource_manager_.GetDrmDevice(displ);
62 std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ);
Alexandru Gheorghec5463582018-03-27 15:52:02 +010063 if (!drm || !importer) {
64 ALOGE("Failed to get a valid drmresource and importer");
Sean Paulac874152016-03-10 16:00:26 -050065 return HWC2::Error::NoResources;
66 }
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030067 displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
Sean Paulf72cccd2018-08-27 13:59:08 -040068 std::forward_as_tuple(&resource_manager_, drm, importer,
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030069 displ, type));
Sean Paulac874152016-03-10 16:00:26 -050070
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030071 DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
Sean Paulac874152016-03-10 16:00:26 -050072 if (!crtc) {
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030073 ALOGE("Failed to get crtc for display %d", static_cast<int>(displ));
Sean Paulac874152016-03-10 16:00:26 -050074 return HWC2::Error::BadDisplay;
75 }
Sean Paulac874152016-03-10 16:00:26 -050076 std::vector<DrmPlane *> display_planes;
Alexandru Gheorghec5463582018-03-27 15:52:02 +010077 for (auto &plane : drm->planes()) {
Sean Paulac874152016-03-10 16:00:26 -050078 if (plane->GetCrtcSupported(*crtc))
79 display_planes.push_back(plane.get());
80 }
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030081 displays_.at(displ).Init(&display_planes);
Sean Paulac874152016-03-10 16:00:26 -050082 return HWC2::Error::None;
83}
84
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +030085HWC2::Error DrmHwcTwo::Init() {
86 int rv = resource_manager_.Init();
87 if (rv) {
88 ALOGE("Can't initialize the resource manager %d", rv);
89 return HWC2::Error::NoResources;
90 }
91
92 HWC2::Error ret = HWC2::Error::None;
93 for (int i = 0; i < resource_manager_.getDisplayCount(); i++) {
94 ret = CreateDisplay(i, HWC2::DisplayType::Physical);
95 if (ret != HWC2::Error::None) {
96 ALOGE("Failed to create display %d with error %d", i, ret);
97 return ret;
98 }
99 }
100
101 auto &drmDevices = resource_manager_.getDrmDevices();
102 for (auto &device : drmDevices) {
103 device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get()));
104 }
105 return ret;
106}
107
Sean Pauled2ec4b2016-03-10 15:35:40 -0500108template <typename... Args>
109static inline HWC2::Error unsupported(char const *func, Args... /*args*/) {
110 ALOGV("Unsupported function: %s", func);
111 return HWC2::Error::Unsupported;
112}
113
Sean Paulac874152016-03-10 16:00:26 -0500114static inline void supported(char const *func) {
115 ALOGV("Supported function: %s", func);
116}
117
Sean Pauled2ec4b2016-03-10 15:35:40 -0500118HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t width, uint32_t height,
119 int32_t *format,
120 hwc2_display_t *display) {
121 // TODO: Implement virtual display
Sean Paulac874152016-03-10 16:00:26 -0500122 return unsupported(__func__, width, height, format, display);
Sean Pauled2ec4b2016-03-10 15:35:40 -0500123}
124
125HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) {
Sean Paulac874152016-03-10 16:00:26 -0500126 // TODO: Implement virtual display
Sean Pauled2ec4b2016-03-10 15:35:40 -0500127 return unsupported(__func__, display);
128}
129
Roman Stratiienko0d1a2cd2019-11-28 17:51:16 +0200130std::string DrmHwcTwo::HwcDisplay::DumpDelta(
131 DrmHwcTwo::HwcDisplay::Stats delta) {
132 if (delta.total_pixops_ == 0)
133 return "No stats yet";
134 double Ratio = 1.0 - double(delta.gpu_pixops_) / double(delta.total_pixops_);
135
136 return (std::stringstream()
137 << " Total frames count: " << delta.total_frames_ << "\n"
138 << " Failed to test commit frames: " << delta.failed_kms_validate_
139 << "\n"
140 << " Failed to commit frames: " << delta.failed_kms_present_ << "\n"
141 << ((delta.failed_kms_present_ > 0)
142 ? " !!! Internal failure, FIX it please\n"
143 : "")
Roman Kovalivskyi9170b312020-02-03 18:13:57 +0200144 << " Flattened frames: " << delta.frames_flattened_ << "\n"
Roman Stratiienko0d1a2cd2019-11-28 17:51:16 +0200145 << " Pixel operations (free units)"
146 << " : [TOTAL: " << delta.total_pixops_
147 << " / GPU: " << delta.gpu_pixops_ << "]\n"
148 << " Composition efficiency: " << Ratio)
149 .str();
150}
151
152std::string DrmHwcTwo::HwcDisplay::Dump() {
153 auto out = (std::stringstream()
154 << "- Display on: " << connector_->name() << "\n"
Roman Kovalivskyi9170b312020-02-03 18:13:57 +0200155 << " Flattening state: " << compositor_.GetFlatteningState()
156 << "\n"
Roman Stratiienko0d1a2cd2019-11-28 17:51:16 +0200157 << "Statistics since system boot:\n"
158 << DumpDelta(total_stats_) << "\n\n"
159 << "Statistics since last dumpsys request:\n"
160 << DumpDelta(total_stats_.minus(prev_stats_)) << "\n\n")
161 .str();
162
163 memcpy(&prev_stats_, &total_stats_, sizeof(Stats));
164 return out;
165}
166
167void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) {
168 supported(__func__);
169
170 if (outBuffer != nullptr) {
171 auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
172 *outSize = static_cast<uint32_t>(copiedBytes);
173 return;
174 }
175
176 std::stringstream output;
177
178 output << "-- drm_hwcomposer --\n\n";
179
180 for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &dp : displays_)
181 output << dp.second.Dump();
182
183 mDumpString = output.str();
184 *outSize = static_cast<uint32_t>(mDumpString.size());
Sean Pauled2ec4b2016-03-10 15:35:40 -0500185}
186
187uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() {
Sean Paulac874152016-03-10 16:00:26 -0500188 // TODO: Implement virtual display
Sean Pauled2ec4b2016-03-10 15:35:40 -0500189 unsupported(__func__);
190 return 0;
191}
192
193HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
Sean Paulac874152016-03-10 16:00:26 -0500194 hwc2_callback_data_t data,
195 hwc2_function_pointer_t function) {
196 supported(__func__);
197 auto callback = static_cast<HWC2::Callback>(descriptor);
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300198
199 if (!function) {
200 callbacks_.erase(callback);
201 return HWC2::Error::None;
202 }
203
Sean Paulac874152016-03-10 16:00:26 -0500204 callbacks_.emplace(callback, HwcCallback(data, function));
205
206 switch (callback) {
207 case HWC2::Callback::Hotplug: {
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300208 auto &drmDevices = resource_manager_.getDrmDevices();
209 for (auto &device : drmDevices)
210 HandleInitialHotplugState(device.get());
Sean Paulac874152016-03-10 16:00:26 -0500211 break;
212 }
Roman Kovalivskyi8fae1562020-01-30 20:20:47 +0200213 case HWC2::Callback::Refresh: {
214 for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
215 displays_)
216 d.second.RegisterRefreshCallback(data, function);
217 break;
218 }
Sean Paulac874152016-03-10 16:00:26 -0500219 case HWC2::Callback::Vsync: {
220 for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
221 displays_)
222 d.second.RegisterVsyncCallback(data, function);
223 break;
224 }
225 default:
226 break;
227 }
228 return HWC2::Error::None;
229}
230
Alexandru Gheorghe6f0030f2018-05-01 17:25:48 +0100231DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
232 DrmDevice *drm,
Sean Paulac874152016-03-10 16:00:26 -0500233 std::shared_ptr<Importer> importer,
Sean Paulac874152016-03-10 16:00:26 -0500234 hwc2_display_t handle, HWC2::DisplayType type)
Alexandru Gheorghe6f0030f2018-05-01 17:25:48 +0100235 : resource_manager_(resource_manager),
236 drm_(drm),
237 importer_(importer),
238 handle_(handle),
Roman Kovalivskyi12b91a32019-12-11 19:09:51 +0200239 type_(type),
240 color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
Sean Paulac874152016-03-10 16:00:26 -0500241 supported(__func__);
Roman Kovalivskyi12b91a32019-12-11 19:09:51 +0200242
243 // clang-format off
244 color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0,
245 0.0, 1.0, 0.0, 0.0,
246 0.0, 0.0, 1.0, 0.0,
247 0.0, 0.0, 0.0, 1.0};
248 // clang-format on
Sean Paulac874152016-03-10 16:00:26 -0500249}
250
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300251void DrmHwcTwo::HwcDisplay::ClearDisplay() {
252 compositor_.ClearDisplay();
253}
254
Sean Paulac874152016-03-10 16:00:26 -0500255HWC2::Error DrmHwcTwo::HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
256 supported(__func__);
257 planner_ = Planner::CreateInstance(drm_);
258 if (!planner_) {
259 ALOGE("Failed to create planner instance for composition");
260 return HWC2::Error::NoResources;
261 }
262
263 int display = static_cast<int>(handle_);
Alexandru Gheorghe62e2d2c2018-05-11 11:40:53 +0100264 int ret = compositor_.Init(resource_manager_, display);
Sean Paulac874152016-03-10 16:00:26 -0500265 if (ret) {
266 ALOGE("Failed display compositor init for display %d (%d)", display, ret);
267 return HWC2::Error::NoResources;
268 }
269
270 // Split up the given display planes into primary and overlay to properly
271 // interface with the composition
272 char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
Jason Macnakf1af9572020-08-20 11:49:51 -0700273 property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
274 "1");
Sean Paulac874152016-03-10 16:00:26 -0500275 bool use_overlay_planes = atoi(use_overlay_planes_prop);
276 for (auto &plane : *planes) {
277 if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
278 primary_planes_.push_back(plane);
279 else if (use_overlay_planes && (plane)->type() == DRM_PLANE_TYPE_OVERLAY)
280 overlay_planes_.push_back(plane);
281 }
282
283 crtc_ = drm_->GetCrtcForDisplay(display);
284 if (!crtc_) {
285 ALOGE("Failed to get crtc for display %d", display);
286 return HWC2::Error::BadDisplay;
287 }
288
289 connector_ = drm_->GetConnectorForDisplay(display);
290 if (!connector_) {
291 ALOGE("Failed to get connector for display %d", display);
292 return HWC2::Error::BadDisplay;
293 }
294
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300295 ret = vsync_worker_.Init(drm_, display);
296 if (ret) {
297 ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
298 return HWC2::Error::BadDisplay;
299 }
300
Matvii Zorinef3c7972020-08-11 15:15:44 +0300301 ret = BackendManager::GetInstance().SetBackendForDisplay(this);
302 if (ret) {
303 ALOGE("Failed to set backend for d=%d %d\n", display, ret);
304 return HWC2::Error::BadDisplay;
305 }
306
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300307 return ChosePreferredConfig();
308}
309
310HWC2::Error DrmHwcTwo::HwcDisplay::ChosePreferredConfig() {
Sean Paulac874152016-03-10 16:00:26 -0500311 // Fetch the number of modes from the display
312 uint32_t num_configs;
313 HWC2::Error err = GetDisplayConfigs(&num_configs, NULL);
314 if (err != HWC2::Error::None || !num_configs)
315 return err;
316
Andrii Chepurnyi1b1e35e2019-02-19 21:38:13 +0200317 return SetActiveConfig(connector_->get_preferred_mode_id());
Sean Paulac874152016-03-10 16:00:26 -0500318}
319
320HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback(
321 hwc2_callback_data_t data, hwc2_function_pointer_t func) {
322 supported(__func__);
323 auto callback = std::make_shared<DrmVsyncCallback>(data, func);
Adrian Salidofa37f672017-02-16 10:29:46 -0800324 vsync_worker_.RegisterCallback(std::move(callback));
Sean Paulac874152016-03-10 16:00:26 -0500325 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500326}
327
Roman Kovalivskyi8fae1562020-01-30 20:20:47 +0200328void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback(
329 hwc2_callback_data_t data, hwc2_function_pointer_t func) {
330 supported(__func__);
331 auto hook = reinterpret_cast<HWC2_PFN_REFRESH>(func);
332 compositor_.SetRefreshCallback([data, hook](int display) {
333 hook(data, static_cast<hwc2_display_t>(display));
334 });
335}
336
Sean Pauled2ec4b2016-03-10 15:35:40 -0500337HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
Sean Paulac874152016-03-10 16:00:26 -0500338 supported(__func__);
Sean Paulac874152016-03-10 16:00:26 -0500339 for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
340 l.second.accept_type_change();
341 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500342}
343
344HWC2::Error DrmHwcTwo::HwcDisplay::CreateLayer(hwc2_layer_t *layer) {
Sean Paulac874152016-03-10 16:00:26 -0500345 supported(__func__);
346 layers_.emplace(static_cast<hwc2_layer_t>(layer_idx_), HwcLayer());
347 *layer = static_cast<hwc2_layer_t>(layer_idx_);
348 ++layer_idx_;
349 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500350}
351
352HWC2::Error DrmHwcTwo::HwcDisplay::DestroyLayer(hwc2_layer_t layer) {
Sean Paulac874152016-03-10 16:00:26 -0500353 supported(__func__);
Vincent Donnefort9abec032019-10-09 15:43:43 +0100354 if (!get_layer(layer))
355 return HWC2::Error::BadLayer;
356
Sean Paulac874152016-03-10 16:00:26 -0500357 layers_.erase(layer);
358 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500359}
360
361HWC2::Error DrmHwcTwo::HwcDisplay::GetActiveConfig(hwc2_config_t *config) {
Sean Paulac874152016-03-10 16:00:26 -0500362 supported(__func__);
363 DrmMode const &mode = connector_->active_mode();
364 if (mode.id() == 0)
365 return HWC2::Error::BadConfig;
366
367 *config = mode.id();
368 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500369}
370
371HWC2::Error DrmHwcTwo::HwcDisplay::GetChangedCompositionTypes(
372 uint32_t *num_elements, hwc2_layer_t *layers, int32_t *types) {
Sean Paulac874152016-03-10 16:00:26 -0500373 supported(__func__);
374 uint32_t num_changes = 0;
375 for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
376 if (l.second.type_changed()) {
377 if (layers && num_changes < *num_elements)
378 layers[num_changes] = l.first;
379 if (types && num_changes < *num_elements)
380 types[num_changes] = static_cast<int32_t>(l.second.validated_type());
381 ++num_changes;
382 }
383 }
384 if (!layers && !types)
385 *num_elements = num_changes;
386 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500387}
388
389HWC2::Error DrmHwcTwo::HwcDisplay::GetClientTargetSupport(uint32_t width,
Sean Paulac874152016-03-10 16:00:26 -0500390 uint32_t height,
391 int32_t /*format*/,
392 int32_t dataspace) {
393 supported(__func__);
394 std::pair<uint32_t, uint32_t> min = drm_->min_resolution();
395 std::pair<uint32_t, uint32_t> max = drm_->max_resolution();
396
397 if (width < min.first || height < min.second)
398 return HWC2::Error::Unsupported;
399
400 if (width > max.first || height > max.second)
401 return HWC2::Error::Unsupported;
402
403 if (dataspace != HAL_DATASPACE_UNKNOWN &&
404 dataspace != HAL_DATASPACE_STANDARD_UNSPECIFIED)
405 return HWC2::Error::Unsupported;
406
407 // TODO: Validate format can be handled by either GL or planes
408 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500409}
410
411HWC2::Error DrmHwcTwo::HwcDisplay::GetColorModes(uint32_t *num_modes,
Sean Paulac874152016-03-10 16:00:26 -0500412 int32_t *modes) {
413 supported(__func__);
Kalyan Kondapallyda5839c2016-11-10 10:59:50 -0800414 if (!modes)
415 *num_modes = 1;
416
417 if (modes)
418 *modes = HAL_COLOR_MODE_NATIVE;
419
420 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500421}
422
423HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayAttribute(hwc2_config_t config,
Sean Paulac874152016-03-10 16:00:26 -0500424 int32_t attribute_in,
425 int32_t *value) {
426 supported(__func__);
Sean Paulf72cccd2018-08-27 13:59:08 -0400427 auto mode = std::find_if(connector_->modes().begin(),
428 connector_->modes().end(),
429 [config](DrmMode const &m) {
430 return m.id() == config;
431 });
Sean Paulac874152016-03-10 16:00:26 -0500432 if (mode == connector_->modes().end()) {
433 ALOGE("Could not find active mode for %d", config);
434 return HWC2::Error::BadConfig;
435 }
436
437 static const int32_t kUmPerInch = 25400;
438 uint32_t mm_width = connector_->mm_width();
439 uint32_t mm_height = connector_->mm_height();
440 auto attribute = static_cast<HWC2::Attribute>(attribute_in);
441 switch (attribute) {
442 case HWC2::Attribute::Width:
443 *value = mode->h_display();
444 break;
445 case HWC2::Attribute::Height:
446 *value = mode->v_display();
447 break;
448 case HWC2::Attribute::VsyncPeriod:
449 // in nanoseconds
450 *value = 1000 * 1000 * 1000 / mode->v_refresh();
451 break;
452 case HWC2::Attribute::DpiX:
453 // Dots per 1000 inches
454 *value = mm_width ? (mode->h_display() * kUmPerInch) / mm_width : -1;
455 break;
456 case HWC2::Attribute::DpiY:
457 // Dots per 1000 inches
458 *value = mm_height ? (mode->v_display() * kUmPerInch) / mm_height : -1;
459 break;
460 default:
461 *value = -1;
462 return HWC2::Error::BadConfig;
463 }
464 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500465}
466
467HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayConfigs(uint32_t *num_configs,
468 hwc2_config_t *configs) {
Sean Paulac874152016-03-10 16:00:26 -0500469 supported(__func__);
470 // Since this callback is normally invoked twice (once to get the count, and
471 // once to populate configs), we don't really want to read the edid
472 // redundantly. Instead, only update the modes on the first invocation. While
473 // it's possible this will result in stale modes, it'll all come out in the
474 // wash when we try to set the active config later.
475 if (!configs) {
476 int ret = connector_->UpdateModes();
477 if (ret) {
478 ALOGE("Failed to update display modes %d", ret);
479 return HWC2::Error::BadDisplay;
480 }
481 }
482
Neil Armstrongb67d0492019-06-20 09:00:21 +0000483 // Since the upper layers only look at vactive/hactive/refresh, height and
484 // width, it doesn't differentiate interlaced from progressive and other
485 // similar modes. Depending on the order of modes we return to SF, it could
486 // end up choosing a suboptimal configuration and dropping the preferred
487 // mode. To workaround this, don't offer interlaced modes to SF if there is
488 // at least one non-interlaced alternative and only offer a single WxH@R
489 // mode with at least the prefered mode from in DrmConnector::UpdateModes()
490
491 // TODO: Remove the following block of code until AOSP handles all modes
492 std::vector<DrmMode> sel_modes;
493
494 // Add the preferred mode first to be sure it's not dropped
495 auto mode = std::find_if(connector_->modes().begin(),
496 connector_->modes().end(), [&](DrmMode const &m) {
497 return m.id() ==
498 connector_->get_preferred_mode_id();
499 });
500 if (mode != connector_->modes().end())
501 sel_modes.push_back(*mode);
502
503 // Add the active mode if different from preferred mode
504 if (connector_->active_mode().id() != connector_->get_preferred_mode_id())
505 sel_modes.push_back(connector_->active_mode());
506
507 // Cycle over the modes and filter out "similar" modes, keeping only the
508 // first ones in the order given by DRM (from CEA ids and timings order)
Sean Paulac874152016-03-10 16:00:26 -0500509 for (const DrmMode &mode : connector_->modes()) {
Neil Armstrongb67d0492019-06-20 09:00:21 +0000510 // TODO: Remove this when 3D Attributes are in AOSP
511 if (mode.flags() & DRM_MODE_FLAG_3D_MASK)
512 continue;
513
Neil Armstrong4c027a72019-06-04 14:48:02 +0000514 // TODO: Remove this when the Interlaced attribute is in AOSP
515 if (mode.flags() & DRM_MODE_FLAG_INTERLACE) {
516 auto m = std::find_if(connector_->modes().begin(),
517 connector_->modes().end(),
518 [&mode](DrmMode const &m) {
519 return !(m.flags() & DRM_MODE_FLAG_INTERLACE) &&
520 m.h_display() == mode.h_display() &&
521 m.v_display() == mode.v_display();
522 });
Neil Armstrongb67d0492019-06-20 09:00:21 +0000523 if (m == connector_->modes().end())
524 sel_modes.push_back(mode);
525
526 continue;
Neil Armstrong4c027a72019-06-04 14:48:02 +0000527 }
Neil Armstrongb67d0492019-06-20 09:00:21 +0000528
529 // Search for a similar WxH@R mode in the filtered list and drop it if
530 // another mode with the same WxH@R has already been selected
531 // TODO: Remove this when AOSP handles duplicates modes
532 auto m = std::find_if(sel_modes.begin(), sel_modes.end(),
533 [&mode](DrmMode const &m) {
534 return m.h_display() == mode.h_display() &&
535 m.v_display() == mode.v_display() &&
536 m.v_refresh() == mode.v_refresh();
537 });
538 if (m == sel_modes.end())
539 sel_modes.push_back(mode);
540 }
541
542 auto num_modes = static_cast<uint32_t>(sel_modes.size());
543 if (!configs) {
544 *num_configs = num_modes;
545 return HWC2::Error::None;
546 }
547
548 uint32_t idx = 0;
549 for (const DrmMode &mode : sel_modes) {
550 if (idx >= *num_configs)
551 break;
552 configs[idx++] = mode.id();
Sean Paulac874152016-03-10 16:00:26 -0500553 }
554 *num_configs = idx;
555 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500556}
557
558HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
Sean Paulac874152016-03-10 16:00:26 -0500559 supported(__func__);
560 std::ostringstream stream;
561 stream << "display-" << connector_->id();
562 std::string string = stream.str();
563 size_t length = string.length();
564 if (!name) {
565 *size = length;
566 return HWC2::Error::None;
567 }
568
569 *size = std::min<uint32_t>(static_cast<uint32_t>(length - 1), *size);
570 strncpy(name, string.c_str(), *size);
571 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500572}
573
Sean Paulac874152016-03-10 16:00:26 -0500574HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayRequests(int32_t *display_requests,
575 uint32_t *num_elements,
576 hwc2_layer_t *layers,
577 int32_t *layer_requests) {
578 supported(__func__);
579 // TODO: I think virtual display should request
580 // HWC2_DISPLAY_REQUEST_WRITE_CLIENT_TARGET_TO_OUTPUT here
581 unsupported(__func__, display_requests, num_elements, layers, layer_requests);
582 *num_elements = 0;
583 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500584}
585
586HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayType(int32_t *type) {
Sean Paulac874152016-03-10 16:00:26 -0500587 supported(__func__);
588 *type = static_cast<int32_t>(type_);
589 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500590}
591
592HWC2::Error DrmHwcTwo::HwcDisplay::GetDozeSupport(int32_t *support) {
Sean Paulac874152016-03-10 16:00:26 -0500593 supported(__func__);
594 *support = 0;
595 return HWC2::Error::None;
596}
597
598HWC2::Error DrmHwcTwo::HwcDisplay::GetHdrCapabilities(
Sean Paulf72cccd2018-08-27 13:59:08 -0400599 uint32_t *num_types, int32_t * /*types*/, float * /*max_luminance*/,
600 float * /*max_average_luminance*/, float * /*min_luminance*/) {
Sean Paulac874152016-03-10 16:00:26 -0500601 supported(__func__);
602 *num_types = 0;
603 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500604}
605
606HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements,
Sean Paulac874152016-03-10 16:00:26 -0500607 hwc2_layer_t *layers,
608 int32_t *fences) {
609 supported(__func__);
610 uint32_t num_layers = 0;
611
612 for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
613 ++num_layers;
614 if (layers == NULL || fences == NULL) {
615 continue;
616 } else if (num_layers > *num_elements) {
617 ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements);
618 return HWC2::Error::None;
619 }
620
621 layers[num_layers - 1] = l.first;
622 fences[num_layers - 1] = l.second.take_release_fence();
623 }
624 *num_elements = num_layers;
625 return HWC2::Error::None;
626}
627
Matteo Franchinc56eede2019-12-03 17:10:38 +0000628void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(int fd) {
Sean Paulac874152016-03-10 16:00:26 -0500629 if (fd < 0)
630 return;
631
Matteo Franchinc56eede2019-12-03 17:10:38 +0000632 if (present_fence_.get() >= 0) {
633 int old_fence = present_fence_.get();
634 present_fence_.Set(sync_merge("dc_present", old_fence, fd));
635 close(fd);
Sean Paulac874152016-03-10 16:00:26 -0500636 } else {
Matteo Franchinc56eede2019-12-03 17:10:38 +0000637 present_fence_.Set(fd);
Sean Paulac874152016-03-10 16:00:26 -0500638 }
Sean Pauled2ec4b2016-03-10 15:35:40 -0500639}
640
Roman Stratiienkoafb36892019-11-08 17:16:11 +0200641bool DrmHwcTwo::HwcDisplay::HardwareSupportsLayerType(
642 HWC2::Composition comp_type) {
643 return comp_type == HWC2::Composition::Device ||
644 comp_type == HWC2::Composition::Cursor;
645}
646
Rob Herring4f6c62e2018-05-17 14:33:02 -0500647HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) {
Sean Paulac874152016-03-10 16:00:26 -0500648 std::vector<DrmCompositionDisplayLayersMap> layers_map;
649 layers_map.emplace_back();
650 DrmCompositionDisplayLayersMap &map = layers_map.back();
651
652 map.display = static_cast<int>(handle_);
653 map.geometry_changed = true; // TODO: Fix this
654
655 // order the layers by z-order
656 bool use_client_layer = false;
Alexandru Gheorghe1542d292018-06-13 16:46:36 +0100657 uint32_t client_z_order = UINT32_MAX;
Sean Paulac874152016-03-10 16:00:26 -0500658 std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
659 for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_) {
Roman Stratiienkof2647232019-11-21 01:58:35 +0200660 switch (l.second.validated_type()) {
Sean Paulac874152016-03-10 16:00:26 -0500661 case HWC2::Composition::Device:
662 z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
663 break;
664 case HWC2::Composition::Client:
Alexandru Gheorghe1542d292018-06-13 16:46:36 +0100665 // Place it at the z_order of the lowest client layer
Sean Paulac874152016-03-10 16:00:26 -0500666 use_client_layer = true;
Alexandru Gheorghe1542d292018-06-13 16:46:36 +0100667 client_z_order = std::min(client_z_order, l.second.z_order());
Sean Paulac874152016-03-10 16:00:26 -0500668 break;
669 default:
670 continue;
671 }
672 }
673 if (use_client_layer)
674 z_map.emplace(std::make_pair(client_z_order, &client_layer_));
675
Rob Herring4f6c62e2018-05-17 14:33:02 -0500676 if (z_map.empty())
677 return HWC2::Error::BadLayer;
678
Sean Paulac874152016-03-10 16:00:26 -0500679 // now that they're ordered by z, add them to the composition
680 for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
681 DrmHwcLayer layer;
682 l.second->PopulateDrmLayer(&layer);
Andrii Chepurnyidc1278c2018-03-20 19:41:18 +0200683 int ret = layer.ImportBuffer(importer_.get());
Sean Paulac874152016-03-10 16:00:26 -0500684 if (ret) {
685 ALOGE("Failed to import layer, ret=%d", ret);
686 return HWC2::Error::NoResources;
687 }
688 map.layers.emplace_back(std::move(layer));
689 }
Sean Paulac874152016-03-10 16:00:26 -0500690
Sean Paulf72cccd2018-08-27 13:59:08 -0400691 std::unique_ptr<DrmDisplayComposition> composition = compositor_
692 .CreateComposition();
Sean Paulac874152016-03-10 16:00:26 -0500693 composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
694
695 // TODO: Don't always assume geometry changed
696 int ret = composition->SetLayers(map.layers.data(), map.layers.size(), true);
697 if (ret) {
698 ALOGE("Failed to set layers in the composition ret=%d", ret);
699 return HWC2::Error::BadLayer;
700 }
701
702 std::vector<DrmPlane *> primary_planes(primary_planes_);
703 std::vector<DrmPlane *> overlay_planes(overlay_planes_);
Rob Herringaf0d9752018-05-04 16:34:19 -0500704 ret = composition->Plan(&primary_planes, &overlay_planes);
Sean Paulac874152016-03-10 16:00:26 -0500705 if (ret) {
706 ALOGE("Failed to plan the composition ret=%d", ret);
707 return HWC2::Error::BadConfig;
708 }
709
710 // Disable the planes we're not using
711 for (auto i = primary_planes.begin(); i != primary_planes.end();) {
712 composition->AddPlaneDisable(*i);
713 i = primary_planes.erase(i);
714 }
715 for (auto i = overlay_planes.begin(); i != overlay_planes.end();) {
716 composition->AddPlaneDisable(*i);
717 i = overlay_planes.erase(i);
718 }
719
Rob Herring4f6c62e2018-05-17 14:33:02 -0500720 if (test) {
721 ret = compositor_.TestComposition(composition.get());
722 } else {
Rob Herring4f6c62e2018-05-17 14:33:02 -0500723 ret = compositor_.ApplyComposition(std::move(composition));
Matteo Franchinc56eede2019-12-03 17:10:38 +0000724 AddFenceToPresentFence(compositor_.TakeOutFence());
Rob Herring4f6c62e2018-05-17 14:33:02 -0500725 }
Sean Paulac874152016-03-10 16:00:26 -0500726 if (ret) {
John Stultz78c9f6c2018-05-24 16:43:35 -0700727 if (!test)
728 ALOGE("Failed to apply the frame composition ret=%d", ret);
Sean Paulac874152016-03-10 16:00:26 -0500729 return HWC2::Error::BadParameter;
730 }
Rob Herring4f6c62e2018-05-17 14:33:02 -0500731 return HWC2::Error::None;
732}
733
Matteo Franchinc56eede2019-12-03 17:10:38 +0000734HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) {
Rob Herring4f6c62e2018-05-17 14:33:02 -0500735 supported(__func__);
736 HWC2::Error ret;
737
Roman Stratiienko0d1a2cd2019-11-28 17:51:16 +0200738 ++total_stats_.total_frames_;
739
Rob Herring4f6c62e2018-05-17 14:33:02 -0500740 ret = CreateComposition(false);
Roman Stratiienko0d1a2cd2019-11-28 17:51:16 +0200741 if (ret != HWC2::Error::None)
742 ++total_stats_.failed_kms_present_;
743
Rob Herring4f6c62e2018-05-17 14:33:02 -0500744 if (ret == HWC2::Error::BadLayer) {
745 // Can we really have no client or device layers?
Matteo Franchinc56eede2019-12-03 17:10:38 +0000746 *present_fence = -1;
Rob Herring4f6c62e2018-05-17 14:33:02 -0500747 return HWC2::Error::None;
748 }
749 if (ret != HWC2::Error::None)
750 return ret;
Sean Paulac874152016-03-10 16:00:26 -0500751
Matteo Franchinc56eede2019-12-03 17:10:38 +0000752 *present_fence = present_fence_.Release();
Sean Paulac874152016-03-10 16:00:26 -0500753
754 ++frame_no_;
755 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500756}
757
758HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) {
Sean Paulac874152016-03-10 16:00:26 -0500759 supported(__func__);
Sean Paulf72cccd2018-08-27 13:59:08 -0400760 auto mode = std::find_if(connector_->modes().begin(),
761 connector_->modes().end(),
762 [config](DrmMode const &m) {
763 return m.id() == config;
764 });
Sean Paulac874152016-03-10 16:00:26 -0500765 if (mode == connector_->modes().end()) {
766 ALOGE("Could not find active mode for %d", config);
767 return HWC2::Error::BadConfig;
768 }
769
Sean Paulf72cccd2018-08-27 13:59:08 -0400770 std::unique_ptr<DrmDisplayComposition> composition = compositor_
771 .CreateComposition();
Sean Paulac874152016-03-10 16:00:26 -0500772 composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
773 int ret = composition->SetDisplayMode(*mode);
Sean Pauled45a8e2017-02-28 13:17:34 -0500774 ret = compositor_.ApplyComposition(std::move(composition));
Sean Paulac874152016-03-10 16:00:26 -0500775 if (ret) {
776 ALOGE("Failed to queue dpms composition on %d", ret);
777 return HWC2::Error::BadConfig;
778 }
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +0300779
780 connector_->set_active_mode(*mode);
Sean Paulac874152016-03-10 16:00:26 -0500781
782 // Setup the client layer's dimensions
783 hwc_rect_t display_frame = {.left = 0,
784 .top = 0,
785 .right = static_cast<int>(mode->h_display()),
786 .bottom = static_cast<int>(mode->v_display())};
787 client_layer_.SetLayerDisplayFrame(display_frame);
788 hwc_frect_t source_crop = {.left = 0.0f,
789 .top = 0.0f,
790 .right = mode->h_display() + 0.0f,
791 .bottom = mode->v_display() + 0.0f};
792 client_layer_.SetLayerSourceCrop(source_crop);
793
794 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500795}
796
797HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target,
798 int32_t acquire_fence,
799 int32_t dataspace,
Rob Herring1b2685c2017-11-29 10:19:57 -0600800 hwc_region_t /*damage*/) {
Sean Paulac874152016-03-10 16:00:26 -0500801 supported(__func__);
802 UniqueFd uf(acquire_fence);
803
804 client_layer_.set_buffer(target);
805 client_layer_.set_acquire_fence(uf.get());
806 client_layer_.SetLayerDataspace(dataspace);
807 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500808}
809
810HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) {
Sean Paulac874152016-03-10 16:00:26 -0500811 supported(__func__);
Kalyan Kondapallyda5839c2016-11-10 10:59:50 -0800812
813 if (mode != HAL_COLOR_MODE_NATIVE)
Vincent Donnefort7834a892019-10-09 15:53:56 +0100814 return HWC2::Error::BadParameter;
Kalyan Kondapallyda5839c2016-11-10 10:59:50 -0800815
816 color_mode_ = mode;
817 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500818}
819
820HWC2::Error DrmHwcTwo::HwcDisplay::SetColorTransform(const float *matrix,
Sean Paulac874152016-03-10 16:00:26 -0500821 int32_t hint) {
822 supported(__func__);
Roman Kovalivskyi12b91a32019-12-11 19:09:51 +0200823 if (hint < HAL_COLOR_TRANSFORM_IDENTITY ||
824 hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA)
825 return HWC2::Error::BadParameter;
826
827 if (!matrix && hint == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
828 return HWC2::Error::BadParameter;
829
830 color_transform_hint_ = static_cast<android_color_transform_t>(hint);
831 if (color_transform_hint_ == HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX)
832 std::copy(matrix, matrix + MATRIX_SIZE, color_transform_matrix_.begin());
833
834 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500835}
836
837HWC2::Error DrmHwcTwo::HwcDisplay::SetOutputBuffer(buffer_handle_t buffer,
Sean Paulac874152016-03-10 16:00:26 -0500838 int32_t release_fence) {
839 supported(__func__);
840 // TODO: Need virtual display support
Sean Pauled2ec4b2016-03-10 15:35:40 -0500841 return unsupported(__func__, buffer, release_fence);
842}
843
Sean Paulac874152016-03-10 16:00:26 -0500844HWC2::Error DrmHwcTwo::HwcDisplay::SetPowerMode(int32_t mode_in) {
845 supported(__func__);
846 uint64_t dpms_value = 0;
847 auto mode = static_cast<HWC2::PowerMode>(mode_in);
848 switch (mode) {
849 case HWC2::PowerMode::Off:
850 dpms_value = DRM_MODE_DPMS_OFF;
851 break;
852 case HWC2::PowerMode::On:
853 dpms_value = DRM_MODE_DPMS_ON;
854 break;
Vincent Donnefort60ef7eb2019-10-09 11:39:28 +0100855 case HWC2::PowerMode::Doze:
856 case HWC2::PowerMode::DozeSuspend:
857 return HWC2::Error::Unsupported;
Sean Paulac874152016-03-10 16:00:26 -0500858 default:
859 ALOGI("Power mode %d is unsupported\n", mode);
Vincent Donnefort60ef7eb2019-10-09 11:39:28 +0100860 return HWC2::Error::BadParameter;
Sean Paulac874152016-03-10 16:00:26 -0500861 };
862
Sean Paulf72cccd2018-08-27 13:59:08 -0400863 std::unique_ptr<DrmDisplayComposition> composition = compositor_
864 .CreateComposition();
Sean Paulac874152016-03-10 16:00:26 -0500865 composition->Init(drm_, crtc_, importer_.get(), planner_.get(), frame_no_);
866 composition->SetDpmsMode(dpms_value);
Sean Pauled45a8e2017-02-28 13:17:34 -0500867 int ret = compositor_.ApplyComposition(std::move(composition));
Sean Paulac874152016-03-10 16:00:26 -0500868 if (ret) {
869 ALOGE("Failed to apply the dpms composition ret=%d", ret);
870 return HWC2::Error::BadParameter;
871 }
872 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500873}
874
875HWC2::Error DrmHwcTwo::HwcDisplay::SetVsyncEnabled(int32_t enabled) {
Sean Paulac874152016-03-10 16:00:26 -0500876 supported(__func__);
Andrii Chepurnyi4bdd0fe2018-07-27 15:14:37 +0300877 vsync_worker_.VSyncControl(HWC2_VSYNC_ENABLE == enabled);
Sean Paulac874152016-03-10 16:00:26 -0500878 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -0500879}
880
Roman Stratiienkob7b81cf2019-12-13 19:28:56 +0200881uint32_t DrmHwcTwo::HwcDisplay::CalcPixOps(
882 std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t first_z,
883 size_t size) {
884 uint32_t pixops = 0;
885 for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
886 if (l.first >= first_z && l.first < first_z + size) {
887 hwc_rect_t df = l.second->display_frame();
888 pixops += (df.right - df.left) * (df.bottom - df.top);
889 }
890 }
891 return pixops;
892}
893
894void DrmHwcTwo::HwcDisplay::MarkValidated(
895 std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map, size_t client_first_z,
896 size_t client_size) {
897 for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
898 if (l.first >= client_first_z && l.first < client_first_z + client_size)
899 l.second->set_validated_type(HWC2::Composition::Client);
900 else
901 l.second->set_validated_type(HWC2::Composition::Device);
902 }
903}
904
Sean Pauled2ec4b2016-03-10 15:35:40 -0500905HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
Sean Paulac874152016-03-10 16:00:26 -0500906 uint32_t *num_requests) {
907 supported(__func__);
Rob Herring4f6c62e2018-05-17 14:33:02 -0500908
Matvii Zorinef3c7972020-08-11 15:15:44 +0300909 return backend_->ValidateDisplay(this, num_types, num_requests);
Sean Pauled2ec4b2016-03-10 15:35:40 -0500910}
911
John Stultz8c7229d2020-02-07 21:31:08 +0000912#if PLATFORM_SDK_VERSION > 28
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800913HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData(
914 uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) {
915 supported(__func__);
916
917 drmModePropertyBlobPtr blob;
918 int ret;
919 uint64_t blob_id;
920
921 std::tie(ret, blob_id) = connector_->edid_property().value();
922 if (ret) {
923 ALOGE("Failed to get edid property value.");
924 return HWC2::Error::Unsupported;
925 }
926
927 blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
928
Andrii Chepurnyi8115dbe2020-04-14 13:03:57 +0300929 if (outData) {
930 *outDataSize = std::min(*outDataSize, blob->length);
931 memcpy(outData, blob->data, *outDataSize);
932 } else {
933 *outDataSize = blob->length;
934 }
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800935 *outPort = connector_->id();
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800936
937 return HWC2::Error::None;
938}
939
940HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities(
941 uint32_t *outNumCapabilities, uint32_t *outCapabilities) {
942 unsupported(__func__, outCapabilities);
943
944 if (outNumCapabilities == NULL) {
945 return HWC2::Error::BadParameter;
946 }
947
948 *outNumCapabilities = 0;
949
950 return HWC2::Error::None;
951}
Andrii Chepurnyi2619aab2020-07-03 11:21:33 +0300952
953HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayBrightnessSupport(
954 bool *supported) {
955 *supported = false;
956 return HWC2::Error::None;
957}
958
959HWC2::Error DrmHwcTwo::HwcDisplay::SetDisplayBrightness(
960 float /* brightness */) {
961 return HWC2::Error::Unsupported;
962}
963
John Stultz8c7229d2020-02-07 21:31:08 +0000964#endif /* PLATFORM_SDK_VERSION > 28 */
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +0800965
Andrii Chepurnyi50d37452020-04-24 14:20:24 +0300966#if PLATFORM_SDK_VERSION > 27
967
968HWC2::Error DrmHwcTwo::HwcDisplay::GetRenderIntents(
969 int32_t mode, uint32_t *outNumIntents,
970 int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
971 if (mode != HAL_COLOR_MODE_NATIVE) {
972 return HWC2::Error::BadParameter;
973 }
974
975 if (outIntents == nullptr) {
976 *outNumIntents = 1;
977 return HWC2::Error::None;
978 }
979 *outNumIntents = 1;
980 outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
981 return HWC2::Error::None;
982}
983
Andrii Chepurnyi857a53f2020-04-29 23:15:28 +0300984HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode,
985 int32_t intent) {
986 if (mode != HAL_COLOR_MODE_NATIVE)
987 return HWC2::Error::BadParameter;
988 if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
989 return HWC2::Error::BadParameter;
990 color_mode_ = mode;
991 return HWC2::Error::None;
992}
993
Andrii Chepurnyi50d37452020-04-24 14:20:24 +0300994#endif /* PLATFORM_SDK_VERSION > 27 */
995
Sean Pauled2ec4b2016-03-10 15:35:40 -0500996HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
Sean Paulac874152016-03-10 16:00:26 -0500997 supported(__func__);
Kalyan Kondapallyda5839c2016-11-10 10:59:50 -0800998 cursor_x_ = x;
999 cursor_y_ = y;
1000 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001001}
1002
1003HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBlendMode(int32_t mode) {
Sean Paulac874152016-03-10 16:00:26 -05001004 supported(__func__);
1005 blending_ = static_cast<HWC2::BlendMode>(mode);
1006 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001007}
1008
1009HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
Sean Paulac874152016-03-10 16:00:26 -05001010 int32_t acquire_fence) {
1011 supported(__func__);
1012 UniqueFd uf(acquire_fence);
1013
Sean Paulac874152016-03-10 16:00:26 -05001014 set_buffer(buffer);
1015 set_acquire_fence(uf.get());
1016 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001017}
1018
1019HWC2::Error DrmHwcTwo::HwcLayer::SetLayerColor(hwc_color_t color) {
Roman Kovalivskyibb375692019-12-11 17:48:44 +02001020 // TODO: Put to client composition here?
1021 supported(__func__);
1022 layer_color_ = color;
1023 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001024}
1025
1026HWC2::Error DrmHwcTwo::HwcLayer::SetLayerCompositionType(int32_t type) {
Sean Paulac874152016-03-10 16:00:26 -05001027 sf_type_ = static_cast<HWC2::Composition>(type);
1028 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001029}
1030
1031HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDataspace(int32_t dataspace) {
Sean Paulac874152016-03-10 16:00:26 -05001032 supported(__func__);
1033 dataspace_ = static_cast<android_dataspace_t>(dataspace);
1034 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001035}
1036
1037HWC2::Error DrmHwcTwo::HwcLayer::SetLayerDisplayFrame(hwc_rect_t frame) {
Sean Paulac874152016-03-10 16:00:26 -05001038 supported(__func__);
1039 display_frame_ = frame;
1040 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001041}
1042
1043HWC2::Error DrmHwcTwo::HwcLayer::SetLayerPlaneAlpha(float alpha) {
Sean Paulac874152016-03-10 16:00:26 -05001044 supported(__func__);
1045 alpha_ = alpha;
1046 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001047}
1048
1049HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSidebandStream(
1050 const native_handle_t *stream) {
Sean Paulac874152016-03-10 16:00:26 -05001051 supported(__func__);
1052 // TODO: We don't support sideband
Sean Pauled2ec4b2016-03-10 15:35:40 -05001053 return unsupported(__func__, stream);
1054}
1055
1056HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSourceCrop(hwc_frect_t crop) {
Sean Paulac874152016-03-10 16:00:26 -05001057 supported(__func__);
1058 source_crop_ = crop;
1059 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001060}
1061
1062HWC2::Error DrmHwcTwo::HwcLayer::SetLayerSurfaceDamage(hwc_region_t damage) {
Sean Paulac874152016-03-10 16:00:26 -05001063 supported(__func__);
1064 // TODO: We don't use surface damage, marking as unsupported
1065 unsupported(__func__, damage);
1066 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001067}
1068
1069HWC2::Error DrmHwcTwo::HwcLayer::SetLayerTransform(int32_t transform) {
Sean Paulac874152016-03-10 16:00:26 -05001070 supported(__func__);
1071 transform_ = static_cast<HWC2::Transform>(transform);
1072 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001073}
1074
1075HWC2::Error DrmHwcTwo::HwcLayer::SetLayerVisibleRegion(hwc_region_t visible) {
Sean Paulac874152016-03-10 16:00:26 -05001076 supported(__func__);
1077 // TODO: We don't use this information, marking as unsupported
1078 unsupported(__func__, visible);
1079 return HWC2::Error::None;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001080}
1081
Sean Paulac874152016-03-10 16:00:26 -05001082HWC2::Error DrmHwcTwo::HwcLayer::SetLayerZOrder(uint32_t order) {
1083 supported(__func__);
1084 z_order_ = order;
1085 return HWC2::Error::None;
1086}
1087
1088void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) {
1089 supported(__func__);
1090 switch (blending_) {
1091 case HWC2::BlendMode::None:
1092 layer->blending = DrmHwcBlending::kNone;
1093 break;
1094 case HWC2::BlendMode::Premultiplied:
1095 layer->blending = DrmHwcBlending::kPreMult;
1096 break;
1097 case HWC2::BlendMode::Coverage:
1098 layer->blending = DrmHwcBlending::kCoverage;
1099 break;
1100 default:
1101 ALOGE("Unknown blending mode b=%d", blending_);
1102 layer->blending = DrmHwcBlending::kNone;
1103 break;
1104 }
1105
1106 OutputFd release_fence = release_fence_output();
1107
1108 layer->sf_handle = buffer_;
1109 layer->acquire_fence = acquire_fence_.Release();
1110 layer->release_fence = std::move(release_fence);
1111 layer->SetDisplayFrame(display_frame_);
Stefan Schake025d0a62018-05-04 18:03:00 +02001112 layer->alpha = static_cast<uint16_t>(65535.0f * alpha_ + 0.5f);
Sean Paulac874152016-03-10 16:00:26 -05001113 layer->SetSourceCrop(source_crop_);
1114 layer->SetTransform(static_cast<int32_t>(transform_));
Sean Pauled2ec4b2016-03-10 15:35:40 -05001115}
1116
Andrii Chepurnyi495e4cc2018-08-01 17:42:56 +03001117void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
1118 auto cb = callbacks_.find(HWC2::Callback::Hotplug);
1119 if (cb == callbacks_.end())
1120 return;
1121
1122 auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(cb->second.func);
1123 hotplug(cb->second.data, displayid,
1124 (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
1125 : HWC2_CONNECTION_DISCONNECTED));
1126}
1127
1128void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
1129 for (auto &conn : drmDevice->connectors()) {
1130 if (conn->state() != DRM_MODE_CONNECTED)
1131 continue;
1132 HandleDisplayHotplug(conn->display(), conn->state());
1133 }
1134}
1135
1136void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) {
1137 for (auto &conn : drm_->connectors()) {
1138 drmModeConnection old_state = conn->state();
1139 drmModeConnection cur_state = conn->UpdateModes()
1140 ? DRM_MODE_UNKNOWNCONNECTION
1141 : conn->state();
1142
1143 if (cur_state == old_state)
1144 continue;
1145
1146 ALOGI("%s event @%" PRIu64 " for connector %u on display %d",
1147 cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
1148 conn->id(), conn->display());
1149
1150 int display_id = conn->display();
1151 if (cur_state == DRM_MODE_CONNECTED) {
1152 auto &display = hwc2_->displays_.at(display_id);
1153 display.ChosePreferredConfig();
1154 } else {
1155 auto &display = hwc2_->displays_.at(display_id);
1156 display.ClearDisplay();
1157 }
1158
1159 hwc2_->HandleDisplayHotplug(display_id, cur_state);
1160 }
1161}
1162
Sean Pauled2ec4b2016-03-10 15:35:40 -05001163// static
1164int DrmHwcTwo::HookDevClose(hw_device_t * /*dev*/) {
1165 unsupported(__func__);
1166 return 0;
1167}
1168
1169// static
1170void DrmHwcTwo::HookDevGetCapabilities(hwc2_device_t * /*dev*/,
Sean Paulac874152016-03-10 16:00:26 -05001171 uint32_t *out_count,
1172 int32_t * /*out_capabilities*/) {
1173 supported(__func__);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001174 *out_count = 0;
1175}
1176
1177// static
Sean Paulac874152016-03-10 16:00:26 -05001178hwc2_function_pointer_t DrmHwcTwo::HookDevGetFunction(
1179 struct hwc2_device * /*dev*/, int32_t descriptor) {
1180 supported(__func__);
1181 auto func = static_cast<HWC2::FunctionDescriptor>(descriptor);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001182 switch (func) {
1183 // Device functions
1184 case HWC2::FunctionDescriptor::CreateVirtualDisplay:
1185 return ToHook<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
1186 DeviceHook<int32_t, decltype(&DrmHwcTwo::CreateVirtualDisplay),
1187 &DrmHwcTwo::CreateVirtualDisplay, uint32_t, uint32_t,
Sean Paulf72cccd2018-08-27 13:59:08 -04001188 int32_t *, hwc2_display_t *>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001189 case HWC2::FunctionDescriptor::DestroyVirtualDisplay:
1190 return ToHook<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
1191 DeviceHook<int32_t, decltype(&DrmHwcTwo::DestroyVirtualDisplay),
1192 &DrmHwcTwo::DestroyVirtualDisplay, hwc2_display_t>);
1193 case HWC2::FunctionDescriptor::Dump:
1194 return ToHook<HWC2_PFN_DUMP>(
1195 DeviceHook<void, decltype(&DrmHwcTwo::Dump), &DrmHwcTwo::Dump,
1196 uint32_t *, char *>);
1197 case HWC2::FunctionDescriptor::GetMaxVirtualDisplayCount:
1198 return ToHook<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
1199 DeviceHook<uint32_t, decltype(&DrmHwcTwo::GetMaxVirtualDisplayCount),
1200 &DrmHwcTwo::GetMaxVirtualDisplayCount>);
1201 case HWC2::FunctionDescriptor::RegisterCallback:
1202 return ToHook<HWC2_PFN_REGISTER_CALLBACK>(
1203 DeviceHook<int32_t, decltype(&DrmHwcTwo::RegisterCallback),
1204 &DrmHwcTwo::RegisterCallback, int32_t,
1205 hwc2_callback_data_t, hwc2_function_pointer_t>);
1206
1207 // Display functions
1208 case HWC2::FunctionDescriptor::AcceptDisplayChanges:
1209 return ToHook<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
1210 DisplayHook<decltype(&HwcDisplay::AcceptDisplayChanges),
1211 &HwcDisplay::AcceptDisplayChanges>);
1212 case HWC2::FunctionDescriptor::CreateLayer:
1213 return ToHook<HWC2_PFN_CREATE_LAYER>(
1214 DisplayHook<decltype(&HwcDisplay::CreateLayer),
1215 &HwcDisplay::CreateLayer, hwc2_layer_t *>);
1216 case HWC2::FunctionDescriptor::DestroyLayer:
1217 return ToHook<HWC2_PFN_DESTROY_LAYER>(
1218 DisplayHook<decltype(&HwcDisplay::DestroyLayer),
1219 &HwcDisplay::DestroyLayer, hwc2_layer_t>);
1220 case HWC2::FunctionDescriptor::GetActiveConfig:
1221 return ToHook<HWC2_PFN_GET_ACTIVE_CONFIG>(
1222 DisplayHook<decltype(&HwcDisplay::GetActiveConfig),
1223 &HwcDisplay::GetActiveConfig, hwc2_config_t *>);
1224 case HWC2::FunctionDescriptor::GetChangedCompositionTypes:
1225 return ToHook<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
1226 DisplayHook<decltype(&HwcDisplay::GetChangedCompositionTypes),
1227 &HwcDisplay::GetChangedCompositionTypes, uint32_t *,
1228 hwc2_layer_t *, int32_t *>);
1229 case HWC2::FunctionDescriptor::GetClientTargetSupport:
1230 return ToHook<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
1231 DisplayHook<decltype(&HwcDisplay::GetClientTargetSupport),
1232 &HwcDisplay::GetClientTargetSupport, uint32_t, uint32_t,
1233 int32_t, int32_t>);
1234 case HWC2::FunctionDescriptor::GetColorModes:
1235 return ToHook<HWC2_PFN_GET_COLOR_MODES>(
1236 DisplayHook<decltype(&HwcDisplay::GetColorModes),
1237 &HwcDisplay::GetColorModes, uint32_t *, int32_t *>);
1238 case HWC2::FunctionDescriptor::GetDisplayAttribute:
Sean Paulf72cccd2018-08-27 13:59:08 -04001239 return ToHook<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
1240 DisplayHook<decltype(&HwcDisplay::GetDisplayAttribute),
1241 &HwcDisplay::GetDisplayAttribute, hwc2_config_t, int32_t,
1242 int32_t *>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001243 case HWC2::FunctionDescriptor::GetDisplayConfigs:
Sean Paulf72cccd2018-08-27 13:59:08 -04001244 return ToHook<HWC2_PFN_GET_DISPLAY_CONFIGS>(
1245 DisplayHook<decltype(&HwcDisplay::GetDisplayConfigs),
1246 &HwcDisplay::GetDisplayConfigs, uint32_t *,
1247 hwc2_config_t *>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001248 case HWC2::FunctionDescriptor::GetDisplayName:
1249 return ToHook<HWC2_PFN_GET_DISPLAY_NAME>(
1250 DisplayHook<decltype(&HwcDisplay::GetDisplayName),
1251 &HwcDisplay::GetDisplayName, uint32_t *, char *>);
1252 case HWC2::FunctionDescriptor::GetDisplayRequests:
1253 return ToHook<HWC2_PFN_GET_DISPLAY_REQUESTS>(
1254 DisplayHook<decltype(&HwcDisplay::GetDisplayRequests),
1255 &HwcDisplay::GetDisplayRequests, int32_t *, uint32_t *,
1256 hwc2_layer_t *, int32_t *>);
1257 case HWC2::FunctionDescriptor::GetDisplayType:
1258 return ToHook<HWC2_PFN_GET_DISPLAY_TYPE>(
1259 DisplayHook<decltype(&HwcDisplay::GetDisplayType),
1260 &HwcDisplay::GetDisplayType, int32_t *>);
1261 case HWC2::FunctionDescriptor::GetDozeSupport:
1262 return ToHook<HWC2_PFN_GET_DOZE_SUPPORT>(
1263 DisplayHook<decltype(&HwcDisplay::GetDozeSupport),
1264 &HwcDisplay::GetDozeSupport, int32_t *>);
Sean Paulac874152016-03-10 16:00:26 -05001265 case HWC2::FunctionDescriptor::GetHdrCapabilities:
1266 return ToHook<HWC2_PFN_GET_HDR_CAPABILITIES>(
1267 DisplayHook<decltype(&HwcDisplay::GetHdrCapabilities),
1268 &HwcDisplay::GetHdrCapabilities, uint32_t *, int32_t *,
1269 float *, float *, float *>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001270 case HWC2::FunctionDescriptor::GetReleaseFences:
1271 return ToHook<HWC2_PFN_GET_RELEASE_FENCES>(
1272 DisplayHook<decltype(&HwcDisplay::GetReleaseFences),
1273 &HwcDisplay::GetReleaseFences, uint32_t *, hwc2_layer_t *,
1274 int32_t *>);
1275 case HWC2::FunctionDescriptor::PresentDisplay:
1276 return ToHook<HWC2_PFN_PRESENT_DISPLAY>(
1277 DisplayHook<decltype(&HwcDisplay::PresentDisplay),
1278 &HwcDisplay::PresentDisplay, int32_t *>);
1279 case HWC2::FunctionDescriptor::SetActiveConfig:
1280 return ToHook<HWC2_PFN_SET_ACTIVE_CONFIG>(
1281 DisplayHook<decltype(&HwcDisplay::SetActiveConfig),
1282 &HwcDisplay::SetActiveConfig, hwc2_config_t>);
1283 case HWC2::FunctionDescriptor::SetClientTarget:
Sean Paulf72cccd2018-08-27 13:59:08 -04001284 return ToHook<HWC2_PFN_SET_CLIENT_TARGET>(
1285 DisplayHook<decltype(&HwcDisplay::SetClientTarget),
1286 &HwcDisplay::SetClientTarget, buffer_handle_t, int32_t,
1287 int32_t, hwc_region_t>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001288 case HWC2::FunctionDescriptor::SetColorMode:
1289 return ToHook<HWC2_PFN_SET_COLOR_MODE>(
1290 DisplayHook<decltype(&HwcDisplay::SetColorMode),
1291 &HwcDisplay::SetColorMode, int32_t>);
1292 case HWC2::FunctionDescriptor::SetColorTransform:
1293 return ToHook<HWC2_PFN_SET_COLOR_TRANSFORM>(
1294 DisplayHook<decltype(&HwcDisplay::SetColorTransform),
1295 &HwcDisplay::SetColorTransform, const float *, int32_t>);
1296 case HWC2::FunctionDescriptor::SetOutputBuffer:
1297 return ToHook<HWC2_PFN_SET_OUTPUT_BUFFER>(
1298 DisplayHook<decltype(&HwcDisplay::SetOutputBuffer),
1299 &HwcDisplay::SetOutputBuffer, buffer_handle_t, int32_t>);
1300 case HWC2::FunctionDescriptor::SetPowerMode:
1301 return ToHook<HWC2_PFN_SET_POWER_MODE>(
1302 DisplayHook<decltype(&HwcDisplay::SetPowerMode),
1303 &HwcDisplay::SetPowerMode, int32_t>);
1304 case HWC2::FunctionDescriptor::SetVsyncEnabled:
1305 return ToHook<HWC2_PFN_SET_VSYNC_ENABLED>(
1306 DisplayHook<decltype(&HwcDisplay::SetVsyncEnabled),
1307 &HwcDisplay::SetVsyncEnabled, int32_t>);
1308 case HWC2::FunctionDescriptor::ValidateDisplay:
1309 return ToHook<HWC2_PFN_VALIDATE_DISPLAY>(
1310 DisplayHook<decltype(&HwcDisplay::ValidateDisplay),
1311 &HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>);
Andrii Chepurnyi50d37452020-04-24 14:20:24 +03001312#if PLATFORM_SDK_VERSION > 27
1313 case HWC2::FunctionDescriptor::GetRenderIntents:
1314 return ToHook<HWC2_PFN_GET_RENDER_INTENTS>(
1315 DisplayHook<decltype(&HwcDisplay::GetRenderIntents),
1316 &HwcDisplay::GetRenderIntents, int32_t, uint32_t *,
1317 int32_t *>);
Andrii Chepurnyi857a53f2020-04-29 23:15:28 +03001318 case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
1319 return ToHook<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>(
1320 DisplayHook<decltype(&HwcDisplay::SetColorModeWithIntent),
1321 &HwcDisplay::SetColorModeWithIntent, int32_t, int32_t>);
Andrii Chepurnyi50d37452020-04-24 14:20:24 +03001322#endif
John Stultz8c7229d2020-02-07 21:31:08 +00001323#if PLATFORM_SDK_VERSION > 28
Lowry Li (Arm Technology China)b3d81782019-12-18 14:28:22 +08001324 case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
1325 return ToHook<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
1326 DisplayHook<decltype(&HwcDisplay::GetDisplayIdentificationData),
1327 &HwcDisplay::GetDisplayIdentificationData, uint8_t *,
1328 uint32_t *, uint8_t *>);
1329 case HWC2::FunctionDescriptor::GetDisplayCapabilities:
1330 return ToHook<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
1331 DisplayHook<decltype(&HwcDisplay::GetDisplayCapabilities),
1332 &HwcDisplay::GetDisplayCapabilities, uint32_t *,
1333 uint32_t *>);
Andrii Chepurnyi2619aab2020-07-03 11:21:33 +03001334 case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport:
1335 return ToHook<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
1336 DisplayHook<decltype(&HwcDisplay::GetDisplayBrightnessSupport),
1337 &HwcDisplay::GetDisplayBrightnessSupport, bool *>);
1338 case HWC2::FunctionDescriptor::SetDisplayBrightness:
1339 return ToHook<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
1340 DisplayHook<decltype(&HwcDisplay::SetDisplayBrightness),
1341 &HwcDisplay::SetDisplayBrightness, float>);
John Stultz8c7229d2020-02-07 21:31:08 +00001342#endif /* PLATFORM_SDK_VERSION > 28 */
Sean Pauled2ec4b2016-03-10 15:35:40 -05001343 // Layer functions
1344 case HWC2::FunctionDescriptor::SetCursorPosition:
1345 return ToHook<HWC2_PFN_SET_CURSOR_POSITION>(
1346 LayerHook<decltype(&HwcLayer::SetCursorPosition),
1347 &HwcLayer::SetCursorPosition, int32_t, int32_t>);
1348 case HWC2::FunctionDescriptor::SetLayerBlendMode:
1349 return ToHook<HWC2_PFN_SET_LAYER_BLEND_MODE>(
1350 LayerHook<decltype(&HwcLayer::SetLayerBlendMode),
1351 &HwcLayer::SetLayerBlendMode, int32_t>);
1352 case HWC2::FunctionDescriptor::SetLayerBuffer:
1353 return ToHook<HWC2_PFN_SET_LAYER_BUFFER>(
1354 LayerHook<decltype(&HwcLayer::SetLayerBuffer),
1355 &HwcLayer::SetLayerBuffer, buffer_handle_t, int32_t>);
1356 case HWC2::FunctionDescriptor::SetLayerColor:
1357 return ToHook<HWC2_PFN_SET_LAYER_COLOR>(
1358 LayerHook<decltype(&HwcLayer::SetLayerColor),
1359 &HwcLayer::SetLayerColor, hwc_color_t>);
1360 case HWC2::FunctionDescriptor::SetLayerCompositionType:
1361 return ToHook<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
1362 LayerHook<decltype(&HwcLayer::SetLayerCompositionType),
1363 &HwcLayer::SetLayerCompositionType, int32_t>);
1364 case HWC2::FunctionDescriptor::SetLayerDataspace:
1365 return ToHook<HWC2_PFN_SET_LAYER_DATASPACE>(
1366 LayerHook<decltype(&HwcLayer::SetLayerDataspace),
1367 &HwcLayer::SetLayerDataspace, int32_t>);
1368 case HWC2::FunctionDescriptor::SetLayerDisplayFrame:
1369 return ToHook<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
1370 LayerHook<decltype(&HwcLayer::SetLayerDisplayFrame),
1371 &HwcLayer::SetLayerDisplayFrame, hwc_rect_t>);
1372 case HWC2::FunctionDescriptor::SetLayerPlaneAlpha:
1373 return ToHook<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
1374 LayerHook<decltype(&HwcLayer::SetLayerPlaneAlpha),
1375 &HwcLayer::SetLayerPlaneAlpha, float>);
1376 case HWC2::FunctionDescriptor::SetLayerSidebandStream:
Sean Paulf72cccd2018-08-27 13:59:08 -04001377 return ToHook<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
1378 LayerHook<decltype(&HwcLayer::SetLayerSidebandStream),
1379 &HwcLayer::SetLayerSidebandStream,
1380 const native_handle_t *>);
Sean Pauled2ec4b2016-03-10 15:35:40 -05001381 case HWC2::FunctionDescriptor::SetLayerSourceCrop:
1382 return ToHook<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
1383 LayerHook<decltype(&HwcLayer::SetLayerSourceCrop),
1384 &HwcLayer::SetLayerSourceCrop, hwc_frect_t>);
1385 case HWC2::FunctionDescriptor::SetLayerSurfaceDamage:
1386 return ToHook<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
1387 LayerHook<decltype(&HwcLayer::SetLayerSurfaceDamage),
1388 &HwcLayer::SetLayerSurfaceDamage, hwc_region_t>);
1389 case HWC2::FunctionDescriptor::SetLayerTransform:
1390 return ToHook<HWC2_PFN_SET_LAYER_TRANSFORM>(
1391 LayerHook<decltype(&HwcLayer::SetLayerTransform),
1392 &HwcLayer::SetLayerTransform, int32_t>);
1393 case HWC2::FunctionDescriptor::SetLayerVisibleRegion:
1394 return ToHook<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
1395 LayerHook<decltype(&HwcLayer::SetLayerVisibleRegion),
1396 &HwcLayer::SetLayerVisibleRegion, hwc_region_t>);
1397 case HWC2::FunctionDescriptor::SetLayerZOrder:
1398 return ToHook<HWC2_PFN_SET_LAYER_Z_ORDER>(
1399 LayerHook<decltype(&HwcLayer::SetLayerZOrder),
1400 &HwcLayer::SetLayerZOrder, uint32_t>);
Sean Paulac874152016-03-10 16:00:26 -05001401 case HWC2::FunctionDescriptor::Invalid:
Sean Pauled2ec4b2016-03-10 15:35:40 -05001402 default:
1403 return NULL;
1404 }
1405}
Sean Paulac874152016-03-10 16:00:26 -05001406
1407// static
1408int DrmHwcTwo::HookDevOpen(const struct hw_module_t *module, const char *name,
1409 struct hw_device_t **dev) {
1410 supported(__func__);
1411 if (strcmp(name, HWC_HARDWARE_COMPOSER)) {
1412 ALOGE("Invalid module name- %s", name);
1413 return -EINVAL;
1414 }
1415
1416 std::unique_ptr<DrmHwcTwo> ctx(new DrmHwcTwo());
1417 if (!ctx) {
1418 ALOGE("Failed to allocate DrmHwcTwo");
1419 return -ENOMEM;
1420 }
1421
1422 HWC2::Error err = ctx->Init();
1423 if (err != HWC2::Error::None) {
1424 ALOGE("Failed to initialize DrmHwcTwo err=%d\n", err);
1425 return -EINVAL;
1426 }
1427
1428 ctx->common.module = const_cast<hw_module_t *>(module);
1429 *dev = &ctx->common;
1430 ctx.release();
1431 return 0;
Sean Pauled2ec4b2016-03-10 15:35:40 -05001432}
Sean Paulf72cccd2018-08-27 13:59:08 -04001433} // namespace android
Sean Paulac874152016-03-10 16:00:26 -05001434
1435static struct hw_module_methods_t hwc2_module_methods = {
1436 .open = android::DrmHwcTwo::HookDevOpen,
1437};
1438
1439hw_module_t HAL_MODULE_INFO_SYM = {
1440 .tag = HARDWARE_MODULE_TAG,
1441 .module_api_version = HARDWARE_MODULE_API_VERSION(2, 0),
1442 .id = HWC_HARDWARE_MODULE_ID,
1443 .name = "DrmHwcTwo module",
1444 .author = "The Android Open Source Project",
1445 .methods = &hwc2_module_methods,
1446 .dso = NULL,
1447 .reserved = {0},
1448};