diff options
| -rw-r--r-- | services/surfaceflinger/Android.mk | 7 | ||||
| -rw-r--r-- | services/surfaceflinger/Client.cpp | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2.cpp | 18 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWC2.h | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 14 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 47 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 34 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 17 |
10 files changed, 108 insertions, 43 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index ce858d2f0f..08115ead61 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -46,8 +46,7 @@ LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES #LOCAL_CFLAGS += -DENABLE_FENCE_TRACKING -USE_HWC2 := false -ifeq ($(USE_HWC2),true) +ifeq ($(TARGET_USES_HWC2),true) LOCAL_CFLAGS += -DUSE_HWC2 LOCAL_SRC_FILES += \ SurfaceFlinger.cpp \ @@ -149,6 +148,10 @@ ifneq ($(ENABLE_CPUSETS),) LOCAL_CFLAGS += -DENABLE_CPUSETS endif +ifeq ($(TARGET_USES_HWC2),true) + LOCAL_CFLAGS += -DUSE_HWC2 +endif + LOCAL_SRC_FILES := \ main_surfaceflinger.cpp diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 2a025b8a93..3e48cd2fa0 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -43,10 +43,7 @@ Client::~Client() { const size_t count = mLayers.size(); for (size_t i=0 ; i<count ; i++) { - sp<Layer> layer(mLayers.valueAt(i).promote()); - if (layer != 0) { - mFlinger->removeLayer(layer); - } + mFlinger->removeLayer(mLayers.valueAt(i)); } } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index ed8cc08ff7..ae6ba98bd5 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -149,7 +149,12 @@ Device::~Device() } for (auto element : mDisplays) { - auto display = element.second; + auto display = element.second.lock(); + if (!display) { + ALOGE("~Device: Found a display (%" PRId64 " that has already been" + " destroyed", element.first); + continue; + } DisplayType displayType = HWC2::DisplayType::Invalid; auto error = display->getType(&displayType); @@ -208,6 +213,10 @@ Error Device::createVirtualDisplay(uint32_t width, uint32_t height, ALOGI("Created virtual display"); *format = static_cast<android_pixel_format_t>(intFormat); *outDisplay = getDisplayById(displayId); + if (!*outDisplay) { + ALOGE("Failed to get display by id"); + return Error::BadDisplay; + } (*outDisplay)->setVirtual(); return Error::None; } @@ -289,7 +298,10 @@ void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp) std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) { if (mDisplays.count(id) != 0) { - return mDisplays.at(id); + auto strongDisplay = mDisplays[id].lock(); + ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no" + " longer alive", id); + return strongDisplay; } auto display = std::make_shared<Display>(*this, id); @@ -430,6 +442,7 @@ void Device::destroyVirtualDisplay(hwc2_display_t display) auto error = static_cast<Error>(intError); ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:" " %s (%d)", display, to_string(error).c_str(), intError); + mDisplays.erase(display); } // Display methods @@ -810,6 +823,7 @@ Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer, auto handle = buffer->getNativeBuffer()->handle; int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle, fenceFd); + close(fenceFd); return static_cast<Error>(intError); } diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h index 1aa4205838..25a7d89c8c 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.h +++ b/services/surfaceflinger/DisplayHardware/HWC2.h @@ -88,7 +88,8 @@ public: // Other Device methods // This will create a Display if one is not found, but it will not be marked - // as connected + // as connected. This Display may be null if the display has been torn down + // but has not been removed from the map yet. std::shared_ptr<Display> getDisplayById(hwc2_display_t id); bool hasCapability(HWC2::Capability capability) const; @@ -181,7 +182,7 @@ private: HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder; std::vector<Capability> mCapabilities; - std::unordered_map<hwc2_display_t, std::shared_ptr<Display>> mDisplays; + std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays; HotplugCallback mHotplug; std::vector<std::pair<std::shared_ptr<Display>, Connection>> diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 26297943b5..216bbc9e55 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -422,6 +422,10 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { Mutex::Autolock _l(mDisplayLock); auto displayId = displayDevice.getHwcDisplayId(); + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + ALOGV("Skipping HWComposer prepare for non-HWC display"); + return NO_ERROR; + } if (!isValidDisplay(displayId)) { return BAD_INDEX; } @@ -515,6 +519,11 @@ status_t HWComposer::prepare(DisplayDevice& displayDevice) { } bool HWComposer::hasDeviceComposition(int32_t displayId) const { + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + // Displays without a corresponding HWC display are never composed by + // the device + return false; + } if (!isValidDisplay(displayId)) { ALOGE("hasDeviceComposition: Invalid display %d", displayId); return false; @@ -523,6 +532,11 @@ bool HWComposer::hasDeviceComposition(int32_t displayId) const { } bool HWComposer::hasClientComposition(int32_t displayId) const { + if (displayId == DisplayDevice::DISPLAY_ID_INVALID) { + // Displays without a corresponding HWC display are always composed by + // the client + return true; + } if (!isValidDisplay(displayId)) { ALOGE("hasClientComposition: Invalid display %d", displayId); return true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 44db852198..9173165d0c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -716,18 +716,33 @@ void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) { return; } - // Client or SolidColor layers - if (mActiveBuffer == nullptr || mActiveBuffer->handle == nullptr || - mHwcLayers[hwcId].forceClientComposition) { - // TODO: This also includes solid color layers, but no API exists to - // setup a solid color layer yet + // Client layers + if (mHwcLayers[hwcId].forceClientComposition || + (mActiveBuffer != nullptr && mActiveBuffer->handle == nullptr)) { ALOGV("[%s] Requesting Client composition", mName.string()); setCompositionType(hwcId, HWC2::Composition::Client); - error = hwcLayer->setBuffer(nullptr, Fence::NO_FENCE); + return; + } + + // SolidColor layers + if (mActiveBuffer == nullptr) { + setCompositionType(hwcId, HWC2::Composition::SolidColor); + + // For now, we only support black for DimLayer + error = hwcLayer->setColor({0, 0, 0, 255}); if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set null buffer: %s (%d)", mName.string(), + ALOGE("[%s] Failed to set color: %s (%d)", mName.string(), to_string(error).c_str(), static_cast<int32_t>(error)); } + + // Clear out the transform, because it doesn't make sense absent a + // source buffer + error = hwcLayer->setTransform(HWC2::Transform::None); + if (error != HWC2::Error::None) { + ALOGE("[%s] Failed to clear transform: %s (%d)", mName.string(), + to_string(error).c_str(), static_cast<int32_t>(error)); + } + return; } @@ -1058,8 +1073,13 @@ void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, } HWC2::Composition Layer::getCompositionType(int32_t hwcId) const { + if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) { + // If we're querying the composition type for a display that does not + // have a HWC counterpart, then it will always be Client + return HWC2::Composition::Client; + } if (mHwcLayers.count(hwcId) == 0) { - ALOGE("getCompositionType called without a valid HWC layer"); + ALOGE("getCompositionType called with an invalid HWC layer"); return HWC2::Composition::Invalid; } return mHwcLayers.at(hwcId).compositionType; @@ -1269,9 +1289,14 @@ void Layer::pushPendingState() { // If this transaction is waiting on the receipt of a frame, generate a sync // point and send it to the remote layer. if (mCurrentState.handle != nullptr) { - sp<Handle> handle = static_cast<Handle*>(mCurrentState.handle.get()); - sp<Layer> handleLayer = handle->owner.promote(); - if (handleLayer == nullptr) { + sp<IBinder> strongBinder = mCurrentState.handle.promote(); + sp<Handle> handle = nullptr; + sp<Layer> handleLayer = nullptr; + if (strongBinder != nullptr) { + handle = static_cast<Handle*>(strongBinder.get()); + handleLayer = handle->owner.promote(); + } + if (strongBinder == nullptr || handleLayer == nullptr) { ALOGE("[%s] Unable to promote Layer handle", mName.string()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 55e3b5461b..c96e7d5ee9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -124,7 +124,7 @@ public: // If set, defers this state update until the Layer identified by handle // receives a frame with the given frameNumber - sp<IBinder> handle; + wp<IBinder> handle; uint64_t frameNumber; // the transparentRegion hint is a bit special, it's latched only diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index c700116fe1..47f5401c13 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1022,7 +1022,12 @@ void SurfaceFlinger::doDebugFlashRegions() } for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - status_t result = mDisplays[displayId]->prepareFrame(*mHwc); + auto& displayDevice = mDisplays[displayId]; + if (!displayDevice->isDisplayOn()) { + continue; + } + + status_t result = displayDevice->prepareFrame(*mHwc); ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" " %d (%s)", displayId, result, strerror(-result)); } @@ -1248,7 +1253,12 @@ void SurfaceFlinger::setUpHWComposer() { } for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { - status_t result = mDisplays[displayId]->prepareFrame(*mHwc); + auto& displayDevice = mDisplays[displayId]; + if (!displayDevice->isDisplayOn()) { + continue; + } + + status_t result = displayDevice->prepareFrame(*mHwc); ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:" " %d (%s)", displayId, result, strerror(-result)); } @@ -1286,6 +1296,9 @@ void SurfaceFlinger::postFramebuffer() for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) { auto& displayDevice = mDisplays[displayId]; + if (!displayDevice->isDisplayOn()) { + continue; + } const auto hwcId = displayDevice->getHwcDisplayId(); if (hwcId >= 0) { mHwc->commit(hwcId); @@ -2093,8 +2106,14 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { +status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { Mutex::Autolock _l(mStateLock); + sp<Layer> layer = weakLayer.promote(); + if (layer == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } + ssize_t index = mCurrentState.layersSortedByZ.remove(layer); if (index >= 0) { mLayersPendingRemoval.push(layer); @@ -2435,14 +2454,7 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) { // called by ~LayerCleaner() when all references to the IBinder (handle) // are gone - status_t err = NO_ERROR; - sp<Layer> l(layer.promote()); - if (l != NULL) { - err = removeLayer(l); - ALOGE_IF(err<0 && err != NAME_NOT_FOUND, - "error removing layer=%p (%s)", l.get(), strerror(-err)); - } - return err; + return removeLayer(layer); } // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 633e956d24..8279a85b45 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -311,7 +311,7 @@ private: status_t onLayerDestroyed(const wp<Layer>& layer); // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const sp<Layer>& layer); + status_t removeLayer(const wp<Layer>& layer); // add a layer to SurfaceFlinger status_t addClientLayer(const sp<Client>& client, diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 7f3b269f0e..072de81773 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -2096,8 +2096,14 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) { +status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { Mutex::Autolock _l(mStateLock); + sp<Layer> layer = weakLayer.promote(); + if (layer == nullptr) { + // The layer has already been removed, carry on + return NO_ERROR; + } + ssize_t index = mCurrentState.layersSortedByZ.remove(layer); if (index >= 0) { mLayersPendingRemoval.push(layer); @@ -2438,14 +2444,7 @@ status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer) { // called by ~LayerCleaner() when all references to the IBinder (handle) // are gone - status_t err = NO_ERROR; - sp<Layer> l(layer.promote()); - if (l != NULL) { - err = removeLayer(l); - ALOGE_IF(err<0 && err != NAME_NOT_FOUND, - "error removing layer=%p (%s)", l.get(), strerror(-err)); - } - return err; + return removeLayer(layer); } // --------------------------------------------------------------------------- |