blob: ae6ba98bd5fdfe5c7429e3d9e67140e4d8e7d0c1 [file] [log] [blame]
Dan Stoza651bf312015-10-23 17:03:17 -07001/*
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// #define LOG_NDEBUG 0
18
19#undef LOG_TAG
20#define LOG_TAG "HWC2"
21#define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
23#include "HWC2.h"
24
25#include "FloatRect.h"
26
27#include <ui/Fence.h>
28#include <ui/GraphicBuffer.h>
29#include <ui/Region.h>
30
31#include <android/configuration.h>
32
Dan Stoza09e7a272016-04-14 12:31:01 -070033#include <algorithm>
Dan Stoza651bf312015-10-23 17:03:17 -070034#include <inttypes.h>
35
36extern "C" {
37 static void hotplug_hook(hwc2_callback_data_t callbackData,
38 hwc2_display_t displayId, int32_t intConnected) {
39 auto device = static_cast<HWC2::Device*>(callbackData);
40 auto display = device->getDisplayById(displayId);
41 if (display) {
42 auto connected = static_cast<HWC2::Connection>(intConnected);
43 device->callHotplug(std::move(display), connected);
44 } else {
45 ALOGE("Hotplug callback called with unknown display %" PRIu64,
46 displayId);
47 }
48 }
49
50 static void refresh_hook(hwc2_callback_data_t callbackData,
51 hwc2_display_t displayId) {
52 auto device = static_cast<HWC2::Device*>(callbackData);
53 auto display = device->getDisplayById(displayId);
54 if (display) {
55 device->callRefresh(std::move(display));
56 } else {
57 ALOGE("Refresh callback called with unknown display %" PRIu64,
58 displayId);
59 }
60 }
61
62 static void vsync_hook(hwc2_callback_data_t callbackData,
63 hwc2_display_t displayId, int64_t timestamp) {
64 auto device = static_cast<HWC2::Device*>(callbackData);
65 auto display = device->getDisplayById(displayId);
66 if (display) {
67 device->callVsync(std::move(display), timestamp);
68 } else {
69 ALOGE("Vsync callback called with unknown display %" PRIu64,
70 displayId);
71 }
72 }
73}
74
75using android::Fence;
76using android::FloatRect;
77using android::GraphicBuffer;
Dan Stoza7d7ae732016-03-16 12:23:40 -070078using android::HdrCapabilities;
Dan Stoza651bf312015-10-23 17:03:17 -070079using android::Rect;
80using android::Region;
81using android::sp;
82
83namespace HWC2 {
84
85// Device methods
86
87Device::Device(hwc2_device_t* device)
88 : mHwcDevice(device),
89 mCreateVirtualDisplay(nullptr),
90 mDestroyVirtualDisplay(nullptr),
91 mDump(nullptr),
92 mGetMaxVirtualDisplayCount(nullptr),
93 mRegisterCallback(nullptr),
94 mAcceptDisplayChanges(nullptr),
95 mCreateLayer(nullptr),
96 mDestroyLayer(nullptr),
97 mGetActiveConfig(nullptr),
98 mGetChangedCompositionTypes(nullptr),
Dan Stoza076ac672016-03-14 10:47:53 -070099 mGetColorModes(nullptr),
Dan Stoza651bf312015-10-23 17:03:17 -0700100 mGetDisplayAttribute(nullptr),
101 mGetDisplayConfigs(nullptr),
102 mGetDisplayName(nullptr),
103 mGetDisplayRequests(nullptr),
104 mGetDisplayType(nullptr),
105 mGetDozeSupport(nullptr),
Dan Stoza7d7ae732016-03-16 12:23:40 -0700106 mGetHdrCapabilities(nullptr),
Dan Stoza651bf312015-10-23 17:03:17 -0700107 mGetReleaseFences(nullptr),
108 mPresentDisplay(nullptr),
109 mSetActiveConfig(nullptr),
110 mSetClientTarget(nullptr),
Dan Stoza076ac672016-03-14 10:47:53 -0700111 mSetColorMode(nullptr),
Dan Stoza5df2a862016-03-24 16:19:37 -0700112 mSetColorTransform(nullptr),
Dan Stoza651bf312015-10-23 17:03:17 -0700113 mSetOutputBuffer(nullptr),
114 mSetPowerMode(nullptr),
115 mSetVsyncEnabled(nullptr),
116 mValidateDisplay(nullptr),
117 mSetCursorPosition(nullptr),
118 mSetLayerBuffer(nullptr),
119 mSetLayerSurfaceDamage(nullptr),
120 mSetLayerBlendMode(nullptr),
121 mSetLayerColor(nullptr),
122 mSetLayerCompositionType(nullptr),
Dan Stoza5df2a862016-03-24 16:19:37 -0700123 mSetLayerDataspace(nullptr),
Dan Stoza651bf312015-10-23 17:03:17 -0700124 mSetLayerDisplayFrame(nullptr),
125 mSetLayerPlaneAlpha(nullptr),
126 mSetLayerSidebandStream(nullptr),
127 mSetLayerSourceCrop(nullptr),
128 mSetLayerTransform(nullptr),
129 mSetLayerVisibleRegion(nullptr),
130 mSetLayerZOrder(nullptr),
131 mCapabilities(),
132 mDisplays(),
133 mHotplug(),
134 mPendingHotplugs(),
135 mRefresh(),
136 mPendingRefreshes(),
137 mVsync(),
138 mPendingVsyncs()
139{
140 loadCapabilities();
141 loadFunctionPointers();
142 registerCallbacks();
143}
144
145Device::~Device()
146{
147 if (mHwcDevice == nullptr) {
148 return;
149 }
150
151 for (auto element : mDisplays) {
Dan Stoza38628982016-07-13 15:48:58 -0700152 auto display = element.second.lock();
153 if (!display) {
154 ALOGE("~Device: Found a display (%" PRId64 " that has already been"
155 " destroyed", element.first);
156 continue;
157 }
Dan Stoza651bf312015-10-23 17:03:17 -0700158
159 DisplayType displayType = HWC2::DisplayType::Invalid;
160 auto error = display->getType(&displayType);
161 if (error != Error::None) {
162 ALOGE("~Device: Failed to determine type of display %" PRIu64
163 ": %s (%d)", display->getId(), to_string(error).c_str(),
164 static_cast<int32_t>(error));
165 continue;
166 }
167
168 if (displayType == HWC2::DisplayType::Physical) {
169 error = display->setVsyncEnabled(HWC2::Vsync::Disable);
170 if (error != Error::None) {
171 ALOGE("~Device: Failed to disable vsync for display %" PRIu64
172 ": %s (%d)", display->getId(), to_string(error).c_str(),
173 static_cast<int32_t>(error));
174 }
175 }
176 }
177
178 hwc2_close(mHwcDevice);
179}
180
181// Required by HWC2 device
182
183std::string Device::dump() const
184{
185 uint32_t numBytes = 0;
186 mDump(mHwcDevice, &numBytes, nullptr);
187
188 std::vector<char> buffer(numBytes);
189 mDump(mHwcDevice, &numBytes, buffer.data());
190
191 return std::string(buffer.data(), buffer.size());
192}
193
194uint32_t Device::getMaxVirtualDisplayCount() const
195{
196 return mGetMaxVirtualDisplayCount(mHwcDevice);
197}
198
199Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
Dan Stoza5cf424b2016-05-20 14:02:39 -0700200 android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
Dan Stoza651bf312015-10-23 17:03:17 -0700201{
202 ALOGI("Creating virtual display");
203
204 hwc2_display_t displayId = 0;
Dan Stoza5cf424b2016-05-20 14:02:39 -0700205 int32_t intFormat = static_cast<int32_t>(*format);
Dan Stoza651bf312015-10-23 17:03:17 -0700206 int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
Dan Stoza5cf424b2016-05-20 14:02:39 -0700207 &intFormat, &displayId);
Dan Stoza651bf312015-10-23 17:03:17 -0700208 auto error = static_cast<Error>(intError);
209 if (error != Error::None) {
210 return error;
211 }
212
213 ALOGI("Created virtual display");
Dan Stoza5cf424b2016-05-20 14:02:39 -0700214 *format = static_cast<android_pixel_format_t>(intFormat);
Dan Stoza651bf312015-10-23 17:03:17 -0700215 *outDisplay = getDisplayById(displayId);
Dan Stoza38628982016-07-13 15:48:58 -0700216 if (!*outDisplay) {
217 ALOGE("Failed to get display by id");
218 return Error::BadDisplay;
219 }
Dan Stoza651bf312015-10-23 17:03:17 -0700220 (*outDisplay)->setVirtual();
221 return Error::None;
222}
223
224void Device::registerHotplugCallback(HotplugCallback hotplug)
225{
226 ALOGV("registerHotplugCallback");
227 mHotplug = hotplug;
228 for (auto& pending : mPendingHotplugs) {
229 auto& display = pending.first;
230 auto connected = pending.second;
231 ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
232 to_string(connected).c_str());
233 mHotplug(std::move(display), connected);
234 }
235}
236
237void Device::registerRefreshCallback(RefreshCallback refresh)
238{
239 mRefresh = refresh;
240 for (auto& pending : mPendingRefreshes) {
241 mRefresh(std::move(pending));
242 }
243}
244
245void Device::registerVsyncCallback(VsyncCallback vsync)
246{
247 mVsync = vsync;
248 for (auto& pending : mPendingVsyncs) {
249 auto& display = pending.first;
250 auto timestamp = pending.second;
251 mVsync(std::move(display), timestamp);
252 }
253}
254
255// For use by Device callbacks
256
257void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
258{
259 if (connected == Connection::Connected) {
260 if (!display->isConnected()) {
261 display->loadConfigs();
262 display->setConnected(true);
263 }
264 } else {
265 display->setConnected(false);
266 mDisplays.erase(display->getId());
267 }
268
269 if (mHotplug) {
270 mHotplug(std::move(display), connected);
271 } else {
272 ALOGV("callHotplug called, but no valid callback registered, storing");
273 mPendingHotplugs.emplace_back(std::move(display), connected);
274 }
275}
276
277void Device::callRefresh(std::shared_ptr<Display> display)
278{
279 if (mRefresh) {
280 mRefresh(std::move(display));
281 } else {
282 ALOGV("callRefresh called, but no valid callback registered, storing");
283 mPendingRefreshes.emplace_back(std::move(display));
284 }
285}
286
287void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
288{
289 if (mVsync) {
290 mVsync(std::move(display), timestamp);
291 } else {
292 ALOGV("callVsync called, but no valid callback registered, storing");
293 mPendingVsyncs.emplace_back(std::move(display), timestamp);
294 }
295}
296
297// Other Device methods
298
299std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
300 if (mDisplays.count(id) != 0) {
Dan Stoza38628982016-07-13 15:48:58 -0700301 auto strongDisplay = mDisplays[id].lock();
302 ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
303 " longer alive", id);
304 return strongDisplay;
Dan Stoza651bf312015-10-23 17:03:17 -0700305 }
306
307 auto display = std::make_shared<Display>(*this, id);
308 mDisplays.emplace(id, display);
309 return display;
310}
311
312// Device initialization methods
313
314void Device::loadCapabilities()
315{
316 static_assert(sizeof(Capability) == sizeof(int32_t),
317 "Capability size has changed");
318 uint32_t numCapabilities = 0;
319 mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
320 mCapabilities.resize(numCapabilities);
321 auto asInt = reinterpret_cast<int32_t*>(mCapabilities.data());
322 mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
323}
324
Dan Stoza09e7a272016-04-14 12:31:01 -0700325bool Device::hasCapability(HWC2::Capability capability) const
326{
327 return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
328 capability) != mCapabilities.cend();
329}
330
Dan Stoza651bf312015-10-23 17:03:17 -0700331void Device::loadFunctionPointers()
332{
333 // For all of these early returns, we log an error message inside
334 // loadFunctionPointer specifying which function failed to load
335
336 // Display function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700337 if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700338 mCreateVirtualDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700339 if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700340 mDestroyVirtualDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700341 if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
342 if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
Dan Stoza651bf312015-10-23 17:03:17 -0700343 mGetMaxVirtualDisplayCount)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700344 if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
Dan Stoza651bf312015-10-23 17:03:17 -0700345 mRegisterCallback)) return;
346
347 // Device function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700348 if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
Dan Stoza651bf312015-10-23 17:03:17 -0700349 mAcceptDisplayChanges)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700350 if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
Dan Stoza651bf312015-10-23 17:03:17 -0700351 mCreateLayer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700352 if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
Dan Stoza651bf312015-10-23 17:03:17 -0700353 mDestroyLayer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700354 if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
Dan Stoza651bf312015-10-23 17:03:17 -0700355 mGetActiveConfig)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700356 if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
Dan Stoza651bf312015-10-23 17:03:17 -0700357 mGetChangedCompositionTypes)) return;
Dan Stoza076ac672016-03-14 10:47:53 -0700358 if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
359 mGetColorModes)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700360 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
Dan Stoza651bf312015-10-23 17:03:17 -0700361 mGetDisplayAttribute)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700362 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
Dan Stoza651bf312015-10-23 17:03:17 -0700363 mGetDisplayConfigs)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700364 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
Dan Stoza651bf312015-10-23 17:03:17 -0700365 mGetDisplayName)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700366 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
Dan Stoza651bf312015-10-23 17:03:17 -0700367 mGetDisplayRequests)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700368 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
Dan Stoza651bf312015-10-23 17:03:17 -0700369 mGetDisplayType)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700370 if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
Dan Stoza651bf312015-10-23 17:03:17 -0700371 mGetDozeSupport)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700372 if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
373 mGetHdrCapabilities)) return;
374 if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
Dan Stoza651bf312015-10-23 17:03:17 -0700375 mGetReleaseFences)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700376 if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700377 mPresentDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700378 if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
Dan Stoza651bf312015-10-23 17:03:17 -0700379 mSetActiveConfig)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700380 if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
Dan Stoza651bf312015-10-23 17:03:17 -0700381 mSetClientTarget)) return;
Dan Stoza076ac672016-03-14 10:47:53 -0700382 if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
383 mSetColorMode)) return;
Dan Stoza5df2a862016-03-24 16:19:37 -0700384 if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
385 mSetColorTransform)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700386 if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
Dan Stoza651bf312015-10-23 17:03:17 -0700387 mSetOutputBuffer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700388 if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
Dan Stoza651bf312015-10-23 17:03:17 -0700389 mSetPowerMode)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700390 if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
Dan Stoza651bf312015-10-23 17:03:17 -0700391 mSetVsyncEnabled)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700392 if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700393 mValidateDisplay)) return;
394
395 // Layer function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700396 if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
Dan Stoza651bf312015-10-23 17:03:17 -0700397 mSetCursorPosition)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700398 if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
Dan Stoza651bf312015-10-23 17:03:17 -0700399 mSetLayerBuffer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700400 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
Dan Stoza651bf312015-10-23 17:03:17 -0700401 mSetLayerSurfaceDamage)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700402 if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
Dan Stoza651bf312015-10-23 17:03:17 -0700403 mSetLayerBlendMode)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700404 if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
Dan Stoza651bf312015-10-23 17:03:17 -0700405 mSetLayerColor)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700406 if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
Dan Stoza651bf312015-10-23 17:03:17 -0700407 mSetLayerCompositionType)) return;
Dan Stoza5df2a862016-03-24 16:19:37 -0700408 if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
409 mSetLayerDataspace)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700410 if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
Dan Stoza651bf312015-10-23 17:03:17 -0700411 mSetLayerDisplayFrame)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700412 if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
Dan Stoza651bf312015-10-23 17:03:17 -0700413 mSetLayerPlaneAlpha)) return;
Dan Stoza09e7a272016-04-14 12:31:01 -0700414 if (hasCapability(Capability::SidebandStream)) {
415 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
416 mSetLayerSidebandStream)) return;
417 }
Dan Stoza7d7ae732016-03-16 12:23:40 -0700418 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
Dan Stoza651bf312015-10-23 17:03:17 -0700419 mSetLayerSourceCrop)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700420 if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
Dan Stoza651bf312015-10-23 17:03:17 -0700421 mSetLayerTransform)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700422 if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
Dan Stoza651bf312015-10-23 17:03:17 -0700423 mSetLayerVisibleRegion)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700424 if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
Dan Stoza651bf312015-10-23 17:03:17 -0700425 mSetLayerZOrder)) return;
426}
427
428void Device::registerCallbacks()
429{
430 registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
431 registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
432 registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
433}
434
435
436// For use by Display
437
438void Device::destroyVirtualDisplay(hwc2_display_t display)
439{
440 ALOGI("Destroying virtual display");
441 int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
442 auto error = static_cast<Error>(intError);
443 ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
444 " %s (%d)", display, to_string(error).c_str(), intError);
Dan Stoza38628982016-07-13 15:48:58 -0700445 mDisplays.erase(display);
Dan Stoza651bf312015-10-23 17:03:17 -0700446}
447
448// Display methods
449
450Display::Display(Device& device, hwc2_display_t id)
451 : mDevice(device),
452 mId(id),
453 mIsConnected(false),
454 mIsVirtual(false)
455{
456 ALOGV("Created display %" PRIu64, id);
457}
458
459Display::~Display()
460{
461 ALOGV("Destroyed display %" PRIu64, mId);
462 if (mIsVirtual) {
463 mDevice.destroyVirtualDisplay(mId);
464 }
465}
466
467Display::Config::Config(Display& display, hwc2_config_t id)
468 : mDisplay(display),
469 mId(id),
470 mWidth(-1),
471 mHeight(-1),
472 mVsyncPeriod(-1),
473 mDpiX(-1),
474 mDpiY(-1) {}
475
476Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
477 : mConfig(new Config(display, id)) {}
478
479float Display::Config::Builder::getDefaultDensity() {
480 // Default density is based on TVs: 1080p displays get XHIGH density, lower-
481 // resolution displays get TV density. Maybe eventually we'll need to update
482 // it for 4k displays, though hopefully those will just report accurate DPI
483 // information to begin with. This is also used for virtual displays and
484 // older HWC implementations, so be careful about orientation.
485
486 auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
487 if (longDimension >= 1080) {
488 return ACONFIGURATION_DENSITY_XHIGH;
489 } else {
490 return ACONFIGURATION_DENSITY_TV;
491 }
492}
493
494// Required by HWC2 display
495
496Error Display::acceptChanges()
497{
498 int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
499 return static_cast<Error>(intError);
500}
501
502Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
503{
504 hwc2_layer_t layerId = 0;
505 int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
506 auto error = static_cast<Error>(intError);
507 if (error != Error::None) {
508 return error;
509 }
510
511 auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
512 mLayers.emplace(layerId, layer);
513 *outLayer = std::move(layer);
514 return Error::None;
515}
516
517Error Display::getActiveConfig(
518 std::shared_ptr<const Display::Config>* outConfig) const
519{
520 ALOGV("[%" PRIu64 "] getActiveConfig", mId);
521 hwc2_config_t configId = 0;
522 int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
523 &configId);
524 auto error = static_cast<Error>(intError);
525
526 if (error != Error::None) {
527 return error;
528 }
529
530 if (mConfigs.count(configId) != 0) {
531 *outConfig = mConfigs.at(configId);
532 } else {
533 ALOGE("[%" PRIu64 "] getActiveConfig returned unknown config %u", mId,
534 configId);
535 // Return no error, but the caller needs to check for a null pointer to
536 // detect this case
537 *outConfig = nullptr;
538 }
539
540 return Error::None;
541}
542
543Error Display::getChangedCompositionTypes(
544 std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
545{
546 uint32_t numElements = 0;
547 int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
548 mId, &numElements, nullptr, nullptr);
549 auto error = static_cast<Error>(intError);
550 if (error != Error::None) {
551 return error;
552 }
553
554 std::vector<hwc2_layer_t> layerIds(numElements);
555 std::vector<int32_t> types(numElements);
556 intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
557 &numElements, layerIds.data(), types.data());
558 error = static_cast<Error>(intError);
559 if (error != Error::None) {
560 return error;
561 }
562
563 outTypes->clear();
564 outTypes->reserve(numElements);
565 for (uint32_t element = 0; element < numElements; ++element) {
566 auto layer = getLayerById(layerIds[element]);
567 if (layer) {
568 auto type = static_cast<Composition>(types[element]);
569 ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s",
570 layer->getId(), to_string(type).c_str());
571 outTypes->emplace(layer, type);
572 } else {
573 ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found"
574 " on display %" PRIu64, layerIds[element], mId);
575 }
576 }
577
578 return Error::None;
579}
580
Dan Stoza076ac672016-03-14 10:47:53 -0700581Error Display::getColorModes(std::vector<int32_t>* outModes) const
582{
583 uint32_t numModes = 0;
584 int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
585 &numModes, nullptr);
586 auto error = static_cast<Error>(intError);
587 if (error != Error::None) {
588 return error;
589 }
590
591 std::vector<int32_t> modes(numModes);
592 intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
593 modes.data());
594 error = static_cast<Error>(intError);
595 if (error != Error::None) {
596 return error;
597 }
598
599 std::swap(*outModes, modes);
600 return Error::None;
601}
602
Dan Stoza651bf312015-10-23 17:03:17 -0700603std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
604{
605 std::vector<std::shared_ptr<const Config>> configs;
606 for (const auto& element : mConfigs) {
607 configs.emplace_back(element.second);
608 }
609 return configs;
610}
611
612Error Display::getName(std::string* outName) const
613{
614 uint32_t size;
615 int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
616 nullptr);
617 auto error = static_cast<Error>(intError);
618 if (error != Error::None) {
619 return error;
620 }
621
622 std::vector<char> rawName(size);
623 intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
624 rawName.data());
625 error = static_cast<Error>(intError);
626 if (error != Error::None) {
627 return error;
628 }
629
630 *outName = std::string(rawName.cbegin(), rawName.cend());
631 return Error::None;
632}
633
634Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
635 std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
636 outLayerRequests)
637{
638 int32_t intDisplayRequests = 0;
639 uint32_t numElements = 0;
640 int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
641 &intDisplayRequests, &numElements, nullptr, nullptr);
642 auto error = static_cast<Error>(intError);
643 if (error != Error::None) {
644 return error;
645 }
646
647 std::vector<hwc2_layer_t> layerIds(numElements);
648 std::vector<int32_t> layerRequests(numElements);
649 intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
650 &intDisplayRequests, &numElements, layerIds.data(),
651 layerRequests.data());
652 error = static_cast<Error>(intError);
653 if (error != Error::None) {
654 return error;
655 }
656
657 *outDisplayRequests = static_cast<DisplayRequest>(intDisplayRequests);
658 outLayerRequests->clear();
659 outLayerRequests->reserve(numElements);
660 for (uint32_t element = 0; element < numElements; ++element) {
661 auto layer = getLayerById(layerIds[element]);
662 if (layer) {
663 auto layerRequest =
664 static_cast<LayerRequest>(layerRequests[element]);
665 outLayerRequests->emplace(layer, layerRequest);
666 } else {
667 ALOGE("getRequests: invalid layer %" PRIu64 " found on display %"
668 PRIu64, layerIds[element], mId);
669 }
670 }
671
672 return Error::None;
673}
674
675Error Display::getType(DisplayType* outType) const
676{
677 int32_t intType = 0;
678 int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
679 &intType);
680 auto error = static_cast<Error>(intError);
681 if (error != Error::None) {
682 return error;
683 }
684
685 *outType = static_cast<DisplayType>(intType);
686 return Error::None;
687}
688
689Error Display::supportsDoze(bool* outSupport) const
690{
691 int32_t intSupport = 0;
692 int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
693 &intSupport);
694 auto error = static_cast<Error>(intError);
695 if (error != Error::None) {
696 return error;
697 }
698 *outSupport = static_cast<bool>(intSupport);
699 return Error::None;
700}
701
Dan Stoza7d7ae732016-03-16 12:23:40 -0700702Error Display::getHdrCapabilities(
703 std::unique_ptr<HdrCapabilities>* outCapabilities) const
704{
705 uint32_t numTypes = 0;
706 float maxLuminance = -1.0f;
707 float maxAverageLuminance = -1.0f;
708 float minLuminance = -1.0f;
709 int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
710 &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
711 &minLuminance);
712 auto error = static_cast<HWC2::Error>(intError);
713 if (error != Error::None) {
714 return error;
715 }
716
717 std::vector<int32_t> types(numTypes);
718 intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
719 types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
720 error = static_cast<HWC2::Error>(intError);
721 if (error != Error::None) {
722 return error;
723 }
724
725 *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
726 maxLuminance, maxAverageLuminance, minLuminance);
727 return Error::None;
728}
729
Dan Stoza651bf312015-10-23 17:03:17 -0700730Error Display::getReleaseFences(
731 std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
732{
733 uint32_t numElements = 0;
734 int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
735 &numElements, nullptr, nullptr);
736 auto error = static_cast<Error>(intError);
737 if (error != Error::None) {
738 return error;
739 }
740
741 std::vector<hwc2_layer_t> layerIds(numElements);
742 std::vector<int32_t> fenceFds(numElements);
743 intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
744 layerIds.data(), fenceFds.data());
745 error = static_cast<Error>(intError);
746 if (error != Error::None) {
747 return error;
748 }
749
750 std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
751 releaseFences.reserve(numElements);
752 for (uint32_t element = 0; element < numElements; ++element) {
753 auto layer = getLayerById(layerIds[element]);
754 if (layer) {
755 sp<Fence> fence(new Fence(fenceFds[element]));
756 releaseFences.emplace(std::move(layer), fence);
757 } else {
758 ALOGE("getReleaseFences: invalid layer %" PRIu64
759 " found on display %" PRIu64, layerIds[element], mId);
760 return Error::BadLayer;
761 }
762 }
763
764 *outFences = std::move(releaseFences);
765 return Error::None;
766}
767
768Error Display::present(sp<Fence>* outRetireFence)
769{
770 int32_t retireFenceFd = 0;
771 int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
772 &retireFenceFd);
773 auto error = static_cast<Error>(intError);
774 if (error != Error::None) {
775 return error;
776 }
777
778 *outRetireFence = new Fence(retireFenceFd);
779 return Error::None;
780}
781
782Error Display::setActiveConfig(const std::shared_ptr<const Config>& config)
783{
784 if (config->getDisplayId() != mId) {
785 ALOGE("setActiveConfig received config %u for the wrong display %"
786 PRIu64 " (expected %" PRIu64 ")", config->getId(),
787 config->getDisplayId(), mId);
788 return Error::BadConfig;
789 }
790 int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
791 config->getId());
792 return static_cast<Error>(intError);
793}
794
795Error Display::setClientTarget(buffer_handle_t target,
796 const sp<Fence>& acquireFence, android_dataspace_t dataspace)
797{
Dan Stoza5cf424b2016-05-20 14:02:39 -0700798 // TODO: Properly encode client target surface damage
Dan Stoza651bf312015-10-23 17:03:17 -0700799 int32_t fenceFd = acquireFence->dup();
800 int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
Dan Stoza5cf424b2016-05-20 14:02:39 -0700801 fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
Dan Stoza651bf312015-10-23 17:03:17 -0700802 return static_cast<Error>(intError);
803}
804
Dan Stoza076ac672016-03-14 10:47:53 -0700805Error Display::setColorMode(int32_t mode)
806{
807 int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
808 return static_cast<Error>(intError);
809}
810
Dan Stoza5df2a862016-03-24 16:19:37 -0700811Error Display::setColorTransform(const android::mat4& matrix,
812 android_color_transform_t hint)
813{
814 int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
815 matrix.asArray(), static_cast<int32_t>(hint));
816 return static_cast<Error>(intError);
817}
818
Dan Stoza651bf312015-10-23 17:03:17 -0700819Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
820 const sp<Fence>& releaseFence)
821{
822 int32_t fenceFd = releaseFence->dup();
823 auto handle = buffer->getNativeBuffer()->handle;
824 int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
825 fenceFd);
Dan Stoza38628982016-07-13 15:48:58 -0700826 close(fenceFd);
Dan Stoza651bf312015-10-23 17:03:17 -0700827 return static_cast<Error>(intError);
828}
829
830Error Display::setPowerMode(PowerMode mode)
831{
832 auto intMode = static_cast<int32_t>(mode);
833 int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
834 return static_cast<Error>(intError);
835}
836
837Error Display::setVsyncEnabled(Vsync enabled)
838{
839 auto intEnabled = static_cast<int32_t>(enabled);
840 int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
841 intEnabled);
842 return static_cast<Error>(intError);
843}
844
845Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
846{
847 uint32_t numTypes = 0;
848 uint32_t numRequests = 0;
849 int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
850 &numTypes, &numRequests);
851 auto error = static_cast<Error>(intError);
852 if (error != Error::None && error != Error::HasChanges) {
853 return error;
854 }
855
856 *outNumTypes = numTypes;
857 *outNumRequests = numRequests;
858 return error;
859}
860
861// For use by Device
862
863int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
864{
865 int32_t value = 0;
866 int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
867 configId, static_cast<int32_t>(attribute), &value);
868 auto error = static_cast<Error>(intError);
869 if (error != Error::None) {
870 ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
871 configId, to_string(attribute).c_str(),
872 to_string(error).c_str(), intError);
873 return -1;
874 }
875 return value;
876}
877
878void Display::loadConfig(hwc2_config_t configId)
879{
880 ALOGV("[%" PRIu64 "] loadConfig(%u)", mId, configId);
881
882 auto config = Config::Builder(*this, configId)
883 .setWidth(getAttribute(configId, Attribute::Width))
884 .setHeight(getAttribute(configId, Attribute::Height))
885 .setVsyncPeriod(getAttribute(configId, Attribute::VsyncPeriod))
886 .setDpiX(getAttribute(configId, Attribute::DpiX))
887 .setDpiY(getAttribute(configId, Attribute::DpiY))
888 .build();
889 mConfigs.emplace(configId, std::move(config));
890}
891
892void Display::loadConfigs()
893{
894 ALOGV("[%" PRIu64 "] loadConfigs", mId);
895
896 uint32_t numConfigs = 0;
897 int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
898 &numConfigs, nullptr);
899 auto error = static_cast<Error>(intError);
900 if (error != Error::None) {
901 ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
902 to_string(error).c_str(), intError);
903 return;
904 }
905
906 std::vector<hwc2_config_t> configIds(numConfigs);
907 intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
908 configIds.data());
909 error = static_cast<Error>(intError);
910 if (error != Error::None) {
911 ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
912 to_string(error).c_str(), intError);
913 return;
914 }
915
916 for (auto configId : configIds) {
917 loadConfig(configId);
918 }
919}
920
921// For use by Layer
922
923void Display::destroyLayer(hwc2_layer_t layerId)
924{
925 int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
926 auto error = static_cast<Error>(intError);
927 ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
928 " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
929 intError);
930 mLayers.erase(layerId);
931}
932
933// Other Display methods
934
935std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
936{
937 if (mLayers.count(id) == 0) {
938 return nullptr;
939 }
940
941 auto layer = mLayers.at(id).lock();
942 return layer;
943}
944
945// Layer methods
946
947Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
948 : mDisplay(display),
949 mDisplayId(display->getId()),
950 mDevice(display->getDevice()),
951 mId(id)
952{
953 ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
954 display->getId());
955}
956
957Layer::~Layer()
958{
959 auto display = mDisplay.lock();
960 if (display) {
961 display->destroyLayer(mId);
962 }
963}
964
965Error Layer::setCursorPosition(int32_t x, int32_t y)
966{
967 int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
968 mDisplayId, mId, x, y);
969 return static_cast<Error>(intError);
970}
971
972Error Layer::setBuffer(buffer_handle_t buffer,
973 const sp<Fence>& acquireFence)
974{
975 int32_t fenceFd = acquireFence->dup();
976 int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
977 mId, buffer, fenceFd);
978 return static_cast<Error>(intError);
979}
980
981Error Layer::setSurfaceDamage(const Region& damage)
982{
983 // We encode default full-screen damage as INVALID_RECT upstream, but as 0
984 // rects for HWC
985 int32_t intError = 0;
986 if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
987 intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
988 mDisplayId, mId, {0, nullptr});
989 } else {
990 size_t rectCount = 0;
991 auto rectArray = damage.getArray(&rectCount);
992
993 std::vector<hwc_rect_t> hwcRects;
994 for (size_t rect = 0; rect < rectCount; ++rect) {
995 hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
996 rectArray[rect].right, rectArray[rect].bottom});
997 }
998
999 hwc_region_t hwcRegion = {};
1000 hwcRegion.numRects = rectCount;
1001 hwcRegion.rects = hwcRects.data();
1002
1003 intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
1004 mDisplayId, mId, hwcRegion);
1005 }
1006
1007 return static_cast<Error>(intError);
1008}
1009
1010Error Layer::setBlendMode(BlendMode mode)
1011{
1012 auto intMode = static_cast<int32_t>(mode);
1013 int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
1014 mDisplayId, mId, intMode);
1015 return static_cast<Error>(intError);
1016}
1017
1018Error Layer::setColor(hwc_color_t color)
1019{
1020 int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
1021 mId, color);
1022 return static_cast<Error>(intError);
1023}
1024
1025Error Layer::setCompositionType(Composition type)
1026{
1027 auto intType = static_cast<int32_t>(type);
1028 int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
1029 mDisplayId, mId, intType);
1030 return static_cast<Error>(intError);
1031}
1032
Dan Stoza5df2a862016-03-24 16:19:37 -07001033Error Layer::setDataspace(android_dataspace_t dataspace)
1034{
1035 auto intDataspace = static_cast<int32_t>(dataspace);
1036 int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
1037 mDisplayId, mId, intDataspace);
1038 return static_cast<Error>(intError);
1039}
1040
Dan Stoza651bf312015-10-23 17:03:17 -07001041Error Layer::setDisplayFrame(const Rect& frame)
1042{
1043 hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
1044 int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
1045 mDisplayId, mId, hwcRect);
1046 return static_cast<Error>(intError);
1047}
1048
1049Error Layer::setPlaneAlpha(float alpha)
1050{
1051 int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
1052 mDisplayId, mId, alpha);
1053 return static_cast<Error>(intError);
1054}
1055
1056Error Layer::setSidebandStream(const native_handle_t* stream)
1057{
Dan Stoza09e7a272016-04-14 12:31:01 -07001058 if (!mDevice.hasCapability(Capability::SidebandStream)) {
1059 ALOGE("Attempted to call setSidebandStream without checking that the "
1060 "device supports sideband streams");
1061 return Error::Unsupported;
1062 }
Dan Stoza651bf312015-10-23 17:03:17 -07001063 int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
1064 mDisplayId, mId, stream);
1065 return static_cast<Error>(intError);
1066}
1067
1068Error Layer::setSourceCrop(const FloatRect& crop)
1069{
1070 hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
1071 int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
1072 mDisplayId, mId, hwcRect);
1073 return static_cast<Error>(intError);
1074}
1075
1076Error Layer::setTransform(Transform transform)
1077{
1078 auto intTransform = static_cast<int32_t>(transform);
1079 int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
1080 mDisplayId, mId, intTransform);
1081 return static_cast<Error>(intError);
1082}
1083
1084Error Layer::setVisibleRegion(const Region& region)
1085{
1086 size_t rectCount = 0;
1087 auto rectArray = region.getArray(&rectCount);
1088
1089 std::vector<hwc_rect_t> hwcRects;
1090 for (size_t rect = 0; rect < rectCount; ++rect) {
1091 hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
1092 rectArray[rect].right, rectArray[rect].bottom});
1093 }
1094
1095 hwc_region_t hwcRegion = {};
1096 hwcRegion.numRects = rectCount;
1097 hwcRegion.rects = hwcRects.data();
1098
1099 int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
1100 mDisplayId, mId, hwcRegion);
1101 return static_cast<Error>(intError);
1102}
1103
1104Error Layer::setZOrder(uint32_t z)
1105{
1106 int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
1107 mId, z);
1108 return static_cast<Error>(intError);
1109}
1110
1111} // namespace HWC2