blob: 87a0e9a13aa2f1d51afbf7211aec9f49fbecc0b9 [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);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700320 std::vector<Capability> capabilities(numCapabilities);
321 auto asInt = reinterpret_cast<int32_t*>(capabilities.data());
Dan Stoza651bf312015-10-23 17:03:17 -0700322 mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
Dan Stoza9f26a9c2016-06-22 14:51:09 -0700323 for (auto capability : capabilities) {
324 mCapabilities.emplace(capability);
325 }
Dan Stoza651bf312015-10-23 17:03:17 -0700326}
327
Dan Stoza09e7a272016-04-14 12:31:01 -0700328bool Device::hasCapability(HWC2::Capability capability) const
329{
330 return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
331 capability) != mCapabilities.cend();
332}
333
Dan Stoza651bf312015-10-23 17:03:17 -0700334void Device::loadFunctionPointers()
335{
336 // For all of these early returns, we log an error message inside
337 // loadFunctionPointer specifying which function failed to load
338
339 // Display function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700340 if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700341 mCreateVirtualDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700342 if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700343 mDestroyVirtualDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700344 if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
345 if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
Dan Stoza651bf312015-10-23 17:03:17 -0700346 mGetMaxVirtualDisplayCount)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700347 if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
Dan Stoza651bf312015-10-23 17:03:17 -0700348 mRegisterCallback)) return;
349
350 // Device function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700351 if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
Dan Stoza651bf312015-10-23 17:03:17 -0700352 mAcceptDisplayChanges)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700353 if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
Dan Stoza651bf312015-10-23 17:03:17 -0700354 mCreateLayer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700355 if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
Dan Stoza651bf312015-10-23 17:03:17 -0700356 mDestroyLayer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700357 if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
Dan Stoza651bf312015-10-23 17:03:17 -0700358 mGetActiveConfig)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700359 if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
Dan Stoza651bf312015-10-23 17:03:17 -0700360 mGetChangedCompositionTypes)) return;
Dan Stoza076ac672016-03-14 10:47:53 -0700361 if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
362 mGetColorModes)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700363 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
Dan Stoza651bf312015-10-23 17:03:17 -0700364 mGetDisplayAttribute)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700365 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
Dan Stoza651bf312015-10-23 17:03:17 -0700366 mGetDisplayConfigs)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700367 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
Dan Stoza651bf312015-10-23 17:03:17 -0700368 mGetDisplayName)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700369 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
Dan Stoza651bf312015-10-23 17:03:17 -0700370 mGetDisplayRequests)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700371 if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
Dan Stoza651bf312015-10-23 17:03:17 -0700372 mGetDisplayType)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700373 if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
Dan Stoza651bf312015-10-23 17:03:17 -0700374 mGetDozeSupport)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700375 if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
376 mGetHdrCapabilities)) return;
377 if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
Dan Stoza651bf312015-10-23 17:03:17 -0700378 mGetReleaseFences)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700379 if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700380 mPresentDisplay)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700381 if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
Dan Stoza651bf312015-10-23 17:03:17 -0700382 mSetActiveConfig)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700383 if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
Dan Stoza651bf312015-10-23 17:03:17 -0700384 mSetClientTarget)) return;
Dan Stoza076ac672016-03-14 10:47:53 -0700385 if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
386 mSetColorMode)) return;
Dan Stoza5df2a862016-03-24 16:19:37 -0700387 if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
388 mSetColorTransform)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700389 if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
Dan Stoza651bf312015-10-23 17:03:17 -0700390 mSetOutputBuffer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700391 if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
Dan Stoza651bf312015-10-23 17:03:17 -0700392 mSetPowerMode)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700393 if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
Dan Stoza651bf312015-10-23 17:03:17 -0700394 mSetVsyncEnabled)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700395 if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
Dan Stoza651bf312015-10-23 17:03:17 -0700396 mValidateDisplay)) return;
397
398 // Layer function pointers
Dan Stoza7d7ae732016-03-16 12:23:40 -0700399 if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
Dan Stoza651bf312015-10-23 17:03:17 -0700400 mSetCursorPosition)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700401 if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
Dan Stoza651bf312015-10-23 17:03:17 -0700402 mSetLayerBuffer)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700403 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
Dan Stoza651bf312015-10-23 17:03:17 -0700404 mSetLayerSurfaceDamage)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700405 if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
Dan Stoza651bf312015-10-23 17:03:17 -0700406 mSetLayerBlendMode)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700407 if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
Dan Stoza651bf312015-10-23 17:03:17 -0700408 mSetLayerColor)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700409 if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
Dan Stoza651bf312015-10-23 17:03:17 -0700410 mSetLayerCompositionType)) return;
Dan Stoza5df2a862016-03-24 16:19:37 -0700411 if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
412 mSetLayerDataspace)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700413 if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
Dan Stoza651bf312015-10-23 17:03:17 -0700414 mSetLayerDisplayFrame)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700415 if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
Dan Stoza651bf312015-10-23 17:03:17 -0700416 mSetLayerPlaneAlpha)) return;
Dan Stoza09e7a272016-04-14 12:31:01 -0700417 if (hasCapability(Capability::SidebandStream)) {
418 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
419 mSetLayerSidebandStream)) return;
420 }
Dan Stoza7d7ae732016-03-16 12:23:40 -0700421 if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
Dan Stoza651bf312015-10-23 17:03:17 -0700422 mSetLayerSourceCrop)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700423 if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
Dan Stoza651bf312015-10-23 17:03:17 -0700424 mSetLayerTransform)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700425 if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
Dan Stoza651bf312015-10-23 17:03:17 -0700426 mSetLayerVisibleRegion)) return;
Dan Stoza7d7ae732016-03-16 12:23:40 -0700427 if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
Dan Stoza651bf312015-10-23 17:03:17 -0700428 mSetLayerZOrder)) return;
429}
430
431void Device::registerCallbacks()
432{
433 registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
434 registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
435 registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
436}
437
438
439// For use by Display
440
441void Device::destroyVirtualDisplay(hwc2_display_t display)
442{
443 ALOGI("Destroying virtual display");
444 int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
445 auto error = static_cast<Error>(intError);
446 ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
447 " %s (%d)", display, to_string(error).c_str(), intError);
Dan Stoza38628982016-07-13 15:48:58 -0700448 mDisplays.erase(display);
Dan Stoza651bf312015-10-23 17:03:17 -0700449}
450
451// Display methods
452
453Display::Display(Device& device, hwc2_display_t id)
454 : mDevice(device),
455 mId(id),
456 mIsConnected(false),
457 mIsVirtual(false)
458{
459 ALOGV("Created display %" PRIu64, id);
460}
461
462Display::~Display()
463{
464 ALOGV("Destroyed display %" PRIu64, mId);
465 if (mIsVirtual) {
466 mDevice.destroyVirtualDisplay(mId);
467 }
468}
469
470Display::Config::Config(Display& display, hwc2_config_t id)
471 : mDisplay(display),
472 mId(id),
473 mWidth(-1),
474 mHeight(-1),
475 mVsyncPeriod(-1),
476 mDpiX(-1),
477 mDpiY(-1) {}
478
479Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
480 : mConfig(new Config(display, id)) {}
481
482float Display::Config::Builder::getDefaultDensity() {
483 // Default density is based on TVs: 1080p displays get XHIGH density, lower-
484 // resolution displays get TV density. Maybe eventually we'll need to update
485 // it for 4k displays, though hopefully those will just report accurate DPI
486 // information to begin with. This is also used for virtual displays and
487 // older HWC implementations, so be careful about orientation.
488
489 auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
490 if (longDimension >= 1080) {
491 return ACONFIGURATION_DENSITY_XHIGH;
492 } else {
493 return ACONFIGURATION_DENSITY_TV;
494 }
495}
496
497// Required by HWC2 display
498
499Error Display::acceptChanges()
500{
501 int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
502 return static_cast<Error>(intError);
503}
504
505Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
506{
507 hwc2_layer_t layerId = 0;
508 int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
509 auto error = static_cast<Error>(intError);
510 if (error != Error::None) {
511 return error;
512 }
513
514 auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
515 mLayers.emplace(layerId, layer);
516 *outLayer = std::move(layer);
517 return Error::None;
518}
519
520Error Display::getActiveConfig(
521 std::shared_ptr<const Display::Config>* outConfig) const
522{
523 ALOGV("[%" PRIu64 "] getActiveConfig", mId);
524 hwc2_config_t configId = 0;
525 int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
526 &configId);
527 auto error = static_cast<Error>(intError);
528
529 if (error != Error::None) {
530 return error;
531 }
532
533 if (mConfigs.count(configId) != 0) {
534 *outConfig = mConfigs.at(configId);
535 } else {
536 ALOGE("[%" PRIu64 "] getActiveConfig returned unknown config %u", mId,
537 configId);
538 // Return no error, but the caller needs to check for a null pointer to
539 // detect this case
540 *outConfig = nullptr;
541 }
542
543 return Error::None;
544}
545
546Error Display::getChangedCompositionTypes(
547 std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
548{
549 uint32_t numElements = 0;
550 int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
551 mId, &numElements, nullptr, nullptr);
552 auto error = static_cast<Error>(intError);
553 if (error != Error::None) {
554 return error;
555 }
556
557 std::vector<hwc2_layer_t> layerIds(numElements);
558 std::vector<int32_t> types(numElements);
559 intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
560 &numElements, layerIds.data(), types.data());
561 error = static_cast<Error>(intError);
562 if (error != Error::None) {
563 return error;
564 }
565
566 outTypes->clear();
567 outTypes->reserve(numElements);
568 for (uint32_t element = 0; element < numElements; ++element) {
569 auto layer = getLayerById(layerIds[element]);
570 if (layer) {
571 auto type = static_cast<Composition>(types[element]);
572 ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s",
573 layer->getId(), to_string(type).c_str());
574 outTypes->emplace(layer, type);
575 } else {
576 ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found"
577 " on display %" PRIu64, layerIds[element], mId);
578 }
579 }
580
581 return Error::None;
582}
583
Dan Stoza076ac672016-03-14 10:47:53 -0700584Error Display::getColorModes(std::vector<int32_t>* outModes) const
585{
586 uint32_t numModes = 0;
587 int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
588 &numModes, nullptr);
589 auto error = static_cast<Error>(intError);
590 if (error != Error::None) {
591 return error;
592 }
593
594 std::vector<int32_t> modes(numModes);
595 intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
596 modes.data());
597 error = static_cast<Error>(intError);
598 if (error != Error::None) {
599 return error;
600 }
601
602 std::swap(*outModes, modes);
603 return Error::None;
604}
605
Dan Stoza651bf312015-10-23 17:03:17 -0700606std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
607{
608 std::vector<std::shared_ptr<const Config>> configs;
609 for (const auto& element : mConfigs) {
610 configs.emplace_back(element.second);
611 }
612 return configs;
613}
614
615Error Display::getName(std::string* outName) const
616{
617 uint32_t size;
618 int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
619 nullptr);
620 auto error = static_cast<Error>(intError);
621 if (error != Error::None) {
622 return error;
623 }
624
625 std::vector<char> rawName(size);
626 intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
627 rawName.data());
628 error = static_cast<Error>(intError);
629 if (error != Error::None) {
630 return error;
631 }
632
633 *outName = std::string(rawName.cbegin(), rawName.cend());
634 return Error::None;
635}
636
637Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
638 std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
639 outLayerRequests)
640{
641 int32_t intDisplayRequests = 0;
642 uint32_t numElements = 0;
643 int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
644 &intDisplayRequests, &numElements, nullptr, nullptr);
645 auto error = static_cast<Error>(intError);
646 if (error != Error::None) {
647 return error;
648 }
649
650 std::vector<hwc2_layer_t> layerIds(numElements);
651 std::vector<int32_t> layerRequests(numElements);
652 intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
653 &intDisplayRequests, &numElements, layerIds.data(),
654 layerRequests.data());
655 error = static_cast<Error>(intError);
656 if (error != Error::None) {
657 return error;
658 }
659
660 *outDisplayRequests = static_cast<DisplayRequest>(intDisplayRequests);
661 outLayerRequests->clear();
662 outLayerRequests->reserve(numElements);
663 for (uint32_t element = 0; element < numElements; ++element) {
664 auto layer = getLayerById(layerIds[element]);
665 if (layer) {
666 auto layerRequest =
667 static_cast<LayerRequest>(layerRequests[element]);
668 outLayerRequests->emplace(layer, layerRequest);
669 } else {
670 ALOGE("getRequests: invalid layer %" PRIu64 " found on display %"
671 PRIu64, layerIds[element], mId);
672 }
673 }
674
675 return Error::None;
676}
677
678Error Display::getType(DisplayType* outType) const
679{
680 int32_t intType = 0;
681 int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
682 &intType);
683 auto error = static_cast<Error>(intError);
684 if (error != Error::None) {
685 return error;
686 }
687
688 *outType = static_cast<DisplayType>(intType);
689 return Error::None;
690}
691
692Error Display::supportsDoze(bool* outSupport) const
693{
694 int32_t intSupport = 0;
695 int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
696 &intSupport);
697 auto error = static_cast<Error>(intError);
698 if (error != Error::None) {
699 return error;
700 }
701 *outSupport = static_cast<bool>(intSupport);
702 return Error::None;
703}
704
Dan Stoza7d7ae732016-03-16 12:23:40 -0700705Error Display::getHdrCapabilities(
706 std::unique_ptr<HdrCapabilities>* outCapabilities) const
707{
708 uint32_t numTypes = 0;
709 float maxLuminance = -1.0f;
710 float maxAverageLuminance = -1.0f;
711 float minLuminance = -1.0f;
712 int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
713 &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
714 &minLuminance);
715 auto error = static_cast<HWC2::Error>(intError);
716 if (error != Error::None) {
717 return error;
718 }
719
720 std::vector<int32_t> types(numTypes);
721 intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
722 types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
723 error = static_cast<HWC2::Error>(intError);
724 if (error != Error::None) {
725 return error;
726 }
727
728 *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
729 maxLuminance, maxAverageLuminance, minLuminance);
730 return Error::None;
731}
732
Dan Stoza651bf312015-10-23 17:03:17 -0700733Error Display::getReleaseFences(
734 std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
735{
736 uint32_t numElements = 0;
737 int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
738 &numElements, nullptr, nullptr);
739 auto error = static_cast<Error>(intError);
740 if (error != Error::None) {
741 return error;
742 }
743
744 std::vector<hwc2_layer_t> layerIds(numElements);
745 std::vector<int32_t> fenceFds(numElements);
746 intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
747 layerIds.data(), fenceFds.data());
748 error = static_cast<Error>(intError);
749 if (error != Error::None) {
750 return error;
751 }
752
753 std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
754 releaseFences.reserve(numElements);
755 for (uint32_t element = 0; element < numElements; ++element) {
756 auto layer = getLayerById(layerIds[element]);
757 if (layer) {
758 sp<Fence> fence(new Fence(fenceFds[element]));
759 releaseFences.emplace(std::move(layer), fence);
760 } else {
761 ALOGE("getReleaseFences: invalid layer %" PRIu64
762 " found on display %" PRIu64, layerIds[element], mId);
763 return Error::BadLayer;
764 }
765 }
766
767 *outFences = std::move(releaseFences);
768 return Error::None;
769}
770
771Error Display::present(sp<Fence>* outRetireFence)
772{
773 int32_t retireFenceFd = 0;
774 int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
775 &retireFenceFd);
776 auto error = static_cast<Error>(intError);
777 if (error != Error::None) {
778 return error;
779 }
780
781 *outRetireFence = new Fence(retireFenceFd);
782 return Error::None;
783}
784
785Error Display::setActiveConfig(const std::shared_ptr<const Config>& config)
786{
787 if (config->getDisplayId() != mId) {
788 ALOGE("setActiveConfig received config %u for the wrong display %"
789 PRIu64 " (expected %" PRIu64 ")", config->getId(),
790 config->getDisplayId(), mId);
791 return Error::BadConfig;
792 }
793 int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
794 config->getId());
795 return static_cast<Error>(intError);
796}
797
798Error Display::setClientTarget(buffer_handle_t target,
799 const sp<Fence>& acquireFence, android_dataspace_t dataspace)
800{
Dan Stoza5cf424b2016-05-20 14:02:39 -0700801 // TODO: Properly encode client target surface damage
Dan Stoza651bf312015-10-23 17:03:17 -0700802 int32_t fenceFd = acquireFence->dup();
803 int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
Dan Stoza5cf424b2016-05-20 14:02:39 -0700804 fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
Dan Stoza651bf312015-10-23 17:03:17 -0700805 return static_cast<Error>(intError);
806}
807
Dan Stoza076ac672016-03-14 10:47:53 -0700808Error Display::setColorMode(int32_t mode)
809{
810 int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
811 return static_cast<Error>(intError);
812}
813
Dan Stoza5df2a862016-03-24 16:19:37 -0700814Error Display::setColorTransform(const android::mat4& matrix,
815 android_color_transform_t hint)
816{
817 int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
818 matrix.asArray(), static_cast<int32_t>(hint));
819 return static_cast<Error>(intError);
820}
821
Dan Stoza651bf312015-10-23 17:03:17 -0700822Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
823 const sp<Fence>& releaseFence)
824{
825 int32_t fenceFd = releaseFence->dup();
826 auto handle = buffer->getNativeBuffer()->handle;
827 int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
828 fenceFd);
Dan Stoza38628982016-07-13 15:48:58 -0700829 close(fenceFd);
Dan Stoza651bf312015-10-23 17:03:17 -0700830 return static_cast<Error>(intError);
831}
832
833Error Display::setPowerMode(PowerMode mode)
834{
835 auto intMode = static_cast<int32_t>(mode);
836 int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
837 return static_cast<Error>(intError);
838}
839
840Error Display::setVsyncEnabled(Vsync enabled)
841{
842 auto intEnabled = static_cast<int32_t>(enabled);
843 int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
844 intEnabled);
845 return static_cast<Error>(intError);
846}
847
848Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
849{
850 uint32_t numTypes = 0;
851 uint32_t numRequests = 0;
852 int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
853 &numTypes, &numRequests);
854 auto error = static_cast<Error>(intError);
855 if (error != Error::None && error != Error::HasChanges) {
856 return error;
857 }
858
859 *outNumTypes = numTypes;
860 *outNumRequests = numRequests;
861 return error;
862}
863
864// For use by Device
865
866int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
867{
868 int32_t value = 0;
869 int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
870 configId, static_cast<int32_t>(attribute), &value);
871 auto error = static_cast<Error>(intError);
872 if (error != Error::None) {
873 ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
874 configId, to_string(attribute).c_str(),
875 to_string(error).c_str(), intError);
876 return -1;
877 }
878 return value;
879}
880
881void Display::loadConfig(hwc2_config_t configId)
882{
883 ALOGV("[%" PRIu64 "] loadConfig(%u)", mId, configId);
884
885 auto config = Config::Builder(*this, configId)
886 .setWidth(getAttribute(configId, Attribute::Width))
887 .setHeight(getAttribute(configId, Attribute::Height))
888 .setVsyncPeriod(getAttribute(configId, Attribute::VsyncPeriod))
889 .setDpiX(getAttribute(configId, Attribute::DpiX))
890 .setDpiY(getAttribute(configId, Attribute::DpiY))
891 .build();
892 mConfigs.emplace(configId, std::move(config));
893}
894
895void Display::loadConfigs()
896{
897 ALOGV("[%" PRIu64 "] loadConfigs", mId);
898
899 uint32_t numConfigs = 0;
900 int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
901 &numConfigs, nullptr);
902 auto error = static_cast<Error>(intError);
903 if (error != Error::None) {
904 ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
905 to_string(error).c_str(), intError);
906 return;
907 }
908
909 std::vector<hwc2_config_t> configIds(numConfigs);
910 intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
911 configIds.data());
912 error = static_cast<Error>(intError);
913 if (error != Error::None) {
914 ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
915 to_string(error).c_str(), intError);
916 return;
917 }
918
919 for (auto configId : configIds) {
920 loadConfig(configId);
921 }
922}
923
924// For use by Layer
925
926void Display::destroyLayer(hwc2_layer_t layerId)
927{
928 int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
929 auto error = static_cast<Error>(intError);
930 ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
931 " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
932 intError);
933 mLayers.erase(layerId);
934}
935
936// Other Display methods
937
938std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
939{
940 if (mLayers.count(id) == 0) {
941 return nullptr;
942 }
943
944 auto layer = mLayers.at(id).lock();
945 return layer;
946}
947
948// Layer methods
949
950Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
951 : mDisplay(display),
952 mDisplayId(display->getId()),
953 mDevice(display->getDevice()),
954 mId(id)
955{
956 ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
957 display->getId());
958}
959
960Layer::~Layer()
961{
962 auto display = mDisplay.lock();
963 if (display) {
964 display->destroyLayer(mId);
965 }
966}
967
968Error Layer::setCursorPosition(int32_t x, int32_t y)
969{
970 int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
971 mDisplayId, mId, x, y);
972 return static_cast<Error>(intError);
973}
974
975Error Layer::setBuffer(buffer_handle_t buffer,
976 const sp<Fence>& acquireFence)
977{
978 int32_t fenceFd = acquireFence->dup();
979 int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
980 mId, buffer, fenceFd);
981 return static_cast<Error>(intError);
982}
983
984Error Layer::setSurfaceDamage(const Region& damage)
985{
986 // We encode default full-screen damage as INVALID_RECT upstream, but as 0
987 // rects for HWC
988 int32_t intError = 0;
989 if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
990 intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
991 mDisplayId, mId, {0, nullptr});
992 } else {
993 size_t rectCount = 0;
994 auto rectArray = damage.getArray(&rectCount);
995
996 std::vector<hwc_rect_t> hwcRects;
997 for (size_t rect = 0; rect < rectCount; ++rect) {
998 hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
999 rectArray[rect].right, rectArray[rect].bottom});
1000 }
1001
1002 hwc_region_t hwcRegion = {};
1003 hwcRegion.numRects = rectCount;
1004 hwcRegion.rects = hwcRects.data();
1005
1006 intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
1007 mDisplayId, mId, hwcRegion);
1008 }
1009
1010 return static_cast<Error>(intError);
1011}
1012
1013Error Layer::setBlendMode(BlendMode mode)
1014{
1015 auto intMode = static_cast<int32_t>(mode);
1016 int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
1017 mDisplayId, mId, intMode);
1018 return static_cast<Error>(intError);
1019}
1020
1021Error Layer::setColor(hwc_color_t color)
1022{
1023 int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
1024 mId, color);
1025 return static_cast<Error>(intError);
1026}
1027
1028Error Layer::setCompositionType(Composition type)
1029{
1030 auto intType = static_cast<int32_t>(type);
1031 int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
1032 mDisplayId, mId, intType);
1033 return static_cast<Error>(intError);
1034}
1035
Dan Stoza5df2a862016-03-24 16:19:37 -07001036Error Layer::setDataspace(android_dataspace_t dataspace)
1037{
1038 auto intDataspace = static_cast<int32_t>(dataspace);
1039 int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
1040 mDisplayId, mId, intDataspace);
1041 return static_cast<Error>(intError);
1042}
1043
Dan Stoza651bf312015-10-23 17:03:17 -07001044Error Layer::setDisplayFrame(const Rect& frame)
1045{
1046 hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
1047 int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
1048 mDisplayId, mId, hwcRect);
1049 return static_cast<Error>(intError);
1050}
1051
1052Error Layer::setPlaneAlpha(float alpha)
1053{
1054 int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
1055 mDisplayId, mId, alpha);
1056 return static_cast<Error>(intError);
1057}
1058
1059Error Layer::setSidebandStream(const native_handle_t* stream)
1060{
Dan Stoza09e7a272016-04-14 12:31:01 -07001061 if (!mDevice.hasCapability(Capability::SidebandStream)) {
1062 ALOGE("Attempted to call setSidebandStream without checking that the "
1063 "device supports sideband streams");
1064 return Error::Unsupported;
1065 }
Dan Stoza651bf312015-10-23 17:03:17 -07001066 int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
1067 mDisplayId, mId, stream);
1068 return static_cast<Error>(intError);
1069}
1070
1071Error Layer::setSourceCrop(const FloatRect& crop)
1072{
1073 hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
1074 int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
1075 mDisplayId, mId, hwcRect);
1076 return static_cast<Error>(intError);
1077}
1078
1079Error Layer::setTransform(Transform transform)
1080{
1081 auto intTransform = static_cast<int32_t>(transform);
1082 int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
1083 mDisplayId, mId, intTransform);
1084 return static_cast<Error>(intError);
1085}
1086
1087Error Layer::setVisibleRegion(const Region& region)
1088{
1089 size_t rectCount = 0;
1090 auto rectArray = region.getArray(&rectCount);
1091
1092 std::vector<hwc_rect_t> hwcRects;
1093 for (size_t rect = 0; rect < rectCount; ++rect) {
1094 hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
1095 rectArray[rect].right, rectArray[rect].bottom});
1096 }
1097
1098 hwc_region_t hwcRegion = {};
1099 hwcRegion.numRects = rectCount;
1100 hwcRegion.rects = hwcRects.data();
1101
1102 int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
1103 mDisplayId, mId, hwcRegion);
1104 return static_cast<Error>(intError);
1105}
1106
1107Error Layer::setZOrder(uint32_t z)
1108{
1109 int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
1110 mId, z);
1111 return static_cast<Error>(intError);
1112}
1113
1114} // namespace HWC2