| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 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 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 17 | // #define LOG_NDEBUG 0 | 
 | 18 |  | 
 | 19 | #undef LOG_TAG | 
 | 20 | #define LOG_TAG "HWComposer" | 
| Mathias Agopian | 2965b26 | 2012-04-08 15:13:32 -0700 | [diff] [blame] | 21 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS | 
 | 22 |  | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 23 | #include <compositionengine/Output.h> | 
 | 24 | #include <compositionengine/OutputLayer.h> | 
 | 25 | #include <compositionengine/impl/OutputLayerCompositionState.h> | 
 | 26 | #include <log/log.h> | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 27 | #include <ui/DebugUtils.h> | 
| Mathias Agopian | 921e6ac | 2012-07-23 23:11:29 -0700 | [diff] [blame] | 28 | #include <ui/GraphicBuffer.h> | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 29 | #include <utils/Errors.h> | 
 | 30 | #include <utils/Trace.h> | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 31 |  | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 32 | #include "HWComposer.h" | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 33 | #include "HWC2.h" | 
| Hendrik Wagenaar | 87670ff | 2017-02-01 12:10:46 -0800 | [diff] [blame] | 34 | #include "ComposerHal.h" | 
| Mathias Agopian | 33ceeb3 | 2013-04-01 16:54:58 -0700 | [diff] [blame] | 35 |  | 
 | 36 | #include "../Layer.h"           // needed only for debugging | 
 | 37 | #include "../SurfaceFlinger.h" | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 38 |  | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 39 | #define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \ | 
 | 40 |     ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg) | 
 | 41 |  | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 42 | #define LOG_DISPLAY_ERROR(displayId, msg) \ | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 43 |     ALOGE("%s failed for display %s: %s", __FUNCTION__, to_string(displayId).c_str(), msg) | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 44 |  | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 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)) | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 48 |  | 
 | 49 | #define RETURN_IF_INVALID_DISPLAY(displayId, ...)            \ | 
 | 50 |     do {                                                     \ | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 51 |         if (mDisplayData.count(displayId) == 0) {            \ | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 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 |  | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 68 | namespace android { | 
| Jesse Hall | 5880cc5 | 2012-06-05 23:40:32 -0700 | [diff] [blame] | 69 |  | 
| Lloyd Pique | 441d504 | 2018-10-18 16:49:51 -0700 | [diff] [blame] | 70 | HWComposer::~HWComposer() = default; | 
 | 71 |  | 
 | 72 | namespace impl { | 
 | 73 |  | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 74 | HWComposer::HWComposer(std::unique_ptr<Hwc2::Composer> composer) | 
| Lloyd Pique | a822d52 | 2017-12-20 16:42:57 -0800 | [diff] [blame] | 75 |       : mHwcDevice(std::make_unique<HWC2::Device>(std::move(composer))) {} | 
| Mathias Agopian | bef42c5 | 2013-08-21 17:45:46 -0700 | [diff] [blame] | 76 |  | 
| Dominik Laskowski | b04f98a | 2018-11-07 21:07:16 -0800 | [diff] [blame] | 77 | HWComposer::~HWComposer() { | 
 | 78 |     mDisplayData.clear(); | 
 | 79 | } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 80 |  | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 81 | void HWComposer::registerCallback(HWC2::ComposerCallback* callback, | 
 | 82 |                                   int32_t sequenceId) { | 
 | 83 |     mHwcDevice->registerCallback(callback, sequenceId); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 84 | } | 
 | 85 |  | 
| Dominik Laskowski | a2edf61 | 2018-06-01 13:15:16 -0700 | [diff] [blame] | 86 | bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort, | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 87 |                                               DisplayIdentificationData* outData) const { | 
| Dominik Laskowski | 0954b1d | 2018-06-13 14:58:49 -0700 | [diff] [blame] | 88 |     const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData); | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 89 |     if (error != HWC2::Error::None) { | 
| Chia-I Wu | d0aff9d | 2018-06-21 13:39:09 +0800 | [diff] [blame] | 90 |         if (error != HWC2::Error::Unsupported) { | 
 | 91 |             LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str()); | 
 | 92 |         } | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 93 |         return false; | 
 | 94 |     } | 
 | 95 |     return true; | 
 | 96 | } | 
 | 97 |  | 
| Dan Stoza | 9f26a9c | 2016-06-22 14:51:09 -0700 | [diff] [blame] | 98 | bool HWComposer::hasCapability(HWC2::Capability capability) const | 
 | 99 | { | 
 | 100 |     return mHwcDevice->getCapabilities().count(capability) > 0; | 
 | 101 | } | 
 | 102 |  | 
| Peiyong Lin | ed531a3 | 2018-10-26 18:27:56 -0700 | [diff] [blame] | 103 | bool HWComposer::hasDisplayCapability(const std::optional<DisplayId>& displayId, | 
 | 104 |                                       HWC2::DisplayCapability capability) const { | 
 | 105 |     if (!displayId) { | 
| Peiyong Lin | df65fd2 | 2019-01-03 15:17:05 -0800 | [diff] [blame] | 106 |         // Checkout global capabilities for displays without a corresponding HWC display. | 
 | 107 |         if (capability == HWC2::DisplayCapability::SkipClientColorTransform) { | 
 | 108 |             return hasCapability(HWC2::Capability::SkipClientColorTransform); | 
 | 109 |         } | 
| Peiyong Lin | ed531a3 | 2018-10-26 18:27:56 -0700 | [diff] [blame] | 110 |         return false; | 
 | 111 |     } | 
 | 112 |     RETURN_IF_INVALID_DISPLAY(*displayId, false); | 
 | 113 |     return mDisplayData.at(*displayId).hwcDisplay->getCapabilities().count(capability) > 0; | 
 | 114 | } | 
 | 115 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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()); | 
| Andy McFadden | b0d1dd3 | 2012-09-10 14:08:09 -0700 | [diff] [blame] | 138 |     } | 
 | 139 | } | 
 | 140 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 141 | std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, | 
 | 142 |                                                                HWC2::Connection connection) { | 
 | 143 |     std::optional<DisplayIdentificationInfo> info; | 
| Lloyd Pique | 715a2c1 | 2017-12-14 17:18:08 -0800 | [diff] [blame] | 144 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 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 {}; | 
| Lloyd Pique | 438e9e7 | 2018-09-04 18:06:08 -0700 | [diff] [blame] | 151 |         } | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 152 |  | 
 | 153 |         info = onHotplugConnect(hwcDisplayId); | 
 | 154 |         if (!info) return {}; | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 155 |     } | 
 | 156 |  | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 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); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 160 |  | 
 | 161 |     mHwcDevice->onHotplug(hwcDisplayId, connection); | 
 | 162 |  | 
| Lloyd Pique | 715a2c1 | 2017-12-14 17:18:08 -0800 | [diff] [blame] | 163 |     // Disconnect is handled through HWComposer::disconnectDisplay via | 
 | 164 |     // SurfaceFlinger's onHotplugReceived callback handling | 
 | 165 |     if (connection == HWC2::Connection::Connected) { | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 166 |         mDisplayData[info->id].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId); | 
 | 167 |         mPhysicalDisplayIdMap[hwcDisplayId] = info->id; | 
| Andy McFadden | b0d1dd3 | 2012-09-10 14:08:09 -0700 | [diff] [blame] | 168 |     } | 
| Dominik Laskowski | e9ef7c4 | 2018-03-12 19:34:30 -0700 | [diff] [blame] | 169 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 170 |     return info; | 
| Andy McFadden | b0d1dd3 | 2012-09-10 14:08:09 -0700 | [diff] [blame] | 171 | } | 
 | 172 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 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"); | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 177 |         return false; | 
| Jesse Hall | 1bd20e0 | 2012-08-29 10:47:52 -0700 | [diff] [blame] | 178 |     } | 
| Jesse Hall | 1bd20e0 | 2012-08-29 10:47:52 -0700 | [diff] [blame] | 179 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 180 |     RETURN_IF_INVALID_DISPLAY(*displayId, false); | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 181 |  | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 182 |     auto& displayData = mDisplayData[*displayId]; | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 183 |     if (displayData.isVirtual) { | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 184 |         LOG_DISPLAY_ERROR(*displayId, "Invalid operation on virtual display"); | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 185 |         return false; | 
| Jesse Hall | 1bd20e0 | 2012-08-29 10:47:52 -0700 | [diff] [blame] | 186 |     } | 
 | 187 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 188 |     { | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 189 |         std::lock_guard lock(displayData.lastHwVsyncLock); | 
| Jesse Hall | 1bd20e0 | 2012-08-29 10:47:52 -0700 | [diff] [blame] | 190 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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. | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 195 |         if (timestamp == displayData.lastHwVsync) { | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 196 |             ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")", | 
 | 197 |                   to_string(*displayId).c_str(), timestamp); | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 198 |             return false; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 199 |         } | 
 | 200 |  | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 201 |         displayData.lastHwVsync = timestamp; | 
| Jesse Hall | 1c569c4 | 2013-04-05 13:44:52 -0700 | [diff] [blame] | 202 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 203 |  | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 204 |     const auto tag = "HW_VSYNC_" + to_string(*displayId); | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 205 |     ATRACE_INT(tag.c_str(), displayData.vsyncTraceToggle); | 
 | 206 |     displayData.vsyncTraceToggle = !displayData.vsyncTraceToggle; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 207 |  | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 208 |     return true; | 
| Jesse Hall | 1c569c4 | 2013-04-05 13:44:52 -0700 | [diff] [blame] | 209 | } | 
 | 210 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 211 | std::optional<DisplayId> HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height, | 
 | 212 |                                                             ui::PixelFormat* format) { | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 213 |     if (mRemainingHwcVirtualDisplays == 0) { | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 214 |         ALOGE("%s: No remaining virtual displays", __FUNCTION__); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 215 |         return {}; | 
| Mathias Agopian | e60b068 | 2012-08-21 23:34:09 -0700 | [diff] [blame] | 216 |     } | 
| Mathias Agopian | e60b068 | 2012-08-21 23:34:09 -0700 | [diff] [blame] | 217 |  | 
| Fabien Sanglard | c8e387e | 2017-03-10 10:30:28 -0800 | [diff] [blame] | 218 |     if (SurfaceFlinger::maxVirtualDisplaySize != 0 && | 
 | 219 |         (width > SurfaceFlinger::maxVirtualDisplaySize || | 
 | 220 |          height > SurfaceFlinger::maxVirtualDisplaySize)) { | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 221 |         ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width, | 
 | 222 |               height, SurfaceFlinger::maxVirtualDisplaySize); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 223 |         return {}; | 
| Fabien Sanglard | e29055f | 2017-03-08 11:36:46 -0800 | [diff] [blame] | 224 |     } | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 225 |     HWC2::Display* display; | 
| Dan Stoza | 5cf424b | 2016-05-20 14:02:39 -0700 | [diff] [blame] | 226 |     auto error = mHwcDevice->createVirtualDisplay(width, height, format, | 
 | 227 |             &display); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 228 |     if (error != HWC2::Error::None) { | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 229 |         ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 230 |         return {}; | 
| Mathias Agopian | e60b068 | 2012-08-21 23:34:09 -0700 | [diff] [blame] | 231 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 232 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 233 |     DisplayId displayId; | 
 | 234 |     if (mFreeVirtualDisplayIds.empty()) { | 
 | 235 |         displayId = getVirtualDisplayId(mNextVirtualDisplayId++); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 236 |     } else { | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 237 |         displayId = *mFreeVirtualDisplayIds.begin(); | 
 | 238 |         mFreeVirtualDisplayIds.erase(displayId); | 
| Mathias Agopian | e60b068 | 2012-08-21 23:34:09 -0700 | [diff] [blame] | 239 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 240 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 241 |     auto& displayData = mDisplayData[displayId]; | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 242 |     displayData.hwcDisplay = display; | 
 | 243 |     displayData.isVirtual = true; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 244 |  | 
 | 245 |     --mRemainingHwcVirtualDisplays; | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 246 |     return displayId; | 
| Mathias Agopian | e60b068 | 2012-08-21 23:34:09 -0700 | [diff] [blame] | 247 | } | 
 | 248 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 249 | HWC2::Layer* HWComposer::createLayer(DisplayId displayId) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 250 |     RETURN_IF_INVALID_DISPLAY(displayId, nullptr); | 
 | 251 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 252 |     auto display = mDisplayData[displayId].hwcDisplay; | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 253 |     HWC2::Layer* layer; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 254 |     auto error = display->createLayer(&layer); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 255 |     RETURN_IF_HWC_ERROR(error, displayId, nullptr); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 256 |     return layer; | 
 | 257 | } | 
 | 258 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 259 | void HWComposer::destroyLayer(DisplayId displayId, HWC2::Layer* layer) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 260 |     RETURN_IF_INVALID_DISPLAY(displayId); | 
 | 261 |  | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 262 |     auto display = mDisplayData[displayId].hwcDisplay; | 
 | 263 |     auto error = display->destroyLayer(layer); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 264 |     RETURN_IF_HWC_ERROR(error, displayId); | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 265 | } | 
 | 266 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 267 | nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const { | 
 | 268 |     RETURN_IF_INVALID_DISPLAY(displayId, 0); | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 269 |     const auto& displayData = mDisplayData.at(displayId); | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 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. | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 273 |     std::lock_guard lock(displayData.lastHwVsyncLock); | 
| Mathias Agopian | d3ee231 | 2012-08-02 14:01:42 -0700 | [diff] [blame] | 274 |     nsecs_t now = systemTime(CLOCK_MONOTONIC); | 
| Fabien Sanglard | df0b705 | 2016-11-30 15:51:53 -0800 | [diff] [blame] | 275 |     auto vsyncPeriod = getActiveConfig(displayId)->getVsyncPeriod(); | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 276 |     return now - ((now - displayData.lastHwVsync) % vsyncPeriod); | 
| Mathias Agopian | 3eb38cb | 2012-04-03 22:09:52 -0700 | [diff] [blame] | 277 | } | 
 | 278 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 279 | bool HWComposer::isConnected(DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 280 |     RETURN_IF_INVALID_DISPLAY(displayId, false); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 281 |     return mDisplayData.at(displayId).hwcDisplay->isConnected(); | 
| Mathias Agopian | 9c6e297 | 2011-09-20 17:21:56 -0700 | [diff] [blame] | 282 | } | 
 | 283 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 284 | std::vector<std::shared_ptr<const HWC2::Display::Config>> HWComposer::getConfigs( | 
 | 285 |         DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 286 |     RETURN_IF_INVALID_DISPLAY(displayId, {}); | 
 | 287 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 288 |     const auto& displayData = mDisplayData.at(displayId); | 
 | 289 |     auto configs = displayData.hwcDisplay->getConfigs(); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 290 |     if (displayData.configMap.empty()) { | 
 | 291 |         for (size_t i = 0; i < configs.size(); ++i) { | 
 | 292 |             displayData.configMap[i] = configs[i]; | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 293 |         } | 
 | 294 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 295 |     return configs; | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 296 | } | 
 | 297 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 298 | std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig( | 
 | 299 |         DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 300 |     RETURN_IF_INVALID_DISPLAY(displayId, nullptr); | 
 | 301 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 302 |     std::shared_ptr<const HWC2::Display::Config> config; | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 303 |     auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfig(&config); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 304 |     if (error == HWC2::Error::BadConfig) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 305 |         LOG_DISPLAY_ERROR(displayId, "No active config"); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 306 |         return nullptr; | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 307 |     } | 
 | 308 |  | 
 | 309 |     RETURN_IF_HWC_ERROR(error, displayId, nullptr); | 
 | 310 |  | 
 | 311 |     if (!config) { | 
 | 312 |         LOG_DISPLAY_ERROR(displayId, "Unknown config"); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 313 |         return nullptr; | 
 | 314 |     } | 
 | 315 |  | 
 | 316 |     return config; | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 317 | } | 
 | 318 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 319 | int HWComposer::getActiveConfigIndex(DisplayId displayId) const { | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 320 |     RETURN_IF_INVALID_DISPLAY(displayId, -1); | 
 | 321 |  | 
| Lloyd Pique | 3c085a0 | 2018-05-09 19:38:32 -0700 | [diff] [blame] | 322 |     int index; | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 323 |     auto error = mDisplayData.at(displayId).hwcDisplay->getActiveConfigIndex(&index); | 
| Lloyd Pique | 3c085a0 | 2018-05-09 19:38:32 -0700 | [diff] [blame] | 324 |     if (error == HWC2::Error::BadConfig) { | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 325 |         LOG_DISPLAY_ERROR(displayId, "No active config"); | 
| Lloyd Pique | 3c085a0 | 2018-05-09 19:38:32 -0700 | [diff] [blame] | 326 |         return -1; | 
| Dominik Laskowski | f3749f8 | 2018-06-13 15:49:25 -0700 | [diff] [blame] | 327 |     } | 
 | 328 |  | 
 | 329 |     RETURN_IF_HWC_ERROR(error, displayId, -1); | 
 | 330 |  | 
 | 331 |     if (index < 0) { | 
 | 332 |         LOG_DISPLAY_ERROR(displayId, "Unknown config"); | 
| Lloyd Pique | 3c085a0 | 2018-05-09 19:38:32 -0700 | [diff] [blame] | 333 |         return -1; | 
 | 334 |     } | 
 | 335 |  | 
 | 336 |     return index; | 
 | 337 | } | 
 | 338 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 339 | std::vector<ui::ColorMode> HWComposer::getColorModes(DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 340 |     RETURN_IF_INVALID_DISPLAY(displayId, {}); | 
 | 341 |  | 
| Peiyong Lin | fd997e0 | 2018-03-28 15:29:00 -0700 | [diff] [blame] | 342 |     std::vector<ui::ColorMode> modes; | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 343 |     auto error = mDisplayData.at(displayId).hwcDisplay->getColorModes(&modes); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 344 |     RETURN_IF_HWC_ERROR(error, displayId, {}); | 
| Courtney Goeltzenleuchter | fad9d8c | 2016-06-23 11:49:50 -0600 | [diff] [blame] | 345 |     return modes; | 
 | 346 | } | 
 | 347 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 348 | status_t HWComposer::setActiveColorMode(DisplayId displayId, ui::ColorMode mode, | 
 | 349 |                                         ui::RenderIntent renderIntent) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 350 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 351 |  | 
 | 352 |     auto& displayData = mDisplayData[displayId]; | 
| Peiyong Lin | 0e7a791 | 2018-04-05 14:36:36 -0700 | [diff] [blame] | 353 |     auto error = displayData.hwcDisplay->setColorMode(mode, renderIntent); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 354 |     RETURN_IF_HWC_ERROR_FOR(("setColorMode(" + decodeColorMode(mode) + ", " + | 
 | 355 |                              decodeRenderIntent(renderIntent) + ")") | 
 | 356 |                                     .c_str(), | 
 | 357 |                             error, displayId, UNKNOWN_ERROR); | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 358 |  | 
 | 359 |     return NO_ERROR; | 
 | 360 | } | 
 | 361 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 362 | void HWComposer::setVsyncEnabled(DisplayId displayId, HWC2::Vsync enabled) { | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 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"); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 368 |         return; | 
 | 369 |     } | 
 | 370 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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. | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 375 |     std::lock_guard lock(displayData.vsyncEnabledLock); | 
 | 376 |     if (enabled == displayData.vsyncEnabled) { | 
 | 377 |         return; | 
| Colin Cross | 10fbdb6 | 2012-07-12 17:56:34 -0700 | [diff] [blame] | 378 |     } | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 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); | 
| Colin Cross | 10fbdb6 | 2012-07-12 17:56:34 -0700 | [diff] [blame] | 388 | } | 
 | 389 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 390 | status_t HWComposer::setClientTarget(DisplayId displayId, uint32_t slot, | 
 | 391 |                                      const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target, | 
 | 392 |                                      ui::Dataspace dataspace) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 393 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Jesse Hall | 851cfe8 | 2013-03-20 13:44:00 -0700 | [diff] [blame] | 394 |  | 
| Dominik Laskowski | 3415776 | 2018-10-31 13:07:19 -0700 | [diff] [blame] | 395 |     ALOGV("%s for display %s", __FUNCTION__, to_string(displayId).c_str()); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 396 |     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; | 
| Daniel Nicoara | 1f42e3a | 2017-04-10 13:27:32 -0400 | [diff] [blame] | 397 |     auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 398 |     RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE); | 
| Jesse Hall | 851cfe8 | 2013-03-20 13:44:00 -0700 | [diff] [blame] | 399 |     return NO_ERROR; | 
 | 400 | } | 
 | 401 |  | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 402 | status_t HWComposer::prepare(DisplayId displayId, const compositionengine::Output& output) { | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 403 |     ATRACE_CALL(); | 
 | 404 |  | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 405 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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; | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 415 |  | 
 | 416 |     HWC2::Error error = HWC2::Error::None; | 
 | 417 |  | 
| Chia-I Wu | 41b98d4 | 2017-12-11 11:04:36 -0800 | [diff] [blame] | 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. | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 426 |     displayData.validateWasSkipped = false; | 
| Chia-I Wu | 41b98d4 | 2017-12-11 11:04:36 -0800 | [diff] [blame] | 427 |     if (!displayData.hasClientComposition) { | 
| Dominik Laskowski | 1af4793 | 2018-11-12 10:20:46 -0800 | [diff] [blame] | 428 |         sp<Fence> outPresentFence; | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 429 |         uint32_t state = UINT32_MAX; | 
 | 430 |         error = hwcDisplay->presentOrValidate(&numTypes, &numRequests, &outPresentFence , &state); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 431 |         if (error != HWC2::Error::HasChanges) { | 
 | 432 |             RETURN_IF_HWC_ERROR_FOR("presentOrValidate", error, displayId, UNKNOWN_ERROR); | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 433 |         } | 
 | 434 |         if (state == 1) { //Present Succeeded. | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 435 |             std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 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"); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 448 |     if (error != HWC2::Error::HasChanges) { | 
 | 449 |         RETURN_IF_HWC_ERROR_FOR("validate", error, displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 450 |     } | 
 | 451 |  | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 452 |     std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 453 |     changedTypes.reserve(numTypes); | 
 | 454 |     error = hwcDisplay->getChangedCompositionTypes(&changedTypes); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 455 |     RETURN_IF_HWC_ERROR_FOR("getChangedCompositionTypes", error, displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 456 |  | 
 | 457 |     displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0); | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 458 |     std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 459 |     layerRequests.reserve(numRequests); | 
 | 460 |     error = hwcDisplay->getRequests(&displayData.displayRequests, | 
 | 461 |             &layerRequests); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 462 |     RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 463 |  | 
 | 464 |     displayData.hasClientComposition = false; | 
 | 465 |     displayData.hasDeviceComposition = false; | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 466 |     for (auto& outputLayer : output.getOutputLayersOrderedByZ()) { | 
 | 467 |         auto& state = outputLayer->editState(); | 
 | 468 |         LOG_FATAL_IF(!state.hwc.); | 
 | 469 |         auto hwcLayer = (*state.hwc).hwcLayer; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 470 |  | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 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); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 477 |         } | 
 | 478 |  | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 479 |         switch ((*state.hwc).hwcCompositionType) { | 
 | 480 |             case Hwc2::IComposerClient::Composition::CLIENT: | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 481 |                 displayData.hasClientComposition = true; | 
 | 482 |                 break; | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 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: | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 487 |                 displayData.hasDeviceComposition = true; | 
 | 488 |                 break; | 
 | 489 |             default: | 
 | 490 |                 break; | 
 | 491 |         } | 
 | 492 |  | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 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 { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 499 |                 LOG_DISPLAY_ERROR(displayId, | 
| Lloyd Pique | 37c2c9b | 2018-12-04 17:25:10 -0800 | [diff] [blame] | 500 |                                   ("Unknown layer request " + to_string(request)).c_str()); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 501 |             } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 502 |         } | 
 | 503 |     } | 
 | 504 |  | 
 | 505 |     error = hwcDisplay->acceptChanges(); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 506 |     RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 507 |  | 
 | 508 |     return NO_ERROR; | 
 | 509 | } | 
 | 510 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 511 | bool HWComposer::hasDeviceComposition(const std::optional<DisplayId>& displayId) const { | 
 | 512 |     if (!displayId) { | 
| Dan Stoza | ec0f717 | 2016-07-21 11:09:40 -0700 | [diff] [blame] | 513 |         // Displays without a corresponding HWC display are never composed by | 
 | 514 |         // the device | 
 | 515 |         return false; | 
 | 516 |     } | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 517 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 518 |     RETURN_IF_INVALID_DISPLAY(*displayId, false); | 
 | 519 |     return mDisplayData.at(*displayId).hasDeviceComposition; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 520 | } | 
 | 521 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 522 | bool HWComposer::hasFlipClientTargetRequest(const std::optional<DisplayId>& displayId) const { | 
 | 523 |     if (!displayId) { | 
| Madhuri Athota | 88a905b | 2017-05-04 16:58:15 +0530 | [diff] [blame] | 524 |         // Displays without a corresponding HWC display are never composed by | 
 | 525 |         // the device | 
 | 526 |         return false; | 
 | 527 |     } | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 528 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 529 |     RETURN_IF_INVALID_DISPLAY(*displayId, false); | 
 | 530 |     return ((static_cast<uint32_t>(mDisplayData.at(*displayId).displayRequests) & | 
| Madhuri Athota | 88a905b | 2017-05-04 16:58:15 +0530 | [diff] [blame] | 531 |              static_cast<uint32_t>(HWC2::DisplayRequest::FlipClientTarget)) != 0); | 
 | 532 | } | 
 | 533 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 534 | bool HWComposer::hasClientComposition(const std::optional<DisplayId>& displayId) const { | 
 | 535 |     if (!displayId) { | 
| Dan Stoza | ec0f717 | 2016-07-21 11:09:40 -0700 | [diff] [blame] | 536 |         // Displays without a corresponding HWC display are always composed by | 
 | 537 |         // the client | 
 | 538 |         return true; | 
 | 539 |     } | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 540 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 541 |     RETURN_IF_INVALID_DISPLAY(*displayId, true); | 
 | 542 |     return mDisplayData.at(*displayId).hasClientComposition; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 543 | } | 
 | 544 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 545 | sp<Fence> HWComposer::getPresentFence(DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 546 |     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 547 |     return mDisplayData.at(displayId).lastPresentFence; | 
| Jesse Hall | 851cfe8 | 2013-03-20 13:44:00 -0700 | [diff] [blame] | 548 | } | 
 | 549 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 550 | sp<Fence> HWComposer::getLayerReleaseFence(DisplayId displayId, HWC2::Layer* layer) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 551 |     RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 552 |     auto displayFences = mDisplayData.at(displayId).releaseFences; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 553 |     if (displayFences.count(layer) == 0) { | 
 | 554 |         ALOGV("getLayerReleaseFence: Release fence not found"); | 
 | 555 |         return Fence::NO_FENCE; | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 556 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 557 |     return displayFences[layer]; | 
| Riley Andrews | 03414a1 | 2014-07-01 14:22:59 -0700 | [diff] [blame] | 558 | } | 
 | 559 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 560 | status_t HWComposer::presentAndGetReleaseFences(DisplayId displayId) { | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 561 |     ATRACE_CALL(); | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 562 |  | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 563 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Pablo Ceballos | d814cf2 | 2015-09-11 14:37:39 -0700 | [diff] [blame] | 564 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 565 |     auto& displayData = mDisplayData[displayId]; | 
 | 566 |     auto& hwcDisplay = displayData.hwcDisplay; | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 567 |  | 
 | 568 |     if (displayData.validateWasSkipped) { | 
| Chia-I Wu | ae5a6b8 | 2017-10-10 09:09:22 -0700 | [diff] [blame] | 569 |         // explicitly flush all pending commands | 
 | 570 |         auto error = mHwcDevice->flushCommands(); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 571 |         RETURN_IF_HWC_ERROR_FOR("flushCommands", error, displayId, UNKNOWN_ERROR); | 
 | 572 |         RETURN_IF_HWC_ERROR_FOR("present", displayData.presentError, displayId, UNKNOWN_ERROR); | 
| Fabien Sanglard | 249c0ae | 2017-06-19 19:22:36 -0700 | [diff] [blame] | 573 |         return NO_ERROR; | 
 | 574 |     } | 
 | 575 |  | 
| Fabien Sanglard | 11d0fc3 | 2016-12-01 15:43:01 -0800 | [diff] [blame] | 576 |     auto error = hwcDisplay->present(&displayData.lastPresentFence); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 577 |     RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR); | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 578 |  | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 579 |     std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 580 |     error = hwcDisplay->getReleaseFences(&releaseFences); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 581 |     RETURN_IF_HWC_ERROR_FOR("getReleaseFences", error, displayId, UNKNOWN_ERROR); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 582 |  | 
 | 583 |     displayData.releaseFences = std::move(releaseFences); | 
 | 584 |  | 
 | 585 |     return NO_ERROR; | 
| Mathias Agopian | a350ff9 | 2010-08-10 17:14:02 -0700 | [diff] [blame] | 586 | } | 
 | 587 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 588 | status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 589 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
 | 590 |  | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 591 |     const auto& displayData = mDisplayData[displayId]; | 
 | 592 |     if (displayData.isVirtual) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 593 |         LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display"); | 
 | 594 |         return INVALID_OPERATION; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 595 |     } | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 596 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 597 |     auto mode = static_cast<HWC2::PowerMode>(intMode); | 
 | 598 |     if (mode == HWC2::PowerMode::Off) { | 
 | 599 |         setVsyncEnabled(displayId, HWC2::Vsync::Disable); | 
 | 600 |     } | 
 | 601 |  | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 602 |     auto& hwcDisplay = displayData.hwcDisplay; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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); | 
| Peiyong Lin | 306e499 | 2018-05-07 16:18:22 -0700 | [diff] [blame] | 609 |                 if (error != HWC2::Error::None) { | 
 | 610 |                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), | 
 | 611 |                                   error, displayId); | 
 | 612 |                 } | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 613 |             } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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); | 
| Peiyong Lin | 306e499 | 2018-05-07 16:18:22 -0700 | [diff] [blame] | 621 |                 if (error != HWC2::Error::None) { | 
 | 622 |                     LOG_HWC_ERROR("supportsDoze", error, displayId); | 
 | 623 |                 } | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 624 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 625 |                 if (!supportsDoze) { | 
 | 626 |                     mode = HWC2::PowerMode::On; | 
 | 627 |                 } | 
 | 628 |  | 
 | 629 |                 error = hwcDisplay->setPowerMode(mode); | 
| Peiyong Lin | 306e499 | 2018-05-07 16:18:22 -0700 | [diff] [blame] | 630 |                 if (error != HWC2::Error::None) { | 
 | 631 |                     LOG_HWC_ERROR(("setPowerMode(" + to_string(mode) + ")").c_str(), | 
 | 632 |                                   error, displayId); | 
 | 633 |                 } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 634 |             } | 
 | 635 |             break; | 
 | 636 |         default: | 
 | 637 |             ALOGV("setPowerMode: Not calling HWC"); | 
 | 638 |             break; | 
| Mathias Agopian | da27af9 | 2012-09-13 18:17:13 -0700 | [diff] [blame] | 639 |     } | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 640 |  | 
 | 641 |     return NO_ERROR; | 
 | 642 | } | 
 | 643 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 644 | status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 645 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 646 |  | 
 | 647 |     auto& displayData = mDisplayData[displayId]; | 
 | 648 |     if (displayData.configMap.count(configId) == 0) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 649 |         LOG_DISPLAY_ERROR(displayId, ("Invalid config " + std::to_string(configId)).c_str()); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 650 |         return BAD_INDEX; | 
 | 651 |     } | 
 | 652 |  | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 653 |     auto error = displayData.hwcDisplay->setActiveConfig(displayData.configMap[configId]); | 
 | 654 |     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 655 |     return NO_ERROR; | 
 | 656 | } | 
 | 657 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 658 | status_t HWComposer::setColorTransform(DisplayId displayId, const mat4& transform) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 659 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Dan Stoza | 9f26a9c | 2016-06-22 14:51:09 -0700 | [diff] [blame] | 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); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 666 |     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); | 
| Dan Stoza | 9f26a9c | 2016-06-22 14:51:09 -0700 | [diff] [blame] | 667 |     return NO_ERROR; | 
 | 668 | } | 
 | 669 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 670 | void HWComposer::disconnectDisplay(DisplayId displayId) { | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 671 |     RETURN_IF_INVALID_DISPLAY(displayId); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 672 |     auto& displayData = mDisplayData[displayId]; | 
 | 673 |  | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 674 |     // If this was a virtual display, add its slot back for reuse by future | 
 | 675 |     // virtual displays | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 676 |     if (displayData.isVirtual) { | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 677 |         mFreeVirtualDisplayIds.insert(displayId); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 678 |         ++mRemainingHwcVirtualDisplays; | 
 | 679 |     } | 
 | 680 |  | 
| Dominik Laskowski | 7e04546 | 2018-05-30 13:02:02 -0700 | [diff] [blame] | 681 |     const auto hwcDisplayId = displayData.hwcDisplay->getId(); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 682 |     mPhysicalDisplayIdMap.erase(hwcDisplayId); | 
 | 683 |     mDisplayData.erase(displayId); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 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 |     } | 
| Steven Thomas | 94e35b9 | 2017-07-26 18:48:28 -0700 | [diff] [blame] | 691 |  | 
| Dominik Laskowski | 7e04546 | 2018-05-30 13:02:02 -0700 | [diff] [blame] | 692 |     mHwcDevice->destroyDisplay(hwcDisplayId); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 693 | } | 
 | 694 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 695 | status_t HWComposer::setOutputBuffer(DisplayId displayId, const sp<Fence>& acquireFence, | 
 | 696 |                                      const sp<GraphicBuffer>& buffer) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 697 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 698 |     const auto& displayData = mDisplayData[displayId]; | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 699 |  | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 700 |     if (!displayData.isVirtual) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 701 |         LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display"); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 702 |         return INVALID_OPERATION; | 
 | 703 |     } | 
 | 704 |  | 
| Dominik Laskowski | c1f18f6 | 2018-06-13 15:17:55 -0700 | [diff] [blame] | 705 |     auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 706 |     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 707 |     return NO_ERROR; | 
 | 708 | } | 
 | 709 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 710 | void HWComposer::clearReleaseFences(DisplayId displayId) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 711 |     RETURN_IF_INVALID_DISPLAY(displayId); | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 712 |     mDisplayData[displayId].releaseFences.clear(); | 
| Mathias Agopian | 3e8b853 | 2012-05-13 20:42:01 -0700 | [diff] [blame] | 713 | } | 
 | 714 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 715 | status_t HWComposer::getHdrCapabilities(DisplayId displayId, HdrCapabilities* outCapabilities) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 716 |     RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX); | 
| Dan Stoza | c4f471e | 2016-03-24 09:31:08 -0700 | [diff] [blame] | 717 |  | 
 | 718 |     auto& hwcDisplay = mDisplayData[displayId].hwcDisplay; | 
| Peiyong Lin | 6266589 | 2018-04-16 11:07:44 -0700 | [diff] [blame] | 719 |     auto error = hwcDisplay->getHdrCapabilities(outCapabilities); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 720 |     RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR); | 
| Peiyong Lin | 6266589 | 2018-04-16 11:07:44 -0700 | [diff] [blame] | 721 |     return NO_ERROR; | 
| Dan Stoza | c4f471e | 2016-03-24 09:31:08 -0700 | [diff] [blame] | 722 | } | 
 | 723 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 724 | int32_t HWComposer::getSupportedPerFrameMetadata(DisplayId displayId) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 725 |     RETURN_IF_INVALID_DISPLAY(displayId, 0); | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 726 |     return mDisplayData.at(displayId).hwcDisplay->getSupportedPerFrameMetadata(); | 
| Peiyong Lin | 0ac5f4e | 2018-04-19 22:06:34 -0700 | [diff] [blame] | 727 | } | 
 | 728 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 729 | std::vector<ui::RenderIntent> HWComposer::getRenderIntents(DisplayId displayId, | 
 | 730 |                                                            ui::ColorMode colorMode) const { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 731 |     RETURN_IF_INVALID_DISPLAY(displayId, {}); | 
| Peiyong Lin | 0e7a791 | 2018-04-05 14:36:36 -0700 | [diff] [blame] | 732 |  | 
 | 733 |     std::vector<ui::RenderIntent> renderIntents; | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 734 |     auto error = mDisplayData.at(displayId).hwcDisplay->getRenderIntents(colorMode, &renderIntents); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 735 |     RETURN_IF_HWC_ERROR(error, displayId, {}); | 
| Peiyong Lin | 0e7a791 | 2018-04-05 14:36:36 -0700 | [diff] [blame] | 736 |     return renderIntents; | 
 | 737 | } | 
 | 738 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 739 | mat4 HWComposer::getDataspaceSaturationMatrix(DisplayId displayId, ui::Dataspace dataspace) { | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 740 |     RETURN_IF_INVALID_DISPLAY(displayId, {}); | 
| Peiyong Lin | 0e7a791 | 2018-04-05 14:36:36 -0700 | [diff] [blame] | 741 |  | 
 | 742 |     mat4 matrix; | 
 | 743 |     auto error = mDisplayData[displayId].hwcDisplay->getDataspaceSaturationMatrix(dataspace, | 
 | 744 |             &matrix); | 
| Dominik Laskowski | fc2c032 | 2018-04-19 14:47:33 -0700 | [diff] [blame] | 745 |     RETURN_IF_HWC_ERROR(error, displayId, {}); | 
| Peiyong Lin | 0e7a791 | 2018-04-05 14:36:36 -0700 | [diff] [blame] | 746 |     return matrix; | 
 | 747 | } | 
 | 748 |  | 
| Kevin DuBois | 9c0a176 | 2018-10-16 13:32:31 -0700 | [diff] [blame] | 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 |  | 
| Kevin DuBois | 74e5377 | 2018-11-19 10:52:38 -0800 | [diff] [blame] | 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 |  | 
| Kevin DuBois | 1d4249a | 2018-08-29 10:45:14 -0700 | [diff] [blame] | 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 |  | 
| Dan Gittik | 57e63c5 | 2019-01-18 16:37:54 +0000 | [diff] [blame] | 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 |  | 
| Hendrik Wagenaar | 87670ff | 2017-02-01 12:10:46 -0800 | [diff] [blame] | 800 | bool HWComposer::isUsingVrComposer() const { | 
| Hendrik Wagenaar | 87670ff | 2017-02-01 12:10:46 -0800 | [diff] [blame] | 801 |     return getComposer()->isUsingVrComposer(); | 
| Hendrik Wagenaar | 87670ff | 2017-02-01 12:10:46 -0800 | [diff] [blame] | 802 | } | 
 | 803 |  | 
| Yiwei Zhang | 5434a78 | 2018-12-05 18:06:32 -0800 | [diff] [blame] | 804 | void HWComposer::dump(std::string& result) const { | 
| Dan Stoza | 9e56aa0 | 2015-11-02 13:00:03 -0800 | [diff] [blame] | 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. | 
| Yiwei Zhang | 5434a78 | 2018-12-05 18:06:32 -0800 | [diff] [blame] | 808 |     result.append(mHwcDevice->dump()); | 
| Mathias Agopian | 8372785 | 2010-09-23 18:13:21 -0700 | [diff] [blame] | 809 | } | 
 | 810 |  | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 811 | 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 |  | 
 | 819 | 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 |  | 
 | 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); | 
| Steven Thomas | 6e8f706 | 2017-11-22 14:15:29 -0800 | [diff] [blame] | 830 |         return {}; | 
 | 831 |     } | 
| Dominik Laskowski | 075d317 | 2018-05-24 15:50:06 -0700 | [diff] [blame] | 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"}; | 
| Steven Thomas | 6e8f706 | 2017-11-22 14:15:29 -0800 | [diff] [blame] | 872 | } | 
 | 873 |  | 
| Lloyd Pique | 441d504 | 2018-10-18 16:49:51 -0700 | [diff] [blame] | 874 | } // namespace impl | 
| Dominik Laskowski | f9750f2 | 2018-06-06 12:24:53 -0700 | [diff] [blame] | 875 | } // namespace android |