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

Commit 60be79ac authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cache EGLImage and VkImage used by SurfaceTexture"

parents 1e15b222 902ce2a7
Loading
Loading
Loading
Loading
+54 −16
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "renderthread/RenderThread.h"
#include "renderthread/VulkanManager.h"
#include "utils/Color.h"
#include <GrAHardwareBufferUtils.h>

// Macro for including the SurfaceTexture name in log messages
#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__)
@@ -30,31 +31,67 @@
namespace android {

void ImageConsumer::onFreeBufferLocked(int slotIndex) {
    mImageSlots[slotIndex].mImage.reset();
    mImageSlots[slotIndex].clear();
}

void ImageConsumer::onAcquireBufferLocked(BufferItem* item) {
    // If item->mGraphicBuffer is not null, this buffer has not been acquired
    // before, so any prior SkImage is created with a stale buffer. This resets the stale SkImage.
    if (item->mGraphicBuffer != nullptr) {
        mImageSlots[item->mSlot].mImage.reset();
        mImageSlots[item->mSlot].clear();
    }
}

void ImageConsumer::onReleaseBufferLocked(int buf) {
    mImageSlots[buf].mEglFence = EGL_NO_SYNC_KHR;
    mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR;
}

void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer,
                                              android_dataspace dataspace, bool forceCreate) {
                                              android_dataspace dataspace, bool forceCreate,
                                              GrContext* context) {
    if (!mImage.get() || dataspace != mDataspace || forceCreate) {
        mImage = graphicBuffer.get()
                         ? SkImage::MakeFromAHardwareBuffer(
        if (!graphicBuffer.get()) {
            clear();
            return;
        }

        if (!mBackendTexture.isValid()) {
            clear();
            bool createProtectedImage =
                0 != (graphicBuffer->getUsage() & GraphicBuffer::USAGE_PROTECTED);
            GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(
                context,
                reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
                                   kPremul_SkAlphaType,
                                   uirenderer::DataSpaceToColorSpace(dataspace))
                         : nullptr;
                graphicBuffer->getPixelFormat(),
                false);
            mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture(
                context,
                reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get()),
                graphicBuffer->getWidth(),
                graphicBuffer->getHeight(),
                &mDeleteProc,
                &mDeleteCtx,
                createProtectedImage,
                backendFormat,
                false);
        }
        mDataspace = dataspace;
        SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(
            graphicBuffer->getPixelFormat());
        mImage = SkImage::MakeFromTexture(context,
            mBackendTexture,
            kTopLeft_GrSurfaceOrigin,
            colorType,
            kPremul_SkAlphaType,
            uirenderer::DataSpaceToColorSpace(dataspace));
    }
}

void ImageConsumer::ImageSlot::clear() {
    mImage.reset();
    if (mBackendTexture.isValid()) {
        mDeleteProc(mDeleteCtx);
        mBackendTexture = {};
    }
}

@@ -71,8 +108,8 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
            if (slot != BufferItem::INVALID_BUFFER_SLOT) {
                *queueEmpty = true;
                mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer,
                        st.mCurrentDataSpace, false);
                return mImageSlots[slot].mImage;
                        st.mCurrentDataSpace, false, renderState.getRenderThread().getGrContext());
                return mImageSlots[slot].getImage();
            }
        }
        return nullptr;
@@ -104,7 +141,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
            uirenderer::RenderPipelineType::SkiaGL) {
            auto& eglManager = renderState.getRenderThread().eglManager();
            display = eglManager.eglDisplay();
            err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].mEglFence,
            err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(),
                                                releaseFence);
        } else {
            err = renderState.getRenderThread().vulkanManager().createReleaseFence(releaseFence);
@@ -129,7 +166,7 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
        // Finally release the old buffer.
        status_t status = st.releaseBufferLocked(
                st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display,
                mImageSlots[st.mCurrentTexture].mEglFence);
                mImageSlots[st.mCurrentTexture].eglFence());
        if (status < NO_ERROR) {
            IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status);
            err = status;
@@ -150,8 +187,9 @@ sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st,
    st.computeCurrentTransformMatrixLocked();

    *queueEmpty = false;
    mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true);
    return mImageSlots[slot].mImage;
    mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true,
        renderState.getRenderThread().getGrContext());
    return mImageSlots[slot].getImage();
}

} /* namespace android */
+24 −3
Original line number Diff line number Diff line
@@ -25,6 +25,12 @@
#include <cutils/compiler.h>
#include <gui/BufferItem.h>
#include <system/graphics.h>
#include <GrBackendSurface.h>

namespace GrAHardwareBufferUtils {
typedef void* DeleteImageCtx;
typedef void (*DeleteImageProc)(DeleteImageCtx);
}

namespace android {

@@ -67,9 +73,21 @@ private:
     * ImageSlot contains the information and object references that
     * ImageConsumer maintains about a BufferQueue buffer slot.
     */
    struct ImageSlot {
    class ImageSlot {
    public:
        ImageSlot() : mDataspace(HAL_DATASPACE_UNKNOWN), mEglFence(EGL_NO_SYNC_KHR) {}

        ~ImageSlot() { clear(); }

        void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace,
                            bool forceCreate, GrContext* context);
        void clear();

        inline EGLSyncKHR& eglFence() { return mEglFence; }

        inline sk_sp<SkImage> getImage() { return mImage; }

    private:
        // mImage is the SkImage created from mGraphicBuffer.
        sk_sp<SkImage> mImage;

@@ -82,8 +100,11 @@ private:
         */
        EGLSyncKHR mEglFence;

        void createIfNeeded(sp<GraphicBuffer> graphicBuffer, android_dataspace dataspace,
                            bool forceCreate);
        GrBackendTexture mBackendTexture;

        GrAHardwareBufferUtils::DeleteImageProc mDeleteProc;

        GrAHardwareBufferUtils::DeleteImageCtx mDeleteCtx;
    };

    /**
+6 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

#include "Matrix.h"
#include "SurfaceTexture.h"
#include "ImageConsumer.h"

namespace android {

@@ -150,7 +151,7 @@ status_t SurfaceTexture::releaseBufferLocked(int buf, sp<GraphicBuffer> graphicB
    // buffer has reallocated the original buffer slot after this buffer
    // was acquired.
    status_t err = ConsumerBase::releaseBufferLocked(buf, graphicBuffer, display, eglFence);
    // We could be releasing an EGL buffer, even if not currently attached to a GL context.
    // We could be releasing an EGL/Vulkan buffer, even if not currently attached to a GL context.
    mImageConsumer.onReleaseBufferLocked(buf);
    mEGLConsumer.onReleaseBufferLocked(buf);
    return err;
@@ -235,6 +236,10 @@ void SurfaceTexture::detachFromView() {

    if (mOpMode == OpMode::attachedToView) {
        mOpMode = OpMode::detached;
        // Free all EglImage and VkImage before the context is destroyed.
        for (int i=0; i < BufferQueueDefs::NUM_BUFFER_SLOTS; i++) {
            mImageConsumer.onFreeBufferLocked(i);
        }
    } else {
        SFT_LOGE("detachFromView: not attached to View");
    }