diff options
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp | 841 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h | 189 |
2 files changed, 424 insertions, 606 deletions
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp index 1d2c178500..d72139e12d 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp @@ -34,33 +34,6 @@ using namespace std::chrono_literals; -static bool operator==(const hwc_color_t& lhs, const hwc_color_t& rhs) { - return lhs.r == rhs.r && - lhs.g == rhs.g && - lhs.b == rhs.b && - lhs.a == rhs.a; -} - -static bool operator==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) { - return lhs.left == rhs.left && - lhs.top == rhs.top && - lhs.right == rhs.right && - lhs.bottom == rhs.bottom; -} - -static bool operator==(const hwc_frect_t& lhs, const hwc_frect_t& rhs) { - return lhs.left == rhs.left && - lhs.top == rhs.top && - lhs.right == rhs.right && - lhs.bottom == rhs.bottom; -} - -template <typename T> -static inline bool operator!=(const T& lhs, const T& rhs) -{ - return !(lhs == rhs); -} - static uint8_t getMinorVersion(struct hwc_composer_device_1* device) { auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; @@ -80,19 +53,6 @@ static constexpr Attribute ColorMode = static_cast<Attribute>(6); namespace android { -void HWC2On1Adapter::DisplayContentsDeleter::operator()( - hwc_display_contents_1_t* contents) -{ - if (contents != nullptr) { - for (size_t l = 0; l < contents->numHwLayers; ++l) { - auto& layer = contents->hwLayers[l]; - std::free(const_cast<hwc_rect_t*>(layer.visibleRegionScreen.rects)); - std::free(const_cast<hwc_rect_t*>(layer.surfaceDamage.rects)); - } - } - std::free(contents); -} - class HWC2On1Adapter::Callbacks : public hwc_procs_t { public: explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) { @@ -161,8 +121,7 @@ HWC2On1Adapter::~HWC2On1Adapter() { } void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount, - int32_t* outCapabilities) -{ + int32_t* outCapabilities) { if (outCapabilities == nullptr) { *outCount = mCapabilities.size(); return; @@ -179,8 +138,7 @@ void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount, } hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( - FunctionDescriptor descriptor) -{ + FunctionDescriptor descriptor) { switch (descriptor) { // Device functions case FunctionDescriptor::CreateVirtualDisplay: @@ -350,8 +308,7 @@ hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( // Device functions Error HWC2On1Adapter::createVirtualDisplay(uint32_t width, - uint32_t height, hwc2_display_t* outDisplay) -{ + uint32_t height, hwc2_display_t* outDisplay) { std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); if (mHwc1VirtualDisplay) { @@ -381,8 +338,7 @@ Error HWC2On1Adapter::createVirtualDisplay(uint32_t width, return Error::None; } -Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) -{ +Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) { std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) { @@ -396,8 +352,7 @@ Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) return Error::None; } -void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) -{ +void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) { if (outBuffer != nullptr) { auto copiedBytes = mDumpString.copy(outBuffer, *outSize); *outSize = static_cast<uint32_t>(copiedBytes); @@ -450,8 +405,7 @@ void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) *outSize = static_cast<uint32_t>(mDumpString.size()); } -uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() -{ +uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() { return mHwc1SupportsVirtualDisplays ? 1 : 0; } @@ -465,8 +419,7 @@ static bool isValid(Callback descriptor) { } Error HWC2On1Adapter::registerCallback(Callback descriptor, - hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) -{ + hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { if (!isValid(descriptor)) { return Error::BadParameter; } @@ -553,11 +506,8 @@ std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1); HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type) : mId(sNextId++), mDevice(device), - mDirtyCount(0), mStateMutex(), - mZIsDirty(false), mHwc1RequestedContents(nullptr), - mHwc1ReceivedContents(nullptr), mRetireFence(), mChanges(), mHwc1Id(-1), @@ -572,10 +522,13 @@ HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type) mOutputBuffer(), mHasColorTransform(false), mLayers(), - mHwc1LayerMap() {} + mHwc1LayerMap(), + mNumAvailableRects(0), + mNextAvailableRect(nullptr), + mGeometryChanged(false) + {} -Error HWC2On1Adapter::Display::acceptChanges() -{ +Error HWC2On1Adapter::Display::acceptChanges() { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!mChanges) { @@ -594,25 +547,21 @@ Error HWC2On1Adapter::Display::acceptChanges() mChanges->clearTypeChanges(); - mHwc1RequestedContents = std::move(mHwc1ReceivedContents); - return Error::None; } -Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) -{ +Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); auto layer = *mLayers.emplace(std::make_shared<Layer>(*this)); mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer)); *outLayerId = layer->getId(); ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId); - mZIsDirty = true; + markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) -{ +Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); const auto mapLayer = mDevice.mLayers.find(layerId); @@ -631,12 +580,11 @@ Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) } } ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId); - mZIsDirty = true; + markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) -{ +Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!mActiveConfig) { @@ -651,8 +599,7 @@ Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) } Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId, - Attribute attribute, int32_t* outValue) -{ + Attribute attribute, int32_t* outValue) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { @@ -667,8 +614,7 @@ Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId, } Error HWC2On1Adapter::Display::getChangedCompositionTypes( - uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) -{ + uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!mChanges) { @@ -701,8 +647,7 @@ Error HWC2On1Adapter::Display::getChangedCompositionTypes( } Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, - int32_t* outModes) -{ + int32_t* outModes) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!outModes) { @@ -717,8 +662,7 @@ Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, } Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, - hwc2_config_t* outConfigs) -{ + hwc2_config_t* outConfigs) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!outConfigs) { @@ -737,8 +681,7 @@ Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, return Error::None; } -Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) -{ +Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) { @@ -751,15 +694,13 @@ Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes, int32_t* /*outTypes*/, float* /*outMaxLuminance*/, - float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) -{ + float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) { // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0 *outNumTypes = 0; return Error::None; } -Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) -{ +Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!outName) { @@ -772,8 +713,7 @@ Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) } Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements, - hwc2_layer_t* outLayers, int32_t* outFences) -{ + hwc2_layer_t* outLayers, int32_t* outFences) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); uint32_t numWritten = 0; @@ -799,8 +739,7 @@ Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements, Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests, uint32_t* outNumElements, hwc2_layer_t* outLayers, - int32_t* outLayerRequests) -{ + int32_t* outLayerRequests) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!mChanges) { @@ -829,16 +768,14 @@ Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests, return Error::None; } -Error HWC2On1Adapter::Display::getType(int32_t* outType) -{ +Error HWC2On1Adapter::Display::getType(int32_t* outType) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); *outType = static_cast<int32_t>(mType); return Error::None; } -Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) -{ +Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (mChanges) { @@ -857,8 +794,7 @@ Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) return Error::None; } -Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) -{ +Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); auto config = getConfig(configId); @@ -890,8 +826,7 @@ Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) } Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, - int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) -{ + int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence); @@ -901,8 +836,7 @@ Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, return Error::None; } -Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) -{ +Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) { std::unique_lock<std::recursive_mutex> lock (mStateMutex); ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); @@ -933,8 +867,7 @@ Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) return Error::None; } -Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) -{ +Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); ALOGV("%" PRIu64 "] setColorTransform(%d)", mId, @@ -944,8 +877,7 @@ Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) } Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer, - int32_t releaseFence) -{ + int32_t releaseFence) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence); @@ -954,30 +886,25 @@ Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer, return Error::None; } -static bool isValid(PowerMode mode) -{ +static bool isValid(PowerMode mode) { switch (mode) { case PowerMode::Off: // Fall-through case PowerMode::DozeSuspend: // Fall-through case PowerMode::Doze: // Fall-through case PowerMode::On: return true; - default: return false; } } -static int getHwc1PowerMode(PowerMode mode) -{ +static int getHwc1PowerMode(PowerMode mode) { switch (mode) { case PowerMode::Off: return HWC_POWER_MODE_OFF; case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND; case PowerMode::Doze: return HWC_POWER_MODE_DOZE; case PowerMode::On: return HWC_POWER_MODE_NORMAL; - default: return HWC_POWER_MODE_OFF; } } -Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) -{ +Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) { if (!isValid(mode)) { return Error::BadParameter; } @@ -1007,12 +934,11 @@ static bool isValid(Vsync enable) { switch (enable) { case Vsync::Enable: // Fall-through case Vsync::Disable: return true; - default: return false; + case Vsync::Invalid: return false; } } -Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) -{ +Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) { if (!isValid(enable)) { return Error::BadParameter; } @@ -1032,8 +958,7 @@ Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) } Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, - uint32_t* outNumRequests) -{ + uint32_t* outNumRequests) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); ALOGV("[%" PRIu64 "] Entering validate", mId); @@ -1042,6 +967,8 @@ Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, if (!mDevice.prepareAllDisplays()) { return Error::BadDisplay; } + } else { + ALOGE("Validate was called more than once!"); } *outNumTypes = mChanges->getNumTypes(); @@ -1055,10 +982,7 @@ Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, return *outNumTypes > 0 ? Error::HasChanges : Error::None; } -// Display helpers - -Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) -{ +Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); const auto mapLayer = mDevice.mLayers.find(layerId); @@ -1090,7 +1014,7 @@ Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) layer->setZ(z); mLayers.emplace(std::move(layer)); - mZIsDirty = true; + markGeometryChanged(); return Error::None; } @@ -1159,8 +1083,7 @@ static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync"); static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(), "Tables out of sync"); -void HWC2On1Adapter::Display::populateConfigs() -{ +void HWC2On1Adapter::Display::populateConfigs() { std::unique_lock<std::recursive_mutex> lock(mStateMutex); ALOGV("[%" PRIu64 "] populateConfigs", mId); @@ -1238,8 +1161,7 @@ void HWC2On1Adapter::Display::populateConfigs() populateColorModes(); } -void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) -{ +void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); mConfigs.emplace_back(std::make_shared<Config>(*this)); @@ -1252,8 +1174,7 @@ void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) mActiveConfig = config; } -bool HWC2On1Adapter::Display::prepare() -{ +bool HWC2On1Adapter::Display::prepare() { std::unique_lock<std::recursive_mutex> lock(mStateMutex); // Only prepare display contents for displays HWC1 knows about @@ -1270,86 +1191,45 @@ bool HWC2On1Adapter::Display::prepare() ALOGV("[%" PRIu64 "] Entering prepare", mId); - auto currentCount = mHwc1RequestedContents ? - mHwc1RequestedContents->numHwLayers : 0; - auto requiredCount = mLayers.size() + 1; - ALOGV("[%" PRIu64 "] Requires %zd layers, %zd allocated in %p", mId, - requiredCount, currentCount, mHwc1RequestedContents.get()); - - bool layerCountChanged = (currentCount != requiredCount); - if (layerCountChanged) { - reallocateHwc1Contents(); - } - - bool applyAllState = false; - if (layerCountChanged || mZIsDirty) { - assignHwc1LayerIds(); - mZIsDirty = false; - applyAllState = true; - } + allocateRequestedContents(); + assignHwc1LayerIds(); mHwc1RequestedContents->retireFenceFd = -1; mHwc1RequestedContents->flags = 0; - if (isDirty() || applyAllState) { + if (mGeometryChanged) { mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED; } + mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer(); + mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence(); + // +1 is for framebuffer target layer. + mHwc1RequestedContents->numHwLayers = mLayers.size() + 1; for (auto& layer : mLayers) { auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()]; hwc1Layer.releaseFenceFd = -1; hwc1Layer.acquireFenceFd = -1; ALOGV("Applying states for layer %" PRIu64 " ", layer->getId()); - layer->applyState(hwc1Layer, applyAllState); + layer->applyState(hwc1Layer); } - mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer(); - mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence(); - prepareFramebufferTarget(); - return true; -} - -static void cloneHWCRegion(hwc_region_t& region) -{ - auto size = sizeof(hwc_rect_t) * region.numRects; - auto newRects = static_cast<hwc_rect_t*>(std::malloc(size)); - std::copy_n(region.rects, region.numRects, newRects); - region.rects = newRects; -} - -HWC2On1Adapter::Display::HWC1Contents - HWC2On1Adapter::Display::cloneRequestedContents() const -{ - std::unique_lock<std::recursive_mutex> lock(mStateMutex); + resetGeometryMarker(); - size_t size = sizeof(hwc_display_contents_1_t) + - sizeof(hwc_layer_1_t) * (mHwc1RequestedContents->numHwLayers); - auto contents = static_cast<hwc_display_contents_1_t*>(std::malloc(size)); - std::memcpy(contents, mHwc1RequestedContents.get(), size); - for (size_t layerId = 0; layerId < contents->numHwLayers; ++layerId) { - auto& layer = contents->hwLayers[layerId]; - // Deep copy the regions to avoid double-frees - cloneHWCRegion(layer.visibleRegionScreen); - cloneHWCRegion(layer.surfaceDamage); - } - return HWC1Contents(contents); + return true; } -void HWC2On1Adapter::Display::setReceivedContents(HWC1Contents contents) -{ +void HWC2On1Adapter::Display::generateChanges() { std::unique_lock<std::recursive_mutex> lock(mStateMutex); - mHwc1ReceivedContents = std::move(contents); - mChanges.reset(new Changes); - size_t numLayers = mHwc1ReceivedContents->numHwLayers; + size_t numLayers = mHwc1RequestedContents->numHwLayers; for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { - const auto& receivedLayer = mHwc1ReceivedContents->hwLayers[hwc1Id]; + const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id]; if (mHwc1LayerMap.count(hwc1Id) == 0) { ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET, - "setReceivedContents: HWC1 layer %zd doesn't have a" + "generateChanges: HWC1 layer %zd doesn't have a" " matching HWC2 layer, and isn't the framebuffer target", hwc1Id); continue; @@ -1361,14 +1241,12 @@ void HWC2On1Adapter::Display::setReceivedContents(HWC1Contents contents) } } -bool HWC2On1Adapter::Display::hasChanges() const -{ +bool HWC2On1Adapter::Display::hasChanges() const { std::unique_lock<std::recursive_mutex> lock(mStateMutex); return mChanges != nullptr; } -Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) -{ +Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); if (!mChanges || (mChanges->getNumTypes() > 0)) { @@ -1404,15 +1282,13 @@ Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) return Error::None; } -void HWC2On1Adapter::Display::addRetireFence(int fenceFd) -{ +void HWC2On1Adapter::Display::addRetireFence(int fenceFd) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); mRetireFence.add(fenceFd); } void HWC2On1Adapter::Display::addReleaseFences( - const hwc_display_contents_1_t& hwcContents) -{ + const hwc_display_contents_1_t& hwcContents) { std::unique_lock<std::recursive_mutex> lock(mStateMutex); size_t numLayers = hwcContents.numHwLayers; @@ -1439,14 +1315,12 @@ void HWC2On1Adapter::Display::addReleaseFences( } } -bool HWC2On1Adapter::Display::hasColorTransform() const -{ +bool HWC2On1Adapter::Display::hasColorTransform() const { std::unique_lock<std::recursive_mutex> lock(mStateMutex); return mHasColorTransform; } -static std::string hwc1CompositionString(int32_t type) -{ +static std::string hwc1CompositionString(int32_t type) { switch (type) { case HWC_FRAMEBUFFER: return "Framebuffer"; case HWC_OVERLAY: return "Overlay"; @@ -1459,8 +1333,7 @@ static std::string hwc1CompositionString(int32_t type) } } -static std::string hwc1TransformString(int32_t transform) -{ +static std::string hwc1TransformString(int32_t transform) { switch (transform) { case 0: return "None"; case HWC_TRANSFORM_FLIP_H: return "FlipH"; @@ -1475,8 +1348,7 @@ static std::string hwc1TransformString(int32_t transform) } } -static std::string hwc1BlendModeString(int32_t mode) -{ +static std::string hwc1BlendModeString(int32_t mode) { switch (mode) { case HWC_BLENDING_NONE: return "None"; case HWC_BLENDING_PREMULT: return "Premultiplied"; @@ -1486,16 +1358,14 @@ static std::string hwc1BlendModeString(int32_t mode) } } -static std::string rectString(hwc_rect_t rect) -{ +static std::string rectString(hwc_rect_t rect) { std::stringstream output; output << "[" << rect.left << ", " << rect.top << ", "; output << rect.right << ", " << rect.bottom << "]"; return output.str(); } -static std::string approximateFloatString(float f) -{ +static std::string approximateFloatString(float f) { if (static_cast<int32_t>(f) == f) { return std::to_string(static_cast<int32_t>(f)); } @@ -1508,8 +1378,7 @@ static std::string approximateFloatString(float f) return std::string(buffer, bytesWritten); } -static std::string frectString(hwc_frect_t frect) -{ +static std::string frectString(hwc_frect_t frect) { std::stringstream output; output << "[" << approximateFloatString(frect.left) << ", "; output << approximateFloatString(frect.top) << ", "; @@ -1518,8 +1387,7 @@ static std::string frectString(hwc_frect_t frect) return output.str(); } -static std::string colorString(hwc_color_t color) -{ +static std::string colorString(hwc_color_t color) { std::stringstream output; output << "RGBA ["; output << static_cast<int32_t>(color.r) << ", "; @@ -1529,8 +1397,7 @@ static std::string colorString(hwc_color_t color) return output.str(); } -static std::string alphaString(float f) -{ +static std::string alphaString(float f) { const size_t BUFFER_SIZE = 8; char buffer[BUFFER_SIZE] = {}; auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f); @@ -1538,8 +1405,7 @@ static std::string alphaString(float f) } static std::string to_string(const hwc_layer_1_t& hwcLayer, - int32_t hwc1MinorVersion) -{ + int32_t hwc1MinorVersion) { const char* fill = " "; std::stringstream output; @@ -1599,8 +1465,7 @@ static std::string to_string(const hwc_layer_1_t& hwcLayer, } static std::string to_string(const hwc_display_contents_1_t& hwcContents, - int32_t hwc1MinorVersion) -{ + int32_t hwc1MinorVersion) { const char* fill = " "; std::stringstream output; @@ -1622,8 +1487,7 @@ static std::string to_string(const hwc_display_contents_1_t& hwcContents, return output.str(); } -std::string HWC2On1Adapter::Display::dump() const -{ +std::string HWC2On1Adapter::Display::dump() const { std::unique_lock<std::recursive_mutex> lock(mStateMutex); std::stringstream output; @@ -1663,10 +1527,7 @@ std::string HWC2On1Adapter::Display::dump() const output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n'; } - if (mHwc1ReceivedContents) { - output << " Last received HWC1 state\n"; - output << to_string(*mHwc1ReceivedContents, mDevice.mHwc1MinorVersion); - } else if (mHwc1RequestedContents) { + if (mHwc1RequestedContents) { output << " Last requested HWC1 state\n"; output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion); } @@ -1674,28 +1535,46 @@ std::string HWC2On1Adapter::Display::dump() const return output.str(); } +hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) { + if (numRects == 0) { + return nullptr; + } + + if (numRects > mNumAvailableRects) { + // This should NEVER happen since we calculated how many rects the + // display would need. + ALOGE("Rect allocation failure! SF is likely to crash soon!"); + return nullptr; + + } + hwc_rect_t* rects = mNextAvailableRect; + mNextAvailableRect += numRects; + mNumAvailableRects -= numRects; + return rects; +} + +hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() { + return mHwc1RequestedContents.get(); +} + void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute, - int32_t value) -{ + int32_t value) { mAttributes[attribute] = value; } -int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const -{ +int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const { if (mAttributes.count(attribute) == 0) { return -1; } return mAttributes.at(attribute); } -void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) -{ +void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode)); mHwc1Ids.emplace(colorMode, id); } -bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const -{ +bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { return true; @@ -1705,8 +1584,7 @@ bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const } Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( - uint32_t id, android_color_mode_t* outMode) const -{ + uint32_t id, android_color_mode_t* outMode) const { for (const auto& idPair : mHwc1Ids) { if (id == idPair.second) { *outMode = idPair.first; @@ -1718,8 +1596,7 @@ Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( } Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode, - uint32_t* outId) const -{ + uint32_t* outId) const { for (const auto& idPair : mHwc1Ids) { if (mode == idPair.first) { *outId = idPair.second; @@ -1730,8 +1607,7 @@ Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_ return Error::BadParameter; } -bool HWC2On1Adapter::Display::Config::merge(const Config& other) -{ +bool HWC2On1Adapter::Display::Config::merge(const Config& other) { auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, HWC2::Attribute::DpiY}; @@ -1753,8 +1629,7 @@ bool HWC2On1Adapter::Display::Config::merge(const Config& other) return true; } -std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const -{ +std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const { std::set<android_color_mode_t> colorModes; for (const auto& idPair : mHwc1Ids) { colorModes.emplace(idPair.first); @@ -1762,8 +1637,7 @@ std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() return colorModes; } -std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const -{ +std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { std::string output; const size_t BUFFER_SIZE = 100; @@ -1819,16 +1693,14 @@ std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const } std::shared_ptr<const HWC2On1Adapter::Display::Config> - HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const -{ + HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const { if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { return nullptr; } return mConfigs[configId]; } -void HWC2On1Adapter::Display::populateColorModes() -{ +void HWC2On1Adapter::Display::populateColorModes() { mColorModes = mConfigs[0]->getColorModes(); for (const auto& config : mConfigs) { std::set<android_color_mode_t> intersection; @@ -1840,8 +1712,7 @@ void HWC2On1Adapter::Display::populateColorModes() } } -void HWC2On1Adapter::Display::initializeActiveConfig() -{ +void HWC2On1Adapter::Display::initializeActiveConfig() { if (mDevice.mHwc1Device->getActiveConfig == nullptr) { ALOGV("getActiveConfig is null, choosing config 0"); mActiveConfig = mConfigs[0]; @@ -1886,22 +1757,40 @@ void HWC2On1Adapter::Display::initializeActiveConfig() } -void HWC2On1Adapter::Display::reallocateHwc1Contents() -{ - // Allocate an additional layer for the framebuffer target +void HWC2On1Adapter::Display::allocateRequestedContents() { + // What needs to be allocated: + // 1 hwc_display_contents_1_t + // 1 hwc_layer_1_t for each layer + // 1 hwc_rect_t for each layer's surfaceDamage + // 1 hwc_rect_t for each layer's visibleRegion + // 1 hwc_layer_1_t for the framebuffer + // 1 hwc_rect_t for the framebuffer's visibleRegion + + // Count # of surfaceDamage + size_t numSurfaceDamages = 0; + for (const auto& layer : mLayers) { + numSurfaceDamages += layer->getNumSurfaceDamages(); + } + + // Count # of visibleRegions (start at 1 for mandatory framebuffer target + // region) + size_t numVisibleRegion = 1; + for (const auto& layer : mLayers) { + numVisibleRegion += layer->getNumVisibleRegions(); + } + + size_t numRects = numVisibleRegion + numSurfaceDamages; auto numLayers = mLayers.size() + 1; size_t size = sizeof(hwc_display_contents_1_t) + - sizeof(hwc_layer_1_t) * numLayers; - ALOGV("[%" PRIu64 "] reallocateHwc1Contents creating %zd layer%s", mId, - numLayers, numLayers != 1 ? "s" : ""); - auto contents = - static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1)); - contents->numHwLayers = numLayers; + sizeof(hwc_layer_1_t) * numLayers + + sizeof(hwc_rect_t) * numRects; + auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1)); mHwc1RequestedContents.reset(contents); + mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]); + mNumAvailableRects = numRects; } -void HWC2On1Adapter::Display::assignHwc1LayerIds() -{ +void HWC2On1Adapter::Display::assignHwc1LayerIds() { mHwc1LayerMap.clear(); size_t nextHwc1Id = 0; for (auto& layer : mLayers) { @@ -1911,8 +1800,7 @@ void HWC2On1Adapter::Display::assignHwc1LayerIds() } void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer, - const Layer& layer) -{ + const Layer& layer) { auto layerId = layer.getId(); switch (hwc1Layer.compositionType) { case HWC_FRAMEBUFFER: @@ -1947,16 +1835,14 @@ void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer, } void HWC2On1Adapter::Display::updateLayerRequests( - const hwc_layer_1_t& hwc1Layer, const Layer& layer) -{ + const hwc_layer_1_t& hwc1Layer, const Layer& layer) { if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) { mChanges->addLayerRequest(layer.getId(), LayerRequest::ClearClientTarget); } } -void HWC2On1Adapter::Display::prepareFramebufferTarget() -{ +void HWC2On1Adapter::Display::prepareFramebufferTarget() { // We check that mActiveConfig is valid in Display::prepare int32_t width = mActiveConfig->getAttribute(Attribute::Width); int32_t height = mActiveConfig->getAttribute(Attribute::Height); @@ -1976,8 +1862,9 @@ void HWC2On1Adapter::Display::prepareFramebufferTarget() } hwc1Target.displayFrame = {0, 0, width, height}; hwc1Target.planeAlpha = 255; + hwc1Target.visibleRegionScreen.numRects = 1; - auto rects = static_cast<hwc_rect_t*>(std::malloc(sizeof(hwc_rect_t))); + hwc_rect_t* rects = GetRects(1); rects[0].left = 0; rects[0].top = 0; rects[0].right = width; @@ -1995,42 +1882,37 @@ std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1); HWC2On1Adapter::Layer::Layer(Display& display) : mId(sNextId++), mDisplay(display), - mDirtyCount(0), mBuffer(), mSurfaceDamage(), - mBlendMode(*this, BlendMode::None), - mColor(*this, {0, 0, 0, 0}), - mCompositionType(*this, Composition::Invalid), - mDisplayFrame(*this, {0, 0, -1, -1}), - mPlaneAlpha(*this, 0.0f), - mSidebandStream(*this, nullptr), - mSourceCrop(*this, {0.0f, 0.0f, -1.0f, -1.0f}), - mTransform(*this, Transform::None), - mVisibleRegion(*this, std::vector<hwc_rect_t>()), + mBlendMode(BlendMode::None), + mColor({0, 0, 0, 0}), + mCompositionType(Composition::Invalid), + mDisplayFrame({0, 0, -1, -1}), + mPlaneAlpha(0.0f), + mSidebandStream(nullptr), + mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}), + mTransform(Transform::None), + mVisibleRegion(), mZ(0), mReleaseFence(), mHwc1Id(0), - mHasUnsupportedPlaneAlpha(false), - mHasUnsupportedBackgroundColor(false) {} + mHasUnsupportedPlaneAlpha(false) {} bool HWC2On1Adapter::SortLayersByZ::operator()( - const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) -{ + const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) { return lhs->getZ() < rhs->getZ(); } Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer, - int32_t acquireFence) -{ + int32_t acquireFence) { ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId); mBuffer.setBuffer(buffer); mBuffer.setFence(acquireFence); return Error::None; } -Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) -{ - if (mCompositionType.getValue() != Composition::Cursor) { +Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) { + if (mCompositionType != Composition::Cursor) { return Error::BadLayer; } @@ -2044,8 +1926,7 @@ Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) return Error::None; } -Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) -{ +Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) { // HWC1 supports surface damage starting only with version 1.5. if (mDisplay.getDevice().mHwc1MinorVersion < 5) { return Error::None; @@ -2057,104 +1938,91 @@ Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) // Layer state functions -Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) -{ - mBlendMode.setPending(mode); +Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) { + mBlendMode = mode; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) -{ - mColor.setPending(color); +Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) { + mColor = color; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setCompositionType(Composition type) -{ - mCompositionType.setPending(type); +Error HWC2On1Adapter::Layer::setCompositionType(Composition type) { + mCompositionType = type; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) -{ +Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) { return Error::None; } -Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) -{ - mDisplayFrame.setPending(frame); +Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) { + mDisplayFrame = frame; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) -{ - mPlaneAlpha.setPending(alpha); +Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) { + mPlaneAlpha = alpha; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) -{ - mSidebandStream.setPending(stream); +Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) { + mSidebandStream = stream; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) -{ - mSourceCrop.setPending(crop); +Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) { + mSourceCrop = crop; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setTransform(Transform transform) -{ - mTransform.setPending(transform); +Error HWC2On1Adapter::Layer::setTransform(Transform transform) { + mTransform = transform; + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t rawVisible) -{ - std::vector<hwc_rect_t> visible(rawVisible.rects, - rawVisible.rects + rawVisible.numRects); - mVisibleRegion.setPending(std::move(visible)); +Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) { + mVisibleRegion.resize(visible.numRects); + std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin()); + mDisplay.markGeometryChanged(); return Error::None; } -Error HWC2On1Adapter::Layer::setZ(uint32_t z) -{ +Error HWC2On1Adapter::Layer::setZ(uint32_t z) { mZ = z; return Error::None; } -void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) -{ +void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) { ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId); mReleaseFence.add(fenceFd); } -const sp<Fence>& HWC2On1Adapter::Layer::getReleaseFence() const -{ +const sp<Fence>& HWC2On1Adapter::Layer::getReleaseFence() const { return mReleaseFence.get(); } -void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer, - bool applyAllState) -{ - applyCommonState(hwc1Layer, applyAllState); - auto compositionType = mCompositionType.getPendingValue(); - if (compositionType == Composition::SolidColor) { - applySolidColorState(hwc1Layer, applyAllState); - } else if (compositionType == Composition::Sideband) { - applySidebandState(hwc1Layer, applyAllState); - } else { - applyBufferState(hwc1Layer); +void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) { + applyCommonState(hwc1Layer); + applyCompositionType(hwc1Layer); + switch (mCompositionType) { + case Composition::SolidColor : applySolidColorState(hwc1Layer); break; + case Composition::Sideband : applySidebandState(hwc1Layer); break; + default: applyBufferState(hwc1Layer); break; } - applyCompositionType(hwc1Layer, applyAllState); } -// Layer dump helpers - static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion, - const std::vector<hwc_rect_t>& surfaceDamage) -{ + const std::vector<hwc_rect_t>& surfaceDamage) { std::string regions; regions += " Visible Region"; regions.resize(40, ' '); @@ -2182,40 +2050,38 @@ static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion, return regions; } -std::string HWC2On1Adapter::Layer::dump() const -{ +std::string HWC2On1Adapter::Layer::dump() const { std::stringstream output; const char* fill = " "; - output << fill << to_string(mCompositionType.getPendingValue()); + output << fill << to_string(mCompositionType); output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " "; output << "Z: " << mZ; - if (mCompositionType.getValue() == HWC2::Composition::SolidColor) { - output << " " << colorString(mColor.getValue()); - } else if (mCompositionType.getValue() == HWC2::Composition::Sideband) { - output << " Handle: " << mSidebandStream.getValue() << '\n'; + if (mCompositionType == HWC2::Composition::SolidColor) { + output << " " << colorString(mColor); + } else if (mCompositionType == HWC2::Composition::Sideband) { + output << " Handle: " << mSidebandStream << '\n'; } else { output << " Buffer: " << mBuffer.getBuffer() << "/" << mBuffer.getFence() << '\n'; output << fill << " Display frame [LTRB]: " << - rectString(mDisplayFrame.getValue()) << '\n'; + rectString(mDisplayFrame) << '\n'; output << fill << " Source crop: " << - frectString(mSourceCrop.getValue()) << '\n'; - output << fill << " Transform: " << to_string(mTransform.getValue()); - output << " Blend mode: " << to_string(mBlendMode.getValue()); - if (mPlaneAlpha.getValue() != 1.0f) { + frectString(mSourceCrop) << '\n'; + output << fill << " Transform: " << to_string(mTransform); + output << " Blend mode: " << to_string(mBlendMode); + if (mPlaneAlpha != 1.0f) { output << " Alpha: " << - alphaString(mPlaneAlpha.getValue()) << '\n'; + alphaString(mPlaneAlpha) << '\n'; } else { output << '\n'; } - output << regionStrings(mVisibleRegion.getValue(), mSurfaceDamage); + output << regionStrings(mVisibleRegion, mSurfaceDamage); } return output.str(); } -static int getHwc1Blending(HWC2::BlendMode blendMode) -{ +static int getHwc1Blending(HWC2::BlendMode blendMode) { switch (blendMode) { case BlendMode::Coverage: return HWC_BLENDING_COVERAGE; case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT; @@ -2223,168 +2089,124 @@ static int getHwc1Blending(HWC2::BlendMode blendMode) } } -void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer, - bool applyAllState) -{ +void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) { auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion(); - if (applyAllState || mBlendMode.isDirty()) { - hwc1Layer.blending = getHwc1Blending(mBlendMode.getPendingValue()); - mBlendMode.latch(); - } - if (applyAllState || mDisplayFrame.isDirty()) { - hwc1Layer.displayFrame = mDisplayFrame.getPendingValue(); - mDisplayFrame.latch(); - } - if (applyAllState || mPlaneAlpha.isDirty()) { - auto pendingAlpha = mPlaneAlpha.getPendingValue(); - if (minorVersion < 2) { - mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f; - } else { - hwc1Layer.planeAlpha = - static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f); - } - mPlaneAlpha.latch(); - } - if (applyAllState || mSourceCrop.isDirty()) { - if (minorVersion < 3) { - auto pending = mSourceCrop.getPendingValue(); - hwc1Layer.sourceCropi.left = - static_cast<int32_t>(std::ceil(pending.left)); - hwc1Layer.sourceCropi.top = - static_cast<int32_t>(std::ceil(pending.top)); - hwc1Layer.sourceCropi.right = - static_cast<int32_t>(std::floor(pending.right)); - hwc1Layer.sourceCropi.bottom = - static_cast<int32_t>(std::floor(pending.bottom)); - } else { - hwc1Layer.sourceCropf = mSourceCrop.getPendingValue(); - } - mSourceCrop.latch(); - } - if (applyAllState || mTransform.isDirty()) { - hwc1Layer.transform = - static_cast<uint32_t>(mTransform.getPendingValue()); - mTransform.latch(); + hwc1Layer.blending = getHwc1Blending(mBlendMode); + hwc1Layer.displayFrame = mDisplayFrame; + + auto pendingAlpha = mPlaneAlpha; + if (minorVersion < 2) { + mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f; + } else { + hwc1Layer.planeAlpha = + static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f); + } + + if (minorVersion < 3) { + auto pending = mSourceCrop; + hwc1Layer.sourceCropi.left = + static_cast<int32_t>(std::ceil(pending.left)); + hwc1Layer.sourceCropi.top = + static_cast<int32_t>(std::ceil(pending.top)); + hwc1Layer.sourceCropi.right = + static_cast<int32_t>(std::floor(pending.right)); + hwc1Layer.sourceCropi.bottom = + static_cast<int32_t>(std::floor(pending.bottom)); + } else { + hwc1Layer.sourceCropf = mSourceCrop; } - if (applyAllState || mVisibleRegion.isDirty()) { - auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen; - std::free(const_cast<hwc_rect_t*>(hwc1VisibleRegion.rects)); + hwc1Layer.transform = static_cast<uint32_t>(mTransform); - auto pending = mVisibleRegion.getPendingValue(); - hwc_rect_t* newRects = static_cast<hwc_rect_t*>( - std::malloc(sizeof(hwc_rect_t) * pending.size())); - std::copy(pending.begin(), pending.end(), newRects); - hwc1VisibleRegion.rects = const_cast<const hwc_rect_t*>(newRects); - hwc1VisibleRegion.numRects = pending.size(); - mVisibleRegion.latch(); + auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen; + hwc1VisibleRegion.numRects = mVisibleRegion.size(); + hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects); + hwc1VisibleRegion.rects = rects; + for (size_t i = 0; i < mVisibleRegion.size(); i++) { + rects[i] = mVisibleRegion[i]; } } -void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer, - bool applyAllState) -{ - if (applyAllState || mColor.isDirty()) { - // If the device does not support background color it is likely to make - // assumption regarding backgroundColor and handle (both fields occupy - // the same location in hwc_layer_1_t union). - // To not confuse these devices we don't set background color and we - // make sure handle is a null pointer. - if (mDisplay.getDevice().supportsBackgroundColor()) { - hwc1Layer.backgroundColor = mColor.getPendingValue(); - mHasUnsupportedBackgroundColor = false; - } else { - hwc1Layer.handle = nullptr; - mHasUnsupportedBackgroundColor = true; - } - mColor.latch(); +void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) { + // If the device does not support background color it is likely to make + // assumption regarding backgroundColor and handle (both fields occupy + // the same location in hwc_layer_1_t union). + // To not confuse these devices we don't set background color and we + // make sure handle is a null pointer. + if (hasUnsupportedBackgroundColor()) { + hwc1Layer.handle = nullptr; + } else { + hwc1Layer.backgroundColor = mColor; } } -void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer, - bool applyAllState) -{ - if (applyAllState || mSidebandStream.isDirty()) { - hwc1Layer.sidebandStream = mSidebandStream.getPendingValue(); - mSidebandStream.latch(); - } +void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) { + hwc1Layer.sidebandStream = mSidebandStream; } -void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) -{ +void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) { hwc1Layer.handle = mBuffer.getBuffer(); hwc1Layer.acquireFenceFd = mBuffer.getFence(); } -void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer, - bool applyAllState) -{ +void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) { // HWC1 never supports color transforms or dataspaces and only sometimes // supports plane alpha (depending on the version). These require us to drop // some or all layers to client composition. - ALOGV("applyCompositionType"); - ALOGV("mHasUnsupportedPlaneAlpha = %d", mHasUnsupportedPlaneAlpha); - ALOGV("mDisplay.hasColorTransform() = %d", mDisplay.hasColorTransform()); - ALOGV("mHasUnsupportedBackgroundColor = %d", mHasUnsupportedBackgroundColor); - if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() || - mHasUnsupportedBackgroundColor) { + hasUnsupportedBackgroundColor()) { hwc1Layer.compositionType = HWC_FRAMEBUFFER; hwc1Layer.flags = HWC_SKIP_LAYER; return; } - if (applyAllState || mCompositionType.isDirty()) { - hwc1Layer.flags = 0; - switch (mCompositionType.getPendingValue()) { - case Composition::Client: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - case Composition::Device: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - break; - case Composition::SolidColor: - // In theory the following line should work, but since the HWC1 - // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1 - // devices may not work correctly. To be on the safe side, we - // fall back to client composition. - // - // hwc1Layer.compositionType = HWC_BACKGROUND; - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - case Composition::Cursor: - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) { - hwc1Layer.hints |= HWC_IS_CURSOR_LAYER; - } - break; - case Composition::Sideband: - if (mDisplay.getDevice().getHwc1MinorVersion() < 4) { - hwc1Layer.compositionType = HWC_SIDEBAND; - } else { - hwc1Layer.compositionType = HWC_FRAMEBUFFER; - hwc1Layer.flags |= HWC_SKIP_LAYER; - } - break; - default: + hwc1Layer.flags = 0; + switch (mCompositionType) { + case Composition::Client: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; + case Composition::Device: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + break; + case Composition::SolidColor: + // In theory the following line should work, but since the HWC1 + // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1 + // devices may not work correctly. To be on the safe side, we + // fall back to client composition. + // + // hwc1Layer.compositionType = HWC_BACKGROUND; + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; + case Composition::Cursor: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) { + hwc1Layer.hints |= HWC_IS_CURSOR_LAYER; + } + break; + case Composition::Sideband: + if (mDisplay.getDevice().getHwc1MinorVersion() < 4) { + hwc1Layer.compositionType = HWC_SIDEBAND; + } else { hwc1Layer.compositionType = HWC_FRAMEBUFFER; hwc1Layer.flags |= HWC_SKIP_LAYER; - break; - } - ALOGV("Layer %" PRIu64 " %s set to %d", mId, - to_string(mCompositionType.getPendingValue()).c_str(), - hwc1Layer.compositionType); - ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping"); - mCompositionType.latch(); + } + break; + default: + hwc1Layer.compositionType = HWC_FRAMEBUFFER; + hwc1Layer.flags |= HWC_SKIP_LAYER; + break; } + ALOGV("Layer %" PRIu64 " %s set to %d", mId, + to_string(mCompositionType).c_str(), + hwc1Layer.compositionType); + ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping"); } // Adapter helpers -void HWC2On1Adapter::populateCapabilities() -{ +void HWC2On1Adapter::populateCapabilities() { ALOGV("populateCapabilities"); if (mHwc1MinorVersion >= 3U) { int supportedTypes = 0; @@ -2412,8 +2234,7 @@ void HWC2On1Adapter::populateCapabilities() } } -HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) -{ +HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) { std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); auto display = mDisplays.find(id); @@ -2425,8 +2246,7 @@ HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) } std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer( - hwc2_display_t displayId, hwc2_layer_t layerId) -{ + hwc2_display_t displayId, hwc2_layer_t layerId) { auto display = getDisplay(displayId); if (!display) { return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay); @@ -2444,22 +2264,19 @@ std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer( return std::make_tuple(layer.get(), Error::None); } -void HWC2On1Adapter::populatePrimary() -{ +void HWC2On1Adapter::populatePrimary() { ALOGV("populatePrimary"); std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); - auto display = - std::make_shared<Display>(*this, HWC2::DisplayType::Physical); + auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical); mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId(); display->setHwc1Id(HWC_DISPLAY_PRIMARY); display->populateConfigs(); mDisplays.emplace(display->getId(), std::move(display)); } -bool HWC2On1Adapter::prepareAllDisplays() -{ +bool HWC2On1Adapter::prepareAllDisplays() { ATRACE_CALL(); std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); @@ -2476,24 +2293,23 @@ bool HWC2On1Adapter::prepareAllDisplays() return false; } + // Build an array of hwc_display_contents_1 to call prepare() on HWC1. + mHwc1Contents.clear(); + // Always push the primary display - std::vector<HWC2On1Adapter::Display::HWC1Contents> requestedContents; auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY]; auto& primaryDisplay = mDisplays[primaryDisplayId]; - auto primaryDisplayContents = primaryDisplay->cloneRequestedContents(); - requestedContents.push_back(std::move(primaryDisplayContents)); + mHwc1Contents.push_back(primaryDisplay->getDisplayContents()); // Push the external display, if present if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) { auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL]; auto& externalDisplay = mDisplays[externalDisplayId]; - auto externalDisplayContents = - externalDisplay->cloneRequestedContents(); - requestedContents.push_back(std::move(externalDisplayContents)); + mHwc1Contents.push_back(externalDisplay->getDisplayContents()); } else { // Even if an external display isn't present, we still need to send // at least two displays down to HWC1 - requestedContents.push_back(nullptr); + mHwc1Contents.push_back(nullptr); } // Push the hardware virtual display, if supported and present @@ -2501,17 +2317,13 @@ bool HWC2On1Adapter::prepareAllDisplays() if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) { auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL]; auto& virtualDisplay = mDisplays[virtualDisplayId]; - auto virtualDisplayContents = - virtualDisplay->cloneRequestedContents(); - requestedContents.push_back(std::move(virtualDisplayContents)); + mHwc1Contents.push_back(virtualDisplay->getDisplayContents()); } else { - requestedContents.push_back(nullptr); + mHwc1Contents.push_back(nullptr); } } - mHwc1Contents.clear(); - for (auto& displayContents : requestedContents) { - mHwc1Contents.push_back(displayContents.get()); + for (auto& displayContents : mHwc1Contents) { if (!displayContents) { continue; } @@ -2549,14 +2361,13 @@ bool HWC2On1Adapter::prepareAllDisplays() auto displayId = mHwc1DisplayMap[hwc1Id]; auto& display = mDisplays[displayId]; - display->setReceivedContents(std::move(requestedContents[hwc1Id])); + display->generateChanges(); } return true; } -Error HWC2On1Adapter::setAllDisplays() -{ +Error HWC2On1Adapter::setAllDisplays() { ATRACE_CALL(); std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); @@ -2602,14 +2413,13 @@ Error HWC2On1Adapter::setAllDisplays() return Error::None; } -void HWC2On1Adapter::hwc1Invalidate() -{ +void HWC2On1Adapter::hwc1Invalidate() { ALOGV("Received hwc1Invalidate"); std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); // If the HWC2-side callback hasn't been registered yet, buffer this until - // it is registered + // it is registered. if (mCallbacks.count(Callback::Refresh) == 0) { mHasPendingInvalidate = true; return; @@ -2621,7 +2431,7 @@ void HWC2On1Adapter::hwc1Invalidate() displays.emplace_back(displayPair.first); } - // Call back without the state lock held + // Call back without the state lock held. lock.unlock(); auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer); @@ -2630,14 +2440,13 @@ void HWC2On1Adapter::hwc1Invalidate() } } -void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) -{ +void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) { ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp); std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); // If the HWC2-side callback hasn't been registered yet, buffer this until - // it is registered + // it is registered. if (mCallbacks.count(Callback::Vsync) == 0) { mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp); return; @@ -2651,15 +2460,14 @@ void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) const auto& callbackInfo = mCallbacks[Callback::Vsync]; auto displayId = mHwc1DisplayMap[hwc1DisplayId]; - // Call back without the state lock held + // Call back without the state lock held. lock.unlock(); auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer); vsync(callbackInfo.data, displayId, timestamp); } -void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) -{ +void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) { ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected); if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) { @@ -2714,5 +2522,4 @@ void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) HWC2::Connection::Disconnected : HWC2::Connection::Connected; hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected)); } - } // namespace android diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h index df33ec3fcd..408bc41649 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h +++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h @@ -134,11 +134,6 @@ private: const std::shared_ptr<Layer>& rhs); }; - class DisplayContentsDeleter { - public: - void operator()(struct hwc_display_contents_1* contents); - }; - // The semantics of the fences returned by the device differ between // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h // for more information. @@ -193,9 +188,6 @@ private: class Display { public: - typedef std::unique_ptr<hwc_display_contents_1, - DisplayContentsDeleter> HWC1Contents; - Display(HWC2On1Adapter& device, HWC2::DisplayType type); hwc2_display_t getId() const { return mId; } @@ -206,10 +198,6 @@ private: void setHwc1Id(int32_t id) { mHwc1Id = id; } int32_t getHwc1Id() const { return mHwc1Id; } - void incDirty() { ++mDirtyCount; } - void decDirty() { --mDirtyCount; } - bool isDirty() const { return mDirtyCount > 0 || mZIsDirty; } - // HWC2 Display functions HWC2::Error acceptChanges(); HWC2::Error createLayer(hwc2_layer_t* outLayerId); @@ -233,7 +221,14 @@ private: uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outLayerRequests); HWC2::Error getType(int32_t* outType); + + // Since HWC1 "presents" (called "set" in HWC1) all Displays + // at once, the first call to any Display::present will trigger + // present() on all Displays in the Device. Subsequent calls without + // first calling validate() are noop (except for duping/returning + // the retire fence). HWC2::Error present(int32_t* outRetireFence); + HWC2::Error setActiveConfig(hwc2_config_t configId); HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence, int32_t dataspace, @@ -244,6 +239,10 @@ private: int32_t releaseFence); HWC2::Error setPowerMode(HWC2::PowerMode mode); HWC2::Error setVsyncEnabled(HWC2::Vsync enabled); + + // Since HWC1 "validates" (called "prepare" in HWC1) all Displays + // at once, the first call to any Display::validate() will trigger + // validate() on all other Displays in the Device. HWC2::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests); @@ -256,10 +255,9 @@ private: void populateConfigs(uint32_t width, uint32_t height); bool prepare(); - HWC1Contents cloneRequestedContents() const; // Called after hwc.prepare() with responses from the device. - void setReceivedContents(HWC1Contents contents); + void generateChanges(); bool hasChanges() const; HWC2::Error set(hwc_display_contents_1& hwcContents); @@ -270,6 +268,13 @@ private: std::string dump() const; + // Return a rect from the pool allocated during validate() + hwc_rect_t* GetRects(size_t numRects); + + hwc_display_contents_1* getDisplayContents(); + + void markGeometryChanged() { mGeometryChanged = true; } + void resetGeometryMarker() { mGeometryChanged = false;} private: class Config { public: @@ -314,7 +319,7 @@ private: std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids; }; - // Store changes requested from the device upon calling prepare(). + // Stores changes requested from the device upon calling prepare(). // Handles change request to: // - Layer composition type. // - Layer hints. @@ -363,7 +368,9 @@ private: void populateColorModes(); void initializeActiveConfig(); - void reallocateHwc1Contents(); + // Creates a bi-directional mapping between index in HWC1 + // prepare/set array and Layer object. Stores mapping in + // mHwc1LayerMap and also updates Layer's attribute mHwc1Id. void assignHwc1LayerIds(); // Called after a response to prepare() has been received: @@ -376,13 +383,16 @@ private: void updateLayerRequests(const struct hwc_layer_1& hwc1Layer, const Layer& layer); + // Set all fields in HWC1 comm array for layer containing the + // HWC_FRAMEBUFFER_TARGET (always the last layer). void prepareFramebufferTarget(); + // Display ID generator. static std::atomic<hwc2_display_t> sNextId; const hwc2_display_t mId; - HWC2On1Adapter& mDevice; - std::atomic<size_t> mDirtyCount; + + HWC2On1Adapter& mDevice; // The state of this display should only be modified from // SurfaceFlinger's main loop, with the exception of when dump is @@ -395,15 +405,18 @@ private: // which require locking. mutable std::recursive_mutex mStateMutex; - bool mZIsDirty; + // Allocate RAM able to store all layers and rects used for + // communication with HWC1. Place allocated RAM in variable + // mHwc1RequestedContents. + void allocateRequestedContents(); // Array of structs exchanged between client and hwc1 device. - HWC1Contents mHwc1RequestedContents; // Sent to device upon calling prepare(). - HWC1Contents mHwc1ReceivedContents; // Returned by device after prepare(). - + // Sent to device upon calling prepare(). + std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents; + private: DeferredFence mRetireFence; - // Will only be non-null after the layer has been validated but + // Will only be non-null after the Display has been validated and // before it has been presented std::unique_ptr<Changes> mChanges; @@ -418,15 +431,34 @@ private: HWC2::PowerMode mPowerMode; HWC2::Vsync mVsyncEnabled; + // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer FencedBuffer mClientTarget; + + FencedBuffer mOutputBuffer; bool mHasColorTransform; + // All layers this Display is aware of. std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers; + + // Mapping between layer index in array of hwc_display_contents_1* + // passed to HWC1 during validate/set and Layer object. std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap; + + // All communication with HWC1 via prepare/set is done with one + // alloc. This pointer is pointing to a pool of hwc_rect_t. + size_t mNumAvailableRects; + hwc_rect_t* mNextAvailableRect; + + // True if any of the Layers contained in this Display have been + // updated with anything other than a buffer since last call to + // Display::set() + bool mGeometryChanged; }; + // Utility template calling a Display object method directly based on the + // hwc2_display_t displayId parameter. template <typename ...Args> static int32_t callDisplayFunction(hwc2_device_t* device, hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...), @@ -468,7 +500,8 @@ private: static int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) { auto mode = static_cast<android_color_mode_t>(intMode); - return callDisplayFunction(device, display, &Display::setColorMode, mode); + return callDisplayFunction(device, display, &Display::setColorMode, + mode); } static int32_t setPowerModeHook(hwc2_device_t* device, @@ -485,46 +518,6 @@ private: enabled); } - // Layer functions - - template <typename T> - class LatchedState { - public: - LatchedState(Layer& parent, T initialValue) - : mParent(parent), - mPendingValue(initialValue), - mValue(initialValue) {} - - void setPending(T value) { - if (value == mPendingValue) { - return; - } - if (mPendingValue == mValue) { - mParent.incDirty(); - } else if (value == mValue) { - mParent.decDirty(); - } - mPendingValue = value; - } - - T getValue() const { return mValue; } - T getPendingValue() const { return mPendingValue; } - - bool isDirty() const { return mPendingValue != mValue; } - - void latch() { - if (isDirty()) { - mValue = mPendingValue; - mParent.decDirty(); - } - } - - private: - Layer& mParent; - T mPendingValue; - T mValue; - }; - class Layer { public: explicit Layer(Display& display); @@ -535,10 +528,6 @@ private: hwc2_layer_t getId() const { return mId; } Display& getDisplay() const { return mDisplay; } - void incDirty() { if (mDirtyCount++ == 0) mDisplay.incDirty(); } - void decDirty() { if (--mDirtyCount == 0) mDisplay.decDirty(); } - bool isDirty() const { return mDirtyCount > 0; } - // HWC2 Layer functions HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence); HWC2::Error setCursorPosition(int32_t x, int32_t y); @@ -558,7 +547,7 @@ private: HWC2::Error setZ(uint32_t z); HWC2::Composition getCompositionType() const { - return mCompositionType.getValue(); + return mCompositionType; } uint32_t getZ() const { return mZ; } @@ -568,47 +557,57 @@ private: void setHwc1Id(size_t id) { mHwc1Id = id; } size_t getHwc1Id() const { return mHwc1Id; } - void applyState(struct hwc_layer_1& hwc1Layer, bool applyAllState); + // Write state to HWC1 communication struct. + void applyState(struct hwc_layer_1& hwc1Layer); std::string dump() const; + std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); } + + std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); } + + // True if a layer cannot be properly rendered by the device due + // to usage of SolidColor (a.k.a BackgroundColor in HWC1). + bool hasUnsupportedBackgroundColor() { + return (mCompositionType == HWC2::Composition::SolidColor && + !mDisplay.getDevice().supportsBackgroundColor()); + } private: - void applyCommonState(struct hwc_layer_1& hwc1Layer, - bool applyAllState); - void applySolidColorState(struct hwc_layer_1& hwc1Layer, - bool applyAllState); - void applySidebandState(struct hwc_layer_1& hwc1Layer, - bool applyAllState); + void applyCommonState(struct hwc_layer_1& hwc1Layer); + void applySolidColorState(struct hwc_layer_1& hwc1Layer); + void applySidebandState(struct hwc_layer_1& hwc1Layer); void applyBufferState(struct hwc_layer_1& hwc1Layer); - void applyCompositionType(struct hwc_layer_1& hwc1Layer, - bool applyAllState); + void applyCompositionType(struct hwc_layer_1& hwc1Layer); static std::atomic<hwc2_layer_t> sNextId; const hwc2_layer_t mId; Display& mDisplay; - size_t mDirtyCount; FencedBuffer mBuffer; std::vector<hwc_rect_t> mSurfaceDamage; - LatchedState<HWC2::BlendMode> mBlendMode; - LatchedState<hwc_color_t> mColor; - LatchedState<HWC2::Composition> mCompositionType; - LatchedState<hwc_rect_t> mDisplayFrame; - LatchedState<float> mPlaneAlpha; - LatchedState<const native_handle_t*> mSidebandStream; - LatchedState<hwc_frect_t> mSourceCrop; - LatchedState<HWC2::Transform> mTransform; - LatchedState<std::vector<hwc_rect_t>> mVisibleRegion; + HWC2::BlendMode mBlendMode; + hwc_color_t mColor; + HWC2::Composition mCompositionType; + hwc_rect_t mDisplayFrame; + float mPlaneAlpha; + const native_handle_t* mSidebandStream; + hwc_frect_t mSourceCrop; + HWC2::Transform mTransform; + std::vector<hwc_rect_t> mVisibleRegion; + uint32_t mZ; DeferredFence mReleaseFence; size_t mHwc1Id; bool mHasUnsupportedPlaneAlpha; - bool mHasUnsupportedBackgroundColor; }; + // Utility tempate calling a Layer object method based on ID parameters: + // hwc2_display_t displayId + // and + // hwc2_layer_t layerId template <typename ...Args> static int32_t callLayerFunction(hwc2_device_t* device, hwc2_display_t displayId, hwc2_layer_t layerId, @@ -677,6 +676,7 @@ private: std::vector<struct hwc_display_contents_1*> mHwc1Contents; HWC2::Error setAllDisplays(); + // Callbacks void hwc1Invalidate(); void hwc1Vsync(int hwc1DisplayId, int64_t timestamp); void hwc1Hotplug(int hwc1DisplayId, int connected); @@ -698,6 +698,8 @@ private: // callbacks or dump std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers; + + // A HWC1 supports only one virtual display. std::shared_ptr<Display> mHwc1VirtualDisplay; // These are potentially accessed from multiple threads, and are protected @@ -712,10 +714,19 @@ private: }; std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks; bool mHasPendingInvalidate; + + // There is a small gap between the time the HWC1 module is started and + // when the callbacks for vsync and hotplugs are registered by the + // HWC2on1Adapter. To prevent losing events they are stored in these arrays + // and fed to the callback as soon as possible. std::vector<std::pair<int, int64_t>> mPendingVsyncs; std::vector<std::pair<int, int>> mPendingHotplugs; + // Mapping between HWC1 display id and Display objects. std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays; + + // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL, + // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects. std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap; }; |