Fix filtering for screenshotting custom displays. am: 5a6d857f33 am: f537ef6c8f

Change-Id: I1521d0fb62cd59948a94988197c0c8a0394fa35f
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index e73f245..d56a82f 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -795,6 +795,7 @@
 
     // Firstly, we need to convert the coordination from layer native coordination space to
     // device coordination space.
+    // TODO(143929254): Verify that this transformation is correct
     const auto transformMatrix = display.globalTransform * layer.geometry.positionTransform;
     const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
     const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
@@ -1015,8 +1016,8 @@
     setOutputDataSpace(display.outputDataspace);
     setDisplayMaxLuminance(display.maxLuminance);
 
-    mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
-    mState.projectionMatrix = projectionMatrix;
+    const mat4 projectionMatrix =
+            ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
     if (!display.clearRegion.isEmpty()) {
         glDisable(GL_BLEND);
         fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index c4a29a9..c0766ab 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -41,6 +41,13 @@
     Rect clip = Rect::INVALID_RECT;
 
     // Global transform to apply to all layers.
+    // The global transform is assumed to automatically apply when projecting
+    // the clip rectangle onto the physical display; however, this should be
+    // explicitly provided to perform CPU-side optimizations such as computing
+    // scissor rectangles for rounded corners which require transformation to
+    // the phsical display space.
+    //
+    // This transform is also assumed to include the orientation flag below.
     mat4 globalTransform = mat4();
 
     // Maximum luminance pulled from the display's HDR capabilities.
@@ -60,7 +67,10 @@
     // rendered layers.
     Region clearRegion = Region::INVALID_REGION;
 
-    // The orientation of the physical display.
+    // An additional orientation flag to be applied after clipping the output.
+    // By way of example, this may be used for supporting fullscreen screenshot
+    // capture of a device in landscape while the buffer is in portrait
+    // orientation.
     uint32_t orientation = ui::Transform::ROT_0;
 };
 
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index afcbc50..ce9131d 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -298,7 +298,7 @@
     void fillBufferPhysicalOffset();
 
     template <typename SourceVariant>
-    void fillBufferCheckers(mat4 transform);
+    void fillBufferCheckers(uint32_t rotation);
 
     template <typename SourceVariant>
     void fillBufferCheckersRotate0();
@@ -509,12 +509,12 @@
 }
 
 template <typename SourceVariant>
-void RenderEngineTest::fillBufferCheckers(mat4 transform) {
+void RenderEngineTest::fillBufferCheckers(uint32_t orientationFlag) {
     renderengine::DisplaySettings settings;
     settings.physicalDisplay = fullscreenRect();
     // Here logical space is 2x2
     settings.clip = Rect(2, 2);
-    settings.globalTransform = transform;
+    settings.orientation = orientationFlag;
 
     std::vector<const renderengine::LayerSettings*> layers;
 
@@ -545,7 +545,7 @@
 
 template <typename SourceVariant>
 void RenderEngineTest::fillBufferCheckersRotate0() {
-    fillBufferCheckers<SourceVariant>(mat4());
+    fillBufferCheckers<SourceVariant>(ui::Transform::ROT_0);
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0,
                       255);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -561,8 +561,7 @@
 
 template <typename SourceVariant>
 void RenderEngineTest::fillBufferCheckersRotate90() {
-    mat4 matrix = mat4(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1);
-    fillBufferCheckers<SourceVariant>(matrix);
+    fillBufferCheckers<SourceVariant>(ui::Transform::ROT_90);
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 255, 0,
                       255);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -578,8 +577,7 @@
 
 template <typename SourceVariant>
 void RenderEngineTest::fillBufferCheckersRotate180() {
-    mat4 matrix = mat4(-1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 2, 2, 0, 1);
-    fillBufferCheckers<SourceVariant>(matrix);
+    fillBufferCheckers<SourceVariant>(ui::Transform::ROT_180);
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 0,
                       0);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -595,8 +593,7 @@
 
 template <typename SourceVariant>
 void RenderEngineTest::fillBufferCheckersRotate270() {
-    mat4 matrix = mat4(0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 1);
-    fillBufferCheckers<SourceVariant>(matrix);
+    fillBufferCheckers<SourceVariant>(ui::Transform::ROT_270);
     expectBufferColor(Rect(0, 0, DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 0, 0, 255,
                       255);
     expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
@@ -928,7 +925,7 @@
     // Here logical space is 4x4
     settings.clip = Rect(4, 4);
     settings.globalTransform = mat4::scale(vec4(2, 4, 0, 1));
-    settings.clearRegion = Region(Rect(1, 1));
+    settings.clearRegion = Region(Rect(2, 4));
     std::vector<const renderengine::LayerSettings*> layers;
     // dummy layer, without bounds should not render anything
     renderengine::LayerSettings layer;
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a32bc2b..5f90566 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -618,6 +618,39 @@
             sourceCrop.getWidth() != displayFrame.getWidth();
 }
 
+bool BufferLayer::needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+                                               const ui::Transform& inverseParentTransform) const {
+    // If we are not capturing based on the state of a known display device,
+    // just return false.
+    if (displayDevice == nullptr) {
+        return false;
+    }
+
+    const auto outputLayer = findOutputLayerForDisplay(displayDevice);
+    if (outputLayer == nullptr) {
+        return false;
+    }
+
+    // We need filtering if the sourceCrop rectangle size does not match the
+    // viewport rectangle size (not a 1:1 render)
+    const auto& compositionState = outputLayer->getState();
+    const ui::Transform& displayTransform = displayDevice->getTransform();
+    const ui::Transform inverseTransform = inverseParentTransform * displayTransform.inverse();
+    // Undo the transformation of the displayFrame so that we're back into
+    // layer-stack space.
+    const Rect frame = inverseTransform.transform(compositionState.displayFrame);
+    const FloatRect sourceCrop = compositionState.sourceCrop;
+
+    int32_t frameHeight = frame.getHeight();
+    int32_t frameWidth = frame.getWidth();
+    // If the display transform had a rotational component then undo the
+    // rotation so that the orientation matches the source crop.
+    if (displayTransform.getOrientation() & ui::Transform::ROT_90) {
+        std::swap(frameHeight, frameWidth);
+    }
+    return sourceCrop.getHeight() != frameHeight || sourceCrop.getWidth() != frameWidth;
+}
+
 uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const {
     if (hasFrameUpdate()) {
         return getFrameNumber(expectedPresentTime);
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index fbec6ee..56bab1b 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -208,6 +208,8 @@
 private:
     // Returns true if this layer requires filtering
     bool needsFiltering(const sp<const DisplayDevice>& displayDevice) const override;
+    bool needsFilteringForScreenshots(const sp<const DisplayDevice>& displayDevice,
+                                      const ui::Transform& inverseParentTransform) const override;
 
     // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame
     // and its parent layer is not bounded
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b72214d..b81eb18 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -220,13 +220,11 @@
     const bool needsFiltering =
             (!globalTransform.preserveRects() || (type >= ui::Transform::SCALE));
 
-    Rect sourceClip = globalTransform.transform(viewport);
-    if (sourceClip.isEmpty()) {
-        sourceClip = displayBounds;
+    const Rect& sourceClip = viewport;
+    Rect destinationClip = globalTransform.transform(viewport);
+    if (destinationClip.isEmpty()) {
+        destinationClip = displayBounds;
     }
-    // For normal display use we always set the source and destination clip
-    // rectangles to the same values.
-    const Rect& destinationClip = sourceClip;
 
     uint32_t transformOrientation;
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 397fedc..e670d78 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -244,14 +244,12 @@
                       uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation,
                       bool allowSecureLayers = true)
           : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, reqDataSpace,
-                       display->getViewport(),
-                       applyInversePhysicalOrientation(rotation,
-                                                       display->getPhysicalOrientation())),
+                       display->getViewport(), applyDeviceOrientation(rotation, display)),
             mDisplay(std::move(display)),
             mSourceCrop(sourceCrop),
             mAllowSecureLayers(allowSecureLayers) {}
 
-    const ui::Transform& getTransform() const override { return mDisplay->getTransform(); }
+    const ui::Transform& getTransform() const override { return mTransform; }
     Rect getBounds() const override { return mDisplay->getBounds(); }
     int getHeight() const override { return mDisplay->getHeight(); }
     int getWidth() const override { return mDisplay->getWidth(); }
@@ -259,15 +257,9 @@
     sp<const DisplayDevice> getDisplayDevice() const override { return mDisplay; }
 
     bool needsFiltering() const override {
-        // check if the projection from the logical display to the physical
-        // display needs filtering
-        if (mDisplay->needsFiltering()) {
-            return true;
-        }
-
-        // check if the projection from the logical render area (i.e., the
-        // physical display) to the physical render area requires filtering
-        const Rect sourceCrop = getSourceCrop();
+        // check if the projection from the logical render area
+        // to the physical render area requires filtering
+        const Rect& sourceCrop = getSourceCrop();
         int width = sourceCrop.width();
         int height = sourceCrop.height();
         if (getRotationFlags() & ui::Transform::ROT_90) {
@@ -282,36 +274,44 @@
             return mDisplay->getSourceClip();
         }
 
-        // Recompute the device transformation for the source crop.
+        // If there is a source crop provided then it is assumed that the device
+        // was in portrait orientation. This may not logically be true, so
+        // correct for the orientation error by undoing the rotation
+
+        ui::Rotation logicalOrientation = mDisplay->getOrientation();
+        if (logicalOrientation == ui::Rotation::Rotation90) {
+            logicalOrientation = ui::Rotation::Rotation270;
+        } else if (logicalOrientation == ui::Rotation::Rotation270) {
+            logicalOrientation = ui::Rotation::Rotation90;
+        }
+
+        const auto flags = ui::Transform::toRotationFlags(logicalOrientation);
+        int width = mDisplay->getSourceClip().getWidth();
+        int height = mDisplay->getSourceClip().getHeight();
         ui::Transform rotation;
-        ui::Transform translatePhysical;
-        ui::Transform translateLogical;
-        ui::Transform scale;
-        const Rect& viewport = mDisplay->getViewport();
-        const Rect& sourceClip = mDisplay->getSourceClip();
-        const Rect& frame = mDisplay->getFrame();
-
-        const auto flags = ui::Transform::toRotationFlags(mDisplay->getPhysicalOrientation());
-        rotation.set(flags, getWidth(), getHeight());
-
-        translateLogical.set(-viewport.left, -viewport.top);
-        translatePhysical.set(sourceClip.left, sourceClip.top);
-        scale.set(frame.getWidth() / float(viewport.getWidth()), 0, 0,
-                  frame.getHeight() / float(viewport.getHeight()));
-        const ui::Transform finalTransform =
-                rotation * translatePhysical * scale * translateLogical;
-        return finalTransform.transform(mSourceCrop);
+        rotation.set(flags, width, height);
+        return rotation.transform(mSourceCrop);
     }
 
 private:
-    static RotationFlags applyInversePhysicalOrientation(RotationFlags orientation,
-                                                         ui::Rotation physicalOrientation) {
+    static RotationFlags applyDeviceOrientation(RotationFlags orientationFlag,
+                                                const sp<const DisplayDevice>& device) {
         uint32_t inverseRotate90 = 0;
         uint32_t inverseReflect = 0;
 
-        switch (physicalOrientation) {
+        // Reverse the logical orientation.
+        ui::Rotation logicalOrientation = device->getOrientation();
+        if (logicalOrientation == ui::Rotation::Rotation90) {
+            logicalOrientation = ui::Rotation::Rotation270;
+        } else if (logicalOrientation == ui::Rotation::Rotation270) {
+            logicalOrientation = ui::Rotation::Rotation90;
+        }
+
+        const ui::Rotation orientation = device->getPhysicalOrientation() + logicalOrientation;
+
+        switch (orientation) {
             case ui::ROTATION_0:
-                return orientation;
+                return orientationFlag;
 
             case ui::ROTATION_90:
                 inverseRotate90 = ui::Transform::ROT_90;
@@ -327,8 +327,8 @@
                 break;
         }
 
-        const uint32_t rotate90 = orientation & ui::Transform::ROT_90;
-        uint32_t reflect = orientation & ui::Transform::ROT_180;
+        const uint32_t rotate90 = orientationFlag & ui::Transform::ROT_90;
+        uint32_t reflect = orientationFlag & ui::Transform::ROT_180;
 
         // Apply reflection for double rotation.
         if (rotate90 & inverseRotate90) {
@@ -342,6 +342,7 @@
     const sp<const DisplayDevice> mDisplay;
     const Rect mSourceCrop;
     const bool mAllowSecureLayers;
+    const ui::Transform mTransform = ui::Transform();
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index be80f78..92ac015 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -535,6 +535,19 @@
     }
     virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
     virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
+    // True if this layer requires filtering
+    // This method is distinct from needsFiltering() in how the filter
+    // requirement is computed. needsFiltering() compares displayFrame and crop,
+    // where as this method transforms the displayFrame to layer-stack space
+    // first. This method should be used if there is no physical display to
+    // project onto when taking screenshots, as the filtering requirements are
+    // different.
+    // If the parent transform needs to be undone when capturing the layer, then
+    // the inverse parent transform is also required.
+    virtual bool needsFilteringForScreenshots(const sp<const DisplayDevice>&,
+                                              const ui::Transform&) const {
+        return false;
+    }
 
     // This layer is not a clone, but it's the parent to the cloned hierarchy. The
     // variable mClonedChild represents the top layer that will be cloned so this
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 9b3a9f4..6b0455a 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -61,10 +61,9 @@
     // render area.  It can be larger than the logical render area.  It can
     // also be optionally rotated.
     //
-    // Layers are first clipped to the source crop (in addition to being
-    // clipped to the logical render area already).  The source crop and the
-    // layers are then rotated around the center of the source crop, and
-    // scaled to the physical render area linearly.
+    // The source crop is specified in layer space (when rendering a layer and
+    // its children), or in layer-stack space (when rendering all layers visible
+    // on the display).
     virtual Rect getSourceCrop() const = 0;
 
     // Returns the rotation of the source crop and the layers.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e22bc61..aa0005d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5357,7 +5357,6 @@
 
     DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace,
                                  renderAreaRotation, captureSecureLayers);
-
     auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
                                     std::placeholders::_1);
     return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
@@ -5485,10 +5484,7 @@
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
         const ui::Transform& getTransform() const override { return mTransform; }
-        Rect getBounds() const override {
-            const Layer::State& layerState(mLayer->getDrawingState());
-            return mLayer->getBufferSize(layerState);
-        }
+        Rect getBounds() const override { return mLayer->getBufferSize(mLayer->getDrawingState()); }
         int getHeight() const override {
             return mLayer->getBufferSize(mLayer->getDrawingState()).getHeight();
         }
@@ -5531,9 +5527,8 @@
                 mTransform = mLayer->getTransform().inverse();
                 drawLayers();
             } else {
-                Rect bounds = getBounds();
-                uint32_t w = static_cast<uint32_t>(bounds.getWidth());
-                uint32_t h = static_cast<uint32_t>(bounds.getHeight());
+                uint32_t w = static_cast<uint32_t>(getWidth());
+                uint32_t h = static_cast<uint32_t>(getHeight());
                 // In the "childrenOnly" case we reparent the children to a screenshot
                 // layer which has no properties set and which does not draw.
                 sp<ContainerLayer> screenshotParentLayer =
@@ -5748,9 +5743,9 @@
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    const auto rotation = renderArea.getRotationFlags();
-    const auto transform = renderArea.getTransform();
     const auto sourceCrop = renderArea.getSourceCrop();
+    const auto transform = renderArea.getTransform();
+    const auto rotation = renderArea.getRotationFlags();
     const auto& displayViewport = renderArea.getDisplayViewport();
 
     renderengine::DisplaySettings clientCompositionDisplay;
@@ -5760,55 +5755,8 @@
     // buffer bounds.
     clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
     clientCompositionDisplay.clip = sourceCrop;
-    clientCompositionDisplay.globalTransform = transform.asMatrix4();
-
-    // Now take into account the rotation flag. We append a transform that
-    // rotates the layer stack about the origin, then translate by buffer
-    // boundaries to be in the right quadrant.
-    mat4 rotMatrix;
-    int displacementX = 0;
-    int displacementY = 0;
-    float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
-    switch (rotation) {
-        case ui::Transform::ROT_90:
-            rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
-            displacementX = renderArea.getBounds().getHeight();
-            break;
-        case ui::Transform::ROT_180:
-            rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
-            displacementY = renderArea.getBounds().getWidth();
-            displacementX = renderArea.getBounds().getHeight();
-            break;
-        case ui::Transform::ROT_270:
-            rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
-            displacementY = renderArea.getBounds().getWidth();
-            break;
-        default:
-            break;
-    }
-
-    // We need to transform the clipping window into the right spot.
-    // First, rotate the clipping rectangle by the rotation hint to get the
-    // right orientation
-    const vec4 clipTL = vec4(sourceCrop.left, sourceCrop.top, 0, 1);
-    const vec4 clipBR = vec4(sourceCrop.right, sourceCrop.bottom, 0, 1);
-    const vec4 rotClipTL = rotMatrix * clipTL;
-    const vec4 rotClipBR = rotMatrix * clipBR;
-    const int newClipLeft = std::min(rotClipTL[0], rotClipBR[0]);
-    const int newClipTop = std::min(rotClipTL[1], rotClipBR[1]);
-    const int newClipRight = std::max(rotClipTL[0], rotClipBR[0]);
-    const int newClipBottom = std::max(rotClipTL[1], rotClipBR[1]);
-
-    // Now reposition the clipping rectangle with the displacement vector
-    // computed above.
-    const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
-    clientCompositionDisplay.clip =
-            Rect(newClipLeft + displacementX, newClipTop + displacementY,
-                 newClipRight + displacementX, newClipBottom + displacementY);
-
-    mat4 clipTransform = displacementMat * rotMatrix;
-    clientCompositionDisplay.globalTransform =
-            clipTransform * clientCompositionDisplay.globalTransform;
+    clientCompositionDisplay.globalTransform = mat4();
+    clientCompositionDisplay.orientation = rotation;
 
     clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
     clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
@@ -5818,7 +5766,8 @@
     compositionengine::LayerFE::LayerSettings fillLayer;
     fillLayer.source.buffer.buffer = nullptr;
     fillLayer.source.solidColor = half3(0.0, 0.0, 0.0);
-    fillLayer.geometry.boundaries = FloatRect(0.0, 0.0, 1.0, 1.0);
+    fillLayer.geometry.boundaries =
+            FloatRect(sourceCrop.left, sourceCrop.top, sourceCrop.right, sourceCrop.bottom);
     fillLayer.alpha = half(alpha);
     clientCompositionLayers.push_back(fillLayer);
 
@@ -5830,7 +5779,8 @@
         compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
                 clip,
                 useIdentityTransform,
-                layer->needsFiltering(renderArea.getDisplayDevice()) || renderArea.needsFiltering(),
+                layer->needsFilteringForScreenshots(renderArea.getDisplayDevice(), transform) ||
+                        renderArea.needsFiltering(),
                 renderArea.isSecure(),
                 supportProtectedContent,
                 clearRegion,
@@ -5842,6 +5792,10 @@
         std::vector<compositionengine::LayerFE::LayerSettings> results =
                 layer->prepareClientCompositionList(targetSettings);
         if (results.size() > 0) {
+            for (auto& settings : results) {
+                settings.geometry.positionTransform =
+                        transform.asMatrix4() * settings.geometry.positionTransform;
+            }
             clientCompositionLayers.insert(clientCompositionLayers.end(),
                                            std::make_move_iterator(results.begin()),
                                            std::make_move_iterator(results.end()));
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
index f8a5b40..06e8761 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -104,7 +104,7 @@
     // Verify color layer renders correctly on virtual display.
     ScreenCapture::captureScreen(&sc, mVirtualDisplay);
     sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor);
-    sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0});
+    sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 255});
 }
 
 TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) {
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 24eeac7..ea3d744 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -1504,7 +1504,7 @@
                                 mHardwareDisplaySize.height),
                   compositionState.transform);
         EXPECT_EQ(TRANSFORM_FLAGS_ROT_90, compositionState.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
+        EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
         EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
         // For 90, the frame and viewport have the hardware display size width and height swapped
         EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);
@@ -1531,7 +1531,7 @@
                                 mHardwareDisplaySize.height),
                   compositionState.transform);
         EXPECT_EQ(TRANSFORM_FLAGS_ROT_270, compositionState.orientation);
-        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.sourceClip);
+        EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.sourceClip);
         EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.destinationClip);
         // For 270, the frame and viewport have the hardware display size width and height swapped
         EXPECT_EQ(Rect(SwapWH(mHardwareDisplaySize)), compositionState.frame);