Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a252d895 authored by chaviw's avatar chaviw
Browse files

Use GraphicBuffer instead of GBP for screenshots.

Migrate screenshot code to render the layers into a
GraphicBuffer instead of creating a GraphicBufferProducer. This cleans
up the code and makes rendering a screen capture simpler and clearer.

Test: Screencaptures for Recents, manual screenshots, and "adb shell
screencap"
Test: Transaction_test

Change-Id: Ifb463c0e98cfaa3f96ad27837b1a2e2921e253d1
parent 503b79e3
Loading
Loading
Loading
Loading
+47 −24
Original line number Diff line number Diff line
@@ -100,17 +100,13 @@ public:
        remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
    }

    virtual status_t captureScreen(const sp<IBinder>& display,
            const sp<IGraphicBufferProducer>& producer,
    virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
            int32_t minLayerZ, int32_t maxLayerZ,
            bool useIdentityTransform,
            ISurfaceComposer::Rotation rotation)
    {
                                   int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
                                   ISurfaceComposer::Rotation rotation) {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        data.writeStrongBinder(display);
        data.writeStrongBinder(IInterface::asBinder(producer));
        data.write(sourceCrop);
        data.writeUint32(reqWidth);
        data.writeUint32(reqHeight);
@@ -118,21 +114,45 @@ public:
        data.writeInt32(maxLayerZ);
        data.writeInt32(static_cast<int32_t>(useIdentityTransform));
        data.writeInt32(static_cast<int32_t>(rotation));
        remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
        return reply.readInt32();
        status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);

        if (err != NO_ERROR) {
            return err;
        }

        err = reply.readInt32();
        if (err != NO_ERROR) {
            return err;
        }

        *outBuffer = new GraphicBuffer();
        reply.read(**outBuffer);
        return err;
    }

    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
                                   const sp<IGraphicBufferProducer>& producer,
                                   const Rect& sourceCrop, float frameScale) {
                                   sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
                                   float frameScale) {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        data.writeStrongBinder(layerHandleBinder);
        data.writeStrongBinder(IInterface::asBinder(producer));
        data.write(sourceCrop);
        data.writeFloat(frameScale);
        remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
        return reply.readInt32();
        status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);

        if (err != NO_ERROR) {
            return err;
        }

        err = reply.readInt32();
        if (err != NO_ERROR) {
            return err;
        }

        *outBuffer = new GraphicBuffer();
        reply.read(**outBuffer);

        return err;
    }

    virtual bool authenticateSurfaceTexture(
@@ -583,8 +603,7 @@ status_t BnSurfaceComposer::onTransact(
        case CAPTURE_SCREEN: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> display = data.readStrongBinder();
            sp<IGraphicBufferProducer> producer =
                    interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
            sp<GraphicBuffer> outBuffer;
            Rect sourceCrop(Rect::EMPTY_RECT);
            data.read(sourceCrop);
            uint32_t reqWidth = data.readUint32();
@@ -594,24 +613,28 @@ status_t BnSurfaceComposer::onTransact(
            bool useIdentityTransform = static_cast<bool>(data.readInt32());
            int32_t rotation = data.readInt32();

            status_t res = captureScreen(display, producer,
                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
                    useIdentityTransform,
            status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
                                         minLayerZ, maxLayerZ, useIdentityTransform,
                                         static_cast<ISurfaceComposer::Rotation>(rotation));
            reply->writeInt32(res);
            if (res == NO_ERROR) {
                reply->write(*outBuffer);
            }
            return NO_ERROR;
        }
        case CAPTURE_LAYERS: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            sp<IBinder> layerHandleBinder = data.readStrongBinder();
            sp<IGraphicBufferProducer> producer =
                    interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
            sp<GraphicBuffer> outBuffer;
            Rect sourceCrop(Rect::EMPTY_RECT);
            data.read(sourceCrop);
            float frameScale = data.readFloat();

            status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale);
            status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale);
            reply->writeInt32(res);
            if (res == NO_ERROR) {
                reply->write(*outBuffer);
            }
            return NO_ERROR;
        }
        case AUTHENTICATE_SURFACE: {
+21 −0
Original line number Diff line number Diff line
@@ -1760,4 +1760,25 @@ status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out)
    return OK;
}

status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
    if (buffer == nullptr) {
        return BAD_VALUE;
    }
    int err = static_cast<ANativeWindow*>(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
                                                            NATIVE_WINDOW_API_CPU);
    if (err != OK) {
        return err;
    }
    err = surface->attachBuffer(buffer->getNativeBuffer());
    if (err != OK) {
        return err;
    }
    err = static_cast<ANativeWindow*>(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1);
    if (err != OK) {
        return err;
    }
    err = surface->disconnect(NATIVE_WINDOW_API_CPU);
    return err;
}

}; // namespace android
+10 −164
Original line number Diff line number Diff line
@@ -717,181 +717,27 @@ status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,

// ----------------------------------------------------------------------------

status_t ScreenshotClient::capture(
        const sp<IBinder>& display,
        const sp<IGraphicBufferProducer>& producer,
        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
        int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) {
    sp<ISurfaceComposer> s(ComposerService::getComposerService());
    if (s == NULL) return NO_INIT;
    return s->captureScreen(display, producer, sourceCrop,
            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
}

status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
        int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
        uint32_t rotation,
status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
                                   uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
                                   bool useIdentityTransform, uint32_t rotation,
                                   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->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
            minLayerZ, maxLayerZ, useIdentityTransform,
    status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
                                    maxLayerZ, useIdentityTransform,
                                    static_cast<ISurfaceComposer::Rotation>(rotation));
    if (ret != NO_ERROR) {
        return ret;
    }
    BufferItem b;
    consumer->acquireBuffer(&b, 0, true);
    *outBuffer = b.mGraphicBuffer;
    return ret;
}

status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
                                         const sp<IGraphicBufferProducer>& producer,
                                         Rect sourceCrop, float frameScale) {
    sp<ISurfaceComposer> s(ComposerService::getComposerService());
    if (s == NULL) return NO_INIT;
    return s->captureLayers(layerHandle, producer, sourceCrop, frameScale);
}

status_t ScreenshotClient::captureLayersToBuffer(const sp<IBinder>& layerHandle, Rect sourceCrop,
status_t ScreenshotClient::captureLayers(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;
    status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale);
    return ret;
}

ScreenshotClient::ScreenshotClient()
    : mHaveBuffer(false) {
    memset(&mBuffer, 0, sizeof(mBuffer));
}

ScreenshotClient::~ScreenshotClient() {
    ScreenshotClient::release();
}

sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
    if (mCpuConsumer == NULL) {
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&mProducer, &consumer);
        mCpuConsumer = new CpuConsumer(consumer, 1);
        mCpuConsumer->setName(String8("ScreenshotClient"));
    }
    return mCpuConsumer;
}

status_t ScreenshotClient::update(const sp<IBinder>& display,
        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
        int32_t minLayerZ, int32_t maxLayerZ,
        bool useIdentityTransform, uint32_t rotation) {
    sp<ISurfaceComposer> s(ComposerService::getComposerService());
    if (s == NULL) return NO_INIT;
    sp<CpuConsumer> cpuConsumer = getCpuConsumer();

    if (mHaveBuffer) {
        mCpuConsumer->unlockBuffer(mBuffer);
        memset(&mBuffer, 0, sizeof(mBuffer));
        mHaveBuffer = false;
    }

    status_t err = s->captureScreen(display, mProducer, sourceCrop,
            reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
            static_cast<ISurfaceComposer::Rotation>(rotation));

    if (err == NO_ERROR) {
        err = mCpuConsumer->lockNextBuffer(&mBuffer);
        if (err == NO_ERROR) {
            mHaveBuffer = true;
        }
    }
    return err;
}

status_t ScreenshotClient::update(const sp<IBinder>& display,
        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
        int32_t minLayerZ, int32_t maxLayerZ,
        bool useIdentityTransform) {

    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
            minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
}

status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
        bool useIdentityTransform) {
    return ScreenshotClient::update(display, sourceCrop, 0, 0,
            INT32_MIN, INT32_MAX,
            useIdentityTransform, ISurfaceComposer::eRotateNone);
}

status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
        uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
    return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
            INT32_MIN, INT32_MAX,
            useIdentityTransform, ISurfaceComposer::eRotateNone);
}

void ScreenshotClient::release() {
    if (mHaveBuffer) {
        mCpuConsumer->unlockBuffer(mBuffer);
        memset(&mBuffer, 0, sizeof(mBuffer));
        mHaveBuffer = false;
    }
    mCpuConsumer.clear();
}

void const* ScreenshotClient::getPixels() const {
    return mBuffer.data;
}

uint32_t ScreenshotClient::getWidth() const {
    return mBuffer.width;
}

uint32_t ScreenshotClient::getHeight() const {
    return mBuffer.height;
}

PixelFormat ScreenshotClient::getFormat() const {
    return mBuffer.format;
}

uint32_t ScreenshotClient::getStride() const {
    return mBuffer.stride;
}

size_t ScreenshotClient::getSize() const {
    return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
}

android_dataspace ScreenshotClient::getDataSpace() const {
    return mBuffer.dataSpace;
}

// ----------------------------------------------------------------------------
}; // namespace android
+7 −8
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
#include <ui/GraphicBuffer.h>

#include <vector>

@@ -167,16 +168,14 @@ public:
    /* Capture the specified screen. requires READ_FRAME_BUFFER permission
     * This function will fail if there is a secure window on screen.
     */
    virtual status_t captureScreen(const sp<IBinder>& display,
            const sp<IGraphicBufferProducer>& producer,
    virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
                                   Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
            int32_t minLayerZ, int32_t maxLayerZ,
            bool useIdentityTransform,
                                   int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
                                   Rotation rotation = eRotateNone) = 0;

    virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
                                   const sp<IGraphicBufferProducer>& producer,
                                   const Rect& sourceCrop, float frameScale = 1.0) = 0;
                                   sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
                                   float frameScale = 1.0) = 0;

    /* Clears the frame statistics for animations.
     *
+2 −0
Original line number Diff line number Diff line
@@ -283,6 +283,8 @@ public:

    android_dataspace_t getBuffersDataSpace();

    static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);

protected:
    enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
    enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
Loading