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

Commit ea0de00d authored by Vishnu Nair's avatar Vishnu Nair
Browse files

BlastBufferQueue: Add buffer rejection

Second attempt at rejecting buffers that do not match layer size when
buffer scaling mode is set to freeze. If we dont reject the buffers,
the layer will scale the buffers incorrectly.

However we do not want to reject buffers that were rendered before the
size change. To prevent this, we gate the size change until we receive
the first buffer with the requested size.

Bug: 168504870
Test: atest SurfaceViewBufferTests libgui_test
Test: go/wm-tests, check logs for no rejected buffers

Change-Id: I3cc43b2bbf32b4fe6cd8d540967f217c0593aa57
parent b8871072
Loading
Loading
Loading
Loading
+26 −16
Original line number Diff line number Diff line
@@ -111,8 +111,8 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont
                                   int width, int height, bool enableTripleBuffering)
      : mName(name),
        mSurfaceControl(surface),
        mWidth(width),
        mHeight(height),
        mSize(width, height),
        mRequestedSize(mSize),
        mNextTransaction(nullptr) {
    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    // since the adapter is in the client process, set dequeue timeout
@@ -130,7 +130,7 @@ BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceCont
    mBufferItemConsumer->setName(String8(consumerName.c_str()));
    mBufferItemConsumer->setFrameAvailableListener(this);
    mBufferItemConsumer->setBufferFreedListener(this);
    mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
    mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);
    mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);

    mTransformHint = mSurfaceControl->getTransformHint();
@@ -146,10 +146,10 @@ void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, uint32_t width,
    std::unique_lock _lock{mMutex};
    mSurfaceControl = surface;

    if (mWidth != width || mHeight != height) {
        mWidth = width;
        mHeight = height;
        mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
    ui::Size newSize(width, height);
    if (mRequestedSize != newSize) {
        mRequestedSize.set(newSize);
        mBufferItemConsumer->setDefaultBufferSize(mRequestedSize.width, mRequestedSize.height);
    }
}

@@ -218,6 +218,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    // number of buffers.
    if (mNumFrameAvailable == 0 || maxBuffersAcquired()) {
        BQA_LOGV("processNextBufferLocked waiting for frame available or callback");
        mCallbackCV.notify_all();
        return;
    }

@@ -252,10 +253,13 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    }

    if (rejectBuffer(bufferItem)) {
        BQA_LOGE("rejecting buffer:configured size=%dx%d, buffer{size=%dx%d transform=%d}", mWidth,
                 mHeight, buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
        // TODO(b/168917217) temporarily don't reject buffers until we can synchronize buffer size
        // changes from ViewRootImpl.
        BQA_LOGE("rejecting buffer:active_size=%dx%d, requested_size=%dx%d"
                 "buffer{size=%dx%d transform=%d}",
                 mSize.width, mSize.height, mRequestedSize.width, mRequestedSize.height,
                 buffer->getWidth(), buffer->getHeight(), bufferItem.mTransform);
        mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
        processNextBufferLocked(useNextTransaction);
        return;
    }

    mNumAcquired++;
@@ -278,7 +282,7 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {
    t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));

    t->setFrame(mSurfaceControl,
                {0, 0, static_cast<int32_t>(mWidth), static_cast<int32_t>(mHeight)});
                {0, 0, static_cast<int32_t>(mSize.width), static_cast<int32_t>(mSize.height)});
    t->setCrop(mSurfaceControl, computeCrop(bufferItem));
    t->setTransform(mSurfaceControl, bufferItem.mTransform);
    t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
@@ -291,13 +295,13 @@ void BLASTBufferQueue::processNextBufferLocked(bool useNextTransaction) {

    BQA_LOGV("processNextBufferLocked size=%dx%d mFrameNumber=%" PRIu64
             " applyTransaction=%s mTimestamp=%" PRId64,
             mWidth, mHeight, bufferItem.mFrameNumber, toString(applyTransaction),
             mSize.width, mSize.height, bufferItem.mFrameNumber, toString(applyTransaction),
             bufferItem.mTimestamp);
}

Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
    if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
        return GLConsumer::scaleDownCrop(item.mCrop, mWidth, mHeight);
        return GLConsumer::scaleDownCrop(item.mCrop, mSize.width, mSize.height);
    }
    return item.mCrop;
}
@@ -332,8 +336,9 @@ void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t)
    mNextTransaction = t;
}

bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) const {
bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) {
    if (item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE) {
        mSize = mRequestedSize;
        // Only reject buffers if scaling mode is freeze.
        return false;
    }
@@ -345,9 +350,14 @@ bool BLASTBufferQueue::rejectBuffer(const BufferItem& item) const {
    if (item.mTransform & ui::Transform::ROT_90) {
        std::swap(bufWidth, bufHeight);
    }
    ui::Size bufferSize(bufWidth, bufHeight);
    if (mRequestedSize != mSize && mRequestedSize == bufferSize) {
        mSize = mRequestedSize;
        return false;
    }

    // reject buffers if the buffer size doesn't match.
    return bufWidth != mWidth || bufHeight != mHeight;
    return mSize != bufferSize;
}

// Check if we have acquired the maximum number of buffers.
+3 −3
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ private:
    void processNextBufferLocked(bool useNextTransaction) REQUIRES(mMutex);
    Rect computeCrop(const BufferItem& item) REQUIRES(mMutex);
    // Return true if we need to reject the buffer based on the scaling mode and the buffer size.
    bool rejectBuffer(const BufferItem& item) const REQUIRES(mMutex);
    bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
    bool maxBuffersAcquired() const REQUIRES(mMutex);

    std::string mName;
@@ -126,8 +126,8 @@ private:
    // is ready to be presented.
    PendingReleaseItem mPendingReleaseItem GUARDED_BY(mMutex);

    uint32_t mWidth GUARDED_BY(mMutex);
    uint32_t mHeight GUARDED_BY(mMutex);
    ui::Size mSize GUARDED_BY(mMutex);
    ui::Size mRequestedSize GUARDED_BY(mMutex);

    uint32_t mTransformHint GUARDED_BY(mMutex);

+11 −4
Original line number Diff line number Diff line
@@ -55,9 +55,9 @@ public:
        mBlastBufferQueueAdapter->setNextTransaction(next);
    }

    int getWidth() { return mBlastBufferQueueAdapter->mWidth; }
    int getWidth() { return mBlastBufferQueueAdapter->mSize.width; }

    int getHeight() { return mBlastBufferQueueAdapter->mHeight; }
    int getHeight() { return mBlastBufferQueueAdapter->mSize.height; }

    Transaction* getNextTransaction() { return mBlastBufferQueueAdapter->mNextTransaction; }

@@ -250,8 +250,15 @@ TEST_F(BLASTBufferQueueTest, Update) {
                                   PIXEL_FORMAT_RGBA_8888);
    adapter.update(updateSurface, mDisplayWidth / 2, mDisplayHeight / 2);
    ASSERT_EQ(updateSurface, adapter.getSurfaceControl());
    ASSERT_EQ(mDisplayWidth / 2, adapter.getWidth());
    ASSERT_EQ(mDisplayHeight / 2, adapter.getHeight());
    sp<IGraphicBufferProducer> igbProducer;
    setUpProducer(adapter, igbProducer);

    int32_t width;
    igbProducer->query(NATIVE_WINDOW_WIDTH, &width);
    ASSERT_EQ(mDisplayWidth / 2, width);
    int32_t height;
    igbProducer->query(NATIVE_WINDOW_HEIGHT, &height);
    ASSERT_EQ(mDisplayHeight / 2, height);
}

TEST_F(BLASTBufferQueueTest, SetNextTransaction) {
+1 −26
Original line number Diff line number Diff line
@@ -526,37 +526,12 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse
        return NO_ERROR;
    }

    const int32_t layerId = getSequence();

    // Reject if the layer is invalid
    uint32_t bufferWidth = s.buffer->width;
    uint32_t bufferHeight = s.buffer->height;

    if (s.transform & ui::Transform::ROT_90) {
        std::swap(bufferWidth, bufferHeight);
    }

    if (s.transformToDisplayInverse) {
        uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
        if (invTransform & ui::Transform::ROT_90) {
            std::swap(bufferWidth, bufferHeight);
        }
    }

    if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
        (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
        ALOGE("[%s] rejecting buffer: "
              "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
              getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h);
        mFlinger->mTimeStats->removeTimeRecord(layerId, mDrawingState.frameNumber);
        return BAD_VALUE;
    }

    for (auto& handle : mDrawingState.callbackHandles) {
        handle->latchTime = latchTime;
        handle->frameNumber = mDrawingState.frameNumber;
    }

    const int32_t layerId = getSequence();
    mFlinger->mTimeStats->setAcquireFence(layerId, mDrawingState.frameNumber,
                                          std::make_shared<FenceTime>(mDrawingState.acquireFence));
    mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime);