Switch GrConfigConversionEffect over to taking GrTextureProxies
Change-Id: Ic8be773e210e1ac05dcb9aad6c89dcd63e9e4ba2
Reviewed-on: https://skia-review.googlesource.com/7521
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 7df3e4d..3013270 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -187,6 +187,7 @@
"$_src/gpu/GrStyle.cpp",
"$_src/gpu/GrStyle.h",
"$_src/gpu/GrSurfaceContextPriv.h",
+ "$_src/gpu/GrSurfaceProxyPriv.h",
"$_src/gpu/GrTessellator.cpp",
"$_src/gpu/GrTessellator.h",
"$_src/gpu/GrTextureOpList.cpp",
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 7e8d4e8..4fe3e72 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -430,10 +430,11 @@
* of effects that make a readToUPM->writeToPM->readToUPM cycle invariant. Otherwise, they
* return NULL. They also can perform a swizzle as part of the draw.
*/
- sk_sp<GrFragmentProcessor> createPMToUPMEffect(GrTexture*, const GrSwizzle&,
- const SkMatrix&) const;
- sk_sp<GrFragmentProcessor> createUPMToPMEffect(GrTexture*, const GrSwizzle&,
- const SkMatrix&) const;
+ sk_sp<GrFragmentProcessor> createPMToUPMEffect(GrTexture*, const GrSwizzle&, const SkMatrix&);
+ sk_sp<GrFragmentProcessor> createPMToUPMEffect(sk_sp<GrTextureProxy>, const GrSwizzle&,
+ const SkMatrix&);
+ sk_sp<GrFragmentProcessor> createUPMToPMEffect(sk_sp<GrTextureProxy>, const GrSwizzle&,
+ const SkMatrix&);
/** Called before either of the above two functions to determine the appropriate fragment
processors for conversions. */
void testPMConversionsIfNecessary(uint32_t flags);
diff --git a/include/gpu/GrProcessorUnitTest.h b/include/gpu/GrProcessorUnitTest.h
index 0826e3d..49f26fd 100644
--- a/include/gpu/GrProcessorUnitTest.h
+++ b/include/gpu/GrProcessorUnitTest.h
@@ -8,6 +8,7 @@
#ifndef GrProcessorUnitTest_DEFINED
#define GrProcessorUnitTest_DEFINED
+#include "../private/GrTextureProxy.h"
#include "../private/SkTArray.h"
#include "GrTestUtils.h"
#include "SkTypes.h"
@@ -53,12 +54,24 @@
, fRenderTargetContext(renderTargetContext) {
fTextures[0] = textures[0];
fTextures[1] = textures[1];
+
+ fProxies[0] = GrSurfaceProxy::MakeWrapped(sk_ref_sp(textures[0]));
+ fProxies[1] = GrSurfaceProxy::MakeWrapped(sk_ref_sp(textures[1]));
}
SkRandom* fRandom;
GrContext* fContext;
const GrCaps* fCaps;
const GrRenderTargetContext* fRenderTargetContext;
GrTexture* fTextures[2];
+
+ GrContext* context() { return fContext; }
+ GrTexture* texture(int index) { return fTextures[index]; }
+ sk_sp<GrTextureProxy> textureProxy(int index) {
+ return sk_ref_sp(fProxies[index]->asTextureProxy());
+ }
+
+private:
+ sk_sp<GrSurfaceProxy> fProxies[2];
};
#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 9363b82..6f2a751 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -17,6 +17,7 @@
class GrRenderTargetOpList;
class GrRenderTargetProxy;
class GrSurfaceContext;
+class GrSurfaceProxyPriv;
class GrTextureOpList;
class GrTextureProvider;
class GrTextureProxy;
@@ -98,6 +99,14 @@
fPendingWrites = 0;
}
+ bool internalHasPendingIO() const {
+ if (fTarget) {
+ return fTarget->internalHasPendingIO();
+ }
+
+ return SkToBool(fPendingWrites | fPendingReads);
+ }
+
// For deferred proxies this will be null. For wrapped proxies it will point to the
// wrapped resource.
GrSurface* fTarget;
@@ -285,6 +294,10 @@
SkDEBUGCODE(void validate(GrContext*) const;)
+ // Provides access to functions that aren't part of the public API.
+ GrSurfaceProxyPriv priv();
+ const GrSurfaceProxyPriv priv() const;
+
protected:
// Deferred version
GrSurfaceProxy(const GrSurfaceDesc& desc, SkBackingFit fit, SkBudgeted budgeted)
@@ -301,6 +314,13 @@
virtual ~GrSurfaceProxy();
+ friend class GrSurfaceProxyPriv;
+
+ // Methods made available via GrSurfaceProxyPriv
+ bool hasPendingIO() const {
+ return this->internalHasPendingIO();
+ }
+
// For wrapped resources, 'fDesc' will always be filled in from the wrapped resource.
const GrSurfaceDesc fDesc;
const SkBackingFit fFit; // always exact for wrapped resources
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 1322e25..1733e28 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -16,6 +16,7 @@
#include "GrSoftwarePathRenderer.h"
#include "GrSurfaceContext.h"
#include "GrSurfacePriv.h"
+#include "GrSurfaceProxyPriv.h"
#include "GrTextureContext.h"
#include "SkConfig8888.h"
@@ -295,42 +296,49 @@
this->flush();
}
- sk_sp<GrTexture> tempTexture;
+ sk_sp<GrTextureProxy> tempTextureProxy;
if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
- tempTexture.reset(
- this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
- if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
+ sk_sp<GrSurfaceProxy> temp = GrSurfaceProxy::MakeDeferred(*this->caps(),
+ tempDrawInfo.fTempSurfaceDesc,
+ SkBackingFit::kApprox,
+ SkBudgeted::kYes);
+ if (temp) {
+ tempTextureProxy = sk_ref_sp(temp->asTextureProxy());
+ }
+ if (!tempTextureProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
return false;
}
}
// temp buffer for doing sw premul conversion, if needed.
SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
- if (tempTexture) {
+ if (tempTextureProxy) {
sk_sp<GrFragmentProcessor> fp;
if (applyPremulToSrc) {
- fp = this->createUPMToPMEffect(tempTexture.get(), tempDrawInfo.fSwizzle, SkMatrix::I());
+ fp = this->createUPMToPMEffect(tempTextureProxy, tempDrawInfo.fSwizzle, SkMatrix::I());
// If premultiplying was the only reason for the draw, fall back to a straight write.
if (!fp) {
if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
- tempTexture.reset(nullptr);
+ tempTextureProxy.reset(nullptr);
}
} else {
applyPremulToSrc = false;
}
}
- if (tempTexture) {
+ if (tempTextureProxy) {
if (!fp) {
- fp = GrConfigConversionEffect::Make(tempTexture.get(), tempDrawInfo.fSwizzle,
+ fp = GrConfigConversionEffect::Make(this, tempTextureProxy, tempDrawInfo.fSwizzle,
GrConfigConversionEffect::kNone_PMConversion,
SkMatrix::I());
if (!fp) {
return false;
}
}
- GrRenderTarget* renderTarget = surface->asRenderTarget();
- SkASSERT(renderTarget);
- if (tempTexture->surfacePriv().hasPendingIO()) {
+ GrTexture* texture = tempTextureProxy->instantiate(this->textureProvider());
+ if (!texture) {
+ return false;
+ }
+ if (texture->surfacePriv().hasPendingIO()) {
this->flush();
}
if (applyPremulToSrc) {
@@ -344,7 +352,7 @@
buffer = tmpPixels.get();
applyPremulToSrc = false;
}
- if (!fGpu->writePixels(tempTexture.get(), 0, 0, width, height,
+ if (!fGpu->writePixels(texture, 0, 0, width, height,
tempDrawInfo.fWriteConfig, buffer,
rowBytes)) {
return false;
@@ -354,6 +362,8 @@
// TODO: Need to decide the semantics of this function for color spaces. Do we support
// conversion from a passed-in color space? For now, specifying nullptr means that this
// path will do no conversion, so it will match the behavior of the non-draw path.
+ GrRenderTarget* renderTarget = surface->asRenderTarget();
+ SkASSERT(renderTarget);
sk_sp<GrRenderTargetContext> renderTargetContext(
this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget),
nullptr));
@@ -373,7 +383,7 @@
}
}
}
- if (!tempTexture) {
+ if (!tempTextureProxy) {
if (applyPremulToSrc) {
size_t tmpRowBytes = 4 * width;
tmpPixels.reset(width * height);
@@ -817,7 +827,7 @@
sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture,
const GrSwizzle& swizzle,
- const SkMatrix& matrix) const {
+ const SkMatrix& matrix) {
ASSERT_SINGLE_OWNER
// We should have already called this->testPMConversionsIfNecessary().
SkASSERT(fDidTestPMConversions);
@@ -830,16 +840,31 @@
}
}
-sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(GrTexture* texture,
+sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy,
const GrSwizzle& swizzle,
- const SkMatrix& matrix) const {
+ const SkMatrix& matrix) {
+ ASSERT_SINGLE_OWNER
+ // We should have already called this->testPMConversionsIfNecessary().
+ SkASSERT(fDidTestPMConversions);
+ GrConfigConversionEffect::PMConversion pmToUPM =
+ static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
+ if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
+ return GrConfigConversionEffect::Make(this, proxy, swizzle, pmToUPM, matrix);
+ } else {
+ return nullptr;
+ }
+}
+
+sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy,
+ const GrSwizzle& swizzle,
+ const SkMatrix& matrix) {
ASSERT_SINGLE_OWNER
// We should have already called this->testPMConversionsIfNecessary().
SkASSERT(fDidTestPMConversions);
GrConfigConversionEffect::PMConversion upmToPM =
static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
- return GrConfigConversionEffect::Make(texture, swizzle, upmToPM, matrix);
+ return GrConfigConversionEffect::Make(this, std::move(proxy), swizzle, upmToPM, matrix);
} else {
return nullptr;
}
diff --git a/src/gpu/GrSurfaceProxyPriv.h b/src/gpu/GrSurfaceProxyPriv.h
new file mode 100644
index 0000000..19b8171
--- /dev/null
+++ b/src/gpu/GrSurfaceProxyPriv.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrSurfaceProxyPriv_DEFINED
+#define GrSurfaceProxyPriv_DEFINED
+
+#include "GrSurfaceProxy.h"
+
+/** Class that adds methods to GrSurfaceProxy that are only intended for use internal to Skia.
+ This class is purely a privileged window into GrSurfaceProxy. It should never have additional
+ data members or virtual methods. */
+class GrSurfaceProxyPriv {
+public:
+ // Beware! This call is only guaranteed to tell you if the proxy in question has
+ // any pending IO in its current state. It won't tell you about the IO state in the
+ // future when the proxy is actually used/instantiated.
+ bool hasPendingIO() const { return fProxy->hasPendingIO(); }
+
+private:
+ explicit GrSurfaceProxyPriv(GrSurfaceProxy* proxy) : fProxy(proxy) {}
+ GrSurfaceProxyPriv(const GrSurfaceProxyPriv&) {} // unimpl
+ GrSurfaceProxyPriv& operator=(const GrSurfaceProxyPriv&); // unimpl
+
+ // No taking addresses of this type.
+ const GrSurfaceProxyPriv* operator&() const;
+ GrSurfaceProxyPriv* operator&();
+
+ GrSurfaceProxy* fProxy;
+
+ friend class GrSurfaceProxy; // to construct/copy this type.
+};
+
+inline GrSurfaceProxyPriv GrSurfaceProxy::priv() { return GrSurfaceProxyPriv(this); }
+
+inline const GrSurfaceProxyPriv GrSurfaceProxy::priv () const {
+ return GrSurfaceProxyPriv(const_cast<GrSurfaceProxy*>(this));
+}
+
+#endif
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index a11be2b..2380ad3 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -94,7 +94,6 @@
};
///////////////////////////////////////////////////////////////////////////////
-
GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
const GrSwizzle& swizzle,
PMConversion pmConversion,
@@ -112,6 +111,24 @@
SkASSERT(swizzle != GrSwizzle::RGBA() || kNone_PMConversion != pmConversion);
}
+GrConfigConversionEffect::GrConfigConversionEffect(GrContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ const GrSwizzle& swizzle,
+ PMConversion pmConversion,
+ const SkMatrix& matrix)
+ : INHERITED(context, proxy, nullptr, matrix)
+ , fSwizzle(swizzle)
+ , fPMConversion(pmConversion) {
+ this->initClassID<GrConfigConversionEffect>();
+ // We expect to get here with non-BGRA/RGBA only if we're doing not doing a premul/unpremul
+ // conversion.
+ SkASSERT((kRGBA_8888_GrPixelConfig == proxy->config() ||
+ kBGRA_8888_GrPixelConfig == proxy->config()) ||
+ kNone_PMConversion == pmConversion);
+ // Why did we pollute our texture cache instead of using a GrSingleTextureEffect?
+ SkASSERT(swizzle != GrSwizzle::RGBA() || kNone_PMConversion != pmConversion);
+}
+
bool GrConfigConversionEffect::onIsEqual(const GrFragmentProcessor& s) const {
const GrConfigConversionEffect& other = s.cast<GrConfigConversionEffect>();
return other.fSwizzle == fSwizzle &&
@@ -138,9 +155,10 @@
do {
swizzle = GrSwizzle::CreateRandom(d->fRandom);
} while (pmConv == kNone_PMConversion && swizzle == GrSwizzle::RGBA());
- return sk_sp<GrFragmentProcessor>(
- new GrConfigConversionEffect(d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx],
- swizzle, pmConv, GrTest::TestMatrix(d->fRandom)));
+ return sk_sp<GrFragmentProcessor>(new GrConfigConversionEffect(
+ d->context(),
+ d->textureProxy(GrProcessorUnitTest::kSkiaPMTextureIdx),
+ swizzle, pmConv, GrTest::TestMatrix(d->fRandom)));
}
#if !defined(__clang__) && _MSC_FULL_VER >= 190024213
@@ -201,9 +219,11 @@
desc.fWidth = kSize;
desc.fHeight = kSize;
desc.fConfig = kConfig;
- sk_sp<GrTexture> dataTex(context->textureProvider()->createTexture(
- desc, SkBudgeted::kYes, data, 0));
- if (!dataTex.get()) {
+
+ sk_sp<GrSurfaceProxy> dataProxy = GrSurfaceProxy::MakeDeferred(*context->caps(),
+ context->textureProvider(),
+ desc, SkBudgeted::kYes, data, 0);
+ if (!dataProxy || !dataProxy->asTextureProxy()) {
return;
}
@@ -231,11 +251,14 @@
GrPaint paint2;
GrPaint paint3;
sk_sp<GrFragmentProcessor> pmToUPM1(new GrConfigConversionEffect(
- dataTex.get(), GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
+ context, sk_ref_sp(dataProxy->asTextureProxy()), GrSwizzle::RGBA(),
+ *pmToUPMRule, SkMatrix::I()));
sk_sp<GrFragmentProcessor> upmToPM(new GrConfigConversionEffect(
- readRTC->asTexture().get(), GrSwizzle::RGBA(), *upmToPMRule, SkMatrix::I()));
+ context, sk_ref_sp(readRTC->asDeferredTexture()), GrSwizzle::RGBA(),
+ *upmToPMRule, SkMatrix::I()));
sk_sp<GrFragmentProcessor> pmToUPM2(new GrConfigConversionEffect(
- tempRTC->asTexture().get(), GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
+ context, sk_ref_sp(tempRTC->asDeferredTexture()), GrSwizzle::RGBA(),
+ *pmToUPMRule, SkMatrix::I()));
paint1.addColorFragmentProcessor(std::move(pmToUPM1));
paint1.setPorterDuffXPFactory(SkBlendMode::kSrc);
@@ -299,3 +322,25 @@
new GrConfigConversionEffect(texture, swizzle, pmConversion, matrix));
}
}
+
+sk_sp<GrFragmentProcessor> GrConfigConversionEffect::Make(GrContext* context,
+ sk_sp<GrTextureProxy> proxy,
+ const GrSwizzle& swizzle,
+ PMConversion pmConversion,
+ const SkMatrix& matrix) {
+ if (swizzle == GrSwizzle::RGBA() && kNone_PMConversion == pmConversion) {
+ // If we returned a GrConfigConversionEffect that was equivalent to a GrSimpleTextureEffect
+ // then we may pollute our texture cache with redundant shaders. So in the case that no
+ // conversions were requested we instead return a GrSimpleTextureEffect.
+ return GrSimpleTextureEffect::Make(context, std::move(proxy), nullptr, matrix);
+ } else {
+ if (kRGBA_8888_GrPixelConfig != proxy->config() &&
+ kBGRA_8888_GrPixelConfig != proxy->config() &&
+ kNone_PMConversion != pmConversion) {
+ // The PM conversions assume colors are 0..255
+ return nullptr;
+ }
+ return sk_sp<GrFragmentProcessor>(
+ new GrConfigConversionEffect(context, std::move(proxy), swizzle, pmConversion, matrix));
+ }
+}
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index 27361f4..46180bb 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -36,6 +36,9 @@
static sk_sp<GrFragmentProcessor> Make(GrTexture*, const GrSwizzle&, PMConversion,
const SkMatrix&);
+ static sk_sp<GrFragmentProcessor> Make(GrContext*, sk_sp<GrTextureProxy>,
+ const GrSwizzle&, PMConversion, const SkMatrix&);
+
const char* name() const override { return "Config Conversion"; }
const GrSwizzle& swizzle() const { return fSwizzle; }
@@ -51,9 +54,9 @@
PMConversion* UPMToPMRule);
private:
- GrConfigConversionEffect(GrTexture*,
- const GrSwizzle&,
- PMConversion pmConversion,
+ GrConfigConversionEffect(GrTexture*, const GrSwizzle&, PMConversion, const SkMatrix& matrix);
+
+ GrConfigConversionEffect(GrContext*, sk_sp<GrTextureProxy>, const GrSwizzle&, PMConversion,
const SkMatrix& matrix);
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;