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

Commit 538cedc3 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

BufferQueue: handle consumer driven size for pre-rotation

This change adds an option for the producer to set auto pre-rotation on the
buffers to be allocated. When auto pre-rotation is enabled, if the current
buffer size is driven by the consumer and there's 90 or 270 degree rotation
specified in the transform hint currently used by the producer, then the
dimension of the buffers to be allocated will be additionally swapped upon
buffers pre-allocaton or dequeueBuffer.

Auto prerotaion will be cached at Surface producer side, and will be
reset to false upon Surface disconnection.

Bug: 129422697
Test: atest libgui_test:SurfaceTest#DequeueWithConsumerDrivenSize

Change-Id: I01ddf3e00d5951935e557d18932ea9869f36b5d6
parent 0f400276
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -97,7 +97,9 @@ BufferQueueCore::BufferQueueCore() :
    mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
            HAL_DATASPACE_UNKNOWN),
    mLastQueuedSlot(INVALID_BUFFER_SLOT),
    mUniqueId(getUniqueId())
    mUniqueId(getUniqueId()),
    mAutoPrerotation(false),
    mTransformHintInUse(0)
{
    int numStartingBuffers = getMaxBufferCountLocked();
    for (int s = 0; s < numStartingBuffers; s++) {
@@ -123,10 +125,12 @@ void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const
                            mQueueBufferCanDrop, mLegacyBufferDrop);
    outResult->appendFormat("%s  default-size=[%dx%d] default-format=%d ", prefix.string(),
                            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat);
    outResult->appendFormat("transform-hint=%02x frame-counter=%" PRIu64, mTransformHint,
                            mFrameCounter);
    outResult->appendFormat("%s  transform-hint=%02x frame-counter=%" PRIu64 "\n", prefix.string(),
                            mTransformHint, mFrameCounter);
    outResult->appendFormat("%s  mTransformHintInUse=%02x mAutoPrerotation=%d\n", prefix.string(),
                            mTransformHintInUse, mAutoPrerotation);

    outResult->appendFormat("\n%sFIFO(%zu):\n", prefix.string(), mQueue.size());
    outResult->appendFormat("%sFIFO(%zu):\n", prefix.string(), mQueue.size());
    Fifo::const_iterator current(mQueue.begin());
    while (current != mQueue.end()) {
        double timestamp = current->mTimestamp / 1e9;
+29 −2
Original line number Diff line number Diff line
@@ -408,6 +408,10 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp<android::Fence>* ou
        if (useDefaultSize) {
            width = mCore->mDefaultWidth;
            height = mCore->mDefaultHeight;
            if (mCore->mAutoPrerotation &&
                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
                std::swap(width, height);
            }
        }

        int found = BufferItem::INVALID_BUFFER_SLOT;
@@ -951,7 +955,7 @@ status_t BufferQueueProducer::queueBuffer(int slot,

        output->width = mCore->mDefaultWidth;
        output->height = mCore->mDefaultHeight;
        output->transformHint = mCore->mTransformHint;
        output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
        output->numPendingBuffers = static_cast<uint32_t>(mCore->mQueue.size());
        output->nextFrameNumber = mCore->mFrameCounter + 1;

@@ -1194,7 +1198,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener,

            output->width = mCore->mDefaultWidth;
            output->height = mCore->mDefaultHeight;
            output->transformHint = mCore->mTransformHint;
            output->transformHint = mCore->mTransformHintInUse = mCore->mTransformHint;
            output->numPendingBuffers =
                    static_cast<uint32_t>(mCore->mQueue.size());
            output->nextFrameNumber = mCore->mFrameCounter + 1;
@@ -1298,6 +1302,7 @@ status_t BufferQueueProducer::disconnect(int api, DisconnectMode mode) {
                    mCore->mConnectedPid = -1;
                    mCore->mSidebandStream.clear();
                    mCore->mDequeueCondition.notify_all();
                    mCore->mAutoPrerotation = false;
                    listener = mCore->mConsumerListener;
                } else if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
                    BQ_LOGE("disconnect: not connected (req=%d)", api);
@@ -1341,6 +1346,8 @@ status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream)
void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
        PixelFormat format, uint64_t usage) {
    ATRACE_CALL();

    const bool useDefaultSize = !width && !height;
    while (true) {
        size_t newBufferCount = 0;
        uint32_t allocWidth = 0;
@@ -1367,6 +1374,11 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,

            allocWidth = width > 0 ? width : mCore->mDefaultWidth;
            allocHeight = height > 0 ? height : mCore->mDefaultHeight;
            if (useDefaultSize && mCore->mAutoPrerotation &&
                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
                std::swap(allocWidth, allocHeight);
            }

            allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
            allocUsage = usage | mCore->mConsumerUsageBits;
            allocName.assign(mCore->mConsumerName.string(), mCore->mConsumerName.size());
@@ -1397,6 +1409,11 @@ void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
            std::unique_lock<std::mutex> lock(mCore->mMutex);
            uint32_t checkWidth = width > 0 ? width : mCore->mDefaultWidth;
            uint32_t checkHeight = height > 0 ? height : mCore->mDefaultHeight;
            if (useDefaultSize && mCore->mAutoPrerotation &&
                (mCore->mTransformHintInUse & NATIVE_WINDOW_TRANSFORM_ROT_90)) {
                std::swap(checkWidth, checkHeight);
            }

            PixelFormat checkFormat = format != 0 ?
                    format : mCore->mDefaultBufferFormat;
            uint64_t checkUsage = usage | mCore->mConsumerUsageBits;
@@ -1599,4 +1616,14 @@ status_t BufferQueueProducer::getConsumerUsage(uint64_t* outUsage) const {
    return NO_ERROR;
}

status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) {
    ATRACE_CALL();
    BQ_LOGV("setAutoPrerotation: %d", autoPrerotation);

    std::lock_guard<std::mutex> lock(mCore->mMutex);

    mCore->mAutoPrerotation = autoPrerotation;
    return NO_ERROR;
}

} // namespace android
+29 −0
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ enum {
    GET_UNIQUE_ID,
    GET_CONSUMER_USAGE,
    SET_LEGACY_BUFFER_DROP,
    SET_AUTO_PREROTATION,
};

class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -547,6 +548,17 @@ public:
        }
        return actualResult;
    }

    virtual status_t setAutoPrerotation(bool autoPrerotation) {
        Parcel data, reply;
        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
        data.writeBool(autoPrerotation);
        status_t result = remote()->transact(SET_AUTO_PREROTATION, data, &reply);
        if (result == NO_ERROR) {
            result = reply.readInt32();
        }
        return result;
    }
};

// Out-of-line virtual method definition to trigger vtable emission in this
@@ -675,6 +687,10 @@ public:
    status_t getConsumerUsage(uint64_t* outUsage) const override {
        return mBase->getConsumerUsage(outUsage);
    }

    status_t setAutoPrerotation(bool autoPrerotation) override {
        return mBase->setAutoPrerotation(autoPrerotation);
    }
};

IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer,
@@ -688,6 +704,12 @@ status_t IGraphicBufferProducer::setLegacyBufferDrop(bool drop) {
    return INVALID_OPERATION;
}

status_t IGraphicBufferProducer::setAutoPrerotation(bool autoPrerotation) {
    // No-op for IGBP other than BufferQueue.
    (void)autoPrerotation;
    return INVALID_OPERATION;
}

status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) {
    status_t res = OK;
    res = parcel->writeUint32(USE_BUFFER_QUEUE);
@@ -1050,6 +1072,13 @@ status_t BnGraphicBufferProducer::onTransact(
            reply->writeInt32(result);
            return NO_ERROR;
        }
        case SET_AUTO_PREROTATION: {
            CHECK_INTERFACE(IGraphicBuffer, data, reply);
            bool autoPrerotation = data.readBool();
            status_t result = setAutoPrerotation(autoPrerotation);
            reply->writeInt32(result);
            return NO_ERROR;
        }
    }
    return BBinder::onTransact(code, data, reply, flags);
}
+27 −0
Original line number Diff line number Diff line
@@ -1072,6 +1072,9 @@ int Surface::perform(int operation, va_list args)
    case NATIVE_WINDOW_GET_CONSUMER_USAGE64:
        res = dispatchGetConsumerUsage64(args);
        break;
    case NATIVE_WINDOW_SET_AUTO_PREROTATION:
        res = dispatchSetAutoPrerotation(args);
        break;
    default:
        res = NAME_NOT_FOUND;
        break;
@@ -1272,6 +1275,11 @@ int Surface::dispatchGetConsumerUsage64(va_list args) {
    return getConsumerUsage(usage);
}

int Surface::dispatchSetAutoPrerotation(va_list args) {
    bool autoPrerotation = va_arg(args, int);
    return setAutoPrerotation(autoPrerotation);
}

bool Surface::transformToDisplayInverse() {
    return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
            NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
@@ -1339,6 +1347,7 @@ int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
        mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
        mTransform = 0;
        mStickyTransform = 0;
        mAutoPrerotation = false;

        if (api == NATIVE_WINDOW_API_CPU) {
            mConnectedToCpu = false;
@@ -1941,4 +1950,22 @@ status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffe
    return err;
}

int Surface::setAutoPrerotation(bool autoPrerotation) {
    ATRACE_CALL();
    ALOGV("Surface::setAutoPrerotation (%d)", autoPrerotation);
    Mutex::Autolock lock(mMutex);

    if (mAutoPrerotation == autoPrerotation) {
        return OK;
    }

    status_t err = mGraphicBufferProducer->setAutoPrerotation(autoPrerotation);
    if (err == NO_ERROR) {
        mAutoPrerotation = autoPrerotation;
    }
    ALOGE_IF(err, "IGraphicBufferProducer::setAutoPrerotation(%d) returned %s", autoPrerotation,
             strerror(-err));
    return err;
}

}; // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -348,6 +348,14 @@ private:

    const uint64_t mUniqueId;

    // When buffer size is driven by the consumer and mTransformHint specifies
    // a 90 or 270 degree rotation, this indicates whether the width and height
    // used by dequeueBuffer will be additionally swapped.
    bool mAutoPrerotation;

    // mTransformHintInUse is to cache the mTransformHint used by the producer.
    uint32_t mTransformHintInUse;

}; // class BufferQueueCore

} // namespace android
Loading