1 /*
2 * Copyright (C) 2010 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 LOG_NDEBUG 0
18
19 #undef LOG_TAG
20 #define LOG_TAG "HWComposer"
21 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
23 #include <compositionengine/Output.h>
24 #include <compositionengine/OutputLayer.h>
25 #include <compositionengine/impl/OutputLayerCompositionState.h>
26 #include <log/log.h>
27 #include <ui/DebugUtils.h>
28 #include <ui/GraphicBuffer.h>
29 #include <utils/Errors.h>
30 #include <utils/Trace.h>
31
32 #include "HWComposer.h"
33 #include "HWC2.h"
34 #include "ComposerHal.h"
35
36 #include "../Layer.h" // needed only for debugging
37 #include "../SurfaceFlinger.h"
38
39 #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
40 ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
41
42 #define LOG_DISPLAY_ERROR(displayId, msg) \
43 ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg)
44
45 #define LOG_HWC_ERROR(what, error, displayId) \
46 ALOGE("%s: %s failed for display %s: %s (%d)", __FUNCTION__, what, \
47 to_string(displayId).c_str(), to_string(error).c_str(), static_cast<int32_t>(error))
48
49 #define RETURN_IF_INVALID_DISPLAY(displayId, ...) \
50 do { \
51 if (mDisplayData.count(displayId) == 0) { \
52 LOG_DISPLAY_ERROR(displayId, "Invalid display"); \
53 return __VA_ARGS__; \
54 } \
55 } while (false)
56
57 #define RETURN_IF_HWC_ERROR_FOR(what, error, displayId, ...) \
58 do { \
59 if (error != HWC2::Error::None) { \
60 LOG_HWC_ERROR(what, error, displayId); \
61 return __VA_ARGS__; \
62 } \
63 } while (false)
64
65 #define RETURN_IF_HWC_ERROR(error, displayId, ...) \
66 RETURN_IF_HWC_ERROR_FOR(__FUNCTION__, error, displayId, __VA_ARGS__)
67
68 namespace android {
69
70 HWComposer::~HWComposer() = default;
71
72 namespace impl {
73
HWComposer(std::unique_ptr<Hwc2::Composer> composer)74 HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer)
75 : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {}
76
~HWComposer()77 HWComposer::~HWComposer() {
78 mDisplayData.clear();
79 }
80
registerCallback(HWC2::ComposerCallback * callback,int32_t sequenceId)81 void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
82 int32_t sequenceId) {
83 mHwcDevice->registerCallback(callback, sequenceId);
84 }
85
getDisplayIdentificationData(hwc2_display_t hwcDisplayId,uint8_t * outPort,DisplayIdentificationData * outData) const86 bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
87 DisplayIdentificationData* outData) const {
88 const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
89 if (error != HWC2::Error::None) {
90 if (error != HWC2::Error::Unsupported) {
91 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
92 }
93 return false;
94 }
95 return true;
96 }
97
hasCapability(HWC2::Capability capability) const98 bool HWComposer::hasCapability(HWC2::Capability capability) const
99 {
100 return mHwcDevice->getCapabilities().count(capability) > 0;
101 }
102
hasDisplayCapability(const std::optional<DisplayId> & displayId,HWC2::DisplayCapability capability) const103 bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId,
104 HWC2::DisplayCapability capability) const {
105 if (!displayId) {
106 // Checkout global capabilities for displays without a corresponding HWC display.
107 if (capability == HWC2::DisplayCapability::SkipClientColorTransform) {
108 return hasCapability(HWC2::Capability::SkipClientColorTransform);
109 }
110 return false;
111 }
112 RETURN_IF_INVALID_DISPLAY(*displayId, false);
113 return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0;
114 }
115
validateChange(HWC2::Composition from,HWC2::Composition to)116 void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
117 bool valid = true;
118 switch (from) {
119 case HWC2::Composition::Client:
120 valid = false;
121 break;
122 case HWC2::Composition::Device:
123 case HWC2::Composition::SolidColor:
124 valid = (to == HWC2::Composition::Client);
125 break;
126 case HWC2::Composition::Cursor:
127 case HWC2::Composition::Sideband:
128 valid = (to == HWC2::Composition::Client ||
129 to == HWC2::Composition::Device);
130 break;
131 default:
132 break;
133 }
134
135 if (!valid) {
136 ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(),
137 to_string(to).c_str());
138 }
139 }
140
onHotplug(hwc2_display_t hwcDisplayId,HWC2::Connection connection)141 std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
142 HWC2::Connection connection) {
143 std::optional<DisplayIdentificationInfo> info;
144
145 if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
146 info = DisplayIdentificationInfo{*displayId, std::string()};
147 } else {
148 if (connection == HWC2::Connection::Disconnected) {
149 ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
150 return {};
151 }
152
153 info = onHotplugConnect(hwcDisplayId);
154 if (!info) return {};
155 }
156
157 ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(),
158 hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
159 to_string(info->id).c_str(), hwcDisplayId);
160
161 mHwcDevice->onHotplug(hwcDisplayId, connection);
162
163 // Disconnect is handled through HWComposer::disconnectDisplay via
164 // SurfaceFlinger's onHotplugReceived callback handling
165 if (connection == HWC2::Connection::Connected) {
166 mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
167 mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
168 }
169
170 return info;
171 }
172
onVsync(hwc2_display_t hwcDisplayId,int64_t timestamp)173 bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
174 const auto displayId = toPhysicalDisplayId(hwcDisplayId);
175 if (!displayId) {
176 LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
177 return false;
178 }
179
180 RETURN_IF_INVALID_DISPLAY(*displayId, false);
181
182 auto& displayData = mDisplayData[*displayId];
183 if (displayData.isVirtual) {
184 LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display");
185 return false;
186 }
187
188 {
189 std::lock_guard lock(displayData.lastHwVsyncLock);
190
191 // There have been reports of HWCs that signal several vsync events
192 // with the same timestamp when turning the display off and on. This
193 // is a bug in the HWC implementation, but filter the extra events
194 // out here so they don't cause havoc downstream.
195 if (timestamp == displayData.lastHwVsync) {
196 ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
197 to_string(*displayId).c_str(), timestamp);
198 return false;
199 }
200
201 displayData.lastHwVsync = timestamp;
202 }
203
204 const auto tag = "HW_VSYNC_" + to_string(*displayId);
205 ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle);
206 displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle;
207
208 return true;
209 }
210
allocateVirtualDisplay(uint32_t width,uint32_t height,ui::PixelFormat * format)211 std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
212 ui::PixelFormat* format) {
213 if (mRemainingHwcVirtualDisplays == 0) {
214 ALOGE("%s: No remaining virtual displays", __FUNCTION__);
215 return {};
216 }
217
218 if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
219 (width > SurfaceFlinger::maxVirtualDisplaySize ||
220 height > SurfaceFlinger::maxVirtualDisplaySize)) {
221 ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
222 height, SurfaceFlinger::maxVirtualDisplaySize);
223 return {};
224 }
225 HWC2::Display* display;
226 auto error = mHwcDevice->createVirtualDisplay(width, height, format,
227 &display);
228 if (error != HWC2::Error::None) {
229 ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
230 return {};
231 }
232
233 DisplayId displayId;
234 if (mFreeVirtualDisplayIds.empty()) {
235 displayId = getVirtualDisplayId(mNextVirtualDisplayId++);
236 } else {
237 displayId = *mFreeVirtualDisplayIds.begin();
238 mFreeVirtualDisplayIds.erase(displayId);
239 }
240
241 auto& displayData = mDisplayData[displayId];
242 displayData.hwcDisplay = display;
243 displayData.isVirtual = true;
244
245 --mRemainingHwcVirtualDisplays;
246 return displayId;
247 }
248
createLayer(DisplayId displayId)249 HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
250 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
251
252 auto display = mDisplayData[displayId].hwcDisplay;
253 HWC2::Layer* layer;
254 auto error = display->createLayer(&layer);
255 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
256 return layer;
257 }
258
destroyLayer(DisplayId displayId,HWC2::Layer * layer)259 void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) {
260 RETURN_IF_INVALID_DISPLAY(displayId);
261
262 auto display = mDisplayData[displayId].hwcDisplay;
263 auto error = display->destroyLayer(layer);
264 RETURN_IF_HWC_ERROR(error, displayId);
265 }
266
getRefreshTimestamp(DisplayId displayId) const267 nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
268 RETURN_IF_INVALID_DISPLAY(displayId, 0);
269 const auto& displayData = mDisplayData.at(displayId);
270 // this returns the last refresh timestamp.
271 // if the last one is not available, we estimate it based on
272 // the refresh period and whatever closest timestamp we have.
273 std::lock_guard lock(displayData.lastHwVsyncLock);
274 nsecs_t now = systemTime(CLOCK_MONOTONIC);
275 auto vsyncPeriod = getActiveConfig(displayId)->getVsyncPeriod();
276 return now - ((now - displayData.lastHwVsync) % vsyncPeriod);
277 }
278
isConnected(DisplayId displayId) const279 bool HWComposer::isConnected(DisplayId displayId) const {
280 RETURN_IF_INVALID_DISPLAY(displayId, false);
281 return mDisplayData.at(displayId).hwcDisplay->isConnected();
282 }
283
getConfigs(DisplayId displayId) const284 std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs(
285 DisplayId displayId) const {
286 RETURN_IF_INVALID_DISPLAY(displayId, {});
287
288 const auto& displayData = mDisplayData.at(displayId);
289 auto configs = displayData.hwcDisplay->getConfigs();
290 if (displayData.configMap.empty()) {
291 for (size_t i = 0; i < configs.size(); ++i) {
292 displayData.configMap[i] = configs[i];
293 }
294 }
295 return configs;
296 }
297
getActiveConfig(DisplayId displayId) const298 std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
299 DisplayId displayId) const {
300 RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
301
302 std::shared_ptr<const HWC2::Display::Config> config;
303 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config);
304 if (error == HWC2::Error::BadConfig) {
305 LOG_DISPLAY_ERROR(displayId, "No active config");
306 return nullptr;
307 }
308
309 RETURN_IF_HWC_ERROR(error, displayId, nullptr);
310
311 if (!config) {
312 LOG_DISPLAY_ERROR(displayId, "Unknown config");
313 return nullptr;
314 }
315
316 return config;
317 }
318
getActiveConfigIndex(DisplayId displayId) const319 int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
320 RETURN_IF_INVALID_DISPLAY(displayId, -1);
321
322 int index;
323 auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index);
324 if (error == HWC2::Error::BadConfig) {
325 LOG_DISPLAY_ERROR(displayId, "No active config");
326 return -1;
327 }
328
329 RETURN_IF_HWC_ERROR(error, displayId, -1);
330
331 if (index < 0) {
332 LOG_DISPLAY_ERROR(displayId, "Unknown config");
333 return -1;
334 }
335
336 return index;
337 }
338
getColorModes(DisplayId displayId) const339 std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const {
340 RETURN_IF_INVALID_DISPLAY(displayId, {});
341
342 std::vector<ui::ColorMode> modes;
343 auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes);
344 RETURN_IF_HWC_ERROR(error, displayId, {});
345 return modes;
346 }
347
setActiveColorMode(DisplayId displayId,ui::ColorMode mode,ui::RenderIntent renderIntent)348 status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode,
349 ui::RenderIntent renderIntent) {
350 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
351
352 auto& displayData = mDisplayData[displayId];
353 auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent);
354 RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " +
355 decodeRenderIntent(renderIntent) + ")")
356 .c_str(),
357 error, displayId, UNKNOWN_ERROR);
358
359 return NO_ERROR;
360 }
361
setVsyncEnabled(DisplayId displayId,HWC2::Vsync enabled)362 void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) {
363 RETURN_IF_INVALID_DISPLAY(displayId);
364 auto& displayData = mDisplayData[displayId];
365
366 if (displayData.isVirtual) {
367 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
368 return;
369 }
370
371 // NOTE: we use our own internal lock here because we have to call
372 // into the HWC with the lock held, and we want to make sure
373 // that even if HWC blocks (which it shouldn't), it won't
374 // affect other threads.
375 std::lock_guard lock(displayData.vsyncEnabledLock);
376 if (enabled == displayData.vsyncEnabled) {
377 return;
378 }
379
380 ATRACE_CALL();
381 auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
382 RETURN_IF_HWC_ERROR(error, displayId);
383
384 displayData.vsyncEnabled = enabled;
385
386 const auto tag = "HW_VSYNC_ON_" + to_string(displayId);
387 ATRACE_INT(tag.c_str(), enabled == HWC2::Vsync::Enable ? 1 : 0);
388 }
389
setClientTarget(DisplayId displayId,uint32_t slot,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & target,ui::Dataspace dataspace)390 status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot,
391 const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
392 ui::Dataspace dataspace) {
393 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
394
395 ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str());
396 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
397 auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
398 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
399 return NO_ERROR;
400 }
401
prepare(DisplayId displayId,const compositionengine::Output & output)402 status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) {
403 ATRACE_CALL();
404
405 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
406
407 auto& displayData = mDisplayData[displayId];
408 auto& hwcDisplay = displayData.hwcDisplay;
409 if (!hwcDisplay->isConnected()) {
410 return NO_ERROR;
411 }
412
413 uint32_t numTypes = 0;
414 uint32_t numRequests = 0;
415
416 HWC2::Error error = HWC2::Error::None;
417
418 // First try to skip validate altogether when there is no client
419 // composition. When there is client composition, since we haven't
420 // rendered to the client target yet, we should not attempt to skip
421 // validate.
422 //
423 // displayData.hasClientComposition hasn't been updated for this frame.
424 // The check below is incorrect. We actually rely on HWC here to fall
425 // back to validate when there is any client layer.
426 displayData.validateWasSkipped = false;
427 if (!displayData.hasClientComposition) {
428 sp<Fence> outPresentFence;
429 uint32_t state = UINT32_MAX;
430 error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state);
431 if (error != HWC2::Error::HasChanges) {
432 RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR);
433 }
434 if (state == 1) { //Present Succeeded.
435 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
436 error = hwcDisplay->getReleaseFences(&releaseFences);
437 displayData.releaseFences = std::move(releaseFences);
438 displayData.lastPresentFence = outPresentFence;
439 displayData.validateWasSkipped = true;
440 displayData.presentError = error;
441 return NO_ERROR;
442 }
443 // Present failed but Validate ran.
444 } else {
445 error = hwcDisplay->validate(&numTypes, &numRequests);
446 }
447 ALOGV("SkipValidate failed, Falling back to SLOW validate/present");
448 if (error != HWC2::Error::HasChanges) {
449 RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX);
450 }
451
452 std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
453 changedTypes.reserve(numTypes);
454 error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
455 RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX);
456
457 displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
458 std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
459 layerRequests.reserve(numRequests);
460 error = hwcDisplay->getRequests(&displayData.displayRequests,
461 &layerRequests);
462 RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
463
464 displayData.hasClientComposition = false;
465 displayData.hasDeviceComposition = false;
466 for (auto& outputLayer : output.getOutputLayersOrderedByZ()) {
467 auto& state = outputLayer->editState();
468 LOG_FATAL_IF(!state.hwc.);
469 auto hwcLayer = (*state.hwc).hwcLayer;
470
471 if (auto it = changedTypes.find(hwcLayer.get()); it != changedTypes.end()) {
472 auto newCompositionType = it->second;
473 validateChange(static_cast<HWC2::Composition>((*state.hwc).hwcCompositionType),
474 newCompositionType);
475 (*state.hwc).hwcCompositionType =
476 static_cast<Hwc2::IComposerClient::Composition>(newCompositionType);
477 }
478
479 switch ((*state.hwc).hwcCompositionType) {
480 case Hwc2::IComposerClient::Composition::CLIENT:
481 displayData.hasClientComposition = true;
482 break;
483 case Hwc2::IComposerClient::Composition::DEVICE:
484 case Hwc2::IComposerClient::Composition::SOLID_COLOR:
485 case Hwc2::IComposerClient::Composition::CURSOR:
486 case Hwc2::IComposerClient::Composition::SIDEBAND:
487 displayData.hasDeviceComposition = true;
488 break;
489 default:
490 break;
491 }
492
493 state.clearClientTarget = false;
494 if (auto it = layerRequests.find(hwcLayer.get()); it != layerRequests.end()) {
495 auto request = it->second;
496 if (request == HWC2::LayerRequest::ClearClientTarget) {
497 state.clearClientTarget = true;
498 } else {
499 LOG_DISPLAY_ERROR(displayId,
500 ("Unknown layer request " + to_string(request)).c_str());
501 }
502 }
503 }
504
505 error = hwcDisplay->acceptChanges();
506 RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
507
508 return NO_ERROR;
509 }
510
hasDeviceComposition(const std::optional<DisplayId> & displayId) const511 bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const {
512 if (!displayId) {
513 // Displays without a corresponding HWC display are never composed by
514 // the device
515 return false;
516 }
517
518 RETURN_IF_INVALID_DISPLAY(*displayId, false);
519 return mDisplayData.at(*displayId).hasDeviceComposition;
520 }
521
hasFlipClientTargetRequest(const std::optional<DisplayId> & displayId) const522 bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const {
523 if (!displayId) {
524 // Displays without a corresponding HWC display are never composed by
525 // the device
526 return false;
527 }
528
529 RETURN_IF_INVALID_DISPLAY(*displayId, false);
530 return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) &
531 static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0);
532 }
533
hasClientComposition(const std::optional<DisplayId> & displayId) const534 bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const {
535 if (!displayId) {
536 // Displays without a corresponding HWC display are always composed by
537 // the client
538 return true;
539 }
540
541 RETURN_IF_INVALID_DISPLAY(*displayId, true);
542 return mDisplayData.at(*displayId).hasClientComposition;
543 }
544
getPresentFence(DisplayId displayId) const545 sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const {
546 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
547 return mDisplayData.at(displayId).lastPresentFence;
548 }
549
getLayerReleaseFence(DisplayId displayId,HWC2::Layer * layer) const550 sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const {
551 RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
552 auto displayFences = mDisplayData.at(displayId).releaseFences;
553 if (displayFences.count(layer) == 0) {
554 ALOGV("getLayerReleaseFence: Release fence not found");
555 return Fence::NO_FENCE;
556 }
557 return displayFences[layer];
558 }
559
presentAndGetReleaseFences(DisplayId displayId)560 status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) {
561 ATRACE_CALL();
562
563 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
564
565 auto& displayData = mDisplayData[displayId];
566 auto& hwcDisplay = displayData.hwcDisplay;
567
568 if (displayData.validateWasSkipped) {
569 // explicitly flush all pending commands
570 auto error = mHwcDevice->flushCommands();
571 RETURN_IF_HWC_ERROR_FOR("flushCommands", error, displayId, UNKNOWN_ERROR);
572 RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR);
573 return NO_ERROR;
574 }
575
576 auto error = hwcDisplay->present(&displayData.lastPresentFence);
577 RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
578
579 std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
580 error = hwcDisplay->getReleaseFences(&releaseFences);
581 RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR);
582
583 displayData.releaseFences = std::move(releaseFences);
584
585 return NO_ERROR;
586 }
587
setPowerMode(DisplayId displayId,int32_t intMode)588 status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) {
589 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
590
591 const auto& displayData = mDisplayData[displayId];
592 if (displayData.isVirtual) {
593 LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
594 return INVALID_OPERATION;
595 }
596
597 auto mode = static_cast<HWC2::PowerMode>(intMode);
598 if (mode == HWC2::PowerMode::Off) {
599 setVsyncEnabled(displayId, HWC2::Vsync::Disable);
600 }
601
602 auto& hwcDisplay = displayData.hwcDisplay;
603 switch (mode) {
604 case HWC2::PowerMode::Off:
605 case HWC2::PowerMode::On:
606 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
607 {
608 auto error = hwcDisplay->setPowerMode(mode);
609 if (error != HWC2::Error::None) {
610 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
611 error, displayId);
612 }
613 }
614 break;
615 case HWC2::PowerMode::Doze:
616 case HWC2::PowerMode::DozeSuspend:
617 ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
618 {
619 bool supportsDoze = false;
620 auto error = hwcDisplay->supportsDoze(&supportsDoze);
621 if (error != HWC2::Error::None) {
622 LOG_HWC_ERROR("supportsDoze", error, displayId);
623 }
624
625 if (!supportsDoze) {
626 mode = HWC2::PowerMode::On;
627 }
628
629 error = hwcDisplay->setPowerMode(mode);
630 if (error != HWC2::Error::None) {
631 LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(),
632 error, displayId);
633 }
634 }
635 break;
636 default:
637 ALOGV("setPowerMode: Not calling HWC");
638 break;
639 }
640
641 return NO_ERROR;
642 }
643
setActiveConfig(DisplayId displayId,size_t configId)644 status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) {
645 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
646
647 auto& displayData = mDisplayData[displayId];
648 if (displayData.configMap.count(configId) == 0) {
649 LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str());
650 return BAD_INDEX;
651 }
652
653 auto error = displayData.hwcDisplay->setActiveConfig(displayData.configMap[configId]);
654 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
655 return NO_ERROR;
656 }
657
setColorTransform(DisplayId displayId,const mat4 & transform)658 status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) {
659 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
660
661 auto& displayData = mDisplayData[displayId];
662 bool isIdentity = transform == mat4();
663 auto error = displayData.hwcDisplay->setColorTransform(transform,
664 isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY :
665 HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX);
666 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
667 return NO_ERROR;
668 }
669
disconnectDisplay(DisplayId displayId)670 void HWComposer::disconnectDisplay(DisplayId displayId) {
671 RETURN_IF_INVALID_DISPLAY(displayId);
672 auto& displayData = mDisplayData[displayId];
673
674 // If this was a virtual display, add its slot back for reuse by future
675 // virtual displays
676 if (displayData.isVirtual) {
677 mFreeVirtualDisplayIds.insert(displayId);
678 ++mRemainingHwcVirtualDisplays;
679 }
680
681 const auto hwcDisplayId = displayData.hwcDisplay->getId();
682 mPhysicalDisplayIdMap.erase(hwcDisplayId);
683 mDisplayData.erase(displayId);
684
685 // TODO(b/74619554): Select internal/external display from remaining displays.
686 if (hwcDisplayId == mInternalHwcDisplayId) {
687 mInternalHwcDisplayId.reset();
688 } else if (hwcDisplayId == mExternalHwcDisplayId) {
689 mExternalHwcDisplayId.reset();
690 }
691
692 mHwcDevice->destroyDisplay(hwcDisplayId);
693 }
694
setOutputBuffer(DisplayId displayId,const sp<Fence> & acquireFence,const sp<GraphicBuffer> & buffer)695 status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence,
696 const sp<GraphicBuffer>& buffer) {
697 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
698 const auto& displayData = mDisplayData[displayId];
699
700 if (!displayData.isVirtual) {
701 LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
702 return INVALID_OPERATION;
703 }
704
705 auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
706 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
707 return NO_ERROR;
708 }
709
clearReleaseFences(DisplayId displayId)710 void HWComposer::clearReleaseFences(DisplayId displayId) {
711 RETURN_IF_INVALID_DISPLAY(displayId);
712 mDisplayData[displayId].releaseFences.clear();
713 }
714
getHdrCapabilities(DisplayId displayId,HdrCapabilities * outCapabilities)715 status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) {
716 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
717
718 auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
719 auto error = hwcDisplay->getHdrCapabilities(outCapabilities);
720 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
721 return NO_ERROR;
722 }
723
getSupportedPerFrameMetadata(DisplayId displayId) const724 int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const {
725 RETURN_IF_INVALID_DISPLAY(displayId, 0);
726 return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata();
727 }
728
getRenderIntents(DisplayId displayId,ui::ColorMode colorMode) const729 std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId,
730 ui::ColorMode colorMode) const {
731 RETURN_IF_INVALID_DISPLAY(displayId, {});
732
733 std::vector<ui::RenderIntent> renderIntents;
734 auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents);
735 RETURN_IF_HWC_ERROR(error, displayId, {});
736 return renderIntents;
737 }
738
getDataspaceSaturationMatrix(DisplayId displayId,ui::Dataspace dataspace)739 mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) {
740 RETURN_IF_INVALID_DISPLAY(displayId, {});
741
742 mat4 matrix;
743 auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace,
744 &matrix);
745 RETURN_IF_HWC_ERROR(error, displayId, {});
746 return matrix;
747 }
748
getDisplayedContentSamplingAttributes(DisplayId displayId,ui::PixelFormat * outFormat,ui::Dataspace * outDataspace,uint8_t * outComponentMask)749 status_t HWComposer::getDisplayedContentSamplingAttributes(DisplayId displayId,
750 ui::PixelFormat* outFormat,
751 ui::Dataspace* outDataspace,
752 uint8_t* outComponentMask) {
753 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
754 const auto error =
755 mDisplayData[displayId]
756 .hwcDisplay->getDisplayedContentSamplingAttributes(outFormat, outDataspace,
757 outComponentMask);
758 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
759 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
760 return NO_ERROR;
761 }
762
setDisplayContentSamplingEnabled(DisplayId displayId,bool enabled,uint8_t componentMask,uint64_t maxFrames)763 status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
764 uint8_t componentMask, uint64_t maxFrames) {
765 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
766 const auto error =
767 mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
768 componentMask,
769 maxFrames);
770
771 if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
772 if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
773 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
774 return NO_ERROR;
775 }
776
getDisplayedContentSample(DisplayId displayId,uint64_t maxFrames,uint64_t timestamp,DisplayedFrameStats * outStats)777 status_t HWComposer::getDisplayedContentSample(DisplayId displayId, uint64_t maxFrames,
778 uint64_t timestamp, DisplayedFrameStats* outStats) {
779 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
780 const auto error =
781 mDisplayData[displayId].hwcDisplay->getDisplayedContentSample(maxFrames, timestamp,
782 outStats);
783 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
784 return NO_ERROR;
785 }
786
setDisplayBrightness(DisplayId displayId,float brightness)787 status_t HWComposer::setDisplayBrightness(DisplayId displayId, float brightness) {
788 RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
789 const auto error = mDisplayData[displayId].hwcDisplay->setDisplayBrightness(brightness);
790 if (error == HWC2::Error::Unsupported) {
791 RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
792 }
793 if (error == HWC2::Error::BadParameter) {
794 RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
795 }
796 RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
797 return NO_ERROR;
798 }
799
isUsingVrComposer() const800 bool HWComposer::isUsingVrComposer() const {
801 return getComposer()->isUsingVrComposer();
802 }
803
dump(std::string & result) const804 void HWComposer::dump(std::string& result) const {
805 // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
806 // all the state going into the layers. This is probably better done in
807 // Layer itself, but it's going to take a bit of work to get there.
808 result.append(mHwcDevice->dump());
809 }
810
toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const811 std::optional<DisplayId> HWComposer::toPhysicalDisplayId(hwc2_display_t hwcDisplayId) const {
812 if (const auto it = mPhysicalDisplayIdMap.find(hwcDisplayId);
813 it != mPhysicalDisplayIdMap.end()) {
814 return it->second;
815 }
816 return {};
817 }
818
fromPhysicalDisplayId(DisplayId displayId) const819 std::optional<hwc2_display_t> HWComposer::fromPhysicalDisplayId(DisplayId displayId) const {
820 if (const auto it = mDisplayData.find(displayId);
821 it != mDisplayData.end() && !it->second.isVirtual) {
822 return it->second.hwcDisplay->getId();
823 }
824 return {};
825 }
826
onHotplugConnect(hwc2_display_t hwcDisplayId)827 std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
828 if (isUsingVrComposer() && mInternalHwcDisplayId) {
829 ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
830 return {};
831 }
832
833 uint8_t port;
834 DisplayIdentificationData data;
835 const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data);
836
837 if (mPhysicalDisplayIdMap.empty()) {
838 mHasMultiDisplaySupport = hasMultiDisplaySupport;
839 ALOGI("Switching to %s multi-display mode",
840 hasMultiDisplaySupport ? "generalized" : "legacy");
841 } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) {
842 ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
843 hwcDisplayId);
844 return {};
845 }
846
847 std::optional<DisplayIdentificationInfo> info;
848
849 if (mHasMultiDisplaySupport) {
850 info = parseDisplayIdentificationData(port, data);
851 ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId);
852 } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) {
853 ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
854 return {};
855 } else {
856 ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64,
857 hwcDisplayId);
858 port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY;
859 }
860
861 if (!mInternalHwcDisplayId) {
862 mInternalHwcDisplayId = hwcDisplayId;
863 } else if (!mExternalHwcDisplayId) {
864 mExternalHwcDisplayId = hwcDisplayId;
865 }
866
867 if (info) return info;
868
869 return DisplayIdentificationInfo{getFallbackDisplayId(port),
870 hwcDisplayId == mInternalHwcDisplayId ? "Internal display"
871 : "External display"};
872 }
873
874 } // namespace impl
875 } // namespace android
876