diff options
| author | 2017-11-28 21:51:34 +0000 | |
|---|---|---|
| committer | 2017-11-28 21:51:34 +0000 | |
| commit | 503b79e3db0d6dce40ea0a8e17bbffd6f6176123 (patch) | |
| tree | 26e0a903d2a3c539cf18c4a3e801fa4bd3bbad62 | |
| parent | c5de5b391c7be208681d7ba9882fa02ea60c4bbc (diff) | |
| parent | 7206d49b2963ce2e926a5f25fe94aca9c06471e6 (diff) | |
Merge "Add additional parameters for the captureLayer functions."
| -rw-r--r-- | libs/gui/ISurfaceComposer.cpp | 12 | ||||
| -rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 29 | ||||
| -rw-r--r-- | libs/gui/include/gui/ISurfaceComposer.h | 2 | ||||
| -rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 6 | ||||
| -rw-r--r-- | libs/gui/tests/Surface_test.cpp | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/RenderArea.h | 3 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 42 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 93 |
9 files changed, 166 insertions, 25 deletions
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index 973302c226..c21c5e3eb8 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -124,12 +124,13 @@ public: virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder, const sp<IGraphicBufferProducer>& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor()); data.writeStrongBinder(layerHandleBinder); data.writeStrongBinder(IInterface::asBinder(producer)); - data.writeInt32(static_cast<int32_t>(rotation)); + data.write(sourceCrop); + data.writeFloat(frameScale); remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply); return reply.readInt32(); } @@ -605,10 +606,11 @@ status_t BnSurfaceComposer::onTransact( sp<IBinder> layerHandleBinder = data.readStrongBinder(); sp<IGraphicBufferProducer> producer = interface_cast<IGraphicBufferProducer>(data.readStrongBinder()); - int32_t rotation = data.readInt32(); + Rect sourceCrop(Rect::EMPTY_RECT); + data.read(sourceCrop); + float frameScale = data.readFloat(); - status_t res = captureLayers(layerHandleBinder, producer, - static_cast<ISurfaceComposer::Rotation>(rotation)); + status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale); reply->writeInt32(res); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2adc273651..2466d2555a 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -757,11 +757,34 @@ status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display, status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, const sp<IGraphicBufferProducer>& producer, - uint32_t rotation) { + Rect sourceCrop, float frameScale) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; - return s->captureLayers(layerHandle, producer, - static_cast<ISurfaceComposer::Rotation>(rotation)); + return s->captureLayers(layerHandle, producer, sourceCrop, frameScale); +} + +status_t ScreenshotClient::captureLayersToBuffer(const sp<IBinder>& layerHandle, Rect sourceCrop, + float frameScale, sp<GraphicBuffer>* outBuffer) { + sp<ISurfaceComposer> s(ComposerService::getComposerService()); + if (s == NULL) return NO_INIT; + + sp<IGraphicBufferConsumer> gbpConsumer; + sp<IGraphicBufferProducer> producer; + BufferQueue::createBufferQueue(&producer, &gbpConsumer); + sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer, + GRALLOC_USAGE_HW_TEXTURE | + GRALLOC_USAGE_SW_READ_NEVER | + GRALLOC_USAGE_SW_WRITE_NEVER, + 1, true)); + + status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale); + if (ret != NO_ERROR) { + return ret; + } + BufferItem b; + consumer->acquireBuffer(&b, 0, true); + *outBuffer = b.mGraphicBuffer; + return ret; } ScreenshotClient::ScreenshotClient() diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h index 13e7473d54..1e4c329e1e 100644 --- a/libs/gui/include/gui/ISurfaceComposer.h +++ b/libs/gui/include/gui/ISurfaceComposer.h @@ -176,7 +176,7 @@ public: virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder, const sp<IGraphicBufferProducer>& producer, - Rotation rotation = eRotateNone) = 0; + const Rect& sourceCrop, float frameScale = 1.0) = 0; /* Clears the frame statistics for animations. * diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 87fdfae111..b0fa922cd9 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -297,8 +297,12 @@ public: bool useIdentityTransform, uint32_t rotation, sp<GraphicBuffer>* outbuffer); + static status_t captureLayers(const sp<IBinder>& layerHandle, - const sp<IGraphicBufferProducer>& producer, uint32_t rotation); + const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, + float frameScale); + static status_t captureLayersToBuffer(const sp<IBinder>& layerHandle, Rect sourceCrop, + float frameScale, sp<GraphicBuffer>* outBuffer); private: mutable sp<CpuConsumer> mCpuConsumer; diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index 660680bf9e..ac4eb0cb1d 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -531,7 +531,7 @@ public: Rotation /*rotation*/) override { return NO_ERROR; } virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/, const sp<IGraphicBufferProducer>& /*producer*/, - ISurfaceComposer::Rotation /*rotation*/) override { + const Rect& /*sourceCrop*/, float /*frameScale*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index 44b9dc9254..fa4df8360f 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -6,7 +6,8 @@ namespace android { class RenderArea { public: - RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation) + RenderArea(uint32_t reqHeight, uint32_t reqWidth, + ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone) : mReqHeight(reqHeight), mReqWidth(reqWidth) { mRotationFlags = Transform::fromRotation(rotation); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cab9219112..d81178c559 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -4392,15 +4392,14 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, const sp<IGraphicBufferProducer>& producer, - ISurfaceComposer::Rotation rotation) { + const Rect& sourceCrop, float frameScale) { ATRACE_CALL(); class LayerRenderArea : public RenderArea { public: - LayerRenderArea(const sp<Layer>& layer, ISurfaceComposer::Rotation rotation) - : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w, - rotation), - mLayer(layer) {} + LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth, + int32_t reqHeight) + : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {} const Transform& getTransform() const override { // Make the top level transform the inverse the transform and it's parent so it sets // the whole capture back to 0,0 @@ -4415,18 +4414,45 @@ status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder, bool isSecure() const override { return false; } bool needsFiltering() const override { return false; } - Rect getSourceCrop() const override { return getBounds(); } + Rect getSourceCrop() const override { + if (mCrop.isEmpty()) { + return getBounds(); + } else { + return mCrop; + } + } bool getWideColorSupport() const override { return false; } android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; } private: - const sp<Layer>& mLayer; + const sp<Layer> mLayer; + const Rect mCrop; }; auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get()); auto parent = layerHandle->owner.promote(); - LayerRenderArea renderArea(parent, rotation); + if (parent == nullptr || parent->isPendingRemoval()) { + ALOGE("captureLayers called with a removed parent"); + return NAME_NOT_FOUND; + } + + Rect crop(sourceCrop); + if (sourceCrop.width() <= 0) { + crop.left = 0; + crop.right = parent->getCurrentState().active.w; + } + + if (sourceCrop.height() <= 0) { + crop.top = 0; + crop.bottom = parent->getCurrentState().active.h; + } + + int32_t reqWidth = crop.width() * frameScale; + int32_t reqHeight = crop.height() * frameScale; + + LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight); + auto traverseLayers = [parent](const LayerVector::Visitor& visitor) { parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { if (!layer->isVisible()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 386d42bef1..f61dc756c2 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -298,7 +298,7 @@ private: bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t captureLayers(const sp<IBinder>& parentHandle, const sp<IGraphicBufferProducer>& producer, - ISurfaceComposer::Rotation rotation); + const Rect& sourceCrop, float frameScale); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); virtual status_t getDisplayConfigs(const sp<IBinder>& display, diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 943fafd213..39aef8164c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -276,15 +276,15 @@ private: class CaptureLayer { public: - static void captureScreen(std::unique_ptr<CaptureLayer>* sc, sp<IBinder>& parentHandle) { + static void captureScreen(std::unique_ptr<CaptureLayer>* sc, sp<IBinder>& parentHandle, + Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) { sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> consumer; BufferQueue::createBufferQueue(&producer, &consumer); sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1); sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain)); SurfaceComposerClient::Transaction().apply(true); - ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer)); + ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale)); *sc = std::make_unique<CaptureLayer>(cpuConsumer); } @@ -2412,4 +2412,89 @@ TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { mCapture->checkPixel(4, 4, 50, 50, 50); } -} // namespace android +TEST_F(ScreenCaptureTest, CaptureCrop) { + sp<SurfaceControl> redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp<SurfaceControl> blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + Rect crop = Rect(0, 0, 30, 30); + CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop); + // Capturing the cropped screen, cropping out the shown red area, should leave only the blue + // area visible. + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureSize) { + sp<SurfaceControl> redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + sp<SurfaceControl> blueLayer = mComposerClient->createSurface( + String8("Blue surface"), + 30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + fillSurfaceRGBA8(blueLayer, 0, 0, 255); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX-1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + CaptureLayer::captureScreen(&mCapture, redLayerHandle); + mCapture->checkPixel(29, 29, 0, 0, 255); + mCapture->checkPixel(30, 30, 255, 0, 0); + + CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. + mCapture->checkPixel(14, 14, 0, 0, 255); + mCapture->checkPixel(15, 15, 255, 0, 0); + mCapture->checkPixel(29, 29, 255, 0, 0); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { + sp<SurfaceControl> redLayer = mComposerClient->createSurface( + String8("Red surface"), + 60, 60, PIXEL_FORMAT_RGBA_8888, 0); + + fillSurfaceRGBA8(redLayer, 255, 0, 0); + + auto redLayerHandle = redLayer->getHandle(); + mComposerClient->destroySurface(redLayerHandle); + SurfaceComposerClient::Transaction().apply(true); + + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&producer, &consumer); + sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1); + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + + // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0)); +} + +}
\ No newline at end of file |