Merge changes from topic "RenderArea"
am: 3b14b7db6f

Change-Id: I6eea9c398eae9b8f67e20eb115e644bb0f7dd481
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 99a3a75..5f79804 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -174,8 +174,25 @@
     virtual status_t setActiveColorMode(const sp<IBinder>& display,
             ui::ColorMode colorMode) = 0;
 
-    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
-     * This function will fail if there is a secure window on screen.
+    /**
+     * Capture the specified screen. This requires READ_FRAME_BUFFER
+     * permission.  This function will fail if there is a secure window on
+     * screen.
+     *
+     * This function can capture a subregion (the source crop) of the screen.
+     * The subregion can be optionally rotated.  It will also be scaled to
+     * match the size of the output buffer.
+     *
+     * At the moment, sourceCrop is ignored and is always set to the visible
+     * region (projected display viewport) of the screen.
+     *
+     * reqWidth and reqHeight specifies the size of the buffer.  When either
+     * of them is 0, they are set to the size of the logical display viewport.
+     *
+     * When useIdentityTransform is true, layer transformations are disabled.
+     *
+     * rotation specifies the rotation of the source crop (and the pixels in
+     * it) around its center.
      */
     virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
                                    Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 788962e..38de701 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -152,10 +152,24 @@
     sp<IBinder> token;
     sp<IGraphicBufferProducer> surface;
     uint32_t layerStack;
+
+    // These states define how layers are projected onto the physical display.
+    //
+    // Layers are first clipped to `viewport'.  They are then translated and
+    // scaled from `viewport' to `frame'.  Finally, they are rotated according
+    // to `orientation', `width', and `height'.
+    //
+    // For example, assume viewport is Rect(0, 0, 200, 100), frame is Rect(20,
+    // 10, 420, 210), and the size of the display is WxH.  When orientation is
+    // 0, layers will be scaled by a factor of 2 and translated by (20, 10).
+    // When orientation is 1, layers will be additionally rotated by 90
+    // degrees around the origin clockwise and translated by (W, 0).
     uint32_t orientation;
     Rect viewport;
     Rect frame;
+
     uint32_t width, height;
+
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
 };
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index f5b5eda..707cb42 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -204,7 +204,7 @@
 
     if (!blackOutLayer) {
         // TODO: we could be more subtle with isFixedSize()
-        const bool useFiltering = getFiltering() || needsFiltering(renderArea) || isFixedSize();
+        const bool useFiltering = needsFiltering(renderArea) || isFixedSize();
 
         // Query the texture matrix given our current filtering mode.
         float textureMatrix[16];
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 309fd0a..65c3839 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -224,6 +224,7 @@
         std::unique_ptr<RE::Surface> renderSurface,
         int displayWidth,
         int displayHeight,
+        int displayInstallOrientation,
         bool hasWideColorGamut,
         const HdrCapabilities& hdrCapabilities,
         const int32_t supportedPerFrameMetadata,
@@ -239,6 +240,7 @@
       mSurface{std::move(renderSurface)},
       mDisplayWidth(displayWidth),
       mDisplayHeight(displayHeight),
+      mDisplayInstallOrientation(displayInstallOrientation),
       mPageFlipCount(0),
       mIsSecure(isSecure),
       mLayerStack(NO_LAYER_STACK),
@@ -610,9 +612,8 @@
     // need to take care of primary display rotation for mGlobalTransform
     // for case if the panel is not installed aligned with device orientation
     if (mType == DisplayType::DISPLAY_PRIMARY) {
-        int primaryDisplayOrientation = mFlinger->getPrimaryDisplayOrientation();
         DisplayDevice::orientationToTransfrom(
-                (orientation + primaryDisplayOrientation) % (DisplayState::eOrientation270 + 1),
+                (orientation + mDisplayInstallOrientation) % (DisplayState::eOrientation270 + 1),
                 w, h, &R);
     }
 
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6c3bd91..3cf06bc 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -25,7 +25,7 @@
 #include <math/mat4.h>
 
 #include <binder/IBinder.h>
-#include <gui/ISurfaceComposer.h>
+#include <gui/LayerState.h>
 #include <hardware/hwcomposer_defs.h>
 #include <ui/GraphicTypes.h>
 #include <ui/HdrCapabilities.h>
@@ -88,6 +88,7 @@
             std::unique_ptr<RE::Surface> renderSurface,
             int displayWidth,
             int displayHeight,
+            int displayInstallOrientation,
             bool hasWideColorGamut,
             const HdrCapabilities& hdrCapabilities,
             const int32_t supportedPerFrameMetadata,
@@ -111,6 +112,7 @@
 
     int         getWidth() const;
     int         getHeight() const;
+    int         getInstallOrientation() const { return mDisplayInstallOrientation; }
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
@@ -234,6 +236,7 @@
     std::unique_ptr<RE::Surface> mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
+    const int       mDisplayInstallOrientation;
     mutable uint32_t mPageFlipCount;
     String8         mDisplayName;
     bool            mIsSecure;
@@ -337,23 +340,108 @@
 class DisplayRenderArea : public RenderArea {
 public:
     DisplayRenderArea(const sp<const DisplayDevice> device,
-                      ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(),
+                      Transform::orientation_flags rotation = Transform::ROT_0)
+          : DisplayRenderArea(device, device->getBounds(), device->getWidth(), device->getHeight(),
                               rotation) {}
-    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqHeight,
-                      uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
-          : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device),
-                              mSourceCrop(sourceCrop) {}
+    DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqWidth,
+                      uint32_t reqHeight, Transform::orientation_flags rotation)
+          : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE,
+                       getDisplayRotation(rotation, device->getInstallOrientation())),
+            mDevice(device),
+            mSourceCrop(sourceCrop) {}
 
     const Transform& getTransform() const override { return mDevice->getTransform(); }
     Rect getBounds() const override { return mDevice->getBounds(); }
     int getHeight() const override { return mDevice->getHeight(); }
     int getWidth() const override { return mDevice->getWidth(); }
     bool isSecure() const override { return mDevice->isSecure(); }
-    bool needsFiltering() const override { return mDevice->needsFiltering(); }
-    Rect getSourceCrop() const override { return mSourceCrop; }
+
+    bool needsFiltering() const override {
+        // check if the projection from the logical display to the physical
+        // display needs filtering
+        if (mDevice->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();
+        int width = sourceCrop.width();
+        int height = sourceCrop.height();
+        if (getRotationFlags() & Transform::ROT_90) {
+            std::swap(width, height);
+        }
+        return width != getReqWidth() || height != getReqHeight();
+    }
+
+    Rect getSourceCrop() const override {
+        // use the (projected) logical display viewport by default
+        if (mSourceCrop.isEmpty()) {
+            return mDevice->getScissor();
+        }
+
+        const int orientation = mDevice->getInstallOrientation();
+        if (orientation == DisplayState::eOrientationDefault) {
+            return mSourceCrop;
+        }
+
+        // Install orientation is transparent to the callers.  Apply it now.
+        uint32_t flags = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                flags = Transform::ROT_90;
+                break;
+            case DisplayState::eOrientation180:
+                flags = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                flags = Transform::ROT_270;
+                break;
+        }
+        Transform tr;
+        tr.set(flags, getWidth(), getHeight());
+        return tr.transform(mSourceCrop);
+    }
 
 private:
+    // Install orientation is transparent to the callers.  We need to cancel
+    // it out by modifying rotation flags.
+    static Transform::orientation_flags getDisplayRotation(
+            Transform::orientation_flags rotation, int orientation) {
+        if (orientation == DisplayState::eOrientationDefault) {
+            return rotation;
+        }
+
+        // convert hw orientation into flag presentation
+        // here inverse transform needed
+        uint8_t hw_rot_90 = 0x00;
+        uint8_t hw_flip_hv = 0x00;
+        switch (orientation) {
+            case DisplayState::eOrientation90:
+                hw_rot_90 = Transform::ROT_90;
+                hw_flip_hv = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation180:
+                hw_flip_hv = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                hw_rot_90 = Transform::ROT_90;
+                break;
+        }
+
+        // transform flags operation
+        // 1) flip H V if both have ROT_90 flag
+        // 2) XOR these flags
+        uint8_t rotation_rot_90 = rotation & Transform::ROT_90;
+        uint8_t rotation_flip_hv = rotation & Transform::ROT_180;
+        if (rotation_rot_90 & hw_rot_90) {
+            rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180;
+        }
+
+        return static_cast<Transform::orientation_flags>(
+                (rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
+    }
+
     const sp<const DisplayDevice> mDevice;
     const Rect mSourceCrop;
 };
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 0caac9b..72f1fc4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -88,7 +88,6 @@
         mCurrentOpacity(true),
         mCurrentFrameNumber(0),
         mFrameLatencyNeeded(false),
-        mFiltering(false),
         mNeedsFiltering(false),
         mProtectedByApp(false),
         mClientRef(client),
@@ -793,14 +792,6 @@
     return true;
 }
 
-void Layer::setFiltering(bool filtering) {
-    mFiltering = filtering;
-}
-
-bool Layer::getFiltering() const {
-    return mFiltering;
-}
-
 // ----------------------------------------------------------------------------
 // local state
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 301f190..239f397 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -530,9 +530,6 @@
     // -----------------------------------------------------------------------
 
     void clearWithOpenGL(const RenderArea& renderArea) const;
-    void setFiltering(bool filtering);
-    bool getFiltering() const;
-
 
     inline const State& getDrawingState() const { return mDrawingState; }
     inline const State& getCurrentState() const { return mCurrentState; }
@@ -755,8 +752,6 @@
     bool mCurrentOpacity;
     std::atomic<uint64_t> mCurrentFrameNumber;
     bool mFrameLatencyNeeded;
-    // Whether filtering is forced on or not
-    bool mFiltering;
     // Whether filtering is needed b/c of the drawingstate
     bool mNeedsFiltering;
 
diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp
index 1a8edf3..93759e8 100644
--- a/services/surfaceflinger/RenderArea.cpp
+++ b/services/surfaceflinger/RenderArea.cpp
@@ -1,7 +1,5 @@
 #include "RenderArea.h"
 
-#include <gui/LayerState.h>
-
 namespace android {
 
 float RenderArea::getCaptureFillValue(CaptureFill captureFill) {
@@ -13,37 +11,5 @@
             return 1.0f;
     }
 }
-/*
- * Checks that the requested width and height are valid and updates them to the render area
- * dimensions if they are set to 0
- */
-status_t RenderArea::updateDimensions(int displayRotation) {
-    // get screen geometry
-
-    uint32_t width = getWidth();
-    uint32_t height = getHeight();
-
-    if (mRotationFlags & Transform::ROT_90) {
-        std::swap(width, height);
-    }
-
-    if (displayRotation & DisplayState::eOrientationSwapMask) {
-        std::swap(width, height);
-    }
-
-    if ((mReqWidth > width) || (mReqHeight > height)) {
-        ALOGE("size mismatch (%d, %d) > (%d, %d)", mReqWidth, mReqHeight, width, height);
-        return BAD_VALUE;
-    }
-
-    if (mReqWidth == 0) {
-        mReqWidth = width;
-    }
-    if (mReqHeight == 0) {
-        mReqHeight = height;
-    }
-
-    return NO_ERROR;
-}
 
 } // namespace android
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 96e4b5f..d980bd5 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -1,50 +1,80 @@
 #pragma once
 
-#include <ui/GraphicTypes.h>
-
 #include "Transform.h"
 
 #include <functional>
 
 namespace android {
 
+// RenderArea describes a rectangular area that layers can be rendered to.
+//
+// There is a logical render area and a physical render area.  When a layer is
+// rendered to the render area, it is first transformed and clipped to the logical
+// render area.  The transformed and clipped layer is then projected onto the
+// physical render area.
 class RenderArea {
-
 public:
     enum class CaptureFill {CLEAR, OPAQUE};
 
     static float getCaptureFillValue(CaptureFill captureFill);
 
-    RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill,
-               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
-          : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) {
-        mRotationFlags = Transform::fromRotation(rotation);
-    }
+    RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill,
+               Transform::orientation_flags rotation = Transform::ROT_0)
+          : mReqWidth(reqWidth),
+            mReqHeight(reqHeight),
+            mCaptureFill(captureFill),
+            mRotationFlags(rotation) {}
 
     virtual ~RenderArea() = default;
 
-    virtual const Transform& getTransform() const = 0;
-    virtual Rect getBounds() const = 0;
-    virtual int getHeight() const = 0;
-    virtual int getWidth() const = 0;
-    virtual bool isSecure() const = 0;
-    virtual bool needsFiltering() const = 0;
-    virtual Rect getSourceCrop() const = 0;
-
+    // Invoke drawLayers to render layers into the render area.
     virtual void render(std::function<void()> drawLayers) { drawLayers(); }
 
-    int getReqHeight() const { return mReqHeight; };
-    int getReqWidth() const { return mReqWidth; };
-    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
-    status_t updateDimensions(int displayRotation);
+    // Returns true if the render area is secure.  A secure layer should be
+    // blacked out / skipped when rendered to an insecure render area.
+    virtual bool isSecure() const = 0;
 
+    // Returns true if the otherwise disabled layer filtering should be
+    // enabled when rendering to this render area.
+    virtual bool needsFiltering() const = 0;
+
+    // Returns the transform to be applied on layers to transform them into
+    // the logical render area.
+    virtual const Transform& getTransform() const = 0;
+
+    // Returns the size of the logical render area.  Layers are clipped to the
+    // logical render area.
+    virtual int getWidth() const = 0;
+    virtual int getHeight() const = 0;
+    virtual Rect getBounds() const = 0;
+
+    // Returns the source crop of the render area.  The source crop defines
+    // how layers are projected from the logical render area onto the physical
+    // 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.
+    virtual Rect getSourceCrop() const = 0;
+
+    // Returns the rotation of the source crop and the layers.
+    Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
+
+    // Returns the size of the physical render area.
+    int getReqWidth() const { return mReqWidth; };
+    int getReqHeight() const { return mReqHeight; };
+
+    // Returns the fill color of the physical render area.  Regions not
+    // covered by any rendered layer should be filled with this color.
     CaptureFill getCaptureFill() const { return mCaptureFill; };
 
 private:
-    uint32_t mReqHeight;
-    uint32_t mReqWidth;
-    Transform::orientation_flags mRotationFlags;
-    CaptureFill mCaptureFill;
+    const uint32_t mReqWidth;
+    const uint32_t mReqHeight;
+    const CaptureFill mCaptureFill;
+    const Transform::orientation_flags mRotationFlags;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4ec1e7f..78d751a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -75,6 +75,7 @@
 #include "LayerVector.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
+#include "Transform.h"
 #include "clz.h"
 
 #include "DisplayHardware/ComposerHal.h"
@@ -112,6 +113,27 @@
 using ui::RenderIntent;
 
 namespace {
+
+#pragma clang diagnostic push
+#pragma clang diagnostic error "-Wswitch-enum"
+
+Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) {
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            return Transform::ROT_0;
+        case ISurfaceComposer::eRotate90:
+            return Transform::ROT_90;
+        case ISurfaceComposer::eRotate180:
+            return Transform::ROT_180;
+        case ISurfaceComposer::eRotate270:
+            return Transform::ROT_270;
+    }
+    ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+    return Transform::ROT_0;
+}
+
+#pragma clang diagnostic pop
+
 class ConditionalLock {
 public:
     ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
@@ -144,7 +166,7 @@
 int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
 // TODO(courtneygo): Rename hasWideColorDisplay to clarify its actual meaning.
 bool SurfaceFlinger::hasWideColorDisplay;
-
+int SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
 
 std::string getHwcServiceName() {
     char value[PROPERTY_VALUE_MAX] = {};
@@ -278,19 +300,19 @@
 
     switch (primaryDisplayOrientation) {
         case V1_1::DisplayOrientation::ORIENTATION_90:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation90;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation90;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_180:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation180;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation180;
             break;
         case V1_1::DisplayOrientation::ORIENTATION_270:
-            mPrimaryDisplayOrientation = DisplayState::eOrientation270;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientation270;
             break;
         default:
-            mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
+            SurfaceFlinger::primaryDisplayOrientation = DisplayState::eOrientationDefault;
             break;
     }
-    ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation);
+    ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation);
 
     mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset);
 
@@ -952,7 +974,7 @@
         info.secure = true;
 
         if (type == DisplayDevice::DISPLAY_PRIMARY &&
-            mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
+            primaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
             std::swap(info.w, info.h);
         }
 
@@ -2395,6 +2417,9 @@
         nativeWindow->setSwapInterval(nativeWindow.get(), 0);
     }
 
+    const int displayInstallOrientation = state.type == DisplayDevice::DISPLAY_PRIMARY ?
+        primaryDisplayOrientation : DisplayState::eOrientationDefault;
+
     // virtual displays are always considered enabled
     auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
                                                                            : HWC_POWER_MODE_OFF;
@@ -2402,7 +2427,7 @@
     sp<DisplayDevice> hw =
             new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
                               dispSurface, std::move(renderSurface), displayWidth, displayHeight,
-                              hasWideColorGamut, hdrCapabilities,
+                              displayInstallOrientation, hasWideColorGamut, hdrCapabilities,
                               supportedPerFrameMetadata, hwcColorModes, initialPowerMode);
 
     if (maxFrameBufferAcquiredBuffers >= 3) {
@@ -4832,20 +4857,24 @@
 
     if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
 
-    const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
-    if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
+    auto renderAreaRotation = fromSurfaceComposerRotation(rotation);
 
-    const Rect& dispScissor = device->getScissor();
-    if (!dispScissor.isEmpty()) {
-        sourceCrop.set(dispScissor);
-        // adb shell screencap will default reqWidth and reqHeight to zeros.
+    sp<DisplayDevice> device;
+    {
+        Mutex::Autolock _l(mStateLock);
+
+        device = getDisplayDeviceLocked(display);
+        if (!device) return BAD_VALUE;
+
+        // set the requested width/height to the logical display viewport size
+        // by default
         if (reqWidth == 0 || reqHeight == 0) {
             reqWidth = uint32_t(device->getViewport().width());
             reqHeight = uint32_t(device->getViewport().height());
         }
     }
 
-    DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+    DisplayRenderArea renderArea(device, sourceCrop, reqWidth, reqHeight, renderAreaRotation);
 
     auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
                                     device, minLayerZ, maxLayerZ, std::placeholders::_1);
@@ -4861,9 +4890,10 @@
     public:
         LayerRenderArea(SurfaceFlinger* flinger, const sp<Layer>& layer, const Rect crop,
                         int32_t reqWidth, int32_t reqHeight, bool childrenOnly)
-              : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR),
+              : RenderArea(reqWidth, reqHeight, CaptureFill::CLEAR),
                 mLayer(layer),
                 mCrop(crop),
+                mNeedsFiltering(false),
                 mFlinger(flinger),
                 mChildrenOnly(childrenOnly) {}
         const Transform& getTransform() const override { return mTransform; }
@@ -4874,7 +4904,7 @@
         int getHeight() const override { return mLayer->getDrawingState().active.h; }
         int getWidth() const override { return mLayer->getDrawingState().active.w; }
         bool isSecure() const override { return false; }
-        bool needsFiltering() const override { return false; }
+        bool needsFiltering() const override { return mNeedsFiltering; }
         Rect getSourceCrop() const override {
             if (mCrop.isEmpty()) {
                 return getBounds();
@@ -4895,6 +4925,11 @@
         };
 
         void render(std::function<void()> drawLayers) override {
+            const Rect sourceCrop = getSourceCrop();
+            // no need to check rotation because there is none
+            mNeedsFiltering = sourceCrop.width() != getReqWidth() ||
+                sourceCrop.height() != getReqHeight();
+
             if (!mChildrenOnly) {
                 mTransform = mLayer->getTransform().inverse();
                 drawLayers();
@@ -4917,6 +4952,7 @@
         // layer which has no properties set and which does not draw.
         sp<ContainerLayer> screenshotParentLayer;
         Transform mTransform;
+        bool mNeedsFiltering;
 
         SurfaceFlinger* mFlinger;
         const bool mChildrenOnly;
@@ -4951,6 +4987,14 @@
     int32_t reqWidth = crop.width() * frameScale;
     int32_t reqHeight = crop.height() * frameScale;
 
+    // really small crop or frameScale
+    if (reqWidth <= 0) {
+        reqWidth = 1;
+    }
+    if (reqHeight <= 0) {
+        reqHeight = 1;
+    }
+
     LayerRenderArea renderArea(this, parent, crop, reqWidth, reqHeight, childrenOnly);
 
     auto traverseLayers = [parent, childrenOnly](const LayerVector::Visitor& visitor) {
@@ -4972,8 +5016,6 @@
                                              bool useIdentityTransform) {
     ATRACE_CALL();
 
-    renderArea.updateDimensions(mPrimaryDisplayOrientation);
-
     const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
             GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
     *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
@@ -5049,57 +5091,12 @@
     auto& engine(getRenderEngine());
 
     // get screen geometry
-    const auto raWidth = renderArea.getWidth();
     const auto raHeight = renderArea.getHeight();
 
     const auto reqWidth = renderArea.getReqWidth();
     const auto reqHeight = renderArea.getReqHeight();
-    Rect sourceCrop = renderArea.getSourceCrop();
-
-    bool filtering = false;
-    if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) {
-        filtering = static_cast<int32_t>(reqWidth) != raHeight ||
-                static_cast<int32_t>(reqHeight) != raWidth;
-    } else {
-        filtering = static_cast<int32_t>(reqWidth) != raWidth ||
-                static_cast<int32_t>(reqHeight) != raHeight;
-    }
-
-    // if a default or invalid sourceCrop is passed in, set reasonable values
-    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 || !sourceCrop.isValid()) {
-        sourceCrop.setLeftTop(Point(0, 0));
-        sourceCrop.setRightBottom(Point(raWidth, raHeight));
-    } else if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        Transform tr;
-        uint32_t flags = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                flags = Transform::ROT_90;
-                break;
-            case DisplayState::eOrientation180:
-                flags = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                flags = Transform::ROT_270;
-                break;
-        }
-        tr.set(flags, raWidth, raHeight);
-        sourceCrop = tr.transform(sourceCrop);
-    }
-
-    // ensure that sourceCrop is inside screen
-    if (sourceCrop.left < 0) {
-        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
-    }
-    if (sourceCrop.right > raWidth) {
-        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, raWidth);
-    }
-    if (sourceCrop.top < 0) {
-        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
-    }
-    if (sourceCrop.bottom > raHeight) {
-        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, raHeight);
-    }
+    const auto sourceCrop = renderArea.getSourceCrop();
+    const auto rotation = renderArea.getRotationFlags();
 
     // assume ColorMode::SRGB / RenderIntent::COLORIMETRIC
     engine.setOutputDataSpace(Dataspace::SRGB);
@@ -5108,37 +5105,6 @@
     // make sure to clear all GL error flags
     engine.checkErrors();
 
-    Transform::orientation_flags rotation = renderArea.getRotationFlags();
-    if (mPrimaryDisplayOrientation != DisplayState::eOrientationDefault) {
-        // convert hw orientation into flag presentation
-        // here inverse transform needed
-        uint8_t hw_rot_90  = 0x00;
-        uint8_t hw_flip_hv = 0x00;
-        switch (mPrimaryDisplayOrientation) {
-            case DisplayState::eOrientation90:
-                hw_rot_90 = Transform::ROT_90;
-                hw_flip_hv = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation180:
-                hw_flip_hv = Transform::ROT_180;
-                break;
-            case DisplayState::eOrientation270:
-                hw_rot_90  = Transform::ROT_90;
-                break;
-        }
-
-        // transform flags operation
-        // 1) flip H V if both have ROT_90 flag
-        // 2) XOR these flags
-        uint8_t rotation_rot_90  = rotation & Transform::ROT_90;
-        uint8_t rotation_flip_hv = rotation & Transform::ROT_180;
-        if (rotation_rot_90 & hw_rot_90) {
-            rotation_flip_hv = (~rotation_flip_hv) & Transform::ROT_180;
-        }
-        rotation = static_cast<Transform::orientation_flags>
-                   ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv));
-    }
-
     // set-up our viewport
     engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap,
                                     rotation);
@@ -5149,9 +5115,7 @@
     engine.clearWithColor(0, 0, 0, alpha);
 
     traverseLayers([&](Layer* layer) {
-        if (filtering) layer->setFiltering(true);
         layer->draw(renderArea, useIdentityTransform);
-        if (filtering) layer->setFiltering(false);
     });
 }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index d2b1233..0914a09 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -286,6 +286,8 @@
     // want to support color management to disable color management.
     static bool hasWideColorDisplay;
 
+    static int primaryDisplayOrientation;
+
     static char const* getServiceName() ANDROID_API {
         return "SurfaceFlinger";
     }
@@ -345,8 +347,6 @@
     bool authenticateSurfaceTextureLocked(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
 
-    int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; }
-
 private:
     friend class Client;
     friend class DisplayEventConnection;
@@ -858,7 +858,6 @@
     mutable std::unique_ptr<MessageQueue> mEventQueue{std::make_unique<impl::MessageQueue>()};
     FrameTracker mAnimFrameTracker;
     DispSync mPrimaryDispSync;
-    int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault;
 
     // protected by mDestroyedLayerLock;
     mutable Mutex mDestroyedLayerLock;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 558845f..4c5fa99 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -110,7 +110,7 @@
      */
 
     auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; }
-
+    auto& mutablePrimaryDisplayOrientation() { return SurfaceFlinger::primaryDisplayOrientation; }
     auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
     auto& mutableCurrentState() { return mFlinger->mCurrentState; }
     auto& mutableDisplays() { return mFlinger->mDisplays; }
@@ -320,10 +320,11 @@
         sp<DisplayDevice> inject() {
             std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents;
             sp<DisplayDevice> device =
-                    new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken,
-                                      mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
-                                      0, false, HdrCapabilities(), 0, hdrAndRenderIntents,
-                                      HWC_POWER_MODE_NORMAL);
+                    new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure,
+                                      mDisplayToken, mNativeWindow, mDisplaySurface,
+                                      std::move(mRenderSurface), 0, 0,
+                                      DisplayState::eOrientationDefault, false, HdrCapabilities(),
+                                      0, hdrAndRenderIntents, HWC_POWER_MODE_NORMAL);
             mFlinger.mutableDisplays().add(mDisplayToken, device);
 
             DisplayDeviceState state(mType, mSecure);