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

Commit 729f721a authored by Jim Shargo's avatar Jim Shargo
Browse files

Surface: Add 'isBufferOwned' call

Camera's StreamSplitter keeps track of buffers and won't attach them if
they're already owned. This allows us to keep that behavior as we move
over from IGBP to surfaces.

Ideally, I think, IGBPs should fail to attach the same buffer multiple
times. Even if not, this call should probably be to the IGBP instead of
the Surface for more accuracy. But this replicates the old behavior.

Bug: 340933206
Flag: com.android.graphics.libgui.flags.wb_stream_splitter
Test: new test

Change-Id: Idbb200202012c9eae2668616dcff277c925c3907
parent 835688b9
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -2230,17 +2230,47 @@ int Surface::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
    return NO_ERROR;
}

int Surface::isBufferOwned(const sp<GraphicBuffer>& buffer, bool* outIsOwned) const {
    ATRACE_CALL();

    if (buffer == nullptr) {
        ALOGE("%s: Bad input, buffer was null", __FUNCTION__);
        return BAD_VALUE;
    }
    if (outIsOwned == nullptr) {
        ALOGE("%s: Bad input, output was null", __FUNCTION__);
        return BAD_VALUE;
    }

    Mutex::Autolock lock(mMutex);

    int slot = this->getSlotFromBufferLocked(buffer->getNativeBuffer());
    if (slot == BAD_VALUE) {
        ALOGV("%s: Buffer %" PRIu64 " is not owned", __FUNCTION__, buffer->getId());
        *outIsOwned = false;
        return NO_ERROR;
    } else if (slot < 0) {
        ALOGV("%s: Buffer %" PRIu64 " look up failed (%d)", __FUNCTION__, buffer->getId(), slot);
        *outIsOwned = false;
        return slot;
    }

    *outIsOwned = true;
    return NO_ERROR;
}

int Surface::attachBuffer(ANativeWindowBuffer* buffer)
{
    ATRACE_CALL();
    ALOGV("Surface::attachBuffer");
    sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));

    ALOGV("Surface::attachBuffer bufferId=%" PRIu64, graphicBuffer->getId());

    Mutex::Autolock lock(mMutex);
    if (mReportRemovedBuffers) {
        mRemovedBuffers.clear();
    }

    sp<GraphicBuffer> graphicBuffer(static_cast<GraphicBuffer*>(buffer));
    uint32_t priorGeneration = graphicBuffer->mGenerationNumber;
    graphicBuffer->mGenerationNumber = mGenerationNumber;
    int32_t attachedSlot = -1;
+3 −0
Original line number Diff line number Diff line
@@ -442,6 +442,9 @@ public:
    status_t detachBuffer(const sp<GraphicBuffer>& buffer);
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

    // Sets outIsOwned to true if the given buffer is currently known to be owned by this Surface.
    status_t isBufferOwned(const sp<GraphicBuffer>& buffer, bool* outIsOwned) const;

    // Batch version of dequeueBuffer, cancelBuffer and queueBuffer
    // Note that these batched operations are not supported when shared buffer mode is being used.
    struct BatchBuffer {
+53 −0
Original line number Diff line number Diff line
@@ -2653,4 +2653,57 @@ TEST_F(SurfaceTest, UnlimitedSlots_BatchOperations) {
    EXPECT_EQ(128u, outputs.size());
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_UNLIMITED_SLOTS)

TEST_F(SurfaceTest, isBufferOwned) {
    const int TEST_USAGE_FLAGS = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER;
    auto [bufferItemConsumer, surface] = BufferItemConsumer::create(TEST_USAGE_FLAGS);

    sp<SurfaceListener> listener = sp<StubSurfaceListener>::make();
    ASSERT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, listener));

    sp<GraphicBuffer> surfaceAttachableBuffer =
            sp<GraphicBuffer>::make(10, 10, PIXEL_FORMAT_RGBA_8888, 1, TEST_USAGE_FLAGS);

    //
    // Attaching a buffer makes it owned.
    //

    bool isOwned;
    EXPECT_EQ(OK, surface->isBufferOwned(surfaceAttachableBuffer, &isOwned));
    EXPECT_FALSE(isOwned);

    EXPECT_EQ(OK, surface->attachBuffer(surfaceAttachableBuffer.get()));
    EXPECT_EQ(OK, surface->isBufferOwned(surfaceAttachableBuffer, &isOwned));
    EXPECT_TRUE(isOwned);

    //
    // A dequeued buffer is always owned.
    //

    sp<GraphicBuffer> buffer;
    sp<Fence> fence;
    EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence));
    EXPECT_EQ(OK, surface->isBufferOwned(buffer, &isOwned));
    EXPECT_TRUE(isOwned);

    //
    // A detached buffer is no longer owned.
    //

    EXPECT_EQ(OK, surface->detachBuffer(buffer));
    EXPECT_EQ(OK, surface->isBufferOwned(buffer, &isOwned));
    EXPECT_FALSE(isOwned);

    //
    // It's not currently possible to verify whether or not a consumer has attached a buffer until
    // it shows up on the Surface.
    //

    sp<GraphicBuffer> consumerAttachableBuffer =
            sp<GraphicBuffer>::make(10, 10, PIXEL_FORMAT_RGBA_8888, 1, TEST_USAGE_FLAGS);

    ASSERT_EQ(OK, bufferItemConsumer->attachBuffer(consumerAttachableBuffer));
    EXPECT_EQ(OK, surface->isBufferOwned(consumerAttachableBuffer, &isOwned));
    EXPECT_FALSE(isOwned);
}
} // namespace android