diff options
Diffstat (limited to 'libs/hwui/surfacetexture/ImageConsumer.cpp')
-rw-r--r-- | libs/hwui/surfacetexture/ImageConsumer.cpp | 299 |
1 files changed, 0 insertions, 299 deletions
diff --git a/libs/hwui/surfacetexture/ImageConsumer.cpp b/libs/hwui/surfacetexture/ImageConsumer.cpp deleted file mode 100644 index 17ee17d5cd1d..000000000000 --- a/libs/hwui/surfacetexture/ImageConsumer.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ImageConsumer.h" -#include <gui/BufferQueue.h> -#include "Properties.h" -#include "SurfaceTexture.h" -#include "renderstate/RenderState.h" -#include "renderthread/EglManager.h" -#include "renderthread/RenderThread.h" -#include "renderthread/VulkanManager.h" -#include "utils/Color.h" -#include <GrAHardwareBufferUtils.h> -#include <GrBackendSurface.h> - -// Macro for including the SurfaceTexture name in log messages -#define IMG_LOGE(x, ...) ALOGE("[%s] " x, st.mName.string(), ##__VA_ARGS__) - -using namespace android::uirenderer::renderthread; - -namespace android { - -void ImageConsumer::onFreeBufferLocked(int slotIndex) { - // This callback may be invoked on any thread. - 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].clear(); - } -} - -void ImageConsumer::onReleaseBufferLocked(int buf) { - mImageSlots[buf].eglFence() = EGL_NO_SYNC_KHR; -} - -/** - * AutoBackendTextureRelease manages EglImage/VkImage lifetime. It is a ref-counted object - * that keeps GPU resources alive until the last SKImage object using them is destroyed. - */ -class AutoBackendTextureRelease { -public: - static void releaseProc(SkImage::ReleaseContext releaseContext); - - AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer); - - const GrBackendTexture& getTexture() const { return mBackendTexture; } - - void ref() { mUsageCount++; } - - void unref(bool releaseImage); - - inline sk_sp<SkImage> getImage() { return mImage; } - - void makeImage(sp<GraphicBuffer>& graphicBuffer, android_dataspace dataspace, - GrContext* context); - - void newBufferContent(GrContext* context); - -private: - // The only way to invoke dtor is with unref, when mUsageCount is 0. - ~AutoBackendTextureRelease() {} - - GrBackendTexture mBackendTexture; - GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; - GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; - GrAHardwareBufferUtils::TexImageCtx mImageCtx; - - // Starting with refcount 1, because the first ref is held by SurfaceTexture. Additional refs - // are held by SkImages. - int mUsageCount = 1; - - // mImage is the SkImage created from mBackendTexture. - sk_sp<SkImage> mImage; -}; - -AutoBackendTextureRelease::AutoBackendTextureRelease(GrContext* context, GraphicBuffer* buffer) { - bool createProtectedImage = - 0 != (buffer->getUsage() & GraphicBuffer::USAGE_PROTECTED); - GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat( - context, - reinterpret_cast<AHardwareBuffer*>(buffer), - buffer->getPixelFormat(), - false); - mBackendTexture = GrAHardwareBufferUtils::MakeBackendTexture( - context, - reinterpret_cast<AHardwareBuffer*>(buffer), - buffer->getWidth(), - buffer->getHeight(), - &mDeleteProc, - &mUpdateProc, - &mImageCtx, - createProtectedImage, - backendFormat, - false); -} - -void AutoBackendTextureRelease::unref(bool releaseImage) { - if (!RenderThread::isCurrent()) { - // EGLImage needs to be destroyed on RenderThread to prevent memory leak. - // ~SkImage dtor for both pipelines needs to be invoked on RenderThread, because it is not - // thread safe. - RenderThread::getInstance().queue().post([this, releaseImage]() { unref(releaseImage); }); - return; - } - - if (releaseImage) { - mImage.reset(); - } - - mUsageCount--; - if (mUsageCount <= 0) { - if (mBackendTexture.isValid()) { - mDeleteProc(mImageCtx); - mBackendTexture = {}; - } - delete this; - } -} - -void AutoBackendTextureRelease::releaseProc(SkImage::ReleaseContext releaseContext) { - AutoBackendTextureRelease* textureRelease = - reinterpret_cast<AutoBackendTextureRelease*>(releaseContext); - textureRelease->unref(false); -} - -void AutoBackendTextureRelease::makeImage(sp<GraphicBuffer>& graphicBuffer, - android_dataspace dataspace, GrContext* context) { - SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat( - graphicBuffer->getPixelFormat()); - mImage = SkImage::MakeFromTexture(context, - mBackendTexture, - kTopLeft_GrSurfaceOrigin, - colorType, - kPremul_SkAlphaType, - uirenderer::DataSpaceToColorSpace(dataspace), - releaseProc, - this); - if (mImage.get()) { - // The following ref will be counteracted by releaseProc, when SkImage is discarded. - ref(); - } -} - -void AutoBackendTextureRelease::newBufferContent(GrContext* context) { - if (mBackendTexture.isValid()) { - mUpdateProc(mImageCtx, context); - } -} - -void ImageConsumer::ImageSlot::createIfNeeded(sp<GraphicBuffer> graphicBuffer, - android_dataspace dataspace, bool forceCreate, - GrContext* context) { - if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace - || forceCreate) { - if (!graphicBuffer.get()) { - clear(); - return; - } - - if (!mTextureRelease) { - mTextureRelease = new AutoBackendTextureRelease(context, graphicBuffer.get()); - } else { - mTextureRelease->newBufferContent(context); - } - - mDataspace = dataspace; - mTextureRelease->makeImage(graphicBuffer, dataspace, context); - } -} - -void ImageConsumer::ImageSlot::clear() { - if (mTextureRelease) { - // The following unref counteracts the initial mUsageCount of 1, set by default initializer. - mTextureRelease->unref(true); - mTextureRelease = nullptr; - } -} - -sk_sp<SkImage> ImageConsumer::ImageSlot::getImage() { - return mTextureRelease ? mTextureRelease->getImage() : nullptr; -} - -sk_sp<SkImage> ImageConsumer::dequeueImage(bool* queueEmpty, SurfaceTexture& st, - uirenderer::RenderState& renderState) { - BufferItem item; - status_t err; - err = st.acquireBufferLocked(&item, 0); - if (err != OK) { - if (err != BufferQueue::NO_BUFFER_AVAILABLE) { - IMG_LOGE("Error acquiring buffer: %s (%d)", strerror(err), err); - } else { - int slot = st.mCurrentTexture; - if (slot != BufferItem::INVALID_BUFFER_SLOT) { - *queueEmpty = true; - mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, - st.mCurrentDataSpace, false, renderState.getRenderThread().getGrContext()); - return mImageSlots[slot].getImage(); - } - } - return nullptr; - } - - int slot = item.mSlot; - if (item.mFence->isValid()) { - // Wait on the producer fence for the buffer to be ready. - if (uirenderer::Properties::getRenderPipelineType() == - uirenderer::RenderPipelineType::SkiaGL) { - err = renderState.getRenderThread().eglManager().fenceWait(item.mFence); - } else { - err = renderState.getRenderThread().vulkanManager().fenceWait( - item.mFence, renderState.getRenderThread().getGrContext()); - } - if (err != OK) { - st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY, - EGL_NO_SYNC_KHR); - return nullptr; - } - } - - // Release old buffer. - if (st.mCurrentTexture != BufferItem::INVALID_BUFFER_SLOT) { - // If needed, set the released slot's fence to guard against a producer accessing the - // buffer before the outstanding accesses have completed. - sp<Fence> releaseFence; - EGLDisplay display = EGL_NO_DISPLAY; - if (uirenderer::Properties::getRenderPipelineType() == - uirenderer::RenderPipelineType::SkiaGL) { - auto& eglManager = renderState.getRenderThread().eglManager(); - display = eglManager.eglDisplay(); - err = eglManager.createReleaseFence(st.mUseFenceSync, &mImageSlots[slot].eglFence(), - releaseFence); - } else { - err = renderState.getRenderThread().vulkanManager().createReleaseFence( - releaseFence, renderState.getRenderThread().getGrContext()); - } - if (OK != err) { - st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY, - EGL_NO_SYNC_KHR); - return nullptr; - } - - if (releaseFence.get()) { - status_t err = st.addReleaseFenceLocked( - st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, releaseFence); - if (err != OK) { - IMG_LOGE("dequeueImage: error adding release fence: %s (%d)", strerror(-err), err); - st.releaseBufferLocked(slot, st.mSlots[slot].mGraphicBuffer, EGL_NO_DISPLAY, - EGL_NO_SYNC_KHR); - return nullptr; - } - } - - // Finally release the old buffer. - status_t status = st.releaseBufferLocked( - st.mCurrentTexture, st.mSlots[st.mCurrentTexture].mGraphicBuffer, display, - mImageSlots[st.mCurrentTexture].eglFence()); - if (status < NO_ERROR) { - IMG_LOGE("dequeueImage: failed to release buffer: %s (%d)", strerror(-status), status); - err = status; - // Keep going, with error raised. - } - } - - // Update the state. - st.mCurrentTexture = slot; - st.mCurrentCrop = item.mCrop; - st.mCurrentTransform = item.mTransform; - st.mCurrentScalingMode = item.mScalingMode; - st.mCurrentTimestamp = item.mTimestamp; - st.mCurrentDataSpace = item.mDataSpace; - st.mCurrentFence = item.mFence; - st.mCurrentFenceTime = item.mFenceTime; - st.mCurrentFrameNumber = item.mFrameNumber; - st.computeCurrentTransformMatrixLocked(); - - *queueEmpty = false; - mImageSlots[slot].createIfNeeded(st.mSlots[slot].mGraphicBuffer, item.mDataSpace, true, - renderState.getRenderThread().getGrContext()); - return mImageSlots[slot].getImage(); -} - -} /* namespace android */ |