summaryrefslogtreecommitdiffstats
path: root/gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp')
-rw-r--r--gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp260
1 files changed, 260 insertions, 0 deletions
diff --git a/gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp b/gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp
new file mode 100644
index 0000000000..91080bd1a3
--- /dev/null
+++ b/gfx/skia/skia/src/core/SkDeferredDisplayListRecorder.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/core/SkDeferredDisplayListRecorder.h"
+
+#include "include/core/SkDeferredDisplayList.h"
+#include "include/core/SkSurface.h"
+#include "include/core/SkSurfaceCharacterization.h"
+#include "src/core/SkMessageBus.h"
+
+#if !defined(SK_GANESH)
+SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {}
+
+SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {}
+
+bool SkDeferredDisplayListRecorder::init() { return false; }
+
+SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; }
+
+sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; }
+
+#else
+
+#include "include/core/SkPromiseImageTexture.h"
+#include "include/gpu/GrRecordingContext.h"
+#include "include/gpu/GrYUVABackendTextures.h"
+#include "src/gpu/SkBackingFit.h"
+#include "src/gpu/ganesh/GrCaps.h"
+#include "src/gpu/ganesh/GrProxyProvider.h"
+#include "src/gpu/ganesh/GrRecordingContextPriv.h"
+#include "src/gpu/ganesh/GrRenderTargetProxy.h"
+#include "src/gpu/ganesh/GrTexture.h"
+#include "src/gpu/ganesh/SkGr.h"
+#include "src/image/SkImage_Gpu.h"
+#include "src/image/SkImage_GpuYUVA.h"
+#include "src/image/SkSurface_Gpu.h"
+
+SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
+ : fCharacterization(c) {
+ if (fCharacterization.isValid()) {
+ fContext = GrRecordingContextPriv::MakeDDL(fCharacterization.refContextInfo());
+ }
+}
+
+SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
+ if (fContext) {
+ auto proxyProvider = fContext->priv().proxyProvider();
+
+ // This allows the uniquely keyed proxies to keep their keys but removes their back
+ // pointer to the about-to-be-deleted proxy provider. The proxies will use their
+ // unique key to reattach to cached versions of themselves or to appropriately tag new
+ // resources (if a cached version was not found). This system operates independent of
+ // the replaying context's proxy provider (i.e., these uniquely keyed proxies will not
+ // appear in the replaying proxy providers uniquely keyed proxy map). This should be fine
+ // since no one else should be trying to reconnect to the orphaned proxies and orphaned
+ // proxies from different DDLs that share the same key should simply reconnect to the
+ // same cached resource.
+ proxyProvider->orphanAllUniqueKeys();
+ }
+}
+
+bool SkDeferredDisplayListRecorder::init() {
+ SkASSERT(fContext);
+ SkASSERT(!fTargetProxy);
+ SkASSERT(!fLazyProxyData);
+ SkASSERT(!fSurface);
+
+ if (!fCharacterization.isValid()) {
+ return false;
+ }
+
+ fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
+ new SkDeferredDisplayList::LazyProxyData);
+
+ auto proxyProvider = fContext->priv().proxyProvider();
+ const GrCaps* caps = fContext->priv().caps();
+
+ bool usesGLFBO0 = fCharacterization.usesGLFBO0();
+ if (usesGLFBO0) {
+ if (GrBackendApi::kOpenGL != fContext->backend() ||
+ fCharacterization.isTextureable()) {
+ return false;
+ }
+ }
+
+ bool vkRTSupportsInputAttachment = fCharacterization.vkRTSupportsInputAttachment();
+ if (vkRTSupportsInputAttachment && GrBackendApi::kVulkan != fContext->backend()) {
+ return false;
+ }
+
+ if (fCharacterization.vulkanSecondaryCBCompatible()) {
+ // Because of the restrictive API allowed for a GrVkSecondaryCBDrawContext, we know ahead
+ // of time that we don't be able to support certain parameter combinations. Specifically we
+ // fail on usesGLFBO0 since we can't mix GL and Vulkan. We can't have a texturable object.
+ // We can't use it as in input attachment since we don't control the render pass this will
+ // be played into and thus can't force it to have an input attachment and the correct
+ // dependencies. And finally the GrVkSecondaryCBDrawContext always assumes a top left
+ // origin.
+ if (usesGLFBO0 ||
+ vkRTSupportsInputAttachment ||
+ fCharacterization.isTextureable() ||
+ fCharacterization.origin() == kBottomLeft_GrSurfaceOrigin) {
+ return false;
+ }
+ }
+
+ GrColorType grColorType = SkColorTypeToGrColorType(fCharacterization.colorType());
+
+ // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
+ // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the
+ // DDL is being replayed into.
+
+ GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
+ if (usesGLFBO0) {
+ surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
+ } else if (fCharacterization.sampleCount() > 1 && !caps->msaaResolvesAutomatically() &&
+ fCharacterization.isTextureable()) {
+ surfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
+ }
+
+ if (vkRTSupportsInputAttachment) {
+ surfaceFlags |= GrInternalSurfaceFlags::kVkRTSupportsInputAttachment;
+ }
+
+ // FIXME: Why do we use GrMipmapped::kNo instead of SkSurfaceCharacterization::fIsMipMapped?
+ static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipmapped::kNo,
+ GrTextureType::k2D};
+ const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr;
+ if (fCharacterization.isTextureable()) {
+ optionalTextureInfo = &kTextureInfo;
+ }
+
+ fTargetProxy = proxyProvider->createLazyRenderTargetProxy(
+ [lazyProxyData = fLazyProxyData](GrResourceProvider* resourceProvider,
+ const GrSurfaceProxy::LazySurfaceDesc&) {
+ // The proxy backing the destination surface had better have been instantiated
+ // prior to this one (i.e., the proxy backing the DDL's surface).
+ // Fulfill this lazy proxy with the destination surface's GrRenderTarget.
+ SkASSERT(lazyProxyData->fReplayDest->peekSurface());
+ auto surface = sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->peekSurface());
+ return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
+ },
+ fCharacterization.backendFormat(),
+ fCharacterization.dimensions(),
+ fCharacterization.sampleCount(),
+ surfaceFlags,
+ optionalTextureInfo,
+ GrMipmapStatus::kNotAllocated,
+ SkBackingFit::kExact,
+ skgpu::Budgeted::kYes,
+ fCharacterization.isProtected(),
+ fCharacterization.vulkanSecondaryCBCompatible(),
+ GrSurfaceProxy::UseAllocator::kYes);
+
+ if (!fTargetProxy) {
+ return false;
+ }
+ fTargetProxy->priv().setIsDDLTarget();
+
+ auto device = fContext->priv().createDevice(grColorType,
+ fTargetProxy,
+ fCharacterization.refColorSpace(),
+ fCharacterization.origin(),
+ fCharacterization.surfaceProps(),
+ skgpu::ganesh::Device::InitContents::kUninit);
+ if (!device) {
+ return false;
+ }
+
+ fSurface = sk_make_sp<SkSurface_Gpu>(std::move(device));
+ return SkToBool(fSurface.get());
+}
+
+SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
+ if (!fContext) {
+ return nullptr;
+ }
+
+ if (!fSurface && !this->init()) {
+ return nullptr;
+ }
+
+ return fSurface->getCanvas();
+}
+
+sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
+ if (!fContext || !fTargetProxy) {
+ return nullptr;
+ }
+
+ if (fSurface) {
+ SkCanvas* canvas = fSurface->getCanvas();
+
+ canvas->restoreToCount(0);
+ }
+
+ auto ddl = sk_sp<SkDeferredDisplayList>(new SkDeferredDisplayList(fCharacterization,
+ std::move(fTargetProxy),
+ std::move(fLazyProxyData)));
+
+ fContext->priv().moveRenderTasksToDDL(ddl.get());
+
+ // We want a new lazy proxy target for each recorded DDL so force the (lazy proxy-backed)
+ // SkSurface to be regenerated for each DDL.
+ fSurface = nullptr;
+ return ddl;
+}
+
+#ifndef SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
+sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
+ const GrBackendFormat& backendFormat,
+ int width,
+ int height,
+ GrMipmapped mipmapped,
+ GrSurfaceOrigin origin,
+ SkColorType colorType,
+ SkAlphaType alphaType,
+ sk_sp<SkColorSpace> colorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContext) {
+ if (!fContext) {
+ return nullptr;
+ }
+ return SkImage::MakePromiseTexture(fContext->threadSafeProxy(),
+ backendFormat,
+ {width, height},
+ mipmapped,
+ origin,
+ colorType,
+ alphaType,
+ std::move(colorSpace),
+ textureFulfillProc,
+ textureReleaseProc,
+ textureContext);
+}
+
+sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
+ const GrYUVABackendTextureInfo& backendTextureInfo,
+ sk_sp<SkColorSpace> imageColorSpace,
+ PromiseImageTextureFulfillProc textureFulfillProc,
+ PromiseImageTextureReleaseProc textureReleaseProc,
+ PromiseImageTextureContext textureContexts[]) {
+ if (!fContext) {
+ return nullptr;
+ }
+ return SkImage::MakePromiseYUVATexture(fContext->threadSafeProxy(),
+ backendTextureInfo,
+ std::move(imageColorSpace),
+ textureFulfillProc,
+ textureReleaseProc,
+ textureContexts);
+}
+#endif // !SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
+
+#endif