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>
This commit is contained in:
Robert Phillips 2017-01-25 15:48:30 -05:00 committed by Skia Commit-Bot
parent b2cd1d7b44
commit 757914d26b
8 changed files with 186 additions and 35 deletions

View File

@ -187,6 +187,7 @@ skia_gpu_sources = [
"$_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",

View File

@ -430,10 +430,11 @@ private:
* 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);

View File

@ -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 @@ struct GrProcessorTestData {
, 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

View File

@ -17,6 +17,7 @@ class GrCaps;
class GrRenderTargetOpList;
class GrRenderTargetProxy;
class GrSurfaceContext;
class GrSurfaceProxyPriv;
class GrTextureOpList;
class GrTextureProvider;
class GrTextureProxy;
@ -98,6 +99,14 @@ protected:
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 @@ public:
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 @@ protected:
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

View File

@ -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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpa
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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpa
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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpa
// 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 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpa
}
}
}
if (!tempTexture) {
if (!tempTextureProxy) {
if (applyPremulToSrc) {
size_t tmpRowBytes = 4 * width;
tmpPixels.reset(width * height);
@ -817,7 +827,7 @@ void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
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::createPMToUPMEffect(GrTexture* texture,
}
}
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;
}

View File

@ -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

View File

@ -94,7 +94,6 @@ private:
};
///////////////////////////////////////////////////////////////////////////////
GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
const GrSwizzle& swizzle,
PMConversion pmConversion,
@ -112,6 +111,24 @@ GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
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 @@ sk_sp<GrFragmentProcessor> GrConfigConversionEffect::TestCreate(GrProcessorTestD
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 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
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 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
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 @@ sk_sp<GrFragmentProcessor> GrConfigConversionEffect::Make(GrTexture* texture,
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));
}
}

View File

@ -36,6 +36,9 @@ public:
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 @@ public:
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;