diff options
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 11 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderArea.cpp | 55 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderArea.h | 67 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 77 |
4 files changed, 119 insertions, 91 deletions
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index da0931e43f..42909880c7 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -25,7 +25,6 @@ #include <binder/IBinder.h> #include <hardware/hwcomposer_defs.h> -#include <gui/ISurfaceComposer.h> #include <math/mat4.h> #include <renderengine/Surface.h> #include <ui/GraphicTypes.h> @@ -334,12 +333,12 @@ private: class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp<const DisplayDevice> device, - ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) - : DisplayRenderArea(device, device->getBounds(), device->getHeight(), device->getWidth(), + ui::Transform::orientation_flags rotation = ui::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), + DisplayRenderArea(const sp<const DisplayDevice> device, Rect sourceCrop, uint32_t reqWidth, + uint32_t reqHeight, ui::Transform::orientation_flags rotation) + : RenderArea(reqWidth, reqHeight, CaptureFill::OPAQUE, rotation), mDevice(device), mSourceCrop(sourceCrop) {} const ui::Transform& getTransform() const override { return mDevice->getTransform(); } diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 7f69ce4b3e..93759e8ad7 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -1,30 +1,7 @@ #include "RenderArea.h" -#include <gui/LayerState.h> - namespace android { -ui::Transform::orientation_flags fromRotation(ISurfaceComposer::Rotation rotation) { - switch (rotation) { - case ISurfaceComposer::eRotateNone: - return ui::Transform::ROT_0; - case ISurfaceComposer::eRotate90: - return ui::Transform::ROT_90; - case ISurfaceComposer::eRotate180: - return ui::Transform::ROT_180; - case ISurfaceComposer::eRotate270: - return ui::Transform::ROT_270; - } - ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); - return ui::Transform::ROT_0; -} - -RenderArea::RenderArea(uint32_t reqHeight, uint32_t reqWidth, CaptureFill captureFill, - ISurfaceComposer::Rotation rotation) - : mReqHeight(reqHeight), mReqWidth(reqWidth), mCaptureFill(captureFill) { - mRotationFlags = fromRotation(rotation); -} - float RenderArea::getCaptureFillValue(CaptureFill captureFill) { switch(captureFill) { case CaptureFill::CLEAR: @@ -34,37 +11,5 @@ float RenderArea::getCaptureFillValue(CaptureFill captureFill) { 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 & ui::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 e38f4621d7..3c11e73199 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -1,47 +1,80 @@ #pragma once -#include <gui/ISurfaceComposer.h> -#include <ui/GraphicTypes.h> #include <ui/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); + RenderArea(uint32_t reqWidth, uint32_t reqHeight, CaptureFill captureFill, + ui::Transform::orientation_flags rotation = ui::Transform::ROT_0) + : mReqWidth(reqWidth), + mReqHeight(reqHeight), + mCaptureFill(captureFill), + mRotationFlags(rotation) {} virtual ~RenderArea() = default; - virtual const ui::Transform& getTransform() const = 0; - virtual Rect getBounds() const = 0; - virtual int getHeight() const = 0; - virtual int getWidth() const = 0; + // Invoke drawLayers to render layers into the render area. + virtual void render(std::function<void()> drawLayers) { drawLayers(); } + + // 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 ui::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; - virtual void render(std::function<void()> drawLayers) { drawLayers(); } + // Returns the rotation of the source crop and the layers. + ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; - int getReqHeight() const { return mReqHeight; }; + // Returns the size of the physical render area. int getReqWidth() const { return mReqWidth; }; - ui::Transform::orientation_flags getRotationFlags() const { return mRotationFlags; }; - status_t updateDimensions(int displayRotation); + 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; - ui::Transform::orientation_flags mRotationFlags; - CaptureFill mCaptureFill; + const uint32_t mReqWidth; + const uint32_t mReqHeight; + const CaptureFill mCaptureFill; + const ui::Transform::orientation_flags mRotationFlags; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 37d014686e..5acfe59c4e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -143,6 +143,21 @@ bool isWideColorMode(const ColorMode colorMode) { return false; } +ui::Transform::orientation_flags fromSurfaceComposerRotation(ISurfaceComposer::Rotation rotation) { + switch (rotation) { + case ISurfaceComposer::eRotateNone: + return ui::Transform::ROT_0; + case ISurfaceComposer::eRotate90: + return ui::Transform::ROT_90; + case ISurfaceComposer::eRotate180: + return ui::Transform::ROT_180; + case ISurfaceComposer::eRotate270: + return ui::Transform::ROT_270; + } + ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation); + return ui::Transform::ROT_0; +} + #pragma clang diagnostic pop class ConditionalLock { @@ -4902,20 +4917,50 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken, if (!displayToken) return BAD_VALUE; - const auto display = getDisplayDeviceLocked(displayToken); - if (!display) return BAD_VALUE; + auto renderAreaRotation = fromSurfaceComposerRotation(rotation); + + sp<DisplayDevice> display; + { + Mutex::Autolock _l(mStateLock); + + display = getDisplayDeviceLocked(displayToken); + if (!display) return BAD_VALUE; + + const Rect& dispScissor = display->getScissor(); + if (!dispScissor.isEmpty()) { + sourceCrop.set(dispScissor); + // adb shell screencap will default reqWidth and reqHeight to zeros. + if (reqWidth == 0 || reqHeight == 0) { + reqWidth = uint32_t(display->getViewport().width()); + reqHeight = uint32_t(display->getViewport().height()); + } + } + + // get screen geometry + uint32_t width = display->getWidth(); + uint32_t height = display->getHeight(); - const Rect& dispScissor = display->getScissor(); - if (!dispScissor.isEmpty()) { - sourceCrop.set(dispScissor); - // adb shell screencap will default reqWidth and reqHeight to zeros. - if (reqWidth == 0 || reqHeight == 0) { - reqWidth = uint32_t(display->getViewport().width()); - reqHeight = uint32_t(display->getViewport().height()); + if (renderAreaRotation & ui::Transform::ROT_90) { + std::swap(width, height); + } + + if (mPrimaryDisplayOrientation & DisplayState::eOrientationSwapMask) { + std::swap(width, height); + } + + if ((reqWidth > width) || (reqHeight > height)) { + ALOGE("size mismatch (%d, %d) > (%d, %d)", reqWidth, reqHeight, width, height); + } else { + if (reqWidth == 0) { + reqWidth = width; + } + if (reqHeight == 0) { + reqHeight = height; + } } } - DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation); + DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, renderAreaRotation); auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this, display, minLayerZ, maxLayerZ, std::placeholders::_1); @@ -4931,7 +4976,7 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, 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), mFlinger(flinger), @@ -5023,6 +5068,14 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, 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) { @@ -5044,8 +5097,6 @@ status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea, 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(), |