| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | * Copyright 2015 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 | #ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H | 
|  | 18 | #define ANDROID_SF_HWC2_ON_1_ADAPTER_H | 
|  | 19 |  | 
|  | 20 | #define HWC2_INCLUDE_STRINGIFICATION | 
|  | 21 | #define HWC2_USE_CPP11 | 
|  | 22 | #include <hardware/hwcomposer2.h> | 
|  | 23 | #undef HWC2_INCLUDE_STRINGIFICATION | 
|  | 24 | #undef HWC2_USE_CPP11 | 
|  | 25 |  | 
|  | 26 | #include <ui/Fence.h> | 
|  | 27 |  | 
|  | 28 | #include <atomic> | 
|  | 29 | #include <map> | 
|  | 30 | #include <mutex> | 
|  | 31 | #include <queue> | 
|  | 32 | #include <set> | 
|  | 33 | #include <unordered_map> | 
|  | 34 | #include <unordered_set> | 
|  | 35 | #include <vector> | 
|  | 36 |  | 
|  | 37 | struct hwc_composer_device_1; | 
|  | 38 | struct hwc_display_contents_1; | 
|  | 39 | struct hwc_layer_1; | 
|  | 40 |  | 
|  | 41 | namespace android { | 
|  | 42 |  | 
|  | 43 | class HWC2On1Adapter : public hwc2_device_t | 
|  | 44 | { | 
|  | 45 | public: | 
| Chih-Hung Hsieh | 342b760 | 2016-09-01 11:34:16 -0700 | [diff] [blame] | 46 | explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 47 | ~HWC2On1Adapter(); | 
|  | 48 |  | 
|  | 49 | struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; } | 
|  | 50 | uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; } | 
|  | 51 |  | 
|  | 52 | private: | 
|  | 53 | static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) { | 
|  | 54 | return static_cast<HWC2On1Adapter*>(device); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | // getCapabilities | 
|  | 58 |  | 
|  | 59 | void doGetCapabilities(uint32_t* outCount, | 
|  | 60 | int32_t* /*hwc2_capability_t*/ outCapabilities); | 
|  | 61 | static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount, | 
|  | 62 | int32_t* /*hwc2_capability_t*/ outCapabilities) { | 
|  | 63 | getAdapter(device)->doGetCapabilities(outCount, outCapabilities); | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | // getFunction | 
|  | 67 |  | 
|  | 68 | hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor); | 
|  | 69 | static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device, | 
|  | 70 | int32_t intDesc) { | 
|  | 71 | auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc); | 
|  | 72 | return getAdapter(device)->doGetFunction(descriptor); | 
|  | 73 | } | 
|  | 74 |  | 
|  | 75 | // Device functions | 
|  | 76 |  | 
|  | 77 | HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height, | 
|  | 78 | hwc2_display_t* outDisplay); | 
|  | 79 | static int32_t createVirtualDisplayHook(hwc2_device_t* device, | 
| Dan Stoza | 5cf424b | 2016-05-20 14:02:39 -0700 | [diff] [blame] | 80 | uint32_t width, uint32_t height, int32_t* /*format*/, | 
|  | 81 | hwc2_display_t* outDisplay) { | 
|  | 82 | // HWC1 implementations cannot override the buffer format requested by | 
|  | 83 | // the consumer | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 84 | auto error = getAdapter(device)->createVirtualDisplay(width, height, | 
|  | 85 | outDisplay); | 
|  | 86 | return static_cast<int32_t>(error); | 
|  | 87 | } | 
|  | 88 |  | 
|  | 89 | HWC2::Error destroyVirtualDisplay(hwc2_display_t display); | 
|  | 90 | static int32_t destroyVirtualDisplayHook(hwc2_device_t* device, | 
|  | 91 | hwc2_display_t display) { | 
|  | 92 | auto error = getAdapter(device)->destroyVirtualDisplay(display); | 
|  | 93 | return static_cast<int32_t>(error); | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | std::string mDumpString; | 
|  | 97 | void dump(uint32_t* outSize, char* outBuffer); | 
|  | 98 | static void dumpHook(hwc2_device_t* device, uint32_t* outSize, | 
|  | 99 | char* outBuffer) { | 
|  | 100 | getAdapter(device)->dump(outSize, outBuffer); | 
|  | 101 | } | 
|  | 102 |  | 
|  | 103 | uint32_t getMaxVirtualDisplayCount(); | 
|  | 104 | static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) { | 
|  | 105 | return getAdapter(device)->getMaxVirtualDisplayCount(); | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | HWC2::Error registerCallback(HWC2::Callback descriptor, | 
|  | 109 | hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer); | 
|  | 110 | static int32_t registerCallbackHook(hwc2_device_t* device, | 
|  | 111 | int32_t intDesc, hwc2_callback_data_t callbackData, | 
|  | 112 | hwc2_function_pointer_t pointer) { | 
|  | 113 | auto descriptor = static_cast<HWC2::Callback>(intDesc); | 
|  | 114 | auto error = getAdapter(device)->registerCallback(descriptor, | 
|  | 115 | callbackData, pointer); | 
|  | 116 | return static_cast<int32_t>(error); | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | // Display functions | 
|  | 120 |  | 
|  | 121 | class Layer; | 
|  | 122 |  | 
|  | 123 | class SortLayersByZ { | 
|  | 124 | public: | 
|  | 125 | bool operator()(const std::shared_ptr<Layer>& lhs, | 
|  | 126 | const std::shared_ptr<Layer>& rhs); | 
|  | 127 | }; | 
|  | 128 |  | 
|  | 129 | class DisplayContentsDeleter { | 
|  | 130 | public: | 
|  | 131 | void operator()(struct hwc_display_contents_1* contents); | 
|  | 132 | }; | 
|  | 133 |  | 
|  | 134 | class DeferredFence { | 
|  | 135 | public: | 
|  | 136 | DeferredFence() | 
|  | 137 | : mMutex(), | 
|  | 138 | mFences({Fence::NO_FENCE, Fence::NO_FENCE}) {} | 
|  | 139 |  | 
|  | 140 | void add(int32_t fenceFd) { | 
|  | 141 | mFences.emplace(new Fence(fenceFd)); | 
|  | 142 | mFences.pop(); | 
|  | 143 | } | 
|  | 144 |  | 
|  | 145 | const sp<Fence>& get() const { | 
|  | 146 | return mFences.front(); | 
|  | 147 | } | 
|  | 148 |  | 
|  | 149 | private: | 
|  | 150 | mutable std::mutex mMutex; | 
|  | 151 | std::queue<sp<Fence>> mFences; | 
|  | 152 | }; | 
|  | 153 |  | 
|  | 154 | class FencedBuffer { | 
|  | 155 | public: | 
|  | 156 | FencedBuffer() : mBuffer(nullptr), mFence(Fence::NO_FENCE) {} | 
|  | 157 |  | 
|  | 158 | void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; } | 
|  | 159 | void setFence(int fenceFd) { mFence = new Fence(fenceFd); } | 
|  | 160 |  | 
|  | 161 | buffer_handle_t getBuffer() const { return mBuffer; } | 
|  | 162 | int getFence() const { return mFence->dup(); } | 
|  | 163 |  | 
|  | 164 | private: | 
|  | 165 | buffer_handle_t mBuffer; | 
|  | 166 | sp<Fence> mFence; | 
|  | 167 | }; | 
|  | 168 |  | 
|  | 169 | class Display { | 
|  | 170 | public: | 
|  | 171 | typedef std::unique_ptr<hwc_display_contents_1, | 
|  | 172 | DisplayContentsDeleter> HWC1Contents; | 
|  | 173 |  | 
|  | 174 | Display(HWC2On1Adapter& device, HWC2::DisplayType type); | 
|  | 175 |  | 
|  | 176 | hwc2_display_t getId() const { return mId; } | 
|  | 177 | HWC2On1Adapter& getDevice() const { return mDevice; } | 
|  | 178 |  | 
|  | 179 | // Does not require locking because it is set before adding the | 
|  | 180 | // Displays to the Adapter's list of displays | 
|  | 181 | void setHwc1Id(int32_t id) { mHwc1Id = id; } | 
|  | 182 | int32_t getHwc1Id() const { return mHwc1Id; } | 
|  | 183 |  | 
|  | 184 | void incDirty() { ++mDirtyCount; } | 
|  | 185 | void decDirty() { --mDirtyCount; } | 
|  | 186 | bool isDirty() const { return mDirtyCount > 0 || mZIsDirty; } | 
|  | 187 |  | 
|  | 188 | // HWC2 Display functions | 
|  | 189 | HWC2::Error acceptChanges(); | 
|  | 190 | HWC2::Error createLayer(hwc2_layer_t* outLayerId); | 
|  | 191 | HWC2::Error destroyLayer(hwc2_layer_t layerId); | 
|  | 192 | HWC2::Error getActiveConfig(hwc2_config_t* outConfigId); | 
|  | 193 | HWC2::Error getAttribute(hwc2_config_t configId, | 
|  | 194 | HWC2::Attribute attribute, int32_t* outValue); | 
|  | 195 | HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, | 
|  | 196 | hwc2_layer_t* outLayers, int32_t* outTypes); | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 197 | HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 198 | HWC2::Error getConfigs(uint32_t* outNumConfigs, | 
|  | 199 | hwc2_config_t* outConfigIds); | 
|  | 200 | HWC2::Error getDozeSupport(int32_t* outSupport); | 
| Dan Stoza | ed40eba | 2016-03-16 12:33:52 -0700 | [diff] [blame] | 201 | HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, | 
|  | 202 | int32_t* outTypes, float* outMaxLuminance, | 
|  | 203 | float* outMaxAverageLuminance, float* outMinLuminance); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 204 | HWC2::Error getName(uint32_t* outSize, char* outName); | 
|  | 205 | HWC2::Error getReleaseFences(uint32_t* outNumElements, | 
|  | 206 | hwc2_layer_t* outLayers, int32_t* outFences); | 
|  | 207 | HWC2::Error getRequests(int32_t* outDisplayRequests, | 
|  | 208 | uint32_t* outNumElements, hwc2_layer_t* outLayers, | 
|  | 209 | int32_t* outLayerRequests); | 
|  | 210 | HWC2::Error getType(int32_t* outType); | 
|  | 211 | HWC2::Error present(int32_t* outRetireFence); | 
|  | 212 | HWC2::Error setActiveConfig(hwc2_config_t configId); | 
|  | 213 | HWC2::Error setClientTarget(buffer_handle_t target, | 
| Dan Stoza | 5cf424b | 2016-05-20 14:02:39 -0700 | [diff] [blame] | 214 | int32_t acquireFence, int32_t dataspace, | 
|  | 215 | hwc_region_t damage); | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 216 | HWC2::Error setColorMode(android_color_mode_t mode); | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 217 | HWC2::Error setColorTransform(android_color_transform_t hint); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 218 | HWC2::Error setOutputBuffer(buffer_handle_t buffer, | 
|  | 219 | int32_t releaseFence); | 
|  | 220 | HWC2::Error setPowerMode(HWC2::PowerMode mode); | 
|  | 221 | HWC2::Error setVsyncEnabled(HWC2::Vsync enabled); | 
|  | 222 | HWC2::Error validate(uint32_t* outNumTypes, | 
|  | 223 | uint32_t* outNumRequests); | 
|  | 224 |  | 
|  | 225 | HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z); | 
|  | 226 |  | 
|  | 227 | // Read configs from HWC1 device | 
|  | 228 | void populateConfigs(); | 
|  | 229 |  | 
|  | 230 | // Set configs for a virtual display | 
|  | 231 | void populateConfigs(uint32_t width, uint32_t height); | 
|  | 232 |  | 
|  | 233 | bool prepare(); | 
|  | 234 | HWC1Contents cloneRequestedContents() const; | 
|  | 235 | void setReceivedContents(HWC1Contents contents); | 
|  | 236 | bool hasChanges() const; | 
|  | 237 | HWC2::Error set(hwc_display_contents_1& hwcContents); | 
|  | 238 | void addRetireFence(int fenceFd); | 
|  | 239 | void addReleaseFences(const hwc_display_contents_1& hwcContents); | 
|  | 240 |  | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 241 | bool hasColorTransform() const; | 
|  | 242 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 243 | std::string dump() const; | 
|  | 244 |  | 
|  | 245 | private: | 
|  | 246 | class Config { | 
|  | 247 | public: | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 248 | Config(Display& display) | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 249 | : mDisplay(display), | 
| Dan Stoza | fc4e202 | 2016-02-23 11:43:19 -0800 | [diff] [blame] | 250 | mAttributes() {} | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 251 |  | 
|  | 252 | bool isOnDisplay(const Display& display) const { | 
|  | 253 | return display.getId() == mDisplay.getId(); | 
|  | 254 | } | 
|  | 255 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 256 | void setAttribute(HWC2::Attribute attribute, int32_t value); | 
|  | 257 | int32_t getAttribute(HWC2::Attribute attribute) const; | 
|  | 258 |  | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 259 | void setHwc1Id(uint32_t id); | 
|  | 260 | bool hasHwc1Id(uint32_t id) const; | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 261 | HWC2::Error getColorModeForHwc1Id(uint32_t id, | 
|  | 262 | android_color_mode_t *outMode) const; | 
|  | 263 | HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode, | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 264 | uint32_t* outId) const; | 
|  | 265 |  | 
|  | 266 | void setId(hwc2_config_t id) { mId = id; } | 
|  | 267 | hwc2_config_t getId() const { return mId; } | 
|  | 268 |  | 
|  | 269 | // Attempts to merge two configs that differ only in color | 
|  | 270 | // mode. Returns whether the merge was successful | 
|  | 271 | bool merge(const Config& other); | 
|  | 272 |  | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 273 | std::set<android_color_mode_t> getColorModes() const; | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 274 |  | 
|  | 275 | // splitLine divides the output into two lines suitable for | 
|  | 276 | // dumpsys SurfaceFlinger | 
|  | 277 | std::string toString(bool splitLine = false) const; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 278 |  | 
|  | 279 | private: | 
|  | 280 | Display& mDisplay; | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 281 | hwc2_config_t mId; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 282 | std::unordered_map<HWC2::Attribute, int32_t> mAttributes; | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 283 |  | 
|  | 284 | // Maps from color transform to HWC1 config ID | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 285 | std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 286 | }; | 
|  | 287 |  | 
|  | 288 | class Changes { | 
|  | 289 | public: | 
|  | 290 | uint32_t getNumTypes() const { | 
|  | 291 | return static_cast<uint32_t>(mTypeChanges.size()); | 
|  | 292 | } | 
|  | 293 |  | 
|  | 294 | uint32_t getNumLayerRequests() const { | 
|  | 295 | return static_cast<uint32_t>(mLayerRequests.size()); | 
|  | 296 | } | 
|  | 297 |  | 
|  | 298 | const std::unordered_map<hwc2_layer_t, HWC2::Composition>& | 
|  | 299 | getTypeChanges() const { | 
|  | 300 | return mTypeChanges; | 
|  | 301 | } | 
|  | 302 |  | 
|  | 303 | const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>& | 
|  | 304 | getLayerRequests() const { | 
|  | 305 | return mLayerRequests; | 
|  | 306 | } | 
|  | 307 |  | 
|  | 308 | int32_t getDisplayRequests() const { | 
|  | 309 | int32_t requests = 0; | 
|  | 310 | for (auto request : mDisplayRequests) { | 
|  | 311 | requests |= static_cast<int32_t>(request); | 
|  | 312 | } | 
|  | 313 | return requests; | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | void addTypeChange(hwc2_layer_t layerId, | 
|  | 317 | HWC2::Composition type) { | 
|  | 318 | mTypeChanges.insert({layerId, type}); | 
|  | 319 | } | 
|  | 320 |  | 
|  | 321 | void clearTypeChanges() { mTypeChanges.clear(); } | 
|  | 322 |  | 
|  | 323 | void addLayerRequest(hwc2_layer_t layerId, | 
|  | 324 | HWC2::LayerRequest request) { | 
|  | 325 | mLayerRequests.insert({layerId, request}); | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | private: | 
|  | 329 | std::unordered_map<hwc2_layer_t, HWC2::Composition> | 
|  | 330 | mTypeChanges; | 
|  | 331 | std::unordered_map<hwc2_layer_t, HWC2::LayerRequest> | 
|  | 332 | mLayerRequests; | 
|  | 333 | std::unordered_set<HWC2::DisplayRequest> mDisplayRequests; | 
|  | 334 | }; | 
|  | 335 |  | 
|  | 336 | std::shared_ptr<const Config> | 
|  | 337 | getConfig(hwc2_config_t configId) const; | 
|  | 338 |  | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 339 | void populateColorModes(); | 
|  | 340 | void initializeActiveConfig(); | 
|  | 341 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 342 | void reallocateHwc1Contents(); | 
|  | 343 | void assignHwc1LayerIds(); | 
|  | 344 |  | 
|  | 345 | void updateTypeChanges(const struct hwc_layer_1& hwc1Layer, | 
|  | 346 | const Layer& layer); | 
|  | 347 | void updateLayerRequests(const struct hwc_layer_1& hwc1Layer, | 
|  | 348 | const Layer& layer); | 
|  | 349 |  | 
|  | 350 | void prepareFramebufferTarget(); | 
|  | 351 |  | 
|  | 352 | static std::atomic<hwc2_display_t> sNextId; | 
|  | 353 | const hwc2_display_t mId; | 
|  | 354 | HWC2On1Adapter& mDevice; | 
|  | 355 |  | 
|  | 356 | std::atomic<size_t> mDirtyCount; | 
|  | 357 |  | 
|  | 358 | // The state of this display should only be modified from | 
|  | 359 | // SurfaceFlinger's main loop, with the exception of when dump is | 
|  | 360 | // called. To prevent a bad state from crashing us during a dump | 
|  | 361 | // call, all public calls into Display must acquire this mutex. | 
|  | 362 | // | 
|  | 363 | // It is recursive because we don't want to deadlock in validate | 
|  | 364 | // (or present) when we call HWC2On1Adapter::prepareAllDisplays | 
|  | 365 | // (or setAllDisplays), which calls back into Display functions | 
|  | 366 | // which require locking. | 
|  | 367 | mutable std::recursive_mutex mStateMutex; | 
|  | 368 |  | 
|  | 369 | bool mZIsDirty; | 
|  | 370 | HWC1Contents mHwc1RequestedContents; | 
|  | 371 | HWC1Contents mHwc1ReceivedContents; | 
|  | 372 | DeferredFence mRetireFence; | 
|  | 373 |  | 
|  | 374 | // Will only be non-null after the layer has been validated but | 
|  | 375 | // before it has been presented | 
|  | 376 | std::unique_ptr<Changes> mChanges; | 
|  | 377 |  | 
|  | 378 | int32_t mHwc1Id; | 
| Dan Stoza | 076ac67 | 2016-03-14 10:47:53 -0700 | [diff] [blame] | 379 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 380 | std::vector<std::shared_ptr<Config>> mConfigs; | 
|  | 381 | std::shared_ptr<const Config> mActiveConfig; | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 382 | std::set<android_color_mode_t> mColorModes; | 
|  | 383 | android_color_mode_t mActiveColorMode; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 384 | std::string mName; | 
|  | 385 | HWC2::DisplayType mType; | 
|  | 386 | HWC2::PowerMode mPowerMode; | 
|  | 387 | HWC2::Vsync mVsyncEnabled; | 
|  | 388 |  | 
|  | 389 | FencedBuffer mClientTarget; | 
|  | 390 | FencedBuffer mOutputBuffer; | 
|  | 391 |  | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 392 | bool mHasColorTransform; | 
|  | 393 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 394 | std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers; | 
|  | 395 | std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap; | 
|  | 396 | }; | 
|  | 397 |  | 
|  | 398 | template <typename ...Args> | 
|  | 399 | static int32_t callDisplayFunction(hwc2_device_t* device, | 
|  | 400 | hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...), | 
|  | 401 | Args... args) { | 
|  | 402 | auto display = getAdapter(device)->getDisplay(displayId); | 
|  | 403 | if (!display) { | 
|  | 404 | return static_cast<int32_t>(HWC2::Error::BadDisplay); | 
|  | 405 | } | 
|  | 406 | auto error = ((*display).*member)(std::forward<Args>(args)...); | 
|  | 407 | return static_cast<int32_t>(error); | 
|  | 408 | } | 
|  | 409 |  | 
|  | 410 | template <typename MF, MF memFunc, typename ...Args> | 
|  | 411 | static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId, | 
|  | 412 | Args... args) { | 
|  | 413 | return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc, | 
|  | 414 | std::forward<Args>(args)...); | 
|  | 415 | } | 
|  | 416 |  | 
|  | 417 | static int32_t getDisplayAttributeHook(hwc2_device_t* device, | 
|  | 418 | hwc2_display_t display, hwc2_config_t config, | 
|  | 419 | int32_t intAttribute, int32_t* outValue) { | 
|  | 420 | auto attribute = static_cast<HWC2::Attribute>(intAttribute); | 
|  | 421 | return callDisplayFunction(device, display, &Display::getAttribute, | 
|  | 422 | config, attribute, outValue); | 
|  | 423 | } | 
|  | 424 |  | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 425 | static int32_t setColorTransformHook(hwc2_device_t* device, | 
|  | 426 | hwc2_display_t display, const float* /*matrix*/, | 
|  | 427 | int32_t /*android_color_transform_t*/ intHint) { | 
|  | 428 | // We intentionally throw away the matrix, because if the hint is | 
|  | 429 | // anything other than IDENTITY, we have to fall back to client | 
|  | 430 | // composition anyway | 
|  | 431 | auto hint = static_cast<android_color_transform_t>(intHint); | 
|  | 432 | return callDisplayFunction(device, display, &Display::setColorTransform, | 
|  | 433 | hint); | 
|  | 434 | } | 
|  | 435 |  | 
| Michael Wright | 28f24d0 | 2016-07-12 13:30:53 -0700 | [diff] [blame] | 436 | static int32_t setColorModeHook(hwc2_device_t* device, | 
|  | 437 | hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) { | 
|  | 438 | auto mode = static_cast<android_color_mode_t>(intMode); | 
|  | 439 | return callDisplayFunction(device, display, &Display::setColorMode, mode); | 
|  | 440 | } | 
|  | 441 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 442 | static int32_t setPowerModeHook(hwc2_device_t* device, | 
|  | 443 | hwc2_display_t display, int32_t intMode) { | 
|  | 444 | auto mode = static_cast<HWC2::PowerMode>(intMode); | 
|  | 445 | return callDisplayFunction(device, display, &Display::setPowerMode, | 
|  | 446 | mode); | 
|  | 447 | } | 
|  | 448 |  | 
|  | 449 | static int32_t setVsyncEnabledHook(hwc2_device_t* device, | 
|  | 450 | hwc2_display_t display, int32_t intEnabled) { | 
|  | 451 | auto enabled = static_cast<HWC2::Vsync>(intEnabled); | 
|  | 452 | return callDisplayFunction(device, display, &Display::setVsyncEnabled, | 
|  | 453 | enabled); | 
|  | 454 | } | 
|  | 455 |  | 
|  | 456 | // Layer functions | 
|  | 457 |  | 
|  | 458 | template <typename T> | 
|  | 459 | class LatchedState { | 
|  | 460 | public: | 
|  | 461 | LatchedState(Layer& parent, T initialValue) | 
|  | 462 | : mParent(parent), | 
|  | 463 | mPendingValue(initialValue), | 
|  | 464 | mValue(initialValue) {} | 
|  | 465 |  | 
|  | 466 | void setPending(T value) { | 
|  | 467 | if (value == mPendingValue) { | 
|  | 468 | return; | 
|  | 469 | } | 
|  | 470 | if (mPendingValue == mValue) { | 
|  | 471 | mParent.incDirty(); | 
|  | 472 | } else if (value == mValue) { | 
|  | 473 | mParent.decDirty(); | 
|  | 474 | } | 
|  | 475 | mPendingValue = value; | 
|  | 476 | } | 
|  | 477 |  | 
|  | 478 | T getValue() const { return mValue; } | 
|  | 479 | T getPendingValue() const { return mPendingValue; } | 
|  | 480 |  | 
|  | 481 | bool isDirty() const { return mPendingValue != mValue; } | 
|  | 482 |  | 
|  | 483 | void latch() { | 
|  | 484 | if (isDirty()) { | 
|  | 485 | mValue = mPendingValue; | 
|  | 486 | mParent.decDirty(); | 
|  | 487 | } | 
|  | 488 | } | 
|  | 489 |  | 
|  | 490 | private: | 
|  | 491 | Layer& mParent; | 
|  | 492 | T mPendingValue; | 
|  | 493 | T mValue; | 
|  | 494 | }; | 
|  | 495 |  | 
|  | 496 | class Layer { | 
|  | 497 | public: | 
| Chih-Hung Hsieh | 342b760 | 2016-09-01 11:34:16 -0700 | [diff] [blame] | 498 | explicit Layer(Display& display); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 499 |  | 
|  | 500 | bool operator==(const Layer& other) { return mId == other.mId; } | 
|  | 501 | bool operator!=(const Layer& other) { return !(*this == other); } | 
|  | 502 |  | 
|  | 503 | hwc2_layer_t getId() const { return mId; } | 
|  | 504 | Display& getDisplay() const { return mDisplay; } | 
|  | 505 |  | 
|  | 506 | void incDirty() { if (mDirtyCount++ == 0) mDisplay.incDirty(); } | 
|  | 507 | void decDirty() { if (--mDirtyCount == 0) mDisplay.decDirty(); } | 
|  | 508 | bool isDirty() const { return mDirtyCount > 0; } | 
|  | 509 |  | 
|  | 510 | // HWC2 Layer functions | 
|  | 511 | HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence); | 
|  | 512 | HWC2::Error setCursorPosition(int32_t x, int32_t y); | 
|  | 513 | HWC2::Error setSurfaceDamage(hwc_region_t damage); | 
|  | 514 |  | 
|  | 515 | // HWC2 Layer state functions | 
|  | 516 | HWC2::Error setBlendMode(HWC2::BlendMode mode); | 
|  | 517 | HWC2::Error setColor(hwc_color_t color); | 
|  | 518 | HWC2::Error setCompositionType(HWC2::Composition type); | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 519 | HWC2::Error setDataspace(android_dataspace_t dataspace); | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 520 | HWC2::Error setDisplayFrame(hwc_rect_t frame); | 
|  | 521 | HWC2::Error setPlaneAlpha(float alpha); | 
|  | 522 | HWC2::Error setSidebandStream(const native_handle_t* stream); | 
|  | 523 | HWC2::Error setSourceCrop(hwc_frect_t crop); | 
|  | 524 | HWC2::Error setTransform(HWC2::Transform transform); | 
|  | 525 | HWC2::Error setVisibleRegion(hwc_region_t visible); | 
|  | 526 | HWC2::Error setZ(uint32_t z); | 
|  | 527 |  | 
|  | 528 | HWC2::Composition getCompositionType() const { | 
|  | 529 | return mCompositionType.getValue(); | 
|  | 530 | } | 
|  | 531 | uint32_t getZ() const { return mZ; } | 
|  | 532 |  | 
|  | 533 | void addReleaseFence(int fenceFd); | 
|  | 534 | const sp<Fence>& getReleaseFence() const; | 
|  | 535 |  | 
|  | 536 | void setHwc1Id(size_t id) { mHwc1Id = id; } | 
|  | 537 | size_t getHwc1Id() const { return mHwc1Id; } | 
|  | 538 |  | 
|  | 539 | void applyState(struct hwc_layer_1& hwc1Layer, bool applyAllState); | 
|  | 540 |  | 
|  | 541 | std::string dump() const; | 
|  | 542 |  | 
|  | 543 | private: | 
|  | 544 | void applyCommonState(struct hwc_layer_1& hwc1Layer, | 
|  | 545 | bool applyAllState); | 
|  | 546 | void applySolidColorState(struct hwc_layer_1& hwc1Layer, | 
|  | 547 | bool applyAllState); | 
|  | 548 | void applySidebandState(struct hwc_layer_1& hwc1Layer, | 
|  | 549 | bool applyAllState); | 
|  | 550 | void applyBufferState(struct hwc_layer_1& hwc1Layer); | 
|  | 551 | void applyCompositionType(struct hwc_layer_1& hwc1Layer, | 
|  | 552 | bool applyAllState); | 
|  | 553 |  | 
|  | 554 | static std::atomic<hwc2_layer_t> sNextId; | 
|  | 555 | const hwc2_layer_t mId; | 
|  | 556 | Display& mDisplay; | 
|  | 557 | size_t mDirtyCount; | 
|  | 558 |  | 
|  | 559 | FencedBuffer mBuffer; | 
|  | 560 | std::vector<hwc_rect_t> mSurfaceDamage; | 
|  | 561 |  | 
|  | 562 | LatchedState<HWC2::BlendMode> mBlendMode; | 
|  | 563 | LatchedState<hwc_color_t> mColor; | 
|  | 564 | LatchedState<HWC2::Composition> mCompositionType; | 
|  | 565 | LatchedState<hwc_rect_t> mDisplayFrame; | 
|  | 566 | LatchedState<float> mPlaneAlpha; | 
|  | 567 | LatchedState<const native_handle_t*> mSidebandStream; | 
|  | 568 | LatchedState<hwc_frect_t> mSourceCrop; | 
|  | 569 | LatchedState<HWC2::Transform> mTransform; | 
|  | 570 | LatchedState<std::vector<hwc_rect_t>> mVisibleRegion; | 
|  | 571 | uint32_t mZ; | 
|  | 572 |  | 
|  | 573 | DeferredFence mReleaseFence; | 
|  | 574 |  | 
|  | 575 | size_t mHwc1Id; | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 576 | bool mHasUnsupportedDataspace; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 577 | bool mHasUnsupportedPlaneAlpha; | 
|  | 578 | }; | 
|  | 579 |  | 
|  | 580 | template <typename ...Args> | 
|  | 581 | static int32_t callLayerFunction(hwc2_device_t* device, | 
|  | 582 | hwc2_display_t displayId, hwc2_layer_t layerId, | 
|  | 583 | HWC2::Error (Layer::*member)(Args...), Args... args) { | 
|  | 584 | auto result = getAdapter(device)->getLayer(displayId, layerId); | 
|  | 585 | auto error = std::get<HWC2::Error>(result); | 
|  | 586 | if (error == HWC2::Error::None) { | 
|  | 587 | auto layer = std::get<Layer*>(result); | 
|  | 588 | error = ((*layer).*member)(std::forward<Args>(args)...); | 
|  | 589 | } | 
|  | 590 | return static_cast<int32_t>(error); | 
|  | 591 | } | 
|  | 592 |  | 
|  | 593 | template <typename MF, MF memFunc, typename ...Args> | 
|  | 594 | static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId, | 
|  | 595 | hwc2_layer_t layerId, Args... args) { | 
|  | 596 | return HWC2On1Adapter::callLayerFunction(device, displayId, layerId, | 
|  | 597 | memFunc, std::forward<Args>(args)...); | 
|  | 598 | } | 
|  | 599 |  | 
|  | 600 | // Layer state functions | 
|  | 601 |  | 
|  | 602 | static int32_t setLayerBlendModeHook(hwc2_device_t* device, | 
|  | 603 | hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) { | 
|  | 604 | auto mode = static_cast<HWC2::BlendMode>(intMode); | 
|  | 605 | return callLayerFunction(device, display, layer, | 
|  | 606 | &Layer::setBlendMode, mode); | 
|  | 607 | } | 
|  | 608 |  | 
|  | 609 | static int32_t setLayerCompositionTypeHook(hwc2_device_t* device, | 
|  | 610 | hwc2_display_t display, hwc2_layer_t layer, int32_t intType) { | 
|  | 611 | auto type = static_cast<HWC2::Composition>(intType); | 
|  | 612 | return callLayerFunction(device, display, layer, | 
|  | 613 | &Layer::setCompositionType, type); | 
|  | 614 | } | 
|  | 615 |  | 
| Dan Stoza | 5df2a86 | 2016-03-24 16:19:37 -0700 | [diff] [blame] | 616 | static int32_t setLayerDataspaceHook(hwc2_device_t* device, | 
|  | 617 | hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) { | 
|  | 618 | auto dataspace = static_cast<android_dataspace_t>(intDataspace); | 
|  | 619 | return callLayerFunction(device, display, layer, &Layer::setDataspace, | 
|  | 620 | dataspace); | 
|  | 621 | } | 
|  | 622 |  | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 623 | static int32_t setLayerTransformHook(hwc2_device_t* device, | 
|  | 624 | hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) { | 
|  | 625 | auto transform = static_cast<HWC2::Transform>(intTransform); | 
|  | 626 | return callLayerFunction(device, display, layer, &Layer::setTransform, | 
|  | 627 | transform); | 
|  | 628 | } | 
|  | 629 |  | 
|  | 630 | static int32_t setLayerZOrderHook(hwc2_device_t* device, | 
|  | 631 | hwc2_display_t display, hwc2_layer_t layer, uint32_t z) { | 
|  | 632 | return callDisplayFunction(device, display, &Display::updateLayerZ, | 
|  | 633 | layer, z); | 
|  | 634 | } | 
|  | 635 |  | 
|  | 636 | // Adapter internals | 
|  | 637 |  | 
|  | 638 | void populateCapabilities(); | 
|  | 639 | Display* getDisplay(hwc2_display_t id); | 
|  | 640 | std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId, | 
|  | 641 | hwc2_layer_t layerId); | 
|  | 642 | void populatePrimary(); | 
|  | 643 |  | 
|  | 644 | bool prepareAllDisplays(); | 
|  | 645 | std::vector<struct hwc_display_contents_1*> mHwc1Contents; | 
|  | 646 | HWC2::Error setAllDisplays(); | 
|  | 647 |  | 
|  | 648 | void hwc1Invalidate(); | 
|  | 649 | void hwc1Vsync(int hwc1DisplayId, int64_t timestamp); | 
|  | 650 | void hwc1Hotplug(int hwc1DisplayId, int connected); | 
|  | 651 |  | 
|  | 652 | // These are set in the constructor and before any asynchronous events are | 
|  | 653 | // possible | 
|  | 654 |  | 
|  | 655 | struct hwc_composer_device_1* const mHwc1Device; | 
|  | 656 | const uint8_t mHwc1MinorVersion; | 
|  | 657 | bool mHwc1SupportsVirtualDisplays; | 
|  | 658 |  | 
|  | 659 | class Callbacks; | 
|  | 660 | const std::unique_ptr<Callbacks> mHwc1Callbacks; | 
|  | 661 |  | 
|  | 662 | std::unordered_set<HWC2::Capability> mCapabilities; | 
|  | 663 |  | 
|  | 664 | // These are only accessed from the main SurfaceFlinger thread (not from | 
|  | 665 | // callbacks or dump | 
|  | 666 |  | 
|  | 667 | std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers; | 
|  | 668 | std::shared_ptr<Display> mHwc1VirtualDisplay; | 
|  | 669 |  | 
|  | 670 | // These are potentially accessed from multiple threads, and are protected | 
| Dan Stoza | fc4e202 | 2016-02-23 11:43:19 -0800 | [diff] [blame] | 671 | // by this mutex. This needs to be recursive, since the HWC1 implementation | 
|  | 672 | // can call back into the invalidate callback on the same thread that is | 
|  | 673 | // calling prepare. | 
|  | 674 | std::recursive_timed_mutex mStateMutex; | 
| Dan Stoza | c6998d2 | 2015-09-24 17:03:36 -0700 | [diff] [blame] | 675 |  | 
|  | 676 | struct CallbackInfo { | 
|  | 677 | hwc2_callback_data_t data; | 
|  | 678 | hwc2_function_pointer_t pointer; | 
|  | 679 | }; | 
|  | 680 | std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks; | 
|  | 681 | bool mHasPendingInvalidate; | 
|  | 682 | std::vector<std::pair<int, int64_t>> mPendingVsyncs; | 
|  | 683 | std::vector<std::pair<int, int>> mPendingHotplugs; | 
|  | 684 |  | 
|  | 685 | std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays; | 
|  | 686 | std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap; | 
|  | 687 | }; | 
|  | 688 |  | 
|  | 689 | } // namespace android | 
|  | 690 |  | 
|  | 691 | #endif |