From a76b271f0e14325fa0ebb98e1cac0a15adfea1cb Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 20 Sep 2017 12:02:26 -0700 Subject: Add captureLayers function to capture a layer and its children. The captureLayers function gets a root layer as its argument. It will capture the content for that layer and its descendants. The capture will set the root layer's transform back to (0, 0). Test: Transaction_test ScreenCaptureTest Change-Id: I84fb66a65cd91434cddc99506b1924cf9f950935 --- services/surfaceflinger/RenderArea.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 services/surfaceflinger/RenderArea.cpp (limited to 'services/surfaceflinger/RenderArea.cpp') diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp new file mode 100644 index 0000000000..6225df134d --- /dev/null +++ b/services/surfaceflinger/RenderArea.cpp @@ -0,0 +1,34 @@ +#include "RenderArea.h" + +namespace android { + +/* + * 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() { + // get screen geometry + + uint32_t width = getWidth(); + uint32_t height = getHeight(); + + if (mRotationFlags & Transform::ROT_90) { + 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 \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 50da5043ad224fd6b6024ed73785a9502bf7978d Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 9 Apr 2018 13:49:37 -0700 Subject: Set window to transparent when screenshotting layer. Set the screenshot to transparent instead of black. This allows the system to draw a color behind without having to crop out the area that may not be drawn into. Bug: 76442549 Test: When going to recents, area not drawn from layers is now transparent instead of black. Test: Transaction_test#CaptureTransparent Change-Id: Id535eb753d3d1cae82658cd33423ce588aaa62f8 --- services/surfaceflinger/DisplayDevice.h | 3 ++- services/surfaceflinger/RenderArea.cpp | 9 +++++++++ services/surfaceflinger/RenderArea.h | 12 ++++++++++-- services/surfaceflinger/SurfaceFlinger.cpp | 5 +++-- services/surfaceflinger/tests/Transaction_test.cpp | 18 ++++++++++++++++++ 5 files changed, 42 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/RenderArea.cpp') diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index e844d115c2..61ce30ca86 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -281,7 +281,8 @@ public: rotation) {} DisplayRenderArea(const sp device, Rect sourceCrop, uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) - : RenderArea(reqHeight, reqWidth, rotation), mDevice(device), mSourceCrop(sourceCrop) {} + : RenderArea(reqHeight, reqWidth, CaptureFill::OPAQUE, rotation), mDevice(device), + mSourceCrop(sourceCrop) {} const Transform& getTransform() const override { return mDevice->getTransform(); } Rect getBounds() const override { return mDevice->getBounds(); } diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 6225df134d..46ec8e68ba 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -2,6 +2,15 @@ namespace android { +float RenderArea::getCaptureFillValue(CaptureFill captureFill) { + switch(captureFill) { + case CaptureFill::CLEAR: + return 0.0f; + case CaptureFill::OPAQUE: + default: + 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 diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index bf0707f13b..62a3d5b333 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -9,10 +9,15 @@ namespace android { class RenderArea { + public: - RenderArea(uint32_t reqHeight, uint32_t reqWidth, + 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) { + : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) { mRotationFlags = Transform::fromRotation(rotation); } @@ -36,10 +41,13 @@ public: status_t updateDimensions(); + CaptureFill getCaptureFill() const { return mCaptureFill; }; + private: uint32_t mReqHeight; uint32_t mReqWidth; Transform::orientation_flags mRotationFlags; + CaptureFill mCaptureFill; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 183c1eb07c..781a30ccf5 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4597,7 +4597,7 @@ status_t SurfaceFlinger::captureLayers(const sp& layerHandleBinder, public: LayerRenderArea(SurfaceFlinger* flinger, const sp& layer, const Rect crop, int32_t reqWidth, int32_t reqHeight, bool childrenOnly) - : RenderArea(reqHeight, reqWidth), + : RenderArea(reqHeight, reqWidth, CaptureFill::CLEAR), mLayer(layer), mCrop(crop), mFlinger(flinger), @@ -4834,8 +4834,9 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, renderArea.getRotationFlags()); engine.disableTexturing(); + const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill()); // redraw the screen entirely... - engine.clearWithColor(0, 0, 0, 1); + engine.clearWithColor(0, 0, 0, alpha); traverseLayers([&](Layer* layer) { if (filtering) layer->setFiltering(true); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 176c691c6a..a0f12f1438 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -2358,6 +2358,24 @@ TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { mCapture->expectChildColor(0, 0); } +TEST_F(ScreenCaptureTest, CaptureTransparent) { + sp child = + mComposerClient->createSurface(String8("Child surface"), 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + + fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + auto childHandle = child->getHandle(); + + // Captures child + ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20}); + mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255}); + // Area outside of child's bounds is transparent. + mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); +} + // In the following tests we verify successful skipping of a parent layer, // so we use the same verification logic and only change how we mutate -- cgit v1.2.3-59-g8ed1b From 7501ed66a05f530062925011d1342e8651216051 Mon Sep 17 00:00:00 2001 From: Iris Chang Date: Mon, 30 Apr 2018 14:45:42 +0800 Subject: Need GSI to support landscape LCM When device uses landscape LCM, the nature of the screen shows that the device is a portrait device. After we flash with GSI, there is vendor solution for landscape LCM used at portrait device. As the result, the screen displays landscape layout and orientation while device is at portrait orientation. In addition, the sensor coordinate system mismatches with android coordinate system. We suggest Google can add config to handle the case "portrait device uses landscape LCM or landscape device uses portrait LCM". Bug: 69691076 Test: We verified following test cases for this patch on Android O-MR1. 1. Make sure homescreen is normal 2. Rotate device and make sure screen is normal 3. Grab screen shot and check if screen shot is normal 4. Connect to Wi-Fi display and make sure WFD screen is normal Test: Tested 1, 2 and 3 on Pixel 2. Test: artifially setup 90 degree rotation on Pixel and make sure that screenshots are aligned to the screen. Change-Id: Ib42c9a216e8a6fe465139d6eece152fb1765b422 --- services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/DisplayDevice.cpp | 9 +++ services/surfaceflinger/RenderArea.cpp | 10 +++- services/surfaceflinger/RenderArea.h | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 88 ++++++++++++++++++++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 3 + 6 files changed, 106 insertions(+), 7 deletions(-) (limited to 'services/surfaceflinger/RenderArea.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 6a69844d9f..c2bb6ad6b4 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -22,6 +22,7 @@ cc_defaults { "android.frameworks.vr.composer@1.0", "android.hardware.configstore-utils", "android.hardware.configstore@1.0", + "android.hardware.configstore@1.1", "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.composer@2.1", "android.hardware.graphics.composer@2.2", diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 2b1e5775ba..48a56bf7e7 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -475,6 +475,15 @@ void DisplayDevice::setProjection(int orientation, TL.set(-src_x, -src_y); TP.set(dst_x, dst_y); + // 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), + w, h, &R); + } + // The viewport and frame are both in the logical orientation. // Apply the logical translation, scale to physical size, apply the // physical translation and finally rotate to the physical orientation. diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 46ec8e68ba..1a8edf3e79 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -1,5 +1,7 @@ #include "RenderArea.h" +#include + namespace android { float RenderArea::getCaptureFillValue(CaptureFill captureFill) { @@ -15,7 +17,7 @@ float RenderArea::getCaptureFillValue(CaptureFill captureFill) { * 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() { +status_t RenderArea::updateDimensions(int displayRotation) { // get screen geometry uint32_t width = getWidth(); @@ -25,6 +27,10 @@ status_t RenderArea::updateDimensions() { 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; @@ -40,4 +46,4 @@ status_t RenderArea::updateDimensions() { return NO_ERROR; } -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 938c3ce0dd..96e4b5f48b 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -36,7 +36,7 @@ public: int getReqHeight() const { return mReqHeight; }; int getReqWidth() const { return mReqWidth; }; Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; - status_t updateDimensions(); + status_t updateDimensions(int displayRotation); CaptureFill getCaptureFill() const { return mCaptureFill; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9117207544..6f3f2520ce 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -88,6 +88,8 @@ #include #include +#include +#include #include #include @@ -282,6 +284,26 @@ SurfaceFlinger::SurfaceFlinger() : SurfaceFlinger(SkipInitialization) { hasWideColorDisplay = getBool(false); + V1_1::DisplayOrientation primaryDisplayOrientation = + getDisplayOrientation< V1_1::ISurfaceFlingerConfigs, &V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>( + V1_1::DisplayOrientation::ORIENTATION_0); + + switch (primaryDisplayOrientation) { + case V1_1::DisplayOrientation::ORIENTATION_90: + mPrimaryDisplayOrientation = DisplayState::eOrientation90; + break; + case V1_1::DisplayOrientation::ORIENTATION_180: + mPrimaryDisplayOrientation = DisplayState::eOrientation180; + break; + case V1_1::DisplayOrientation::ORIENTATION_270: + mPrimaryDisplayOrientation = DisplayState::eOrientation270; + break; + default: + mPrimaryDisplayOrientation = DisplayState::eOrientationDefault; + break; + } + ALOGV("Primary Display Orientation is set to %2d.", mPrimaryDisplayOrientation); + mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework, SurfaceFlinger::dispSyncPresentTimeOffset); // debugging stuff... @@ -895,6 +917,11 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& display, // All non-virtual displays are currently considered secure. info.secure = true; + if (type == DisplayDevice::DISPLAY_PRIMARY && + mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + std::swap(info.w, info.h); + } + configs->push_back(info); } @@ -4913,7 +4940,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, bool useIdentityTransform) { ATRACE_CALL(); - renderArea.updateDimensions(); + 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; @@ -4997,13 +5024,35 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, const auto reqHeight = renderArea.getReqHeight(); Rect sourceCrop = renderArea.getSourceCrop(); - const bool filtering = static_cast(reqWidth) != raWidth || - static_cast(reqHeight) != raHeight; + bool filtering = false; + if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + filtering = static_cast(reqWidth) != raHeight || + static_cast(reqHeight) != raWidth; + } else { + filtering = static_cast(reqWidth) != raWidth || + static_cast(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 @@ -5027,9 +5076,40 @@ void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, // 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 + ((rotation_rot_90 ^ hw_rot_90) | (rotation_flip_hv ^ hw_flip_hv)); + } + // set-up our viewport engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, raHeight, yswap, - renderArea.getRotationFlags()); + rotation); engine.disableTexturing(); const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill()); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d9cf9461ca..c5a676bab4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -341,6 +341,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; + int getPrimaryDisplayOrientation() const { return mPrimaryDisplayOrientation; } + private: friend class Client; friend class DisplayEventConnection; @@ -845,6 +847,7 @@ private: mutable std::unique_ptr mEventQueue{std::make_unique()}; FrameTracker mAnimFrameTracker; DispSync mPrimaryDispSync; + int mPrimaryDisplayOrientation = DisplayState::eOrientationDefault; // protected by mDestroyedLayerLock; mutable Mutex mDestroyedLayerLock; -- cgit v1.2.3-59-g8ed1b