Create processDisplayChangesLocked
This simply extracts the code in handleTransactionLocked for the
eDisplayTransactionNeeded case into its own function.
There were no changes other than a quick clang-format of the extracted function.
Bug: 38464421
Test: Builds
Change-Id: Id84f5b990fb6818db1f8b0c37ac02bf3caa26002
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e967265..a180606 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2112,6 +2112,149 @@
// here the transaction has been committed
}
+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 (!draw[i].isMainDisplay()) {
+ // Call makeCurrent() on the primary display so we can
+ // be sure that nothing associated with this display
+ // is current.
+ const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
+ defaultDisplay->makeCurrent();
+ sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
+ if (hw != nullptr) hw->disconnect(getHwComposer());
+ if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
+ mEventThread->onHotplugReceived(draw[i].type, false);
+ mDisplays.removeItem(draw.keyAt(i));
+ } else {
+ ALOGW("trying to remove the main display");
+ }
+ } else {
+ // this display is in both lists. see if something changed.
+ const DisplayDeviceState& state(curr[j]);
+ const wp<IBinder>& display(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.
+ sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
+ if (hw != nullptr) hw->disconnect(getHwComposer());
+ mDisplays.removeItem(display);
+ mDrawingState.displays.removeItemsAt(i);
+ dc--;
+ // at this point we must loop to the next item
+ continue;
+ }
+
+ const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
+ if (disp != nullptr) {
+ if (state.layerStack != draw[i].layerStack) {
+ disp->setLayerStack(state.layerStack);
+ }
+ if ((state.orientation != draw[i].orientation) ||
+ (state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) {
+ disp->setProjection(state.orientation, state.viewport, state.frame);
+ }
+ if (state.width != draw[i].width || state.height != draw[i].height) {
+ disp->setDisplaySize(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]);
+
+ sp<DisplaySurface> dispSurface;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferProducer> bqProducer;
+ sp<IGraphicBufferConsumer> bqConsumer;
+ BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
+
+ int32_t hwcId = -1;
+ if (state.isVirtualDisplay()) {
+ // Virtual displays without a surface are dormant:
+ // they have external state (layer stack, projection,
+ // etc.) but no internal state (i.e. a DisplayDevice).
+ if (state.surface != nullptr) {
+ // Allow VR composer to use virtual displays.
+ if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) {
+ int width = 0;
+ int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+ ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
+ int height = 0;
+ status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
+ int intFormat = 0;
+ status = state.surface->query(NATIVE_WINDOW_FORMAT, &intFormat);
+ ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
+ auto format = static_cast<android_pixel_format_t>(intFormat);
+
+ getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId);
+ }
+
+ // TODO: Plumb requested format back up to consumer
+
+ sp<VirtualDisplaySurface> vds =
+ new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface,
+ bqProducer, bqConsumer,
+ state.displayName);
+
+ dispSurface = vds;
+ producer = vds;
+ }
+ } else {
+ ALOGE_IF(state.surface != nullptr,
+ "adding a supported display, but rendering "
+ "surface is provided (%p), ignoring it",
+ state.surface.get());
+
+ hwcId = state.type;
+ dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
+ producer = bqProducer;
+ }
+
+ const wp<IBinder>& display(curr.keyAt(i));
+ if (dispSurface != nullptr) {
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
+ dispSurface, producer, hasWideColorDisplay);
+ hw->setLayerStack(state.layerStack);
+ hw->setProjection(state.orientation, state.viewport, state.frame);
+ hw->setDisplayName(state.displayName);
+ mDisplays.add(display, hw);
+ if (!state.isVirtualDisplay()) {
+ mEventThread->onHotplugReceived(state.type, true);
+ }
+ }
+ }
+ }
+ }
+}
+
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
// Notify all layers of available frames
@@ -2140,161 +2283,7 @@
*/
if (transactionFlags & eDisplayTransactionNeeded) {
- // 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 (!draw[i].isMainDisplay()) {
- // Call makeCurrent() on the primary display so we can
- // be sure that nothing associated with this display
- // is current.
- const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
- defaultDisplay->makeCurrent();
- sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
- if (hw != nullptr)
- hw->disconnect(getHwComposer());
- if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
- mEventThread->onHotplugReceived(draw[i].type, false);
- mDisplays.removeItem(draw.keyAt(i));
- } else {
- ALOGW("trying to remove the main display");
- }
- } else {
- // this display is in both lists. see if something changed.
- const DisplayDeviceState& state(curr[j]);
- const wp<IBinder>& display(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.
- sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
- if (hw != nullptr)
- hw->disconnect(getHwComposer());
- mDisplays.removeItem(display);
- mDrawingState.displays.removeItemsAt(i);
- dc--;
- // at this point we must loop to the next item
- continue;
- }
-
- const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
- if (disp != nullptr) {
- if (state.layerStack != draw[i].layerStack) {
- disp->setLayerStack(state.layerStack);
- }
- if ((state.orientation != draw[i].orientation)
- || (state.viewport != draw[i].viewport)
- || (state.frame != draw[i].frame))
- {
- disp->setProjection(state.orientation,
- state.viewport, state.frame);
- }
- if (state.width != draw[i].width || state.height != draw[i].height) {
- disp->setDisplaySize(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]);
-
- sp<DisplaySurface> dispSurface;
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferProducer> bqProducer;
- sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
-
- int32_t hwcId = -1;
- if (state.isVirtualDisplay()) {
- // Virtual displays without a surface are dormant:
- // they have external state (layer stack, projection,
- // etc.) but no internal state (i.e. a DisplayDevice).
- if (state.surface != nullptr) {
-
- // Allow VR composer to use virtual displays.
- if (mUseHwcVirtualDisplays || getBE().mHwc->isUsingVrComposer()) {
- int width = 0;
- int status = state.surface->query(
- NATIVE_WINDOW_WIDTH, &width);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query width (%d)", status);
- int height = 0;
- status = state.surface->query(
- NATIVE_WINDOW_HEIGHT, &height);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query height (%d)", status);
- int intFormat = 0;
- status = state.surface->query(
- NATIVE_WINDOW_FORMAT, &intFormat);
- ALOGE_IF(status != NO_ERROR,
- "Unable to query format (%d)", status);
- auto format = static_cast<android_pixel_format_t>(
- intFormat);
-
- getBE().mHwc->allocateVirtualDisplay(width, height, &format,
- &hwcId);
- }
-
- // TODO: Plumb requested format back up to consumer
-
- sp<VirtualDisplaySurface> vds =
- new VirtualDisplaySurface(*getBE().mHwc,
- hwcId, state.surface, bqProducer,
- bqConsumer, state.displayName);
-
- dispSurface = vds;
- producer = vds;
- }
- } else {
- ALOGE_IF(state.surface != nullptr,
- "adding a supported display, but rendering "
- "surface is provided (%p), ignoring it",
- state.surface.get());
-
- hwcId = state.type;
- dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
- producer = bqProducer;
- }
-
- const wp<IBinder>& display(curr.keyAt(i));
- if (dispSurface != nullptr) {
- sp<DisplayDevice> hw =
- new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
- dispSurface, producer, hasWideColorDisplay);
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation,
- state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
- mDisplays.add(display, hw);
- if (!state.isVirtualDisplay()) {
- mEventThread->onHotplugReceived(state.type, true);
- }
- }
- }
- }
- }
+ processDisplayChangesLocked();
}
if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {