diff options
| author | 2024-03-11 20:08:27 -0400 | |
|---|---|---|
| committer | 2024-03-14 19:02:00 +0000 | |
| commit | fc125ece97c0cc3025c7ca0ce08ffc00c24301cb (patch) | |
| tree | d90c742a2d8a2382082927092caa60becc4dd2a2 | |
| parent | 17e255148c36a0ee8b3dc28e40e96c491074ddf9 (diff) | |
Add and plumb abstraction layer over GrDirectContext
Also changed GaussianBlurFilter's surface origin from
kBottomLeft_GrSurfaceOrigin to kTopLeft_GrSurfaceOrigin. This doesn't
seem to have an effect in practice, but aligns it with KawaseBlurFilter.
Additionally, both blur filters now set the protected bit on the
surfaces they create to reflect the protection status of the active
context, as opposed to either the protection status of the input SkImage
that is being blurred (Kawase) or always false (Gaussian). This should
be equivalent behavior in the case of Kawase (and aligns with Graphite),
and is likely a bug fix for Gaussian.
Test: manual validation (GL+VK) & existing tests (refactor)
Bug: b/293371537
Change-Id: I19b0258035ea5f319d04207ceb266f2cd1e87674
19 files changed, 361 insertions, 134 deletions
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 09d7cb5d3f..39902b1635 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -88,6 +88,7 @@ filegroup { "skia/SkiaGLRenderEngine.cpp", "skia/SkiaVkRenderEngine.cpp", "skia/VulkanInterface.cpp", + "skia/compat/GaneshGpuContext.cpp", "skia/debug/CaptureTimer.cpp", "skia/debug/CommonPool.cpp", "skia/debug/SkiaCapture.cpp", diff --git a/libs/renderengine/skia/AutoBackendTexture.cpp b/libs/renderengine/skia/AutoBackendTexture.cpp index 26b280d520..02e7337053 100644 --- a/libs/renderengine/skia/AutoBackendTexture.cpp +++ b/libs/renderengine/skia/AutoBackendTexture.cpp @@ -21,12 +21,12 @@ #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 <android/hardware_buffer.h> #include "ColorSpaces.h" #include "log/log_main.h" #include "utils/Trace.h" @@ -35,47 +35,37 @@ namespace android { namespace renderengine { namespace skia { -AutoBackendTexture::AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, +AutoBackendTexture::AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) - : mGrContext(context), mCleanupMgr(cleanupMgr), mIsOutputBuffer(isOutputBuffer) { + : 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 = context->backend(); + GrBackendApi backend = mGrContext->backend(); if (backend == GrBackendApi::kOpenGL) { backendFormat = - GrAHardwareBufferUtils::GetGLBackendFormat(context, desc.format, false); + GrAHardwareBufferUtils::GetGLBackendFormat(mGrContext.get(), desc.format, false); mBackendTexture = - GrAHardwareBufferUtils::MakeGLBackendTexture(context, - buffer, - desc.width, - desc.height, - &mDeleteProc, - &mUpdateProc, - &mImageCtx, - createProtectedImage, - backendFormat, + GrAHardwareBufferUtils::MakeGLBackendTexture(mGrContext.get(), buffer, desc.width, + desc.height, &mDeleteProc, + &mUpdateProc, &mImageCtx, + createProtectedImage, backendFormat, isOutputBuffer); } else if (backend == GrBackendApi::kVulkan) { - backendFormat = - GrAHardwareBufferUtils::GetVulkanBackendFormat(context, - buffer, - desc.format, - false); + backendFormat = GrAHardwareBufferUtils::GetVulkanBackendFormat(mGrContext.get(), buffer, + desc.format, false); mBackendTexture = - GrAHardwareBufferUtils::MakeVulkanBackendTexture(context, - buffer, - desc.width, - desc.height, - &mDeleteProc, - &mUpdateProc, - &mImageCtx, - createProtectedImage, - backendFormat, - isOutputBuffer); + 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)); } @@ -162,7 +152,7 @@ sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaTyp ATRACE_CALL(); if (mBackendTexture.isValid()) { - mUpdateProc(mImageCtx, mGrContext); + mUpdateProc(mImageCtx, mGrContext.get()); } auto colorType = mColorType; @@ -173,7 +163,7 @@ sk_sp<SkImage> AutoBackendTexture::makeImage(ui::Dataspace dataspace, SkAlphaTyp } sk_sp<SkImage> image = - SkImages::BorrowTextureFrom(mGrContext, mBackendTexture, kTopLeft_GrSurfaceOrigin, + SkImages::BorrowTextureFrom(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, colorType, alphaType, toSkColorSpace(dataspace), releaseImageProc, this); if (image.get()) { @@ -194,7 +184,7 @@ sk_sp<SkSurface> AutoBackendTexture::getOrCreateSurface(ui::Dataspace dataspace) LOG_ALWAYS_FATAL_IF(!mIsOutputBuffer, "You can't generate a SkSurface for a read-only texture"); if (!mSurface.get() || mDataspace != dataspace) { sk_sp<SkSurface> surface = - SkSurfaces::WrapBackendTexture(mGrContext, mBackendTexture, + SkSurfaces::WrapBackendTexture(mGrContext.get(), mBackendTexture, kTopLeft_GrSurfaceOrigin, 0, mColorType, toSkColorSpace(dataspace), nullptr, releaseSurfaceProc, this); diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index 17e183a64e..1d5b5655db 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -24,6 +24,7 @@ #include <ui/GraphicTypes.h> #include "android-base/macros.h" +#include "compat/SkiaGpuContext.h" #include <mutex> #include <vector> @@ -80,7 +81,7 @@ public: // of shared ownership with Skia objects, so we wrap it here instead. class LocalRef { public: - LocalRef(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, + LocalRef(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr) { mTexture = new AutoBackendTexture(context, buffer, isOutputBuffer, cleanupMgr); mTexture->ref(); @@ -113,8 +114,10 @@ public: }; private: + DISALLOW_COPY_AND_ASSIGN(AutoBackendTexture); + // Creates a GrBackendTexture whose contents come from the provided buffer. - AutoBackendTexture(GrDirectContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, + AutoBackendTexture(SkiaGpuContext* context, AHardwareBuffer* buffer, bool isOutputBuffer, CleanupManager& cleanupMgr); // The only way to invoke dtor is with unref, when mUsageCount is 0. @@ -139,14 +142,14 @@ private: GrAHardwareBufferUtils::UpdateImageProc mUpdateProc; GrAHardwareBufferUtils::TexImageCtx mImageCtx; - const GrDirectContext* mGrContext = nullptr; + // 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); int mUsageCount = 0; - const bool mIsOutputBuffer; sk_sp<SkImage> mImage = nullptr; sk_sp<SkSurface> mSurface = nullptr; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index fea4129ec0..f10c98d6e2 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -21,6 +21,8 @@ #include "SkiaGLRenderEngine.h" +#include "compat/SkiaGpuContext.h" + #include <EGL/egl.h> #include <EGL/eglext.h> #include <GrContextOptions.h> @@ -207,7 +209,7 @@ std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create( std::unique_ptr<SkiaGLRenderEngine> engine(new SkiaGLRenderEngine(args, display, ctxt, placeholder, protectedContext, protectedPlaceholder)); - engine->ensureGrContextsCreated(); + engine->ensureContextsCreated(); ALOGI("OpenGL ES informations:"); ALOGI("vendor : %s", extensions.getVendor()); @@ -295,9 +297,7 @@ SkiaGLRenderEngine::~SkiaGLRenderEngine() { eglReleaseThread(); } -SkiaRenderEngine::Contexts SkiaGLRenderEngine::createDirectContexts( - const GrContextOptions& options) { - +SkiaRenderEngine::Contexts SkiaGLRenderEngine::createContexts() { LOG_ALWAYS_FATAL_IF(isProtected(), "Cannot setup contexts while already in protected mode"); @@ -306,10 +306,10 @@ SkiaRenderEngine::Contexts SkiaGLRenderEngine::createDirectContexts( LOG_ALWAYS_FATAL_IF(!glInterface.get(), "GrGLMakeNativeInterface() failed"); SkiaRenderEngine::Contexts contexts; - contexts.first = GrDirectContexts::MakeGL(glInterface, options); + contexts.first = SkiaGpuContext::MakeGL_Ganesh(glInterface, mSkSLCacheMonitor); if (supportsProtectedContentImpl()) { useProtectedContextImpl(GrProtected::kYes); - contexts.second = GrDirectContexts::MakeGL(glInterface, options); + contexts.second = SkiaGpuContext::MakeGL_Ganesh(glInterface, mSkSLCacheMonitor); useProtectedContextImpl(GrProtected::kNo); } @@ -330,14 +330,14 @@ bool SkiaGLRenderEngine::useProtectedContextImpl(GrProtected isProtected) { return eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE; } -void SkiaGLRenderEngine::waitFence(GrDirectContext*, base::borrowed_fd fenceFd) { +void SkiaGLRenderEngine::waitFence(SkiaGpuContext*, base::borrowed_fd fenceFd) { if (fenceFd.get() >= 0 && !waitGpuFence(fenceFd)) { ATRACE_NAME("SkiaGLRenderEngine::waitFence"); sync_wait(fenceFd.get(), -1); } } -base::unique_fd SkiaGLRenderEngine::flushAndSubmit(GrDirectContext* grContext) { +base::unique_fd SkiaGLRenderEngine::flushAndSubmit(SkiaGpuContext* context) { base::unique_fd drawFence = flush(); bool requireSync = drawFence.get() < 0; @@ -346,8 +346,8 @@ base::unique_fd SkiaGLRenderEngine::flushAndSubmit(GrDirectContext* grContext) { } else { ATRACE_BEGIN("Submit(sync=false)"); } - bool success = grContext->submit(requireSync ? GrSyncCpu::kYes : - GrSyncCpu::kNo); + bool success = + context->grDirectContext()->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo); ATRACE_END(); if (!success) { ALOGE("Failed to flush RenderEngine commands"); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index af3311041d..2e22478274 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -59,11 +59,11 @@ public: protected: // Implementations of abstract SkiaRenderEngine functions specific to // rendering backend - virtual SkiaRenderEngine::Contexts createDirectContexts(const GrContextOptions& options); + virtual SkiaRenderEngine::Contexts createContexts(); bool supportsProtectedContentImpl() const override; bool useProtectedContextImpl(GrProtected isProtected) override; - void waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) override; - base::unique_fd flushAndSubmit(GrDirectContext* context) override; + void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override; + base::unique_fd flushAndSubmit(SkiaGpuContext* context) override; void appendBackendSpecificInfoToDump(std::string& result) override; private: diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp index aeedb0369e..27daeba092 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -74,6 +74,7 @@ #include "Cache.h" #include "ColorSpaces.h" +#include "compat/SkiaGpuContext.h" #include "filters/BlurFilter.h" #include "filters/GaussianBlurFilter.h" #include "filters/KawaseBlurFilter.h" @@ -290,14 +291,12 @@ void SkiaRenderEngine::finishRenderingAndAbandonContext() { delete mBlurFilter; } - if (mGrContext) { - mGrContext->flushAndSubmit(GrSyncCpu::kYes); - mGrContext->abandonContext(); + if (mContext) { + mContext->finishRenderingAndAbandonContext(); } - if (mProtectedGrContext) { - mProtectedGrContext->flushAndSubmit(GrSyncCpu::kYes); - mProtectedGrContext->abandonContext(); + if (mProtectedContext) { + mProtectedContext->finishRenderingAndAbandonContext(); } } @@ -308,24 +307,24 @@ void SkiaRenderEngine::useProtectedContext(bool useProtectedContext) { } // release any scratch resources before switching into a new mode - if (getActiveGrContext()) { - getActiveGrContext()->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly); + if (getActiveContext()) { + getActiveContext()->purgeUnlockedScratchResources(); } // Backend-specific way to switch to protected context if (useProtectedContextImpl( useProtectedContext ? GrProtected::kYes : GrProtected::kNo)) { mInProtectedContext = useProtectedContext; - // given that we are sharing the same thread between two GrContexts we need to + // given that we are sharing the same thread between two contexts we need to // make sure that the thread state is reset when switching between the two. - if (getActiveGrContext()) { - getActiveGrContext()->resetContext(); + if (getActiveContext()) { + getActiveContext()->resetContextIfApplicable(); } } } -GrDirectContext* SkiaRenderEngine::getActiveGrContext() { - return mInProtectedContext ? mProtectedGrContext.get() : mGrContext.get(); +SkiaGpuContext* SkiaRenderEngine::getActiveContext() { + return mInProtectedContext ? mProtectedContext.get() : mContext.get(); } static float toDegrees(uint32_t transform) { @@ -374,17 +373,12 @@ static bool needsToneMapping(ui::Dataspace sourceDataspace, ui::Dataspace destin sourceTransfer != destTransfer; } -void SkiaRenderEngine::ensureGrContextsCreated() { - if (mGrContext) { +void SkiaRenderEngine::ensureContextsCreated() { + if (mContext) { return; } - GrContextOptions options; - options.fDisableDriverCorrectnessWorkarounds = true; - options.fDisableDistanceFieldPaths = true; - options.fReducedShaderVariations = true; - options.fPersistentCache = &mSkSLCacheMonitor; - std::tie(mGrContext, mProtectedGrContext) = createDirectContexts(options); + std::tie(mContext, mProtectedContext) = createContexts(); } void SkiaRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, @@ -413,7 +407,7 @@ void SkiaRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, // switch back after the buffer is cached). However, for non-protected content we can bind // the texture in either GL context because they are initialized with the same share_context // which allows the texture state to be shared between them. - auto grContext = getActiveGrContext(); + auto context = getActiveContext(); auto& cache = mTextureCache; std::lock_guard<std::mutex> lock(mRenderingMutex); @@ -424,8 +418,7 @@ void SkiaRenderEngine::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, isRenderable = buffer->getUsage() & GRALLOC_USAGE_HW_RENDER; } std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef = - std::make_shared<AutoBackendTexture::LocalRef>(grContext, - buffer->toAHardwareBuffer(), + std::make_shared<AutoBackendTexture::LocalRef>(context, buffer->toAHardwareBuffer(), isRenderable, mTextureCleanupMgr); cache.insert({buffer->getId(), imageTextureRef}); } @@ -477,7 +470,7 @@ std::shared_ptr<AutoBackendTexture::LocalRef> SkiaRenderEngine::getOrCreateBacke return it->second; } } - return std::make_shared<AutoBackendTexture::LocalRef>(getActiveGrContext(), + return std::make_shared<AutoBackendTexture::LocalRef>(getActiveContext(), buffer->toAHardwareBuffer(), isOutputBuffer, mTextureCleanupMgr); } @@ -667,8 +660,8 @@ void SkiaRenderEngine::drawLayersInternal( validateOutputBufferUsage(buffer->getBuffer()); - auto grContext = getActiveGrContext(); - LOG_ALWAYS_FATAL_IF(grContext->abandoned(), "GrContext is abandoned/device lost at start of %s", + auto context = getActiveContext(); + LOG_ALWAYS_FATAL_IF(context->isAbandoned(), "Context is abandoned/device lost at start of %s", __func__); // any AutoBackendTexture deletions will now be deferred until cleanupPostRender is called @@ -677,7 +670,7 @@ void SkiaRenderEngine::drawLayersInternal( auto surfaceTextureRef = getOrCreateBackendTexture(buffer->getBuffer(), true); // wait on the buffer to be ready to use prior to using it - waitFence(grContext, bufferFence); + waitFence(context, bufferFence); sk_sp<SkSurface> dstSurface = surfaceTextureRef->getOrCreateSurface(display.outputDataspace); @@ -844,7 +837,7 @@ void SkiaRenderEngine::drawLayersInternal( if (blurRect.width() > 0 && blurRect.height() > 0) { if (layer.backgroundBlurRadius > 0) { ATRACE_NAME("BackgroundBlur"); - auto blurredImage = mBlurFilter->generate(grContext, layer.backgroundBlurRadius, + auto blurredImage = mBlurFilter->generate(context, layer.backgroundBlurRadius, blurInput, blurRect); cachedBlurs[layer.backgroundBlurRadius] = blurredImage; @@ -858,7 +851,7 @@ void SkiaRenderEngine::drawLayersInternal( if (cachedBlurs[region.blurRadius] == nullptr) { ATRACE_NAME("BlurRegion"); cachedBlurs[region.blurRadius] = - mBlurFilter->generate(grContext, region.blurRadius, blurInput, + mBlurFilter->generate(context, region.blurRadius, blurInput, blurRect); } @@ -947,7 +940,7 @@ void SkiaRenderEngine::drawLayersInternal( // if the layer's buffer has a fence, then we must must respect the fence prior to using // the buffer. if (layer.source.buffer.fence != nullptr) { - waitFence(grContext, layer.source.buffer.fence->get()); + waitFence(context, layer.source.buffer.fence->get()); } // isOpaque means we need to ignore the alpha in the image, @@ -1158,7 +1151,7 @@ void SkiaRenderEngine::drawLayersInternal( skgpu::ganesh::Flush(activeSurface); } - auto drawFence = sp<Fence>::make(flushAndSubmit(grContext)); + auto drawFence = sp<Fence>::make(flushAndSubmit(context)); if (ATRACE_ENABLED()) { static gui::FenceMonitor sMonitor("RE Completion"); @@ -1168,11 +1161,11 @@ void SkiaRenderEngine::drawLayersInternal( } size_t SkiaRenderEngine::getMaxTextureSize() const { - return mGrContext->maxTextureSize(); + return mContext->getMaxTextureSize(); } size_t SkiaRenderEngine::getMaxViewportDims() const { - return mGrContext->maxRenderTargetSize(); + return mContext->getMaxRenderTargetSize(); } void SkiaRenderEngine::drawShadow(SkCanvas* canvas, @@ -1198,13 +1191,13 @@ void SkiaRenderEngine::onActiveDisplaySizeChanged(ui::Size size) { const int maxResourceBytes = size.width * size.height * SURFACE_SIZE_MULTIPLIER; // start by resizing the current context - getActiveGrContext()->setResourceCacheLimit(maxResourceBytes); + getActiveContext()->setResourceCacheLimit(maxResourceBytes); // if it is possible to switch contexts then we will resize the other context const bool originalProtectedState = mInProtectedContext; useProtectedContext(!mInProtectedContext); if (mInProtectedContext != originalProtectedState) { - getActiveGrContext()->setResourceCacheLimit(maxResourceBytes); + getActiveContext()->setResourceCacheLimit(maxResourceBytes); // reset back to the initial context that was active when this method was called useProtectedContext(originalProtectedState); } @@ -1244,7 +1237,7 @@ void SkiaRenderEngine::dump(std::string& result) { {"skia", "Other"}, }; SkiaMemoryReporter gpuReporter(gpuResourceMap, true); - mGrContext->dumpMemoryStatistics(&gpuReporter); + mContext->dumpMemoryStatistics(&gpuReporter); StringAppendF(&result, "Skia's GPU Caches: "); gpuReporter.logTotals(result); gpuReporter.logOutput(result); @@ -1268,8 +1261,8 @@ void SkiaRenderEngine::dump(std::string& result) { StringAppendF(&result, "\n"); SkiaMemoryReporter gpuProtectedReporter(gpuResourceMap, true); - if (mProtectedGrContext) { - mProtectedGrContext->dumpMemoryStatistics(&gpuProtectedReporter); + if (mProtectedContext) { + mProtectedContext->dumpMemoryStatistics(&gpuProtectedReporter); } StringAppendF(&result, "Skia's GPU Protected Caches: "); gpuProtectedReporter.logTotals(result); diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index e88d44cca6..9f892bd0f7 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -21,21 +21,21 @@ #include <sys/types.h> #include <GrBackendSemaphore.h> -#include <GrDirectContext.h> #include <SkSurface.h> #include <android-base/thread_annotations.h> #include <renderengine/ExternalTexture.h> #include <renderengine/RenderEngine.h> #include <sys/types.h> +#include <memory> #include <mutex> #include <unordered_map> #include "AutoBackendTexture.h" #include "GrContextOptions.h" #include "SkImageInfo.h" -#include "SkiaRenderEngine.h" #include "android-base/macros.h" +#include "compat/SkiaGpuContext.h" #include "debug/SkiaCapture.h" #include "filters/BlurFilter.h" #include "filters/LinearEffect.h" @@ -76,24 +76,25 @@ public: bool supportsProtectedContent() const override { return supportsProtectedContentImpl(); } - void ensureGrContextsCreated(); + void ensureContextsCreated(); + protected: // This is so backends can stop the generic rendering state first before // cleaning up backend-specific state void finishRenderingAndAbandonContext(); // Functions that a given backend (GLES, Vulkan) must implement - using Contexts = std::pair<sk_sp<GrDirectContext>, sk_sp<GrDirectContext>>; - virtual Contexts createDirectContexts(const GrContextOptions& options) = 0; + using Contexts = std::pair<unique_ptr<SkiaGpuContext>, unique_ptr<SkiaGpuContext>>; + virtual Contexts createContexts() = 0; virtual bool supportsProtectedContentImpl() const = 0; virtual bool useProtectedContextImpl(GrProtected isProtected) = 0; - virtual void waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) = 0; - virtual base::unique_fd flushAndSubmit(GrDirectContext* context) = 0; + virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) = 0; + virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) = 0; virtual void appendBackendSpecificInfoToDump(std::string& result) = 0; size_t getMaxTextureSize() const override final; size_t getMaxViewportDims() const override final; - GrDirectContext* getActiveGrContext(); + SkiaGpuContext* getActiveContext(); bool isProtected() const { return mInProtectedContext; } @@ -121,6 +122,8 @@ protected: int mTotalShadersCompiled = 0; }; + SkSLCacheMonitor mSkSLCacheMonitor; + private: void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer, bool isRenderable) override final; @@ -183,12 +186,11 @@ private: // Mutex guarding rendering operations, so that internal state related to // rendering that is potentially modified by multiple threads is guaranteed thread-safe. mutable std::mutex mRenderingMutex; - SkSLCacheMonitor mSkSLCacheMonitor; // Graphics context used for creating surfaces and submitting commands - sk_sp<GrDirectContext> mGrContext; + unique_ptr<SkiaGpuContext> mContext; // Same as above, but for protected content (eg. DRM) - sk_sp<GrDirectContext> mProtectedGrContext; + unique_ptr<SkiaGpuContext> mProtectedContext; bool mInProtectedContext = false; }; diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp index f2f1b5d0ca..d854929960 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp @@ -21,12 +21,15 @@ #include "SkiaVkRenderEngine.h" +#include "compat/SkiaGpuContext.h" + #include <GrBackendSemaphore.h> #include <GrContextOptions.h> -#include <vk/GrVkExtensions.h> -#include <vk/GrVkTypes.h> +#include <GrDirectContext.h> #include <include/gpu/ganesh/vk/GrVkBackendSemaphore.h> #include <include/gpu/ganesh/vk/GrVkDirectContext.h> +#include <vk/GrVkExtensions.h> +#include <vk/GrVkTypes.h> #include <android-base/stringprintf.h> #include <gui/TraceUtils.h> @@ -82,7 +85,7 @@ using base::StringAppendF; std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create( const RenderEngineCreationArgs& args) { std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args)); - engine->ensureGrContextsCreated(); + engine->ensureContextsCreated(); if (sVulkanInterface.isInitialized()) { ALOGD("SkiaVkRenderEngine::%s: successfully initialized SkiaVkRenderEngine", __func__); @@ -103,16 +106,16 @@ SkiaVkRenderEngine::~SkiaVkRenderEngine() { finishRenderingAndAbandonContext(); } -SkiaRenderEngine::Contexts SkiaVkRenderEngine::createDirectContexts( - const GrContextOptions& options) { +SkiaRenderEngine::Contexts SkiaVkRenderEngine::createContexts() { sSetupVulkanInterface(); SkiaRenderEngine::Contexts contexts; - contexts.first = GrDirectContexts::MakeVulkan(sVulkanInterface.getBackendContext(), options); + contexts.first = SkiaGpuContext::MakeVulkan_Ganesh(sVulkanInterface.getGaneshBackendContext(), + mSkSLCacheMonitor); if (supportsProtectedContentImpl()) { - contexts.second = - GrDirectContexts::MakeVulkan(sProtectedContentVulkanInterface.getBackendContext(), - options); + contexts.second = SkiaGpuContext::MakeVulkan_Ganesh(sProtectedContentVulkanInterface + .getGaneshBackendContext(), + mSkSLCacheMonitor); } return contexts; @@ -139,7 +142,7 @@ static VulkanInterface& getVulkanInterface(bool protectedContext) { return sVulkanInterface; } -void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) { +void SkiaVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) { if (fenceFd.get() < 0) return; int dupedFd = dup(fenceFd.get()); @@ -153,10 +156,11 @@ void SkiaVkRenderEngine::waitFence(GrDirectContext* grContext, base::borrowed_fd VkSemaphore waitSemaphore = getVulkanInterface(isProtected()).importSemaphoreFromSyncFd(fenceDup.release()); GrBackendSemaphore beSemaphore = GrBackendSemaphores::MakeVk(waitSemaphore); - grContext->wait(1, &beSemaphore, true /* delete after wait */); + context->grDirectContext()->wait(1, &beSemaphore, true /* delete after wait */); } -base::unique_fd SkiaVkRenderEngine::flushAndSubmit(GrDirectContext* grContext) { +base::unique_fd SkiaVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) { + sk_sp<GrDirectContext> grContext = context->grDirectContext(); VulkanInterface& vi = getVulkanInterface(isProtected()); VkSemaphore semaphore = vi.createExportableSemaphore(); diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h index ca0dcbf4ae..28b7595d41 100644 --- a/libs/renderengine/skia/SkiaVkRenderEngine.h +++ b/libs/renderengine/skia/SkiaVkRenderEngine.h @@ -21,6 +21,7 @@ #include "SkiaRenderEngine.h" #include "VulkanInterface.h" +#include "compat/SkiaGpuContext.h" namespace android { namespace renderengine { @@ -72,11 +73,11 @@ public: protected: // Implementations of abstract SkiaRenderEngine functions specific to // rendering backend - virtual SkiaRenderEngine::Contexts createDirectContexts(const GrContextOptions& options); + SkiaRenderEngine::Contexts createContexts() override; bool supportsProtectedContentImpl() const override; bool useProtectedContextImpl(GrProtected isProtected) override; - void waitFence(GrDirectContext* grContext, base::borrowed_fd fenceFd) override; - base::unique_fd flushAndSubmit(GrDirectContext* context) override; + void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override; + base::unique_fd flushAndSubmit(SkiaGpuContext* context) override; void appendBackendSpecificInfoToDump(std::string& result) override; private: diff --git a/libs/renderengine/skia/VulkanInterface.cpp b/libs/renderengine/skia/VulkanInterface.cpp index 453cdc1196..2f09a382d7 100644 --- a/libs/renderengine/skia/VulkanInterface.cpp +++ b/libs/renderengine/skia/VulkanInterface.cpp @@ -30,7 +30,7 @@ namespace android { namespace renderengine { namespace skia { -GrVkBackendContext VulkanInterface::getBackendContext() { +GrVkBackendContext VulkanInterface::getGaneshBackendContext() { GrVkBackendContext backendContext; backendContext.fInstance = mInstance; backendContext.fPhysicalDevice = mPhysicalDevice; diff --git a/libs/renderengine/skia/VulkanInterface.h b/libs/renderengine/skia/VulkanInterface.h index c3936d9869..512e62c8f2 100644 --- a/libs/renderengine/skia/VulkanInterface.h +++ b/libs/renderengine/skia/VulkanInterface.h @@ -40,7 +40,7 @@ public: void teardown(); // TODO: b/293371537 - Graphite variant (external/skia/include/gpu/vk/VulkanBackendContext.h) - GrVkBackendContext getBackendContext(); + GrVkBackendContext getGaneshBackendContext(); VkSemaphore createExportableSemaphore(); VkSemaphore importSemaphoreFromSyncFd(int syncFd); int exportSemaphoreSyncFd(VkSemaphore semaphore); diff --git a/libs/renderengine/skia/compat/GaneshGpuContext.cpp b/libs/renderengine/skia/compat/GaneshGpuContext.cpp new file mode 100644 index 0000000000..51c6a6cd1c --- /dev/null +++ b/libs/renderengine/skia/compat/GaneshGpuContext.cpp @@ -0,0 +1,111 @@ +/* + * 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 "GaneshGpuContext.h" + +#include <include/core/SkImageInfo.h> +#include <include/core/SkSurface.h> +#include <include/core/SkTraceMemoryDump.h> +#include <include/gpu/GrDirectContext.h> +#include <include/gpu/GrTypes.h> +#include <include/gpu/ganesh/SkSurfaceGanesh.h> +#include <include/gpu/ganesh/gl/GrGLDirectContext.h> +#include <include/gpu/ganesh/vk/GrVkDirectContext.h> +#include <include/gpu/gl/GrGLInterface.h> +#include <include/gpu/vk/GrVkBackendContext.h> + +#include <android-base/macros.h> +#include <log/log_main.h> + +namespace android::renderengine::skia { + +namespace { +// TODO: b/293371537 - Graphite variant. +static GrContextOptions ganeshOptions(GrContextOptions::PersistentCache& skSLCacheMonitor) { + GrContextOptions options; + options.fDisableDriverCorrectnessWorkarounds = true; + options.fDisableDistanceFieldPaths = true; + options.fReducedShaderVariations = true; + options.fPersistentCache = &skSLCacheMonitor; + return options; +} +} // namespace + +std::unique_ptr<SkiaGpuContext> SkiaGpuContext::MakeGL_Ganesh( + sk_sp<const GrGLInterface> glInterface, + GrContextOptions::PersistentCache& skSLCacheMonitor) { + return std::make_unique<GaneshGpuContext>( + GrDirectContexts::MakeGL(glInterface, ganeshOptions(skSLCacheMonitor))); +} + +std::unique_ptr<SkiaGpuContext> SkiaGpuContext::MakeVulkan_Ganesh( + const GrVkBackendContext& grVkBackendContext, + GrContextOptions::PersistentCache& skSLCacheMonitor) { + return std::make_unique<GaneshGpuContext>( + GrDirectContexts::MakeVulkan(grVkBackendContext, ganeshOptions(skSLCacheMonitor))); +} + +GaneshGpuContext::GaneshGpuContext(sk_sp<GrDirectContext> grContext) : mGrContext(grContext) { + LOG_ALWAYS_FATAL_IF(mGrContext.get() == nullptr, "GrDirectContext creation failed"); +} + +sk_sp<GrDirectContext> GaneshGpuContext::grDirectContext() { + return mGrContext; +} + +sk_sp<SkSurface> GaneshGpuContext::createRenderTarget(SkImageInfo imageInfo) { + constexpr int kSampleCount = 1; // enable AA + constexpr SkSurfaceProps* kProps = nullptr; + constexpr bool kMipmapped = false; + return SkSurfaces::RenderTarget(mGrContext.get(), skgpu::Budgeted::kNo, imageInfo, kSampleCount, + kTopLeft_GrSurfaceOrigin, kProps, kMipmapped, + mGrContext->supportsProtectedContent()); +} + +size_t GaneshGpuContext::getMaxRenderTargetSize() const { + return mGrContext->maxRenderTargetSize(); +}; + +size_t GaneshGpuContext::getMaxTextureSize() const { + return mGrContext->maxTextureSize(); +}; + +bool GaneshGpuContext::isAbandoned() { + return mGrContext->abandoned(); +} + +void GaneshGpuContext::setResourceCacheLimit(size_t maxResourceBytes) { + mGrContext->setResourceCacheLimit(maxResourceBytes); +} + +void GaneshGpuContext::finishRenderingAndAbandonContext() { + mGrContext->flushAndSubmit(GrSyncCpu::kYes); + mGrContext->abandonContext(); +}; + +void GaneshGpuContext::purgeUnlockedScratchResources() { + mGrContext->purgeUnlockedResources(GrPurgeResourceOptions::kScratchResourcesOnly); +} + +void GaneshGpuContext::resetContextIfApplicable() { + mGrContext->resetContext(); // Only applicable to GL +}; + +void GaneshGpuContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const { + mGrContext->dumpMemoryStatistics(traceMemoryDump); +} + +} // namespace android::renderengine::skia diff --git a/libs/renderengine/skia/compat/GaneshGpuContext.h b/libs/renderengine/skia/compat/GaneshGpuContext.h new file mode 100644 index 0000000000..59001eccc2 --- /dev/null +++ b/libs/renderengine/skia/compat/GaneshGpuContext.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#pragma once + +#include "SkiaGpuContext.h" + +#include <android-base/macros.h> + +namespace android::renderengine::skia { + +class GaneshGpuContext : public SkiaGpuContext { +public: + GaneshGpuContext(sk_sp<GrDirectContext> grContext); + ~GaneshGpuContext() override = default; + + sk_sp<GrDirectContext> grDirectContext() override; + + sk_sp<SkSurface> createRenderTarget(SkImageInfo imageInfo) override; + + size_t getMaxRenderTargetSize() const override; + size_t getMaxTextureSize() const override; + bool isAbandoned() override; + void setResourceCacheLimit(size_t maxResourceBytes) override; + + void finishRenderingAndAbandonContext() override; + void purgeUnlockedScratchResources() override; + void resetContextIfApplicable() override; + + void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override; + +private: + DISALLOW_COPY_AND_ASSIGN(GaneshGpuContext); + + const sk_sp<GrDirectContext> mGrContext; +}; + +} // namespace android::renderengine::skia diff --git a/libs/renderengine/skia/compat/SkiaGpuContext.h b/libs/renderengine/skia/compat/SkiaGpuContext.h new file mode 100644 index 0000000000..ba167f352d --- /dev/null +++ b/libs/renderengine/skia/compat/SkiaGpuContext.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#pragma once + +#undef LOG_TAG +#define LOG_TAG "RenderEngine" + +#include <include/core/SkSurface.h> +#include <include/gpu/GrDirectContext.h> +#include <include/gpu/gl/GrGLInterface.h> +#include <include/gpu/vk/GrVkBackendContext.h> + +#include <log/log.h> + +namespace android::renderengine::skia { + +/** + * Abstraction over Ganesh and Graphite's underlying context-like objects. + */ +class SkiaGpuContext { +public: + static std::unique_ptr<SkiaGpuContext> MakeGL_Ganesh( + sk_sp<const GrGLInterface> glInterface, + GrContextOptions::PersistentCache& skSLCacheMonitor); + + // TODO: b/293371537 - Graphite variant. + static std::unique_ptr<SkiaGpuContext> MakeVulkan_Ganesh( + const GrVkBackendContext& grVkBackendContext, + GrContextOptions::PersistentCache& skSLCacheMonitor); + + virtual ~SkiaGpuContext() = default; + + // TODO: b/293371537 - Maybe expose whether this SkiaGpuContext is using Ganesh or Graphite? + /** + * Only callable on Ganesh-backed instances of SkiaGpuContext, otherwise fatal. + */ + virtual sk_sp<GrDirectContext> grDirectContext() { + LOG_ALWAYS_FATAL("grDirectContext() called on a non-Ganesh instance of SkiaGpuContext!"); + } + + /** + * Notes: + * - The surface doesn't count against Skia's caching budgets. + * - Protected status is set to match the implementation's underlying context. + * - The origin of the surface in texture space corresponds to the top-left content pixel. + * - AA is always enabled. + */ + virtual sk_sp<SkSurface> createRenderTarget(SkImageInfo imageInfo) = 0; + + virtual bool isAbandoned() = 0; + virtual size_t getMaxRenderTargetSize() const = 0; + virtual size_t getMaxTextureSize() const = 0; + virtual void setResourceCacheLimit(size_t maxResourceBytes) = 0; + + virtual void finishRenderingAndAbandonContext() = 0; + virtual void purgeUnlockedScratchResources() = 0; + virtual void resetContextIfApplicable() = 0; // No-op outside of GL (&& Ganesh at this point.) + + virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const = 0; +}; + +} // namespace android::renderengine::skia diff --git a/libs/renderengine/skia/filters/BlurFilter.h b/libs/renderengine/skia/filters/BlurFilter.h index 9cddc757fc..180c92262f 100644 --- a/libs/renderengine/skia/filters/BlurFilter.h +++ b/libs/renderengine/skia/filters/BlurFilter.h @@ -21,6 +21,8 @@ #include <SkRuntimeEffect.h> #include <SkSurface.h> +#include "../compat/SkiaGpuContext.h" + using namespace std; namespace android { @@ -38,8 +40,9 @@ public: virtual ~BlurFilter(){} // Execute blur, saving it to a texture - virtual sk_sp<SkImage> generate(GrRecordingContext* context, const uint32_t radius, - const sk_sp<SkImage> blurInput, const SkRect& blurRect) const = 0; + virtual sk_sp<SkImage> generate(SkiaGpuContext* context, const uint32_t radius, + const sk_sp<SkImage> blurInput, + const SkRect& blurRect) const = 0; /** * Draw the blurred content (from the generate method) into the canvas. diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp index e72c501336..c9499cbc24 100644 --- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp +++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp @@ -42,14 +42,13 @@ static const float BLUR_SIGMA_SCALE = 0.57735f; GaussianBlurFilter::GaussianBlurFilter(): BlurFilter(/* maxCrossFadeRadius= */ 0.0f) {} -sk_sp<SkImage> GaussianBlurFilter::generate(GrRecordingContext* context, const uint32_t blurRadius, - const sk_sp<SkImage> input, const SkRect& blurRect) - const { +sk_sp<SkImage> GaussianBlurFilter::generate(SkiaGpuContext* context, const uint32_t blurRadius, + const sk_sp<SkImage> input, + const SkRect& blurRect) const { // Create blur surface with the bit depth and colorspace of the original surface SkImageInfo scaledInfo = input->imageInfo().makeWH(std::ceil(blurRect.width() * kInputScale), std::ceil(blurRect.height() * kInputScale)); - sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(context, - skgpu::Budgeted::kNo, scaledInfo); + sk_sp<SkSurface> surface = context->createRenderTarget(scaledInfo); SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.h b/libs/renderengine/skia/filters/GaussianBlurFilter.h index a4febd2257..878ab21b36 100644 --- a/libs/renderengine/skia/filters/GaussianBlurFilter.h +++ b/libs/renderengine/skia/filters/GaussianBlurFilter.h @@ -37,9 +37,8 @@ public: virtual ~GaussianBlurFilter(){} // Execute blur, saving it to a texture - sk_sp<SkImage> generate(GrRecordingContext* context, const uint32_t radius, + sk_sp<SkImage> generate(SkiaGpuContext* context, const uint32_t radius, const sk_sp<SkImage> blurInput, const SkRect& blurRect) const override; - }; } // namespace skia diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp index 09f09a697a..7a070d7024 100644 --- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp +++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp @@ -73,8 +73,7 @@ static sk_sp<SkImage> makeImage(SkSurface* surface, SkRuntimeShaderBuilder* buil return surface->makeImageSnapshot(); } -sk_sp<SkImage> KawaseBlurFilter::generate(GrRecordingContext* context, - const uint32_t blurRadius, +sk_sp<SkImage> KawaseBlurFilter::generate(SkiaGpuContext* context, const uint32_t blurRadius, const sk_sp<SkImage> input, const SkRect& blurRect) const { LOG_ALWAYS_FATAL_IF(context == nullptr, "%s: Needs GPU context", __func__); @@ -108,12 +107,7 @@ sk_sp<SkImage> KawaseBlurFilter::generate(GrRecordingContext* context, input->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, linear, blurMatrix); blurBuilder.uniform("in_blurOffset") = radiusByPasses * kInputScale; - constexpr int kSampleCount = 1; - constexpr bool kMipmapped = false; - constexpr SkSurfaceProps* kProps = nullptr; - sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kNo, scaledInfo, - kSampleCount, kTopLeft_GrSurfaceOrigin, - kProps, kMipmapped, input->isProtected()); + sk_sp<SkSurface> surface = context->createRenderTarget(scaledInfo); LOG_ALWAYS_FATAL_IF(!surface, "%s: Failed to create surface for blurring!", __func__); sk_sp<SkImage> tmpBlur = makeImage(surface.get(), &blurBuilder); diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.h b/libs/renderengine/skia/filters/KawaseBlurFilter.h index 0ac5ac8866..429a5378a3 100644 --- a/libs/renderengine/skia/filters/KawaseBlurFilter.h +++ b/libs/renderengine/skia/filters/KawaseBlurFilter.h @@ -42,7 +42,7 @@ public: virtual ~KawaseBlurFilter(){} // Execute blur, saving it to a texture - sk_sp<SkImage> generate(GrRecordingContext* context, const uint32_t radius, + sk_sp<SkImage> generate(SkiaGpuContext* context, const uint32_t radius, const sk_sp<SkImage> blurInput, const SkRect& blurRect) const override; private: |