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

Commit 083efd3c authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Add Blast FrameEventHistory tests to validate behavior for dropped frames

Also adds tests for BQ to check for functional parity.

Bug: n/a
Test: atest BLASTFrameEventHistoryTest
Change-Id: I1e8eb7d85f9ab442a0f16ac22d01fd310968d76a
parent a9b9fe40
Loading
Loading
Loading
Loading
+179 −4
Original line number Diff line number Diff line
@@ -129,7 +129,11 @@ protected:
    }

    void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) {
        auto igbProducer = adapter.getIGraphicBufferProducer();
        producer = adapter.getIGraphicBufferProducer();
        setUpProducer(producer);
    }

    void setUpProducer(sp<IGraphicBufferProducer>& igbProducer) {
        ASSERT_NE(nullptr, igbProducer.get());
        ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
        IGraphicBufferProducer::QueueBufferOutput qbOutput;
@@ -137,7 +141,6 @@ protected:
                  igbProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
                                       &qbOutput));
        ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
        producer = igbProducer;
    }

    void fillBuffer(uint32_t* bufData, Rect rect, uint32_t stride, uint8_t r, uint8_t g,
@@ -555,6 +558,8 @@ TEST_F(BLASTBufferQueueTest, QueryNativeWindowQueuesToWindowComposer) {
    ASSERT_EQ(queuesToNativeWindow, 1);
}

// Test a slow producer doesn't hold up a faster producer from the same client. Essentially tests
// BBQ uses separate transaction queues.
TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) {
    sp<SurfaceControl> bgSurface =
            mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
@@ -781,7 +786,7 @@ public:
    void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer,
                             nsecs_t* requestedPresentTime, nsecs_t* postedTime,
                             IGraphicBufferProducer::QueueBufferOutput* qbOutput,
                             bool getFrameTimestamps) {
                             bool getFrameTimestamps, nsecs_t requestedPresentTimeDelay = 0) {
        int slot;
        sp<Fence> fence;
        sp<GraphicBuffer> buf;
@@ -791,7 +796,7 @@ public:
        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
        ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));

        nsecs_t requestedTime = systemTime();
        nsecs_t requestedTime = systemTime() + requestedPresentTimeDelay;
        if (requestedPresentTime) *requestedPresentTime = requestedTime;
        IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN,
                                                       Rect(mDisplayWidth, mDisplayHeight),
@@ -801,6 +806,27 @@ public:
        if (postedTime) *postedTime = systemTime();
        igbProducer->queueBuffer(slot, input, qbOutput);
    }

    void createBufferQueueProducer(sp<IGraphicBufferProducer>* bqIgbp) {
        mBufferQueueSurfaceControl =
                mClient->createSurface(String8("BqSurface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
                                       ISurfaceComposerClient::eFXSurfaceBufferQueue);
        ASSERT_NE(nullptr, mBufferQueueSurfaceControl.get());
        Transaction()
                .setLayerStack(mBufferQueueSurfaceControl, 0)
                .show(mBufferQueueSurfaceControl)
                .setDataspace(mBufferQueueSurfaceControl, ui::Dataspace::V0_SRGB)
                .setSize(mBufferQueueSurfaceControl, mDisplayWidth, mDisplayHeight)
                .setLayer(mBufferQueueSurfaceControl, std::numeric_limits<int32_t>::max())
                .apply();

        sp<Surface> bqSurface = mBufferQueueSurfaceControl->getSurface();
        ASSERT_NE(nullptr, bqSurface.get());

        *bqIgbp = bqSurface->getIGraphicBufferProducer();
        setUpProducer(*bqIgbp);
    }
    sp<SurfaceControl> mBufferQueueSurfaceControl;
};

TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) {
@@ -853,4 +879,153 @@ TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) {
    // wait for any callbacks that have not been received
    adapter.waitForCallbacks();
}

// Runs the same Frame Event History test
TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic_BufferQueue) {
    sp<IGraphicBufferProducer> bqIgbp;
    createBufferQueueProducer(&bqIgbp);

    ProducerFrameEventHistory history;
    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    nsecs_t requestedPresentTimeA = 0;
    nsecs_t postedTimeA = 0;
    setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
    history.applyDelta(qbOutput.frameTimestamps);

    FrameEvents* events = nullptr;
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    // wait for buffer to be presented
    std::this_thread::sleep_for(200ms);

    nsecs_t requestedPresentTimeB = 0;
    nsecs_t postedTimeB = 0;
    setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
    history.applyDelta(qbOutput.frameTimestamps);
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);

    // frame number, requestedPresentTime, and postTime should not have changed
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    ASSERT_GE(events->latchTime, postedTimeA);
    ASSERT_FALSE(events->hasDequeueReadyInfo());

    ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
    ASSERT_NE(nullptr, events->displayPresentFence);
    ASSERT_NE(nullptr, events->releaseFence);

    // we should also have gotten the initial values for the next frame
    events = history.getFrame(2);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(2, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeB);
}

TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) {
    BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
    sp<IGraphicBufferProducer> igbProducer;
    setUpProducer(adapter, igbProducer);

    ProducerFrameEventHistory history;
    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    nsecs_t requestedPresentTimeA = 0;
    nsecs_t postedTimeA = 0;
    nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
                        presentTimeDelay);
    history.applyDelta(qbOutput.frameTimestamps);

    FrameEvents* events = nullptr;
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    // queue another buffer so the first can be dropped
    nsecs_t requestedPresentTimeB = 0;
    nsecs_t postedTimeB = 0;
    setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
    history.applyDelta(qbOutput.frameTimestamps);
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);

    // frame number, requestedPresentTime, and postTime should not have changed
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    // a valid latchtime should not be set
    ASSERT_FALSE(events->hasLatchInfo());
    ASSERT_FALSE(events->hasDequeueReadyInfo());

    ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
    ASSERT_NE(nullptr, events->displayPresentFence);
    ASSERT_NE(nullptr, events->releaseFence);

    // we should also have gotten the initial values for the next frame
    events = history.getFrame(2);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(2, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeB);
}

TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame_BufferQueue) {
    sp<IGraphicBufferProducer> bqIgbp;
    createBufferQueueProducer(&bqIgbp);

    ProducerFrameEventHistory history;
    IGraphicBufferProducer::QueueBufferOutput qbOutput;
    nsecs_t requestedPresentTimeA = 0;
    nsecs_t postedTimeA = 0;
    nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
    setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
                        presentTimeDelay);
    history.applyDelta(qbOutput.frameTimestamps);

    FrameEvents* events = nullptr;
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    // queue another buffer so the first can be dropped
    nsecs_t requestedPresentTimeB = 0;
    nsecs_t postedTimeB = 0;
    setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
    history.applyDelta(qbOutput.frameTimestamps);
    events = history.getFrame(1);
    ASSERT_NE(nullptr, events);

    // frame number, requestedPresentTime, and postTime should not have changed
    ASSERT_EQ(1, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeA);

    // a valid latchtime should not be set
    ASSERT_FALSE(events->hasLatchInfo());
    ASSERT_FALSE(events->hasDequeueReadyInfo());

    ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
    ASSERT_NE(nullptr, events->displayPresentFence);
    ASSERT_NE(nullptr, events->releaseFence);

    // we should also have gotten the initial values for the next frame
    events = history.getFrame(2);
    ASSERT_NE(nullptr, events);
    ASSERT_EQ(2, events->frameNumber);
    ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
    ASSERT_GE(events->postedTime, postedTimeB);
}

} // namespace android