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
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 09d7cb5..39902b1 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -88,6 +88,7 @@
"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 26b280d..02e7337 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 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 @@
ATRACE_CALL();
if (mBackendTexture.isValid()) {
- mUpdateProc(mImageCtx, mGrContext);
+ mUpdateProc(mImageCtx, mGrContext.get());
}
auto colorType = mColorType;
@@ -173,7 +163,7 @@
}
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 @@
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 17e183a..1d5b565 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 @@
// 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 @@
};
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 @@
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 fea4129..f10c98d 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> 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 @@
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 @@
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 @@
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 @@
} 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 af33110..2e22478 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -59,11 +59,11 @@
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 aeedb03..27daeba 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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
}
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 @@
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 @@
{"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 @@
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 e88d44c..9f892bd 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 @@
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 @@
int mTotalShadersCompiled = 0;
};
+ SkSLCacheMonitor mSkSLCacheMonitor;
+
private:
void mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
bool isRenderable) override final;
@@ -183,12 +186,11 @@
// 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 f2f1b5d..d854929 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 @@
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 @@
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 @@
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 @@
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 ca0dcbf..28b7595 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 @@
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 453cdc1..2f09a38 100644
--- a/libs/renderengine/skia/VulkanInterface.cpp
+++ b/libs/renderengine/skia/VulkanInterface.cpp
@@ -30,7 +30,7 @@
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 c3936d9..512e62c 100644
--- a/libs/renderengine/skia/VulkanInterface.h
+++ b/libs/renderengine/skia/VulkanInterface.h
@@ -40,7 +40,7 @@
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 0000000..51c6a6c
--- /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 0000000..59001ec
--- /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 0000000..ba167f3
--- /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 9cddc75..180c922 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 @@
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 e72c501..c9499cb 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
@@ -42,14 +42,13 @@
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 a4febd2..878ab21 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.h
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.h
@@ -37,9 +37,8 @@
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 09f09a6..7a070d7 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -73,8 +73,7 @@
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 @@
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 0ac5ac8..429a537 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.h
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.h
@@ -42,7 +42,7 @@
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: