diff options
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: |