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

Commit b71a4beb authored by Jamie Gennis's avatar Jamie Gennis
Browse files

SurfaceTexture: add a deadlock scenario test

This change adds a test to ensure that a GL driver that's blocking on a
call to dequeueBuffer does not block other GL threads from rendering and
queueing buffers.

Change-Id: Ifdd234effc534b6a9cf8522ca87f64da5bb0bbd6
parent e333d3c8
Loading
Loading
Loading
Loading
+70 −4
Original line number Diff line number Diff line
@@ -1205,7 +1205,7 @@ protected:
    sp<FrameCondition> mFC;
};

TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) {
    class PT : public ProducerThread {
        virtual void render() {
            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1223,7 +1223,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageBeforeFrameFinishedWorks) {
    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}

TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedCompletes) {
    class PT : public ProducerThread {
        virtual void render() {
            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
@@ -1241,7 +1241,7 @@ TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
}

TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) {
    enum { NUM_ITERATIONS = 1024 };

    class PT : public ProducerThread {
@@ -1269,7 +1269,7 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedWorks)
    }
}

TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks) {
TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) {
    enum { NUM_ITERATIONS = 1024 };

    class PT : public ProducerThread {
@@ -1297,4 +1297,70 @@ TEST_F(SurfaceTextureGLToGLTest, RepeatedUpdateTexImageAfterFrameFinishedWorks)
    }
}

// XXX: This test is disabled because it is currently hanging on some devices.
TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) {
    enum { NUM_ITERATIONS = 64 };

    class PT : public ProducerThread {
        virtual void render() {
            for (int i = 0; i < NUM_ITERATIONS; i++) {
                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
                glClear(GL_COLOR_BUFFER_BIT);
                LOGV("+swapBuffers");
                swapBuffers();
                LOGV("-swapBuffers");
            }
        }
    };

    ASSERT_EQ(OK, mST->setSynchronousMode(true));
    ASSERT_EQ(OK, mST->setBufferCountServer(2));

    runProducerThread(new PT());

    // Allow three frames to be rendered and queued before starting the
    // rendering in this thread.  For the latter two frames we don't call
    // updateTexImage so the next dequeue from the producer thread will block
    // waiting for a frame to become available.
    mFC->waitForFrame();
    mFC->finishFrame();

    // We must call updateTexImage to consume the first frame so that the
    // SurfaceTexture is able to reduce the buffer count to 2.  This is because
    // the GL driver may dequeue a buffer when the EGLSurface is created, and
    // that happens before we call setBufferCountServer.  It's possible that the
    // driver does not dequeue a buffer at EGLSurface creation time, so we
    // cannot rely on this to cause the second dequeueBuffer call to block.
    mST->updateTexImage();

    mFC->waitForFrame();
    mFC->finishFrame();
    mFC->waitForFrame();
    mFC->finishFrame();

    // Sleep for 100ms to allow the producer thread's dequeueBuffer call to
    // block waiting for a buffer to become available.
    usleep(100000);

    // Render and present a number of images.  This thread should not be blocked
    // by the fact that the producer thread is blocking in dequeue.
    for (int i = 0; i < NUM_ITERATIONS; i++) {
        glClear(GL_COLOR_BUFFER_BIT);
        eglSwapBuffers(mEglDisplay, mEglSurface);
    }

    // Consume the two pending buffers to unblock the producer thread.
    mST->updateTexImage();
    mST->updateTexImage();

    // Consume the remaining buffers from the producer thread.
    for (int i = 0; i < NUM_ITERATIONS-3; i++) {
        mFC->waitForFrame();
        mFC->finishFrame();
        LOGV("+updateTexImage");
        mST->updateTexImage();
        LOGV("-updateTexImage");
    }
}

} // namespace android