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// #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#include "ComposerHal.h"
25
26#include <ui/Fence.h>
27#include <ui/FloatRect.h>
28#include <ui/GraphicBuffer.h>
29#include <ui/Region.h>
30
31#include <android/configuration.h>
32
33#include <algorithm>
34#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;
78using android::HdrCapabilities;
79using android::Rect;
80using android::Region;
81using android::sp;
82using android::hardware::Return;
83using android::hardware::Void;
84
85namespace HWC2 {
86
87namespace Hwc2 = android::Hwc2;
88
89// Device methods
90
91Device::Device(bool useVrComposer)
92  : mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),
93    mCapabilities(),
94    mDisplays(),
95    mHotplug(),
96    mPendingHotplugs(),
97    mRefresh(),
98    mPendingRefreshes(),
99    mVsync(),
100    mPendingVsyncs()
101{
102    loadCapabilities();
103    registerCallbacks();
104}
105
106Device::~Device()
107{
108    for (auto element : mDisplays) {
109        auto display = element.second.lock();
110        if (!display) {
111            ALOGE("~Device: Found a display (%" PRId64 " that has already been"
112                    " destroyed", element.first);
113            continue;
114        }
115
116        DisplayType displayType = HWC2::DisplayType::Invalid;
117        auto error = display->getType(&displayType);
118        if (error != Error::None) {
119            ALOGE("~Device: Failed to determine type of display %" PRIu64
120                    ": %s (%d)", display->getId(), to_string(error).c_str(),
121                    static_cast<int32_t>(error));
122            continue;
123        }
124
125        if (displayType == HWC2::DisplayType::Physical) {
126            error = display->setVsyncEnabled(HWC2::Vsync::Disable);
127            if (error != Error::None) {
128                ALOGE("~Device: Failed to disable vsync for display %" PRIu64
129                        ": %s (%d)", display->getId(), to_string(error).c_str(),
130                        static_cast<int32_t>(error));
131            }
132        }
133    }
134}
135
136// Required by HWC2 device
137
138std::string Device::dump() const
139{
140    return mComposer->dumpDebugInfo();
141}
142
143uint32_t Device::getMaxVirtualDisplayCount() const
144{
145    return mComposer->getMaxVirtualDisplayCount();
146}
147
148Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
149        android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
150{
151    ALOGI("Creating virtual display");
152
153    hwc2_display_t displayId = 0;
154    auto intFormat = static_cast<Hwc2::PixelFormat>(*format);
155    auto intError = mComposer->createVirtualDisplay(width, height,
156            &intFormat, &displayId);
157    auto error = static_cast<Error>(intError);
158    if (error != Error::None) {
159        return error;
160    }
161
162    ALOGI("Created virtual display");
163    *format = static_cast<android_pixel_format_t>(intFormat);
164    *outDisplay = getDisplayById(displayId);
165    if (!*outDisplay) {
166        ALOGE("Failed to get display by id");
167        return Error::BadDisplay;
168    }
169    (*outDisplay)->setConnected(true);
170    return Error::None;
171}
172
173void Device::registerHotplugCallback(HotplugCallback hotplug)
174{
175    ALOGV("registerHotplugCallback");
176    mHotplug = hotplug;
177    for (auto& pending : mPendingHotplugs) {
178        auto& display = pending.first;
179        auto connected = pending.second;
180        ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
181                to_string(connected).c_str());
182        mHotplug(std::move(display), connected);
183    }
184}
185
186void Device::registerRefreshCallback(RefreshCallback refresh)
187{
188    mRefresh = refresh;
189    for (auto& pending : mPendingRefreshes) {
190        mRefresh(std::move(pending));
191    }
192}
193
194void Device::registerVsyncCallback(VsyncCallback vsync)
195{
196    mVsync = vsync;
197    for (auto& pending : mPendingVsyncs) {
198        auto& display = pending.first;
199        auto timestamp = pending.second;
200        mVsync(std::move(display), timestamp);
201    }
202}
203
204// For use by Device callbacks
205
206void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
207{
208    if (connected == Connection::Connected) {
209        if (!display->isConnected()) {
210            mComposer->setClientTargetSlotCount(display->getId());
211            display->loadConfigs();
212            display->setConnected(true);
213        }
214    } else {
215        display->setConnected(false);
216        mDisplays.erase(display->getId());
217    }
218
219    if (mHotplug) {
220        mHotplug(std::move(display), connected);
221    } else {
222        ALOGV("callHotplug called, but no valid callback registered, storing");
223        mPendingHotplugs.emplace_back(std::move(display), connected);
224    }
225}
226
227void Device::callRefresh(std::shared_ptr<Display> display)
228{
229    if (mRefresh) {
230        mRefresh(std::move(display));
231    } else {
232        ALOGV("callRefresh called, but no valid callback registered, storing");
233        mPendingRefreshes.emplace_back(std::move(display));
234    }
235}
236
237void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
238{
239    if (mVsync) {
240        mVsync(std::move(display), timestamp);
241    } else {
242        ALOGV("callVsync called, but no valid callback registered, storing");
243        mPendingVsyncs.emplace_back(std::move(display), timestamp);
244    }
245}
246
247// Other Device methods
248
249std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
250    if (mDisplays.count(id) != 0) {
251        auto strongDisplay = mDisplays[id].lock();
252        ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
253                " longer alive", id);
254        return strongDisplay;
255    }
256
257    auto display = std::make_shared<Display>(*this, id);
258    mDisplays.emplace(id, display);
259    return display;
260}
261
262// Device initialization methods
263
264void Device::loadCapabilities()
265{
266    static_assert(sizeof(Capability) == sizeof(int32_t),
267            "Capability size has changed");
268    auto capabilities = mComposer->getCapabilities();
269    for (auto capability : capabilities) {
270        mCapabilities.emplace(static_cast<Capability>(capability));
271    }
272}
273
274bool Device::hasCapability(HWC2::Capability capability) const
275{
276    return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
277            capability) != mCapabilities.cend();
278}
279
280namespace {
281class ComposerCallback : public Hwc2::IComposerCallback {
282public:
283    ComposerCallback(Device* device) : mDevice(device) {}
284
285    Return<void> onHotplug(Hwc2::Display display,
286            Connection connected) override
287    {
288        hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
289        return Void();
290    }
291
292    Return<void> onRefresh(Hwc2::Display display) override
293    {
294        refresh_hook(mDevice, display);
295        return Void();
296    }
297
298    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
299    {
300        vsync_hook(mDevice, display, timestamp);
301        return Void();
302    }
303
304private:
305    Device* mDevice;
306};
307} // namespace anonymous
308
309void Device::registerCallbacks()
310{
311    sp<ComposerCallback> callback = new ComposerCallback(this);
312    mComposer->registerCallback(callback);
313}
314
315
316// For use by Display
317
318void Device::destroyVirtualDisplay(hwc2_display_t display)
319{
320    ALOGI("Destroying virtual display");
321    auto intError = mComposer->destroyVirtualDisplay(display);
322    auto error = static_cast<Error>(intError);
323    ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
324            " %s (%d)", display, to_string(error).c_str(), intError);
325    mDisplays.erase(display);
326}
327
328// Display methods
329
330Display::Display(Device& device, hwc2_display_t id)
331  : mDevice(device),
332    mId(id),
333    mIsConnected(false),
334    mType(DisplayType::Invalid)
335{
336    ALOGV("Created display %" PRIu64, id);
337
338    auto intError = mDevice.mComposer->getDisplayType(mId,
339            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
340    auto error = static_cast<Error>(intError);
341    if (error != Error::None) {
342        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
343              id, to_string(error).c_str(), intError);
344    }
345}
346
347Display::~Display()
348{
349    ALOGV("Destroyed display %" PRIu64, mId);
350    if (mType == DisplayType::Virtual) {
351        mDevice.destroyVirtualDisplay(mId);
352    }
353}
354
355Display::Config::Config(Display& display, hwc2_config_t id)
356  : mDisplay(display),
357    mId(id),
358    mWidth(-1),
359    mHeight(-1),
360    mVsyncPeriod(-1),
361    mDpiX(-1),
362    mDpiY(-1) {}
363
364Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
365  : mConfig(new Config(display, id)) {}
366
367float Display::Config::Builder::getDefaultDensity() {
368    // Default density is based on TVs: 1080p displays get XHIGH density, lower-
369    // resolution displays get TV density. Maybe eventually we'll need to update
370    // it for 4k displays, though hopefully those will just report accurate DPI
371    // information to begin with. This is also used for virtual displays and
372    // older HWC implementations, so be careful about orientation.
373
374    auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
375    if (longDimension >= 1080) {
376        return ACONFIGURATION_DENSITY_XHIGH;
377    } else {
378        return ACONFIGURATION_DENSITY_TV;
379    }
380}
381
382// Required by HWC2 display
383
384Error Display::acceptChanges()
385{
386    auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
387    return static_cast<Error>(intError);
388}
389
390Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
391{
392    hwc2_layer_t layerId = 0;
393    auto intError = mDevice.mComposer->createLayer(mId, &layerId);
394    auto error = static_cast<Error>(intError);
395    if (error != Error::None) {
396        return error;
397    }
398
399    auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
400    mLayers.emplace(layerId, layer);
401    *outLayer = std::move(layer);
402    return Error::None;
403}
404
405Error Display::getActiveConfig(
406        std::shared_ptr<const Display::Config>* outConfig) const
407{
408    ALOGV("[%" PRIu64 "] getActiveConfig", mId);
409    hwc2_config_t configId = 0;
410    auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
411    auto error = static_cast<Error>(intError);
412
413    if (error != Error::None) {
414        ALOGE("Unable to get active config for mId:[%" PRIu64 "]", mId);
415        *outConfig = nullptr;
416        return error;
417    }
418
419    if (mConfigs.count(configId) != 0) {
420        *outConfig = mConfigs.at(configId);
421    } else {
422        ALOGE("[%" PRIu64 "] getActiveConfig returned unknown config %u", mId,
423                configId);
424        // Return no error, but the caller needs to check for a null pointer to
425        // detect this case
426        *outConfig = nullptr;
427    }
428
429    return Error::None;
430}
431
432Error Display::getChangedCompositionTypes(
433        std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
434{
435    std::vector<Hwc2::Layer> layerIds;
436    std::vector<Hwc2::IComposerClient::Composition> types;
437    auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
438            &layerIds, &types);
439    uint32_t numElements = layerIds.size();
440    auto error = static_cast<Error>(intError);
441    error = static_cast<Error>(intError);
442    if (error != Error::None) {
443        return error;
444    }
445
446    outTypes->clear();
447    outTypes->reserve(numElements);
448    for (uint32_t element = 0; element < numElements; ++element) {
449        auto layer = getLayerById(layerIds[element]);
450        if (layer) {
451            auto type = static_cast<Composition>(types[element]);
452            ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s",
453                    layer->getId(), to_string(type).c_str());
454            outTypes->emplace(layer, type);
455        } else {
456            ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found"
457                    " on display %" PRIu64, layerIds[element], mId);
458        }
459    }
460
461    return Error::None;
462}
463
464Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
465{
466    std::vector<Hwc2::ColorMode> modes;
467    auto intError = mDevice.mComposer->getColorModes(mId, &modes);
468    uint32_t numModes = modes.size();
469    auto error = static_cast<Error>(intError);
470    if (error != Error::None) {
471        return error;
472    }
473
474    outModes->resize(numModes);
475    for (size_t i = 0; i < numModes; i++) {
476        (*outModes)[i] = static_cast<android_color_mode_t>(modes[i]);
477    }
478    return Error::None;
479}
480
481std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
482{
483    std::vector<std::shared_ptr<const Config>> configs;
484    for (const auto& element : mConfigs) {
485        configs.emplace_back(element.second);
486    }
487    return configs;
488}
489
490Error Display::getName(std::string* outName) const
491{
492    auto intError = mDevice.mComposer->getDisplayName(mId, outName);
493    return static_cast<Error>(intError);
494}
495
496Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
497        std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
498                outLayerRequests)
499{
500    uint32_t intDisplayRequests;
501    std::vector<Hwc2::Layer> layerIds;
502    std::vector<uint32_t> layerRequests;
503    auto intError = mDevice.mComposer->getDisplayRequests(mId,
504            &intDisplayRequests, &layerIds, &layerRequests);
505    uint32_t numElements = layerIds.size();
506    auto error = static_cast<Error>(intError);
507    if (error != Error::None) {
508        return error;
509    }
510
511    *outDisplayRequests = static_cast<DisplayRequest>(intDisplayRequests);
512    outLayerRequests->clear();
513    outLayerRequests->reserve(numElements);
514    for (uint32_t element = 0; element < numElements; ++element) {
515        auto layer = getLayerById(layerIds[element]);
516        if (layer) {
517            auto layerRequest =
518                    static_cast<LayerRequest>(layerRequests[element]);
519            outLayerRequests->emplace(layer, layerRequest);
520        } else {
521            ALOGE("getRequests: invalid layer %" PRIu64 " found on display %"
522                    PRIu64, layerIds[element], mId);
523        }
524    }
525
526    return Error::None;
527}
528
529Error Display::getType(DisplayType* outType) const
530{
531    *outType = mType;
532    return Error::None;
533}
534
535Error Display::supportsDoze(bool* outSupport) const
536{
537    bool intSupport = false;
538    auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
539    auto error = static_cast<Error>(intError);
540    if (error != Error::None) {
541        return error;
542    }
543    *outSupport = static_cast<bool>(intSupport);
544    return Error::None;
545}
546
547Error Display::getHdrCapabilities(
548        std::unique_ptr<HdrCapabilities>* outCapabilities) const
549{
550    uint32_t numTypes = 0;
551    float maxLuminance = -1.0f;
552    float maxAverageLuminance = -1.0f;
553    float minLuminance = -1.0f;
554    std::vector<Hwc2::Hdr> intTypes;
555    auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
556            &maxLuminance, &maxAverageLuminance, &minLuminance);
557    auto error = static_cast<HWC2::Error>(intError);
558
559    std::vector<int32_t> types;
560    for (auto type : intTypes) {
561        types.push_back(static_cast<int32_t>(type));
562    }
563    numTypes = types.size();
564    if (error != Error::None) {
565        return error;
566    }
567
568    *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
569            maxLuminance, maxAverageLuminance, minLuminance);
570    return Error::None;
571}
572
573Error Display::getReleaseFences(
574        std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
575{
576    std::vector<Hwc2::Layer> layerIds;
577    std::vector<int> fenceFds;
578    auto intError = mDevice.mComposer->getReleaseFences(mId,
579            &layerIds, &fenceFds);
580    auto error = static_cast<Error>(intError);
581    uint32_t numElements = layerIds.size();
582    if (error != Error::None) {
583        return error;
584    }
585
586    std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
587    releaseFences.reserve(numElements);
588    for (uint32_t element = 0; element < numElements; ++element) {
589        auto layer = getLayerById(layerIds[element]);
590        if (layer) {
591            sp<Fence> fence(new Fence(fenceFds[element]));
592            releaseFences.emplace(std::move(layer), fence);
593        } else {
594            ALOGE("getReleaseFences: invalid layer %" PRIu64
595                    " found on display %" PRIu64, layerIds[element], mId);
596            for (; element < numElements; ++element) {
597                close(fenceFds[element]);
598            }
599            return Error::BadLayer;
600        }
601    }
602
603    *outFences = std::move(releaseFences);
604    return Error::None;
605}
606
607Error Display::present(sp<Fence>* outPresentFence)
608{
609    int32_t presentFenceFd = -1;
610    auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
611    auto error = static_cast<Error>(intError);
612    if (error != Error::None) {
613        return error;
614    }
615
616    *outPresentFence = new Fence(presentFenceFd);
617    return Error::None;
618}
619
620Error Display::setActiveConfig(const std::shared_ptr<const Config>& config)
621{
622    if (config->getDisplayId() != mId) {
623        ALOGE("setActiveConfig received config %u for the wrong display %"
624                PRIu64 " (expected %" PRIu64 ")", config->getId(),
625                config->getDisplayId(), mId);
626        return Error::BadConfig;
627    }
628    auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
629    return static_cast<Error>(intError);
630}
631
632Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
633        const sp<Fence>& acquireFence, android_dataspace_t dataspace)
634{
635    // TODO: Properly encode client target surface damage
636    int32_t fenceFd = acquireFence->dup();
637    auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
638            fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
639            std::vector<Hwc2::IComposerClient::Rect>());
640    return static_cast<Error>(intError);
641}
642
643Error Display::setColorMode(android_color_mode_t mode)
644{
645    auto intError = mDevice.mComposer->setColorMode(mId,
646            static_cast<Hwc2::ColorMode>(mode));
647    return static_cast<Error>(intError);
648}
649
650Error Display::setColorTransform(const android::mat4& matrix,
651        android_color_transform_t hint)
652{
653    auto intError = mDevice.mComposer->setColorTransform(mId,
654            matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
655    return static_cast<Error>(intError);
656}
657
658Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
659        const sp<Fence>& releaseFence)
660{
661    int32_t fenceFd = releaseFence->dup();
662    auto handle = buffer->getNativeBuffer()->handle;
663    auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
664    close(fenceFd);
665    return static_cast<Error>(intError);
666}
667
668Error Display::setPowerMode(PowerMode mode)
669{
670    auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
671    auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
672    return static_cast<Error>(intError);
673}
674
675Error Display::setVsyncEnabled(Vsync enabled)
676{
677    auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
678    auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
679    return static_cast<Error>(intError);
680}
681
682Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
683{
684    uint32_t numTypes = 0;
685    uint32_t numRequests = 0;
686    auto intError = mDevice.mComposer->validateDisplay(mId,
687            &numTypes, &numRequests);
688    auto error = static_cast<Error>(intError);
689    if (error != Error::None && error != Error::HasChanges) {
690        return error;
691    }
692
693    *outNumTypes = numTypes;
694    *outNumRequests = numRequests;
695    return error;
696}
697
698Error Display::presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
699                                 sp<android::Fence>* outPresentFence, uint32_t* state) {
700
701    uint32_t numTypes = 0;
702    uint32_t numRequests = 0;
703    int32_t presentFenceFd = -1;
704    auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
705    auto error = static_cast<Error>(intError);
706    if (error != Error::None && error != Error::HasChanges) {
707        return error;
708    }
709
710    if (*state == 1) {
711        *outPresentFence = new Fence(presentFenceFd);
712    }
713
714    if (*state == 0) {
715        *outNumTypes = numTypes;
716        *outNumRequests = numRequests;
717    }
718    return error;
719}
720
721void Display::discardCommands()
722{
723    mDevice.mComposer->resetCommands();
724}
725
726// For use by Device
727
728int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
729{
730    int32_t value = 0;
731    auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
732            static_cast<Hwc2::IComposerClient::Attribute>(attribute),
733            &value);
734    auto error = static_cast<Error>(intError);
735    if (error != Error::None) {
736        ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
737                configId, to_string(attribute).c_str(),
738                to_string(error).c_str(), intError);
739        return -1;
740    }
741    return value;
742}
743
744void Display::loadConfig(hwc2_config_t configId)
745{
746    ALOGV("[%" PRIu64 "] loadConfig(%u)", mId, configId);
747
748    auto config = Config::Builder(*this, configId)
749            .setWidth(getAttribute(configId, Attribute::Width))
750            .setHeight(getAttribute(configId, Attribute::Height))
751            .setVsyncPeriod(getAttribute(configId, Attribute::VsyncPeriod))
752            .setDpiX(getAttribute(configId, Attribute::DpiX))
753            .setDpiY(getAttribute(configId, Attribute::DpiY))
754            .build();
755    mConfigs.emplace(configId, std::move(config));
756}
757
758void Display::loadConfigs()
759{
760    ALOGV("[%" PRIu64 "] loadConfigs", mId);
761
762    std::vector<Hwc2::Config> configIds;
763    auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
764    auto error = static_cast<Error>(intError);
765    if (error != Error::None) {
766        ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
767                to_string(error).c_str(), intError);
768        return;
769    }
770
771    for (auto configId : configIds) {
772        loadConfig(configId);
773    }
774}
775
776// For use by Layer
777
778void Display::destroyLayer(hwc2_layer_t layerId)
779{
780    auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
781    auto error = static_cast<Error>(intError);
782    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
783            " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
784            intError);
785    mLayers.erase(layerId);
786}
787
788// Other Display methods
789
790std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
791{
792    if (mLayers.count(id) == 0) {
793        return nullptr;
794    }
795
796    auto layer = mLayers.at(id).lock();
797    return layer;
798}
799
800// Layer methods
801
802Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
803  : mDisplay(display),
804    mDisplayId(display->getId()),
805    mDevice(display->getDevice()),
806    mId(id)
807{
808    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
809            display->getId());
810}
811
812Layer::~Layer()
813{
814    auto display = mDisplay.lock();
815    if (display) {
816        display->destroyLayer(mId);
817    }
818}
819
820Error Layer::setCursorPosition(int32_t x, int32_t y)
821{
822    auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
823            mId, x, y);
824    return static_cast<Error>(intError);
825}
826
827Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
828        const sp<Fence>& acquireFence)
829{
830    int32_t fenceFd = acquireFence->dup();
831    auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
832            mId, slot, buffer, fenceFd);
833    return static_cast<Error>(intError);
834}
835
836Error Layer::setSurfaceDamage(const Region& damage)
837{
838    // We encode default full-screen damage as INVALID_RECT upstream, but as 0
839    // rects for HWC
840    Hwc2::Error intError = Hwc2::Error::NONE;
841    if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
842        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
843                mId, std::vector<Hwc2::IComposerClient::Rect>());
844    } else {
845        size_t rectCount = 0;
846        auto rectArray = damage.getArray(&rectCount);
847
848        std::vector<Hwc2::IComposerClient::Rect> hwcRects;
849        for (size_t rect = 0; rect < rectCount; ++rect) {
850            hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
851                    rectArray[rect].right, rectArray[rect].bottom});
852        }
853
854        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
855                mId, hwcRects);
856    }
857
858    return static_cast<Error>(intError);
859}
860
861Error Layer::setBlendMode(BlendMode mode)
862{
863    auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
864    auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
865            mId, intMode);
866    return static_cast<Error>(intError);
867}
868
869Error Layer::setColor(hwc_color_t color)
870{
871    Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
872    auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
873            mId, hwcColor);
874    return static_cast<Error>(intError);
875}
876
877Error Layer::setCompositionType(Composition type)
878{
879    auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
880    auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
881            mId, intType);
882    return static_cast<Error>(intError);
883}
884
885Error Layer::setDataspace(android_dataspace_t dataspace)
886{
887    auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
888    auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
889            mId, intDataspace);
890    return static_cast<Error>(intError);
891}
892
893Error Layer::setDisplayFrame(const Rect& frame)
894{
895    Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
896        frame.right, frame.bottom};
897    auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
898            mId, hwcRect);
899    return static_cast<Error>(intError);
900}
901
902Error Layer::setPlaneAlpha(float alpha)
903{
904    auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
905            mId, alpha);
906    return static_cast<Error>(intError);
907}
908
909Error Layer::setSidebandStream(const native_handle_t* stream)
910{
911    if (!mDevice.hasCapability(Capability::SidebandStream)) {
912        ALOGE("Attempted to call setSidebandStream without checking that the "
913                "device supports sideband streams");
914        return Error::Unsupported;
915    }
916    auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
917            mId, stream);
918    return static_cast<Error>(intError);
919}
920
921Error Layer::setSourceCrop(const FloatRect& crop)
922{
923    Hwc2::IComposerClient::FRect hwcRect{
924        crop.left, crop.top, crop.right, crop.bottom};
925    auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
926            mId, hwcRect);
927    return static_cast<Error>(intError);
928}
929
930Error Layer::setTransform(Transform transform)
931{
932    auto intTransform = static_cast<Hwc2::Transform>(transform);
933    auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
934            mId, intTransform);
935    return static_cast<Error>(intError);
936}
937
938Error Layer::setVisibleRegion(const Region& region)
939{
940    size_t rectCount = 0;
941    auto rectArray = region.getArray(&rectCount);
942
943    std::vector<Hwc2::IComposerClient::Rect> hwcRects;
944    for (size_t rect = 0; rect < rectCount; ++rect) {
945        hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
946                rectArray[rect].right, rectArray[rect].bottom});
947    }
948
949    auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
950            mId, hwcRects);
951    return static_cast<Error>(intError);
952}
953
954Error Layer::setZOrder(uint32_t z)
955{
956    auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
957    return static_cast<Error>(intError);
958}
959
960Error Layer::setInfo(uint32_t type, uint32_t appId)
961{
962  auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
963  return static_cast<Error>(intError);
964}
965
966} // namespace HWC2
967