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

Commit 67b4cff3 authored by Jamie Gennis's avatar Jamie Gennis Committed by Android (Google) Code Review
Browse files

Merge changes I9fb59763,I8b2c6e00

* changes:
  SurfaceTexture: consume buffers after err checks
  SurfaceTexture: change onFrameAvailable behavior
parents 124d3761 50c4efc2
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -46,11 +46,14 @@ public:
    enum { NUM_BUFFER_SLOTS = 32 };

    struct FrameAvailableListener : public virtual RefBase {
        // onFrameAvailable() is called from queueBuffer() is the FIFO is
        // empty. You can use SurfaceTexture::getQueuedCount() to
        // figure out if there are more frames waiting.
        // This is called without any lock held can be called concurrently by
        // multiple threads.
        // onFrameAvailable() is called from queueBuffer() each time an
        // additional frame becomes available for consumption. This means that
        // frames that are queued while in asynchronous mode only trigger the
        // callback if no previous frames are pending. Frames queued while in
        // synchronous mode always trigger the callback.
        //
        // This is called without any lock held and can be called concurrently
        // by multiple threads.
        virtual void onFrameAvailable() = 0;
    };

@@ -101,11 +104,6 @@ public:
    // target texture belongs is bound to the calling thread.
    status_t updateTexImage();

    // getqueuedCount returns the number of queued frames waiting in the
    // FIFO. In asynchronous mode, this always returns 0 or 1 since
    // frames are not accumulating in the FIFO.
    size_t getQueuedCount() const;

    // setBufferCountServer set the buffer count. If the client has requested
    // a buffer count using setBufferCount, the server-buffer count will
    // take effect once the client sets the count back to zero.
+20 −25
Original line number Diff line number Diff line
@@ -417,17 +417,22 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
            return -EINVAL;
        }

        if (mQueue.empty()) {
            listener = mFrameAvailableListener;
        }

        if (mSynchronousMode) {
            // in synchronous mode we queue all buffers in a FIFO
            // In synchronous mode we queue all buffers in a FIFO.
            mQueue.push_back(buf);

            // Synchronous mode always signals that an additional frame should
            // be consumed.
            listener = mFrameAvailableListener;
        } else {
            // in asynchronous mode we only keep the most recent buffer
            // In asynchronous mode we only keep the most recent buffer.
            if (mQueue.empty()) {
                mQueue.push_back(buf);

                // Asynchronous mode only signals that a frame should be
                // consumed if no previous frame was pending. If a frame were
                // pending then the consumer would have already been notified.
                listener = mFrameAvailableListener;
            } else {
                Fifo::iterator front(mQueue.begin());
                // buffer currently queued is freed
@@ -483,24 +488,14 @@ status_t SurfaceTexture::setTransform(uint32_t transform) {

status_t SurfaceTexture::updateTexImage() {
    LOGV("SurfaceTexture::updateTexImage");

    Mutex::Autolock lock(mMutex);

    int buf = mCurrentTexture;
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    if (!mQueue.empty()) {
        // in asynchronous mode the list is guaranteed to be one buffer deep,
        // while in synchronous mode we use the oldest buffer
        Fifo::iterator front(mQueue.begin());
        buf = *front;
        mQueue.erase(front);
        if (mQueue.isEmpty()) {
            mDequeueCondition.signal();
        }
    }
        int buf = *front;

    // Initially both mCurrentTexture and buf are INVALID_BUFFER_SLOT,
    // so this check will fail until a buffer gets queued.
    if (mCurrentTexture != buf) {
        // Update the GL texture object.
        EGLImageKHR image = mSlots[buf].mEglImage;
        if (image == EGL_NO_IMAGE_KHR) {
@@ -538,7 +533,7 @@ status_t SurfaceTexture::updateTexImage() {
        }

        if (mCurrentTexture != INVALID_BUFFER_SLOT) {
            // the current buffer becomes FREE if it was still in the queued
            // The current buffer becomes FREE if it was still in the queued
            // state. If it has already been given to the client
            // (synchronous mode), then it stays in DEQUEUED state.
            if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED)
@@ -553,17 +548,17 @@ status_t SurfaceTexture::updateTexImage() {
        mCurrentTransform = mSlots[buf].mTransform;
        mCurrentTimestamp = mSlots[buf].mTimestamp;
        computeCurrentTransformMatrix();

        // Now that we've passed the point at which failures can happen,
        // it's safe to remove the buffer from the front of the queue.
        mQueue.erase(front);
        mDequeueCondition.signal();
    } else {
        // We always bind the texture even if we don't update its contents.
        glBindTexture(mCurrentTextureTarget, mTexName);
    }
    return OK;
}

size_t SurfaceTexture::getQueuedCount() const {
    Mutex::Autolock lock(mMutex);
    return mQueue.size();
    return OK;
}

bool SurfaceTexture::isExternalFormat(uint32_t format)
+8 −11
Original line number Diff line number Diff line
@@ -101,10 +101,9 @@ Layer::~Layer()
}

void Layer::onFrameQueued() {
    if (android_atomic_or(1, &mQueuedFrames) == 0) {
    android_atomic_inc(&mQueuedFrames);
    mFlinger->signalEvent();
}
}

// called with SurfaceFlinger::mStateLock as soon as the layer is entered
// in the purgatory list
@@ -406,20 +405,18 @@ bool Layer::isCropped() const {

void Layer::lockPageFlip(bool& recomputeVisibleRegions)
{
    if (android_atomic_and(0, &mQueuedFrames)) {
    if (mQueuedFrames > 0) {
        // signal another event if we have more frames pending
        if (android_atomic_dec(&mQueuedFrames) > 1) {
            mFlinger->signalEvent();
        }

        if (mSurfaceTexture->updateTexImage() < NO_ERROR) {
            // something happened!
            recomputeVisibleRegions = true;
            return;
        }

        // signal another event if we have more frames waiting
        if (mSurfaceTexture->getQueuedCount()) {
            if (android_atomic_or(1, &mQueuedFrames) == 0) {
                mFlinger->signalEvent();
            }
        }

        mActiveBuffer = mSurfaceTexture->getCurrentBuffer();
        mSurfaceTexture->getTransformMatrix(mTextureMatrix);