Loading libs/renderengine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ filegroup { "skia/SkiaGLRenderEngine.cpp", "skia/SkiaVkRenderEngine.cpp", "skia/VulkanInterface.cpp", "skia/compat/GaneshBackendTexture.cpp", "skia/compat/GaneshGpuContext.cpp", "skia/debug/CaptureTimer.cpp", "skia/debug/CommonPool.cpp", Loading libs/renderengine/skia/AutoBackendTexture.cpp +19 −130 Original line number Diff line number Diff line Loading @@ -20,71 +20,21 @@ #define LOG_TAG "RenderEngine" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <SkImage.h> #include <android/hardware_buffer.h> #include <include/gpu/ganesh/SkImageGanesh.h> #include <include/gpu/ganesh/SkSurfaceGanesh.h> #include <include/gpu/ganesh/gl/GrGLBackendSurface.h> #include <include/gpu/ganesh/vk/GrVkBackendSurface.h> #include <include/gpu/vk/GrVkTypes.h> #include "ColorSpaces.h" #include "log/log_main.h" #include "utils/Trace.h" #include <include/core/SkImage.h> #include <include/core/SkSurface.h> #include "compat/SkiaBackendTexture.h" #include <log/log_main.h> #include <utils/Trace.h> namespace android { namespace renderengine { namespace skia { AutoBackendTexture::AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) : mGrContext(context->grDirectContext()), mCleanupMgr(cleanupMgr), mIsOutputBuffer(isOutputBuffer) { ATRACE_CALL(); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); GrBackendFormat backendFormat; GrBackendApi backend = mGrContext->backend(); if (backend == GrBackendApi::kOpenGL) { backendFormat = GrAHardwareBufferUtils::GetGLBackendFormat(mGrContext.get(), desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeGLBackendTexture(mGrContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else if (backend == GrBackendApi::kVulkan) { backendFormat = GrAHardwareBufferUtils::GetVulkanBackendFormat(mGrContext.get(), buffer, desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeVulkanBackendTexture(mGrContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else { LOG_ALWAYS_FATAL("Unexpected backend %u", static_cast<unsigned>(backend)); } mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format); if (!mBackendTexture.isValid() || !desc.width || !desc.height) { LOG_ALWAYS_FATAL("Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d " "isWriteable:%d format:%d", this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format); } } AutoBackendTexture::~AutoBackendTexture() { if (mBackendTexture.isValid()) { mDeleteProc(mImageCtx); mBackendTexture = {}; } } AutoBackendTexture::AutoBackendTexture(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr) : mCleanupMgr(cleanupMgr), mBackendTexture(std::move(backendTexture)) {} void AutoBackendTexture::unref(bool releaseLocalResources) { if (releaseLocalResources) { Loading Loading @@ -112,93 +62,32 @@ void AutoBackendTexture::releaseImageProc(SkImages::ReleaseContext releaseContex textureRelease->unref(false); } void logFatalTexture(const char* msg, const GrBackendTexture& tex, ui::Dataspace dataspace, SkColorType colorType) { switch (tex.backend()) { case GrBackendApi::kOpenGL: { GrGLTextureInfo textureInfo; bool retrievedTextureInfo = GrBackendTextures::GetGLTextureInfo(tex, &textureInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tGrGLTextureInfo: success: %i fTarget: %u fFormat: %u" " colorType %i", msg, tex.isValid(), static_cast<int32_t>(dataspace), tex.width(), tex.height(), tex.hasMipmaps(), tex.isProtected(), static_cast<int>(tex.textureType()), retrievedTextureInfo, textureInfo.fTarget, textureInfo.fFormat, colorType); break; } case GrBackendApi::kVulkan: { GrVkImageInfo imageInfo; bool retrievedImageInfo = GrBackendTextures::GetVkImageInfo(tex, &imageInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tVkImageInfo: success: %i fFormat: %i " "fSampleCount: %u fLevelCount: %u colorType %i", msg, tex.isValid(), static_cast<int32_t>(dataspace), tex.width(), tex.height(), tex.hasMipmaps(), tex.isProtected(), static_cast<int>(tex.textureType()), retrievedImageInfo, imageInfo.fFormat, imageInfo.fSampleCount, imageInfo.fLevelCount, colorType); break; } default: LOG_ALWAYS_FATAL("%s Unexpected backend %u", msg, static_cast<unsigned>(tex.backend())); break; } } sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaType alphaType) { ATRACE_CALL(); if (mBackendTexture.isValid()) { mUpdateProc(mImageCtx, mGrContext.get()); } auto colorType = mColorType; if (alphaType == kOpaque_SkAlphaType) { if (colorType == kRGBA_8888_SkColorType) { colorType = kRGB_888x_SkColorType; } } sk_sp<SkImage> image = SkImages::BorrowTextureFrom(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, alphaType, toSkColorSpace(dataspace), releaseImageProc, this); if (image.get()) { sk_sp<SkImage> image = mBackendTexture->makeImage(alphaType, dataspace, releaseImageProc, this); // The following ref will be counteracted by releaseProc, when SkImage is discarded. ref(); } mImage = image; mDataspace = dataspace; if (!mImage) { logFatalTexture("Unable to generate SkImage.", mBackendTexture, dataspace, colorType); } return mImage; } sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace) { ATRACE_CALL(); LOG_ALWAYS_FATAL_IF(!mIsOutputBuffer, "You can't generate a SkSurface for a read-only texture"); LOG_ALWAYS_FATAL_IF(!mBackendTexture->isOutputBuffer(), "You can't generate an SkSurface for a read-only texture"); if (!mSurface.get() || mDataspace != dataspace) { sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, 0, mColorType, toSkColorSpace(dataspace), nullptr, releaseSurfaceProc, this); if (surface.get()) { mBackendTexture->makeSurface(dataspace, releaseSurfaceProc, this); // The following ref will be counteracted by releaseProc, when SkSurface is discarded. ref(); } mSurface = surface; } mDataspace = dataspace; if (!mSurface) { logFatalTexture("Unable to generate SkSurface.", mBackendTexture, dataspace, mColorType); } return mSurface; } Loading libs/renderengine/skia/AutoBackendTexture.h +10 −19 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <GrAHardwareBufferUtils.h> #include <GrDirectContext.h> #include <SkImage.h> #include <SkSurface.h> Loading @@ -24,9 +23,9 @@ #include <ui/GraphicTypes.h> #include "android-base/macros.h" #include "compat/SkiaGpuContext.h" #include "compat/SkiaBackendTexture.h" #include <mutex> #include <memory> #include <vector> namespace android { Loading Loading @@ -81,9 +80,8 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: LocalRef(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) { mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr); LocalRef(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr) { mTexture = new AutoBackendTexture(std::move(backendTexture), cleanupMgr); mTexture->ref(); } Loading @@ -105,7 +103,7 @@ public: return mTexture->getOrCreateSurface(dataspace); } SkColorType colorType() const { return mTexture->mColorType; } SkColorType colorType() const { return mTexture->mBackendTexture->internalColorType(); } DISALLOW_COPY_AND_ASSIGN(LocalRef); Loading @@ -116,12 +114,13 @@ public: private: DISALLOW_COPY_AND_ASSIGN(AutoBackendTexture); // Creates a GrBackendTexture whose contents come from the provided buffer. AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, // Creates an AutoBackendTexture to manage the lifecycle of a given SkiaBackendTexture, which is // in turn backed by an underlying backend-specific texture type. AutoBackendTexture(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr); // The only way to invoke dtor is with unref, when mUsageCount is 0. ~AutoBackendTexture(); ~AutoBackendTexture() = default; void ref() { mUsageCount++; } Loading @@ -137,24 +136,16 @@ private: // Makes a new SkSurface from the texture content, if needed. sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace); GrBackendTexture mBackendTexture; GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; GrAHardwareBufferUtils::TexImageCtx mImageCtx; // TODO: b/293371537 - Graphite abstractions for ABT. const sk_sp<GrDirectContext> mGrContext = nullptr; CleanupManager& mCleanupMgr; static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext); static void releaseImageProc(SkImages::ReleaseContext releaseContext); std::unique_ptr<SkiaBackendTexture> mBackendTexture; int mUsageCount = 0; const bool mIsOutputBuffer; sk_sp<SkImage> mImage = nullptr; sk_sp<SkSurface> mSurface = nullptr; ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN; SkColorType mColorType = kUnknown_SkColorType; }; } // namespace skia Loading libs/renderengine/skia/SkiaRenderEngine.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ #include "filters/KawaseBlurFilter.h" #include "filters/LinearEffect.h" #include "log/log_main.h" #include "skia/compat/SkiaBackendTexture.h" #include "skia/debug/SkiaCapture.h" #include "skia/debug/SkiaMemoryReporter.h" #include "skia/filters/StretchShaderFactory.h" Loading Loading @@ -417,9 +418,11 @@ void SkiaRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, if (FlagManager::getInstance().renderable_buffer_usage()) { isRenderable = buffer->getUsage() & GRALLOC_USAGE_HW_RENDER; } std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(context, buffer->toAHardwareBuffer(), isRenderable, mTextureCleanupMgr); std::unique_ptr<SkiaBackendTexture> backendTexture = context->makeBackendTexture(buffer->toAHardwareBuffer(), isRenderable); auto imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(std::move(backendTexture), mTextureCleanupMgr); cache.insert({buffer->getId(), imageTextureRef}); } } Loading Loading @@ -470,9 +473,10 @@ std::shared_ptr<AutoBackendTexture::LocalRef> SkiaRenderEngine::getOrCreateBacke return it->second; } } return std::make_shared<AutoBackendTexture::LocalRef>(getActiveContext(), buffer->toAHardwareBuffer(), isOutputBuffer, mTextureCleanupMgr); std::unique_ptr<SkiaBackendTexture> backendTexture = getActiveContext()->makeBackendTexture(buffer->toAHardwareBuffer(), isOutputBuffer); return std::make_shared<AutoBackendTexture::LocalRef>(std::move(backendTexture), mTextureCleanupMgr); } bool SkiaRenderEngine::canSkipPostRenderCleanup() const { Loading libs/renderengine/skia/compat/GaneshBackendTexture.cpp 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright 2024 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 "GaneshBackendTexture.h" #undef LOG_TAG #define LOG_TAG "RenderEngine" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <include/core/SkImage.h> #include <include/gpu/GrDirectContext.h> #include <include/gpu/ganesh/SkImageGanesh.h> #include <include/gpu/ganesh/SkSurfaceGanesh.h> #include <include/gpu/ganesh/gl/GrGLBackendSurface.h> #include <include/gpu/ganesh/vk/GrVkBackendSurface.h> #include <include/gpu/vk/GrVkTypes.h> #include "skia/ColorSpaces.h" #include "skia/compat/SkiaBackendTexture.h" #include <android/hardware_buffer.h> #include <log/log_main.h> #include <utils/Trace.h> namespace android::renderengine::skia { GaneshBackendTexture::GaneshBackendTexture(sk_sp<GrDirectContext> grContext, AHardwareBuffer* buffer, bool isOutputBuffer) : SkiaBackendTexture(buffer, isOutputBuffer), mGrContext(grContext) { ATRACE_CALL(); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); GrBackendFormat backendFormat; const GrBackendApi graphicsApi = grContext->backend(); if (graphicsApi == GrBackendApi::kOpenGL) { backendFormat = GrAHardwareBufferUtils::GetGLBackendFormat(grContext.get(), desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeGLBackendTexture(grContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else if (graphicsApi == GrBackendApi::kVulkan) { backendFormat = GrAHardwareBufferUtils::GetVulkanBackendFormat(grContext.get(), buffer, desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeVulkanBackendTexture(grContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else { LOG_ALWAYS_FATAL("Unexpected graphics API %u", static_cast<unsigned>(graphicsApi)); } if (!mBackendTexture.isValid() || !desc.width || !desc.height) { LOG_ALWAYS_FATAL("Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d " "isWriteable:%d format:%d", this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format); } } GaneshBackendTexture::~GaneshBackendTexture() { if (mBackendTexture.isValid()) { mDeleteProc(mImageCtx); mBackendTexture = {}; } } sk_sp<SkImage> GaneshBackendTexture::makeImage(SkAlphaType alphaType, ui::Dataspace dataspace, TextureReleaseProc releaseImageProc, ReleaseContext releaseContext) { if (mBackendTexture.isValid()) { mUpdateProc(mImageCtx, mGrContext.get()); } const SkColorType colorType = colorTypeForImage(alphaType); sk_sp<SkImage> image = SkImages::BorrowTextureFrom(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, alphaType, toSkColorSpace(dataspace), releaseImageProc, releaseContext); if (!image) { logFatalTexture("Unable to generate SkImage.", dataspace, colorType); } return image; } sk_sp<SkSurface> GaneshBackendTexture::makeSurface(ui::Dataspace dataspace, TextureReleaseProc releaseSurfaceProc, ReleaseContext releaseContext) { const SkColorType colorType = internalColorType(); sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, 0, colorType, toSkColorSpace(dataspace), nullptr, releaseSurfaceProc, releaseContext); if (!surface) { logFatalTexture("Unable to generate SkSurface.", dataspace, colorType); } return surface; } void GaneshBackendTexture::logFatalTexture(const char* msg, ui::Dataspace dataspace, SkColorType colorType) { switch (mBackendTexture.backend()) { case GrBackendApi::kOpenGL: { GrGLTextureInfo textureInfo; bool retrievedTextureInfo = GrBackendTextures::GetGLTextureInfo(mBackendTexture, &textureInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tGrGLTextureInfo: success: %i fTarget: %u fFormat: %u" " colorType %i", msg, mBackendTexture.isValid(), static_cast<int32_t>(dataspace), mBackendTexture.width(), mBackendTexture.height(), mBackendTexture.hasMipmaps(), mBackendTexture.isProtected(), static_cast<int>(mBackendTexture.textureType()), retrievedTextureInfo, textureInfo.fTarget, textureInfo.fFormat, colorType); break; } case GrBackendApi::kVulkan: { GrVkImageInfo imageInfo; bool retrievedImageInfo = GrBackendTextures::GetVkImageInfo(mBackendTexture, &imageInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tVkImageInfo: success: %i fFormat: %i " "fSampleCount: %u fLevelCount: %u colorType %i", msg, mBackendTexture.isValid(), static_cast<int32_t>(dataspace), mBackendTexture.width(), mBackendTexture.height(), mBackendTexture.hasMipmaps(), mBackendTexture.isProtected(), static_cast<int>(mBackendTexture.textureType()), retrievedImageInfo, imageInfo.fFormat, imageInfo.fSampleCount, imageInfo.fLevelCount, colorType); break; } default: LOG_ALWAYS_FATAL("%s Unexpected backend %u", msg, static_cast<unsigned>(mBackendTexture.backend())); break; } } } // namespace android::renderengine::skia Loading
libs/renderengine/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ filegroup { "skia/SkiaGLRenderEngine.cpp", "skia/SkiaVkRenderEngine.cpp", "skia/VulkanInterface.cpp", "skia/compat/GaneshBackendTexture.cpp", "skia/compat/GaneshGpuContext.cpp", "skia/debug/CaptureTimer.cpp", "skia/debug/CommonPool.cpp", Loading
libs/renderengine/skia/AutoBackendTexture.cpp +19 −130 Original line number Diff line number Diff line Loading @@ -20,71 +20,21 @@ #define LOG_TAG "RenderEngine" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <SkImage.h> #include <android/hardware_buffer.h> #include <include/gpu/ganesh/SkImageGanesh.h> #include <include/gpu/ganesh/SkSurfaceGanesh.h> #include <include/gpu/ganesh/gl/GrGLBackendSurface.h> #include <include/gpu/ganesh/vk/GrVkBackendSurface.h> #include <include/gpu/vk/GrVkTypes.h> #include "ColorSpaces.h" #include "log/log_main.h" #include "utils/Trace.h" #include <include/core/SkImage.h> #include <include/core/SkSurface.h> #include "compat/SkiaBackendTexture.h" #include <log/log_main.h> #include <utils/Trace.h> namespace android { namespace renderengine { namespace skia { AutoBackendTexture::AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) : mGrContext(context->grDirectContext()), mCleanupMgr(cleanupMgr), mIsOutputBuffer(isOutputBuffer) { ATRACE_CALL(); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); GrBackendFormat backendFormat; GrBackendApi backend = mGrContext->backend(); if (backend == GrBackendApi::kOpenGL) { backendFormat = GrAHardwareBufferUtils::GetGLBackendFormat(mGrContext.get(), desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeGLBackendTexture(mGrContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else if (backend == GrBackendApi::kVulkan) { backendFormat = GrAHardwareBufferUtils::GetVulkanBackendFormat(mGrContext.get(), buffer, desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeVulkanBackendTexture(mGrContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else { LOG_ALWAYS_FATAL("Unexpected backend %u", static_cast<unsigned>(backend)); } mColorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format); if (!mBackendTexture.isValid() || !desc.width || !desc.height) { LOG_ALWAYS_FATAL("Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d " "isWriteable:%d format:%d", this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format); } } AutoBackendTexture::~AutoBackendTexture() { if (mBackendTexture.isValid()) { mDeleteProc(mImageCtx); mBackendTexture = {}; } } AutoBackendTexture::AutoBackendTexture(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr) : mCleanupMgr(cleanupMgr), mBackendTexture(std::move(backendTexture)) {} void AutoBackendTexture::unref(bool releaseLocalResources) { if (releaseLocalResources) { Loading Loading @@ -112,93 +62,32 @@ void AutoBackendTexture::releaseImageProc(SkImages::ReleaseContext releaseContex textureRelease->unref(false); } void logFatalTexture(const char* msg, const GrBackendTexture& tex, ui::Dataspace dataspace, SkColorType colorType) { switch (tex.backend()) { case GrBackendApi::kOpenGL: { GrGLTextureInfo textureInfo; bool retrievedTextureInfo = GrBackendTextures::GetGLTextureInfo(tex, &textureInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tGrGLTextureInfo: success: %i fTarget: %u fFormat: %u" " colorType %i", msg, tex.isValid(), static_cast<int32_t>(dataspace), tex.width(), tex.height(), tex.hasMipmaps(), tex.isProtected(), static_cast<int>(tex.textureType()), retrievedTextureInfo, textureInfo.fTarget, textureInfo.fFormat, colorType); break; } case GrBackendApi::kVulkan: { GrVkImageInfo imageInfo; bool retrievedImageInfo = GrBackendTextures::GetVkImageInfo(tex, &imageInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tVkImageInfo: success: %i fFormat: %i " "fSampleCount: %u fLevelCount: %u colorType %i", msg, tex.isValid(), static_cast<int32_t>(dataspace), tex.width(), tex.height(), tex.hasMipmaps(), tex.isProtected(), static_cast<int>(tex.textureType()), retrievedImageInfo, imageInfo.fFormat, imageInfo.fSampleCount, imageInfo.fLevelCount, colorType); break; } default: LOG_ALWAYS_FATAL("%s Unexpected backend %u", msg, static_cast<unsigned>(tex.backend())); break; } } sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaType alphaType) { ATRACE_CALL(); if (mBackendTexture.isValid()) { mUpdateProc(mImageCtx, mGrContext.get()); } auto colorType = mColorType; if (alphaType == kOpaque_SkAlphaType) { if (colorType == kRGBA_8888_SkColorType) { colorType = kRGB_888x_SkColorType; } } sk_sp<SkImage> image = SkImages::BorrowTextureFrom(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, alphaType, toSkColorSpace(dataspace), releaseImageProc, this); if (image.get()) { sk_sp<SkImage> image = mBackendTexture->makeImage(alphaType, dataspace, releaseImageProc, this); // The following ref will be counteracted by releaseProc, when SkImage is discarded. ref(); } mImage = image; mDataspace = dataspace; if (!mImage) { logFatalTexture("Unable to generate SkImage.", mBackendTexture, dataspace, colorType); } return mImage; } sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace) { ATRACE_CALL(); LOG_ALWAYS_FATAL_IF(!mIsOutputBuffer, "You can't generate a SkSurface for a read-only texture"); LOG_ALWAYS_FATAL_IF(!mBackendTexture->isOutputBuffer(), "You can't generate an SkSurface for a read-only texture"); if (!mSurface.get() || mDataspace != dataspace) { sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, 0, mColorType, toSkColorSpace(dataspace), nullptr, releaseSurfaceProc, this); if (surface.get()) { mBackendTexture->makeSurface(dataspace, releaseSurfaceProc, this); // The following ref will be counteracted by releaseProc, when SkSurface is discarded. ref(); } mSurface = surface; } mDataspace = dataspace; if (!mSurface) { logFatalTexture("Unable to generate SkSurface.", mBackendTexture, dataspace, mColorType); } return mSurface; } Loading
libs/renderengine/skia/AutoBackendTexture.h +10 −19 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #pragma once #include <GrAHardwareBufferUtils.h> #include <GrDirectContext.h> #include <SkImage.h> #include <SkSurface.h> Loading @@ -24,9 +23,9 @@ #include <ui/GraphicTypes.h> #include "android-base/macros.h" #include "compat/SkiaGpuContext.h" #include "compat/SkiaBackendTexture.h" #include <mutex> #include <memory> #include <vector> namespace android { Loading Loading @@ -81,9 +80,8 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: LocalRef(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) { mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr); LocalRef(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr) { mTexture = new AutoBackendTexture(std::move(backendTexture), cleanupMgr); mTexture->ref(); } Loading @@ -105,7 +103,7 @@ public: return mTexture->getOrCreateSurface(dataspace); } SkColorType colorType() const { return mTexture->mColorType; } SkColorType colorType() const { return mTexture->mBackendTexture->internalColorType(); } DISALLOW_COPY_AND_ASSIGN(LocalRef); Loading @@ -116,12 +114,13 @@ public: private: DISALLOW_COPY_AND_ASSIGN(AutoBackendTexture); // Creates a GrBackendTexture whose contents come from the provided buffer. AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, // Creates an AutoBackendTexture to manage the lifecycle of a given SkiaBackendTexture, which is // in turn backed by an underlying backend-specific texture type. AutoBackendTexture(std::unique_ptr<SkiaBackendTexture> backendTexture, CleanupManager& cleanupMgr); // The only way to invoke dtor is with unref, when mUsageCount is 0. ~AutoBackendTexture(); ~AutoBackendTexture() = default; void ref() { mUsageCount++; } Loading @@ -137,24 +136,16 @@ private: // Makes a new SkSurface from the texture content, if needed. sk_sp<SkSurface> getOrCreateSurface(ui::Dataspace dataspace); GrBackendTexture mBackendTexture; GrAHardwareBufferUtils::DeleteImageProc mDeleteProc; GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; GrAHardwareBufferUtils::TexImageCtx mImageCtx; // TODO: b/293371537 - Graphite abstractions for ABT. const sk_sp<GrDirectContext> mGrContext = nullptr; CleanupManager& mCleanupMgr; static void releaseSurfaceProc(SkSurface::ReleaseContext releaseContext); static void releaseImageProc(SkImages::ReleaseContext releaseContext); std::unique_ptr<SkiaBackendTexture> mBackendTexture; int mUsageCount = 0; const bool mIsOutputBuffer; sk_sp<SkImage> mImage = nullptr; sk_sp<SkSurface> mSurface = nullptr; ui::Dataspace mDataspace = ui::Dataspace::UNKNOWN; SkColorType mColorType = kUnknown_SkColorType; }; } // namespace skia Loading
libs/renderengine/skia/SkiaRenderEngine.cpp +10 −6 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ #include "filters/KawaseBlurFilter.h" #include "filters/LinearEffect.h" #include "log/log_main.h" #include "skia/compat/SkiaBackendTexture.h" #include "skia/debug/SkiaCapture.h" #include "skia/debug/SkiaMemoryReporter.h" #include "skia/filters/StretchShaderFactory.h" Loading Loading @@ -417,9 +418,11 @@ void SkiaRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, if (FlagManager::getInstance().renderable_buffer_usage()) { isRenderable = buffer->getUsage() & GRALLOC_USAGE_HW_RENDER; } std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(context, buffer->toAHardwareBuffer(), isRenderable, mTextureCleanupMgr); std::unique_ptr<SkiaBackendTexture> backendTexture = context->makeBackendTexture(buffer->toAHardwareBuffer(), isRenderable); auto imageTextureRef = std::make_shared<AutoBackendTexture::LocalRef>(std::move(backendTexture), mTextureCleanupMgr); cache.insert({buffer->getId(), imageTextureRef}); } } Loading Loading @@ -470,9 +473,10 @@ std::shared_ptr<AutoBackendTexture::LocalRef> SkiaRenderEngine::getOrCreateBacke return it->second; } } return std::make_shared<AutoBackendTexture::LocalRef>(getActiveContext(), buffer->toAHardwareBuffer(), isOutputBuffer, mTextureCleanupMgr); std::unique_ptr<SkiaBackendTexture> backendTexture = getActiveContext()->makeBackendTexture(buffer->toAHardwareBuffer(), isOutputBuffer); return std::make_shared<AutoBackendTexture::LocalRef>(std::move(backendTexture), mTextureCleanupMgr); } bool SkiaRenderEngine::canSkipPostRenderCleanup() const { Loading
libs/renderengine/skia/compat/GaneshBackendTexture.cpp 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright 2024 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 "GaneshBackendTexture.h" #undef LOG_TAG #define LOG_TAG "RenderEngine" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include <include/core/SkImage.h> #include <include/gpu/GrDirectContext.h> #include <include/gpu/ganesh/SkImageGanesh.h> #include <include/gpu/ganesh/SkSurfaceGanesh.h> #include <include/gpu/ganesh/gl/GrGLBackendSurface.h> #include <include/gpu/ganesh/vk/GrVkBackendSurface.h> #include <include/gpu/vk/GrVkTypes.h> #include "skia/ColorSpaces.h" #include "skia/compat/SkiaBackendTexture.h" #include <android/hardware_buffer.h> #include <log/log_main.h> #include <utils/Trace.h> namespace android::renderengine::skia { GaneshBackendTexture::GaneshBackendTexture(sk_sp<GrDirectContext> grContext, AHardwareBuffer* buffer, bool isOutputBuffer) : SkiaBackendTexture(buffer, isOutputBuffer), mGrContext(grContext) { ATRACE_CALL(); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); const bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT); GrBackendFormat backendFormat; const GrBackendApi graphicsApi = grContext->backend(); if (graphicsApi == GrBackendApi::kOpenGL) { backendFormat = GrAHardwareBufferUtils::GetGLBackendFormat(grContext.get(), desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeGLBackendTexture(grContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else if (graphicsApi == GrBackendApi::kVulkan) { backendFormat = GrAHardwareBufferUtils::GetVulkanBackendFormat(grContext.get(), buffer, desc.format, false); mBackendTexture = GrAHardwareBufferUtils::MakeVulkanBackendTexture(grContext.get(), buffer, desc.width, desc.height, &mDeleteProc, &mUpdateProc, &mImageCtx, createProtectedImage, backendFormat, isOutputBuffer); } else { LOG_ALWAYS_FATAL("Unexpected graphics API %u", static_cast<unsigned>(graphicsApi)); } if (!mBackendTexture.isValid() || !desc.width || !desc.height) { LOG_ALWAYS_FATAL("Failed to create a valid texture. [%p]:[%d,%d] isProtected:%d " "isWriteable:%d format:%d", this, desc.width, desc.height, createProtectedImage, isOutputBuffer, desc.format); } } GaneshBackendTexture::~GaneshBackendTexture() { if (mBackendTexture.isValid()) { mDeleteProc(mImageCtx); mBackendTexture = {}; } } sk_sp<SkImage> GaneshBackendTexture::makeImage(SkAlphaType alphaType, ui::Dataspace dataspace, TextureReleaseProc releaseImageProc, ReleaseContext releaseContext) { if (mBackendTexture.isValid()) { mUpdateProc(mImageCtx, mGrContext.get()); } const SkColorType colorType = colorTypeForImage(alphaType); sk_sp<SkImage> image = SkImages::BorrowTextureFrom(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, alphaType, toSkColorSpace(dataspace), releaseImageProc, releaseContext); if (!image) { logFatalTexture("Unable to generate SkImage.", dataspace, colorType); } return image; } sk_sp<SkSurface> GaneshBackendTexture::makeSurface(ui::Dataspace dataspace, TextureReleaseProc releaseSurfaceProc, ReleaseContext releaseContext) { const SkColorType colorType = internalColorType(); sk_sp<SkSurface> surface = SkSurfaces::WrapBackendTexture(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, 0, colorType, toSkColorSpace(dataspace), nullptr, releaseSurfaceProc, releaseContext); if (!surface) { logFatalTexture("Unable to generate SkSurface.", dataspace, colorType); } return surface; } void GaneshBackendTexture::logFatalTexture(const char* msg, ui::Dataspace dataspace, SkColorType colorType) { switch (mBackendTexture.backend()) { case GrBackendApi::kOpenGL: { GrGLTextureInfo textureInfo; bool retrievedTextureInfo = GrBackendTextures::GetGLTextureInfo(mBackendTexture, &textureInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tGrGLTextureInfo: success: %i fTarget: %u fFormat: %u" " colorType %i", msg, mBackendTexture.isValid(), static_cast<int32_t>(dataspace), mBackendTexture.width(), mBackendTexture.height(), mBackendTexture.hasMipmaps(), mBackendTexture.isProtected(), static_cast<int>(mBackendTexture.textureType()), retrievedTextureInfo, textureInfo.fTarget, textureInfo.fFormat, colorType); break; } case GrBackendApi::kVulkan: { GrVkImageInfo imageInfo; bool retrievedImageInfo = GrBackendTextures::GetVkImageInfo(mBackendTexture, &imageInfo); LOG_ALWAYS_FATAL("%s isTextureValid:%d dataspace:%d" "\n\tGrBackendTexture: (%i x %i) hasMipmaps: %i isProtected: %i " "texType: %i\n\t\tVkImageInfo: success: %i fFormat: %i " "fSampleCount: %u fLevelCount: %u colorType %i", msg, mBackendTexture.isValid(), static_cast<int32_t>(dataspace), mBackendTexture.width(), mBackendTexture.height(), mBackendTexture.hasMipmaps(), mBackendTexture.isProtected(), static_cast<int>(mBackendTexture.textureType()), retrievedImageInfo, imageInfo.fFormat, imageInfo.fSampleCount, imageInfo.fLevelCount, colorType); break; } default: LOG_ALWAYS_FATAL("%s Unexpected backend %u", msg, static_cast<unsigned>(mBackendTexture.backend())); break; } } } // namespace android::renderengine::skia