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:
parent
b2cd1d7b44
commit
757914d26b
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
43
src/gpu/GrSurfaceProxyPriv.h
Normal file
43
src/gpu/GrSurfaceProxyPriv.h
Normal 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
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user