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

Commit dc5b485f authored by Jesse Hall's avatar Jesse Hall
Browse files

Pass fence to HWC on first use of buffer

Also do a CPU-wait on the fence before using it for GL composition.

Change-Id: I0f645a42a44803276cae11b904e5a26d65871562
parent b42b1ac1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -172,6 +172,10 @@ public:
    // getCurrentScalingMode returns the scaling mode of the current buffer.
    uint32_t getCurrentScalingMode() const;

    // getCurrentFence returns the fence indicating when the current buffer is
    // ready to be read from.
    sp<Fence> getCurrentFence() const;

    // isSynchronousMode returns whether the SurfaceTexture is currently in
    // synchronous mode.
    bool isSynchronousMode() const;
@@ -303,6 +307,9 @@ private:
    // set to each time updateTexImage is called.
    uint32_t mCurrentScalingMode;

    // mCurrentFence is the fence received from BufferQueue in updateTexImage.
    sp<Fence> mCurrentFence;

    // mCurrentTransformMatrix is the transform matrix for the current texture.
    // It gets computed by computeTransformMatrix each time updateTexImage is
    // called.
+6 −8
Original line number Diff line number Diff line
@@ -260,14 +260,6 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
            }
        }

        // Temporary; fence will be provided to clients soon
        if (item.mFence.get()) {
            err = item.mFence->wait(Fence::TIMEOUT_NEVER);
            if (err != OK) {
                ST_LOGE("updateTexImage: failure waiting for fence: %d", err);
            }
        }

        if (err == NO_ERROR) {
            GLint error;
            while ((error = glGetError()) != GL_NO_ERROR) {
@@ -322,6 +314,7 @@ status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
        mCurrentTransform = item.mTransform;
        mCurrentScalingMode = item.mScalingMode;
        mCurrentTimestamp = item.mTimestamp;
        mCurrentFence = item.mFence;
        computeCurrentTransformMatrix();
    } else  {
        if (err < 0) {
@@ -733,6 +726,11 @@ uint32_t SurfaceTexture::getCurrentScalingMode() const {
    return mCurrentScalingMode;
}

sp<Fence> SurfaceTexture::getCurrentFence() const {
    Mutex::Autolock lock(mMutex);
    return mCurrentFence;
}

bool SurfaceTexture::isSynchronousMode() const {
    Mutex::Autolock lock(mMutex);
    return mBufferQueue->isSynchronousMode();
+9 −0
Original line number Diff line number Diff line
@@ -350,6 +350,12 @@ public:
        // not supported on VERSION_03
        return -1;
    }
    virtual void setAcquireFenceFd(int fenceFd) {
        if (fenceFd != -1) {
            ALOGE("HWC 0.x can't handle acquire fences");
            close(fenceFd);
        }
    }

    virtual void setDefaultState() {
        getLayer()->compositionType = HWC_FRAMEBUFFER;
@@ -416,6 +422,9 @@ public:
        getLayer()->releaseFenceFd = -1;
        return fd;
    }
    virtual void setAcquireFenceFd(int fenceFd) {
        getLayer()->acquireFenceFd = fenceFd;
    }

    virtual void setDefaultState() {
        getLayer()->compositionType = HWC_FRAMEBUFFER;
+1 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ public:
        virtual void setCrop(const Rect& crop) = 0;
        virtual void setVisibleRegionScreen(const Region& reg) = 0;
        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
        virtual void setAcquireFenceFd(int fenceFd) = 0;
    };

    /*
+25 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ Layer::Layer(SurfaceFlinger* flinger,
        mCurrentOpacity(true),
        mRefreshPending(false),
        mFrameLatencyNeeded(false),
        mNeedHwcFence(false),
        mFrameLatencyOffset(0),
        mFormat(PIXEL_FORMAT_NONE),
        mGLExtensions(GLExtensions::getInstance()),
@@ -299,6 +300,20 @@ void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
    // NOTE: buffer can be NULL if the client never drew into this
    // layer yet, or if we ran out of memory
    layer.setBuffer(buffer);

    if (mNeedHwcFence) {
        sp<Fence> fence = mSurfaceTexture->getCurrentFence();
        if (fence.get()) {
            int fenceFd = fence->dup();
            if (fenceFd == -1) {
                ALOGW("failed to dup layer fence, skipping sync: %d", errno);
            }
            layer.setAcquireFenceFd(fenceFd);
        }
        mNeedHwcFence = false;
    } else {
        layer.setAcquireFenceFd(-1);
    }
}

void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
@@ -333,6 +348,15 @@ void Layer::onDraw(const DisplayHardware& hw, const Region& clip) const
        return;
    }

    // TODO: replace this with a server-side wait
    sp<Fence> fence = mSurfaceTexture->getCurrentFence();
    if (fence.get()) {
        status_t err = fence->wait(Fence::TIMEOUT_NEVER);
        ALOGW_IF(err != OK, "Layer::onDraw: failed waiting for fence: %d", err);
        // Go ahead and draw the buffer anyway; no matter what we do the screen
        // is probably going to have something visibly wrong.
    }

    if (!isProtected()) {
        // TODO: we could be more subtle with isFixedSize()
        const bool useFiltering = getFiltering() || needsFiltering() || isFixedSize();
@@ -627,6 +651,7 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)

        mRefreshPending = true;
        mFrameLatencyNeeded = true;
        mNeedHwcFence = true;
        if (oldActiveBuffer == NULL) {
             // the first time we receive a buffer, we need to trigger a
             // geometry invalidation.
Loading