Loading services/surfaceflinger/SurfaceFlinger.cpp +148 −141 Original line number Diff line number Diff line Loading @@ -2383,13 +2383,14 @@ void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bo sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer) { auto displayId = compositionDisplay->getDisplayId(); DisplayDeviceCreationArgs creationArgs(this, displayToken, compositionDisplay); creationArgs.sequenceId = state.sequenceId; creationArgs.isSecure = state.isSecure; creationArgs.displaySurface = dispSurface; creationArgs.displaySurface = displaySurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; Loading Loading @@ -2465,90 +2466,14 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( return display; } void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical const KeyedVector<wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; const size_t cc = curr.size(); size_t dc = draw.size(); // find the displays that were removed // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i = 0; i < dc;) { const ssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { // in drawing state but not in current state if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { // Save display ID before disconnecting. const auto displayId = display->getId(); display->disconnect(); if (!display->isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, false); } } mDisplays.erase(draw.keyAt(i)); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); const wp<IBinder>& displayToken = curr.keyAt(j); const sp<IBinder> state_binder = IInterface::asBinder(state.surface); const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface); if (state_binder != draw_binder) { // changing the surface is like destroying and // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. if (const auto display = getDisplayDeviceLocked(displayToken)) { display->disconnect(); } mDisplays.erase(displayToken); mDrawingState.displays.removeItemsAt(i); dc--; // at this point we must loop to the next item continue; } if (const auto display = getDisplayDeviceLocked(displayToken)) { if (state.layerStack != draw[i].layerStack) { display->setLayerStack(state.layerStack); } if ((state.orientation != draw[i].orientation) || (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) { display->setProjection(state.orientation, state.viewport, state.frame); } if (state.width != draw[i].width || state.height != draw[i].height) { display->setDisplaySize(state.width, state.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height); } } } } ++i; } // find displays that were added // (ie: in current state but not in drawing state) for (size_t i = 0; i < cc; i++) { if (draw.indexOfKey(curr.keyAt(i)) < 0) { const DisplayDeviceState& state(curr[i]); void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state) { int width = 0; int height = 0; ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN); if (state.physical) { const auto& activeConfig = getCompositionEngine().getHwComposer().getActiveConfig( state.physical->id); getCompositionEngine().getHwComposer().getActiveConfig(state.physical->id); width = activeConfig->getWidth(); height = activeConfig->getHeight(); pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888); Loading @@ -2565,7 +2490,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). continue; return; } compositionengine::DisplayCreationArgsBuilder builder; Loading @@ -2577,25 +2502,24 @@ void SurfaceFlinger::processDisplayChangesLocked() { builder.setIsSecure(state.isSecure); builder.setLayerStackId(state.layerStack); builder.setPowerAdvisor(&mPowerAdvisor); builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()); builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); sp<compositionengine::DisplaySurface> dispSurface; sp<compositionengine::DisplaySurface> displaySurface; sp<IGraphicBufferProducer> producer; sp<IGraphicBufferProducer> bqProducer; sp<IGraphicBufferConsumer> bqConsumer; getFactory().createBufferQueue(&bqProducer, &bqConsumer, false); getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false); std::optional<DisplayId> displayId = compositionDisplay->getId(); if (state.isVirtual()) { sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); dispSurface = vds; displaySurface = vds; producer = vds; } else { ALOGE_IF(state.surface != nullptr, Loading @@ -2604,17 +2528,15 @@ void SurfaceFlinger::processDisplayChangesLocked() { state.surface.get()); LOG_ALWAYS_FATAL_IF(!displayId); dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer, displaySurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer, maxGraphicsWidth, maxGraphicsHeight); producer = bqProducer; } const wp<IBinder>& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { if (displaySurface != nullptr) { mDisplays.emplace(displayToken, setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, dispSurface, producer)); setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, displaySurface, producer)); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, true); Loading @@ -2627,6 +2549,91 @@ void SurfaceFlinger::processDisplayChangesLocked() { } } } void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (const auto display = getDisplayDeviceLocked(displayToken)) { // Save display ID before disconnecting. const auto displayId = display->getId(); display->disconnect(); if (!display->isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, false); } } mDisplays.erase(displayToken); } void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState) { const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface); const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface); if (currentBinder != drawingBinder) { // changing the surface is like destroying and recreating the DisplayDevice if (const auto display = getDisplayDeviceLocked(displayToken)) { display->disconnect(); } mDisplays.erase(displayToken); processDisplayAdded(displayToken, currentState); return; } if (const auto display = getDisplayDeviceLocked(displayToken)) { if (currentState.layerStack != drawingState.layerStack) { display->setLayerStack(currentState.layerStack); } if ((currentState.orientation != drawingState.orientation) || (currentState.viewport != drawingState.viewport) || (currentState.frame != drawingState.frame)) { display->setProjection(currentState.orientation, currentState.viewport, currentState.frame); } if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } } } } void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical const KeyedVector<wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; // find the displays that were removed // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i = 0; i < draw.size(); i++) { const wp<IBinder>& displayToken = draw.keyAt(i); const ssize_t j = curr.indexOfKey(displayToken); if (j < 0) { // in drawing state but not in current state processDisplayRemoved(displayToken); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& currentState = curr[j]; const DisplayDeviceState& drawingState = draw[i]; processDisplayChanged(displayToken, currentState, drawingState); } } // find displays that were added // (ie: in current state but not in drawing state) for (size_t i = 0; i < curr.size(); i++) { const wp<IBinder>& displayToken = curr.keyAt(i); if (draw.indexOfKey(displayToken) < 0) { processDisplayAdded(displayToken, curr[i]); } } } Loading services/surfaceflinger/SurfaceFlinger.h +6 −1 Original line number Diff line number Diff line Loading @@ -820,9 +820,14 @@ private: const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer); void processDisplayChangesLocked(); void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp<IBinder>& displayToken); void processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState); void processDisplayHotplugEventsLocked(); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); Loading Loading
services/surfaceflinger/SurfaceFlinger.cpp +148 −141 Original line number Diff line number Diff line Loading @@ -2383,13 +2383,14 @@ void SurfaceFlinger::dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bo sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer) { auto displayId = compositionDisplay->getDisplayId(); DisplayDeviceCreationArgs creationArgs(this, displayToken, compositionDisplay); creationArgs.sequenceId = state.sequenceId; creationArgs.isSecure = state.isSecure; creationArgs.displaySurface = dispSurface; creationArgs.displaySurface = displaySurface; creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; Loading Loading @@ -2465,90 +2466,14 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( return display; } void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical const KeyedVector<wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; const size_t cc = curr.size(); size_t dc = draw.size(); // find the displays that were removed // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i = 0; i < dc;) { const ssize_t j = curr.indexOfKey(draw.keyAt(i)); if (j < 0) { // in drawing state but not in current state if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) { // Save display ID before disconnecting. const auto displayId = display->getId(); display->disconnect(); if (!display->isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, false); } } mDisplays.erase(draw.keyAt(i)); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& state(curr[j]); const wp<IBinder>& displayToken = curr.keyAt(j); const sp<IBinder> state_binder = IInterface::asBinder(state.surface); const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface); if (state_binder != draw_binder) { // changing the surface is like destroying and // recreating the DisplayDevice, so we just remove it // from the drawing state, so that it get re-added // below. if (const auto display = getDisplayDeviceLocked(displayToken)) { display->disconnect(); } mDisplays.erase(displayToken); mDrawingState.displays.removeItemsAt(i); dc--; // at this point we must loop to the next item continue; } if (const auto display = getDisplayDeviceLocked(displayToken)) { if (state.layerStack != draw[i].layerStack) { display->setLayerStack(state.layerStack); } if ((state.orientation != draw[i].orientation) || (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) { display->setProjection(state.orientation, state.viewport, state.frame); } if (state.width != draw[i].width || state.height != draw[i].height) { display->setDisplaySize(state.width, state.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height); } } } } ++i; } // find displays that were added // (ie: in current state but not in drawing state) for (size_t i = 0; i < cc; i++) { if (draw.indexOfKey(curr.keyAt(i)) < 0) { const DisplayDeviceState& state(curr[i]); void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state) { int width = 0; int height = 0; ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN); if (state.physical) { const auto& activeConfig = getCompositionEngine().getHwComposer().getActiveConfig( state.physical->id); getCompositionEngine().getHwComposer().getActiveConfig(state.physical->id); width = activeConfig->getWidth(); height = activeConfig->getHeight(); pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888); Loading @@ -2565,7 +2490,7 @@ void SurfaceFlinger::processDisplayChangesLocked() { // Virtual displays without a surface are dormant: // they have external state (layer stack, projection, // etc.) but no internal state (i.e. a DisplayDevice). continue; return; } compositionengine::DisplayCreationArgsBuilder builder; Loading @@ -2577,25 +2502,24 @@ void SurfaceFlinger::processDisplayChangesLocked() { builder.setIsSecure(state.isSecure); builder.setLayerStackId(state.layerStack); builder.setPowerAdvisor(&mPowerAdvisor); builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()); builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()); builder.setName(state.displayName); auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build()); sp<compositionengine::DisplaySurface> dispSurface; sp<compositionengine::DisplaySurface> displaySurface; sp<IGraphicBufferProducer> producer; sp<IGraphicBufferProducer> bqProducer; sp<IGraphicBufferConsumer> bqConsumer; getFactory().createBufferQueue(&bqProducer, &bqConsumer, false); getFactory().createBufferQueue(&bqProducer, &bqConsumer, /*consumerIsSurfaceFlinger =*/false); std::optional<DisplayId> displayId = compositionDisplay->getId(); if (state.isVirtual()) { sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer, bqConsumer, state.displayName); dispSurface = vds; displaySurface = vds; producer = vds; } else { ALOGE_IF(state.surface != nullptr, Loading @@ -2604,17 +2528,15 @@ void SurfaceFlinger::processDisplayChangesLocked() { state.surface.get()); LOG_ALWAYS_FATAL_IF(!displayId); dispSurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer, displaySurface = new FramebufferSurface(getHwComposer(), *displayId, bqConsumer, maxGraphicsWidth, maxGraphicsHeight); producer = bqProducer; } const wp<IBinder>& displayToken = curr.keyAt(i); if (dispSurface != nullptr) { if (displaySurface != nullptr) { mDisplays.emplace(displayToken, setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, dispSurface, producer)); setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state, displaySurface, producer)); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, true); Loading @@ -2627,6 +2549,91 @@ void SurfaceFlinger::processDisplayChangesLocked() { } } } void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) { if (const auto display = getDisplayDeviceLocked(displayToken)) { // Save display ID before disconnecting. const auto displayId = display->getId(); display->disconnect(); if (!display->isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, false); } } mDisplays.erase(displayToken); } void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState) { const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface); const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface); if (currentBinder != drawingBinder) { // changing the surface is like destroying and recreating the DisplayDevice if (const auto display = getDisplayDeviceLocked(displayToken)) { display->disconnect(); } mDisplays.erase(displayToken); processDisplayAdded(displayToken, currentState); return; } if (const auto display = getDisplayDeviceLocked(displayToken)) { if (currentState.layerStack != drawingState.layerStack) { display->setLayerStack(currentState.layerStack); } if ((currentState.orientation != drawingState.orientation) || (currentState.viewport != drawingState.viewport) || (currentState.frame != drawingState.frame)) { display->setProjection(currentState.orientation, currentState.viewport, currentState.frame); } if (currentState.width != drawingState.width || currentState.height != drawingState.height) { display->setDisplaySize(currentState.width, currentState.height); if (display->isPrimary()) { mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height); } } } } void SurfaceFlinger::processDisplayChangesLocked() { // here we take advantage of Vector's copy-on-write semantics to // improve performance by skipping the transaction entirely when // know that the lists are identical const KeyedVector<wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays); const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays); if (!curr.isIdenticalTo(draw)) { mVisibleRegionsDirty = true; // find the displays that were removed // (ie: in drawing state but not in current state) // also handle displays that changed // (ie: displays that are in both lists) for (size_t i = 0; i < draw.size(); i++) { const wp<IBinder>& displayToken = draw.keyAt(i); const ssize_t j = curr.indexOfKey(displayToken); if (j < 0) { // in drawing state but not in current state processDisplayRemoved(displayToken); } else { // this display is in both lists. see if something changed. const DisplayDeviceState& currentState = curr[j]; const DisplayDeviceState& drawingState = draw[i]; processDisplayChanged(displayToken, currentState, drawingState); } } // find displays that were added // (ie: in current state but not in drawing state) for (size_t i = 0; i < curr.size(); i++) { const wp<IBinder>& displayToken = curr.keyAt(i); if (draw.indexOfKey(displayToken) < 0) { processDisplayAdded(displayToken, curr[i]); } } } Loading
services/surfaceflinger/SurfaceFlinger.h +6 −1 Original line number Diff line number Diff line Loading @@ -820,9 +820,14 @@ private: const wp<IBinder>& displayToken, std::shared_ptr<compositionengine::Display> compositionDisplay, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, const sp<compositionengine::DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer); void processDisplayChangesLocked(); void processDisplayAdded(const wp<IBinder>& displayToken, const DisplayDeviceState& state); void processDisplayRemoved(const wp<IBinder>& displayToken); void processDisplayChanged(const wp<IBinder>& displayToken, const DisplayDeviceState& currentState, const DisplayDeviceState& drawingState); void processDisplayHotplugEventsLocked(); void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected); Loading