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

Commit 52ef3e02 authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge changes Iaa0846b8,Id9420941

* changes:
  Remove extra isCurrent calls.
  Move image creation out of latchBuffer().
parents e588e318 1dd1b879
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ private:

    virtual void setFilteringEnabled(bool enabled) = 0;

    virtual status_t bindTextureImage() const = 0;
    virtual status_t bindTextureImage() = 0;
    virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                                    const sp<Fence>& flushFence) = 0;

+53 −68
Original line number Diff line number Diff line
@@ -111,12 +111,6 @@ status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t e
        return NO_INIT;
    }

    // Make sure RenderEngine is current
    if (!mRE.isCurrent()) {
        BLC_LOGE("updateTexImage: RenderEngine is not current");
        return INVALID_OPERATION;
    }

    BufferItem item;

    // Acquire the next buffer.
@@ -185,8 +179,7 @@ void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
        return;
    }

    auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
                                            : mCurrentTextureImage->graphicBuffer();
    auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer : mCurrentTextureBuffer;
    auto err = addReleaseFence(slot, buffer, fence);
    if (err != OK) {
        BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
@@ -222,10 +215,9 @@ status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t pres
    }

    // If item->mGraphicBuffer is not null, this buffer has not been acquired
    // before, so any prior EglImage created is using a stale buffer. This
    // replaces any old EglImage with a new one (using the new buffer).
    // before.
    if (item->mGraphicBuffer != nullptr) {
        mImages[item->mSlot] = new Image(item->mGraphicBuffer, mRE);
        mImages[item->mSlot] = nullptr;
    }

    return NO_ERROR;
@@ -252,19 +244,18 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
    }

    BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
             mCurrentTextureImage != nullptr ? mCurrentTextureImage->graphicBufferHandle() : 0,
             slot, mSlots[slot].mGraphicBuffer->handle);
             mCurrentTextureBuffer != nullptr ? mCurrentTextureBuffer->handle : 0, slot,
             mSlots[slot].mGraphicBuffer->handle);

    // Hang onto the pointer so that it isn't freed in the call to
    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
    // the same.
    sp<Image> nextTextureImage = mImages[slot];
    sp<GraphicBuffer> nextTextureBuffer = mSlots[slot].mGraphicBuffer;

    // release old buffer
    if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
        if (pendingRelease == nullptr) {
            status_t status =
                    releaseBufferLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer());
            status_t status = releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer);
            if (status < NO_ERROR) {
                BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
                         status);
@@ -273,14 +264,15 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
            }
        } else {
            pendingRelease->currentTexture = mCurrentTexture;
            pendingRelease->graphicBuffer = mCurrentTextureImage->graphicBuffer();
            pendingRelease->graphicBuffer = mCurrentTextureBuffer;
            pendingRelease->isPending = true;
        }
    }

    // Update the BufferLayerConsumer state.
    mCurrentTexture = slot;
    mCurrentTextureImage = nextTextureImage;
    mCurrentTextureBuffer = nextTextureBuffer;
    mCurrentTextureImageFreed = nullptr;
    mCurrentCrop = item.mCrop;
    mCurrentTransform = item.mTransform;
    mCurrentScalingMode = item.mScalingMode;
@@ -301,22 +293,46 @@ status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,

status_t BufferLayerConsumer::bindTextureImageLocked() {
    ATRACE_CALL();

    mRE.checkErrors();

    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureImage == nullptr) {
    // It is possible for the current slot's buffer to be freed before a new one
    // is bound. In that scenario we still want to bind the image.
    if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureBuffer == nullptr) {
        BLC_LOGE("bindTextureImage: no currently-bound texture");
        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
        return NO_INIT;
    }

    status_t err = mCurrentTextureImage->createIfNeeded();
    if (err != NO_ERROR) {
    renderengine::Image* imageToRender;

    // mCurrentTextureImageFreed is non-null iff mCurrentTexture ==
    // BufferQueue::INVALID_BUFFER_SLOT, so we can omit that check.
    if (mCurrentTextureImageFreed) {
        imageToRender = mCurrentTextureImageFreed.get();
    } else if (mImages[mCurrentTexture]) {
        imageToRender = mImages[mCurrentTexture].get();
    } else {
        std::unique_ptr<renderengine::Image> image = mRE.createImage();
        bool success = image->setNativeWindowBuffer(mCurrentTextureBuffer->getNativeBuffer(),
                                                    mCurrentTextureBuffer->getUsage() &
                                                            GRALLOC_USAGE_PROTECTED);
        if (!success) {
            BLC_LOGE("bindTextureImage: Failed to create image. size=%ux%u st=%u usage=%#" PRIx64
                     " fmt=%d",
                     mCurrentTextureBuffer->getWidth(), mCurrentTextureBuffer->getHeight(),
                     mCurrentTextureBuffer->getStride(), mCurrentTextureBuffer->getUsage(),
                     mCurrentTextureBuffer->getPixelFormat());
            BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
        mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
            mRE.bindExternalTextureImage(mTexName, *image);
            return UNKNOWN_ERROR;
        }
        imageToRender = image.get();
        // Cache the image here so that we can reuse it.
        mImages[mCurrentTexture] = std::move(image);
    }

    mRE.bindExternalTextureImage(mTexName, mCurrentTextureImage->image());
    mRE.bindExternalTextureImage(mTexName, *imageToRender);

    // Wait for the new buffer to be ready.
    return doFenceWaitLocked();
@@ -333,8 +349,7 @@ status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence
                return UNKNOWN_ERROR;
            }
            status_t err =
                    addReleaseFenceLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
                                          releaseFence);
                    addReleaseFenceLocked(mCurrentTexture, mCurrentTextureBuffer, releaseFence);
            if (err != OK) {
                BLC_LOGE("syncForReleaseLocked: error adding release fence: "
                         "%s (%d)",
@@ -361,24 +376,22 @@ void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
    bool needsRecompute = mFilteringEnabled != enabled;
    mFilteringEnabled = enabled;

    if (needsRecompute && mCurrentTextureImage == nullptr) {
        BLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == nullptr");
    if (needsRecompute && mCurrentTextureBuffer == nullptr) {
        BLC_LOGD("setFilteringEnabled called with mCurrentTextureBuffer == nullptr");
    }

    if (needsRecompute && mCurrentTextureImage != nullptr) {
    if (needsRecompute && mCurrentTextureBuffer != nullptr) {
        computeCurrentTransformMatrixLocked();
    }
}

void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
    BLC_LOGV("computeCurrentTransformMatrixLocked");
    sp<GraphicBuffer> buf =
            (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
    if (buf == nullptr) {
    if (mCurrentTextureBuffer == nullptr) {
        BLC_LOGD("computeCurrentTransformMatrixLocked: "
                 "mCurrentTextureImage is nullptr");
                 "mCurrentTextureBuffer is nullptr");
    }
    GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, buf, mCurrentCrop,
    GLConsumer::computeTransformMatrix(mCurrentTransformMatrix, mCurrentTextureBuffer, mCurrentCrop,
                                       mCurrentTransform, mFilteringEnabled);
}

@@ -427,7 +440,7 @@ sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
        *outSlot = mCurrentTexture;
    }

    return (mCurrentTextureImage == nullptr) ? nullptr : mCurrentTextureImage->graphicBuffer();
    return mCurrentTextureBuffer;
}

Rect BufferLayerConsumer::getCurrentCrop() const {
@@ -458,11 +471,6 @@ std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
}

status_t BufferLayerConsumer::doFenceWaitLocked() const {
    if (!mRE.isCurrent()) {
        BLC_LOGE("doFenceWait: RenderEngine is not current");
        return INVALID_OPERATION;
    }

    if (mCurrentFence->isValid()) {
        if (mRE.useWaitSync()) {
            base::unique_fd fenceFd(mCurrentFence->dup());
@@ -490,8 +498,10 @@ void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
    BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
    if (slotIndex == mCurrentTexture) {
        mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
        mCurrentTextureImageFreed = std::move(mImages[slotIndex]);
    } else {
        mImages[slotIndex] = nullptr;
    }
    mImages[slotIndex].clear();
    ConsumerBase::freeBufferLocked(slotIndex);
}

@@ -530,7 +540,7 @@ void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* ne

void BufferLayerConsumer::abandonLocked() {
    BLC_LOGV("abandonLocked");
    mCurrentTextureImage.clear();
    mCurrentTextureBuffer.clear();
    ConsumerBase::abandonLocked();
}

@@ -548,29 +558,4 @@ void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const
    ConsumerBase::dumpLocked(result, prefix);
}

BufferLayerConsumer::Image::Image(sp<GraphicBuffer> graphicBuffer,
                                  renderengine::RenderEngine& engine)
      : mGraphicBuffer(graphicBuffer),
        mImage{engine.createImage()},
        mCreated(false),
        mCropWidth(0),
        mCropHeight(0) {}

BufferLayerConsumer::Image::~Image() = default;

status_t BufferLayerConsumer::Image::createIfNeeded() {
    if (mCreated) return OK;

    mCreated = mImage->setNativeWindowBuffer(mGraphicBuffer->getNativeBuffer(),
                                             mGraphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED);
    if (!mCreated) {
        const sp<GraphicBuffer>& buffer = mGraphicBuffer;
        ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
              buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
              buffer->getPixelFormat());
    }

    return mCreated ? OK : UNKNOWN_ERROR;
}

}; // namespace android
+17 −55
Original line number Diff line number Diff line
@@ -185,8 +185,7 @@ protected:
    // specific info in addition to the ConsumerBase behavior.
    virtual void dumpLocked(String8& result, const char* prefix) const;

    // acquireBufferLocked overrides the ConsumerBase method to update the
    // mImages array in addition to the ConsumerBase behavior.
    // See ConsumerBase::acquireBufferLocked
    virtual status_t acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
                                         uint64_t maxFrameNumber = 0) override;

@@ -210,53 +209,14 @@ protected:
                                    PendingRelease* pendingRelease = nullptr,
                                    const sp<Fence>& releaseFence = Fence::NO_FENCE);

    // Binds mTexName and the current buffer to TEXTURE_EXTERNAL target.  Uses
    // mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
    // bind succeeds, this calls doFenceWait.
    // Binds mTexName and the current buffer to TEXTURE_EXTERNAL target.
    // If the bind succeeds, this calls doFenceWait.
    status_t bindTextureImageLocked();

private:
    // Image is a utility class for tracking and creating renderengine::Images. There
    // is primarily just one image per slot, but there is also special cases:
    //  - After freeBuffer, we must still keep the current image/buffer
    // Reference counting renderengine::Images lets us handle all these cases easily while
    // also only creating new renderengine::Images from buffers when required.
    class Image : public LightRefBase<Image> {
    public:
        Image(sp<GraphicBuffer> graphicBuffer, renderengine::RenderEngine& engine);

        Image(const Image& rhs) = delete;
        Image& operator=(const Image& rhs) = delete;

        // createIfNeeded creates an renderengine::Image if we haven't created one yet.
        status_t createIfNeeded();

        const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
        const native_handle* graphicBufferHandle() {
            return mGraphicBuffer == nullptr ? nullptr : mGraphicBuffer->handle;
        }

        const renderengine::Image& image() const { return *mImage; }

    private:
        // Only allow instantiation using ref counting.
        friend class LightRefBase<Image>;
        virtual ~Image();

        // mGraphicBuffer is the buffer that was used to create this image.
        sp<GraphicBuffer> mGraphicBuffer;

        // mImage is the image created from mGraphicBuffer.
        std::unique_ptr<renderengine::Image> mImage;
        bool mCreated;
        int32_t mCropWidth;
        int32_t mCropHeight;
    };

    // freeBufferLocked frees up the given buffer slot. If the slot has been
    // initialized this will release the reference to the GraphicBuffer in
    // that slot and destroy the renderengine::Image in that slot.  Otherwise it has no
    // effect.
    // that slot.  Otherwise it has no effect.
    //
    // This method must be called with mMutex locked.
    virtual void freeBufferLocked(int slotIndex);
@@ -290,10 +250,10 @@ private:
    // consume buffers as hardware textures.
    static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;

    // mCurrentTextureImage is the Image/buffer of the current texture. It's
    // mCurrentTextureImage is the buffer containing the current texture. It's
    // possible that this buffer is not associated with any buffer slot, so we
    // must track it separately in order to support the getCurrentBuffer method.
    sp<Image> mCurrentTextureImage;
    sp<GraphicBuffer> mCurrentTextureBuffer;

    // mCurrentCrop is the crop rectangle that applies to the current texture.
    // It gets set each time updateTexImage is called.
@@ -363,15 +323,6 @@ private:

    wp<ContentsChangedListener> mContentsChangedListener;

    // mImages stores the buffers that have been allocated by the BufferQueue
    // for each buffer slot.  It is initialized to null pointers, and gets
    // filled in with the result of BufferQueue::acquire when the
    // client dequeues a buffer from a
    // slot that has not yet been used. The buffer allocated to a slot will also
    // be replaced if the requested buffer usage or geometry differs from that
    // of the buffer allocated to a slot.
    sp<Image> mImages[BufferQueueDefs::NUM_BUFFER_SLOTS];

    // mCurrentTexture is the buffer slot index of the buffer that is currently
    // bound to the RenderEngine texture. It is initialized to INVALID_BUFFER_SLOT,
    // indicating that no buffer slot is currently bound to the texture. Note,
@@ -380,6 +331,17 @@ private:
    // reset mCurrentTexture to INVALID_BUFFER_SLOT.
    int mCurrentTexture;

    // Cached image used for rendering the current texture through GPU
    // composition, which contains the cached image after freeBufferLocked is
    // called on the current buffer. Whenever latchBuffer is called, this is
    // expected to be cleared. Then, if bindTexImage is called before the next
    // buffer is acquired, then this image is bound.
    std::unique_ptr<renderengine::Image> mCurrentTextureImageFreed;

    // Cached images used for rendering the current texture through GPU
    // composition.
    std::unique_ptr<renderengine::Image> mImages[BufferQueueDefs::NUM_BUFFER_SLOTS];

    // A release that is pending on the receipt of a new release fence from
    // presentDisplay
    PendingRelease mPendingRelease;
+1 −1
Original line number Diff line number Diff line
@@ -216,7 +216,7 @@ void BufferQueueLayer::setFilteringEnabled(bool enabled) {
    return mConsumer->setFilteringEnabled(enabled);
}

status_t BufferQueueLayer::bindTextureImage() const {
status_t BufferQueueLayer::bindTextureImage() {
    return mConsumer->bindTextureImage();
}

+1 −1
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ private:

    void setFilteringEnabled(bool enabled) override;

    status_t bindTextureImage() const override;
    status_t bindTextureImage() override;
    status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
                            const sp<Fence>& releaseFence) override;

Loading