Make swizzling in read/write pixel copy code more generic
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1617433002 Review URL: https://codereview.chromium.org/1617433002
This commit is contained in:
parent
0ac723b6f4
commit
6c9cd55f00
@ -43,6 +43,7 @@ class GrTextContext;
|
||||
class GrTextureParams;
|
||||
class GrVertexBuffer;
|
||||
class GrStrokeInfo;
|
||||
class GrSwizzle;
|
||||
class SkTraceMemoryDump;
|
||||
|
||||
class SK_API GrContext : public SkRefCnt {
|
||||
@ -429,11 +430,11 @@ private:
|
||||
/**
|
||||
* These functions create premul <-> unpremul effects if it is possible to generate a pair
|
||||
* of effects that make a readToUPM->writeToPM->readToUPM cycle invariant. Otherwise, they
|
||||
* return NULL.
|
||||
* return NULL. They also can perform a swizzle as part of the draw.
|
||||
*/
|
||||
const GrFragmentProcessor* createPMToUPMEffect(GrTexture*, bool swapRAndB,
|
||||
const GrFragmentProcessor* createPMToUPMEffect(GrTexture*, const GrSwizzle&,
|
||||
const SkMatrix&) const;
|
||||
const GrFragmentProcessor* createUPMToPMEffect(GrTexture*, bool swapRAndB,
|
||||
const GrFragmentProcessor* createUPMToPMEffect(GrTexture*, const GrSwizzle&,
|
||||
const SkMatrix&) const;
|
||||
/** Called before either of the above two functions to determine the appropriate fragment
|
||||
processors for conversions. This must be called by readSurfacePixels before a mutex is
|
||||
|
@ -298,7 +298,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
||||
SkMatrix textureMatrix;
|
||||
textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
|
||||
if (applyPremulToSrc) {
|
||||
fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwapRAndB,
|
||||
fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwizzle,
|
||||
textureMatrix));
|
||||
// If premultiplying was the only reason for the draw, fall back to a straight write.
|
||||
if (!fp) {
|
||||
@ -311,7 +311,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
||||
}
|
||||
if (tempTexture) {
|
||||
if (!fp) {
|
||||
fp.reset(GrConfigConversionEffect::Create(tempTexture, tempDrawInfo.fSwapRAndB,
|
||||
fp.reset(GrConfigConversionEffect::Create(tempTexture, tempDrawInfo.fSwizzle,
|
||||
GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
|
||||
if (!fp) {
|
||||
return false;
|
||||
@ -334,7 +334,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface,
|
||||
applyPremulToSrc = false;
|
||||
}
|
||||
if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
|
||||
tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
|
||||
tempDrawInfo.fWriteConfig, buffer,
|
||||
rowBytes)) {
|
||||
return false;
|
||||
}
|
||||
@ -438,7 +438,7 @@ bool GrContext::readSurfacePixels(GrSurface* src,
|
||||
textureMatrix.postIDiv(src->width(), src->height());
|
||||
SkAutoTUnref<const GrFragmentProcessor> fp;
|
||||
if (unpremul) {
|
||||
fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwapRAndB,
|
||||
fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
|
||||
textureMatrix));
|
||||
if (fp) {
|
||||
unpremul = false; // we no longer need to do this on CPU after the read back.
|
||||
@ -449,7 +449,7 @@ bool GrContext::readSurfacePixels(GrSurface* src,
|
||||
}
|
||||
}
|
||||
if (!fp && temp) {
|
||||
fp.reset(GrConfigConversionEffect::Create(src->asTexture(), tempDrawInfo.fSwapRAndB,
|
||||
fp.reset(GrConfigConversionEffect::Create(src->asTexture(), tempDrawInfo.fSwizzle,
|
||||
GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
|
||||
}
|
||||
if (fp) {
|
||||
@ -473,10 +473,7 @@ bool GrContext::readSurfacePixels(GrSurface* src,
|
||||
GrPixelConfig configToRead = dstConfig;
|
||||
if (didTempDraw) {
|
||||
this->flushSurfaceWrites(surfaceToRead);
|
||||
// We swapped R and B while doing the temp draw. Swap back on the read.
|
||||
if (tempDrawInfo.fSwapRAndB) {
|
||||
configToRead = GrPixelConfigSwapRAndB(dstConfig);
|
||||
}
|
||||
configToRead = tempDrawInfo.fReadConfig;
|
||||
}
|
||||
if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
|
||||
rowBytes)) {
|
||||
@ -608,7 +605,7 @@ void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
|
||||
}
|
||||
|
||||
const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
|
||||
bool swapRAndB,
|
||||
const GrSwizzle& swizzle,
|
||||
const SkMatrix& matrix) const {
|
||||
ASSERT_SINGLE_OWNER
|
||||
// We should have already called this->testPMConversionsIfNecessary().
|
||||
@ -616,14 +613,14 @@ const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
|
||||
GrConfigConversionEffect::PMConversion pmToUPM =
|
||||
static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
|
||||
if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
|
||||
return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
|
||||
return GrConfigConversionEffect::Create(texture, swizzle, pmToUPM, matrix);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
|
||||
bool swapRAndB,
|
||||
const GrSwizzle& swizzle,
|
||||
const SkMatrix& matrix) const {
|
||||
ASSERT_SINGLE_OWNER
|
||||
// We should have already called this->testPMConversionsIfNecessary().
|
||||
@ -631,7 +628,7 @@ const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
|
||||
GrConfigConversionEffect::PMConversion upmToPM =
|
||||
static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
|
||||
if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
|
||||
return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
|
||||
return GrConfigConversionEffect::Create(texture, swizzle, upmToPM, matrix);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "GrPipelineBuilder.h"
|
||||
#include "GrProgramDesc.h"
|
||||
#include "GrStencil.h"
|
||||
#include "GrSwizzle.h"
|
||||
#include "GrTextureParamsAdjuster.h"
|
||||
#include "GrXferProcessor.h"
|
||||
#include "SkPath.h"
|
||||
@ -155,13 +156,15 @@ public:
|
||||
/** Indicates whether there is a performance advantage to using an exact match texture
|
||||
(in terms of width and height) for the intermediate texture instead of approximate. */
|
||||
bool fUseExactScratch;
|
||||
/** The caller should swap the R and B channel in the temp draw and then instead of reading
|
||||
the desired config back it should read GrPixelConfigSwapRAndB(readConfig). The swap
|
||||
during the draw and the swap at readback time cancel and the client gets the correct
|
||||
data. The swapped read back is either faster for or required by the underlying backend
|
||||
3D API. */
|
||||
bool fSwapRAndB;
|
||||
/** Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
performance limitations in the underlying 3D API. */
|
||||
GrSwizzle fSwizzle;
|
||||
/** The config that should be used to read from the temp surface after the draw. This may be
|
||||
different than the original read config in order to compensate for swizzling. The
|
||||
read data will effectively be in the original read config. */
|
||||
GrPixelConfig fReadConfig;
|
||||
};
|
||||
|
||||
/** Describes why an intermediate draw must/should be performed before readPixels. */
|
||||
enum DrawPreference {
|
||||
/** On input means that the caller would proceed without draw if the GrGpu doesn't request
|
||||
@ -202,12 +205,13 @@ public:
|
||||
should upload the pixels such that the upper left pixel of the upload rect is at 0,0 in
|
||||
the intermediate surface.*/
|
||||
GrSurfaceDesc fTempSurfaceDesc;
|
||||
/** If set, fTempSurfaceDesc's config will be a R/B swap of the src pixel config. The caller
|
||||
should upload the pixels as is such that R and B will be swapped in the intermediate
|
||||
surface. When the intermediate is drawn to the dst the shader should swap R/B again
|
||||
such that the correct swizzle results in the dst. This is done to work around either
|
||||
performance or API restrictions in the backend 3D API implementation. */
|
||||
bool fSwapRAndB;
|
||||
/** Swizzle to apply during the draw. This is used to compensate for either feature or
|
||||
performance limitations in the underlying 3D API. */
|
||||
GrSwizzle fSwizzle;
|
||||
/** The config that should be specified when uploading the *original* data to the temp
|
||||
surface before the draw. This may be different than the original src data config in
|
||||
order to compensate for swizzling that will occur when drawing. */
|
||||
GrPixelConfig fWriteConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -8,8 +8,8 @@
|
||||
#ifndef GrSwizzle_DEFINED
|
||||
#define GrSwizzle_DEFINED
|
||||
|
||||
#include "GrTypes.h"
|
||||
#include "GrColor.h"
|
||||
#include "SkRandom.h"
|
||||
|
||||
/** Represents a rgba swizzle. It can be converted either into a string or a eight bit int.
|
||||
Currently there is no way to specify an arbitrary swizzle, just some static swizzles and an
|
||||
@ -84,6 +84,22 @@ public:
|
||||
return gBGRA;
|
||||
}
|
||||
|
||||
static const GrSwizzle& CreateRandom(SkRandom* random) {
|
||||
switch (random->nextU() % 4) {
|
||||
case 0:
|
||||
return RGBA();
|
||||
case 1:
|
||||
return BGRA();
|
||||
case 2:
|
||||
return RRRR();
|
||||
case 3:
|
||||
return AAAA();
|
||||
default:
|
||||
SkFAIL("Mod is broken?!?");
|
||||
return RGBA();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
char fSwiz[5];
|
||||
uint8_t fKey;
|
||||
|
@ -16,14 +16,13 @@
|
||||
|
||||
class GrGLConfigConversionEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLConfigConversionEffect(const GrProcessor& processor) {
|
||||
const GrConfigConversionEffect& configConversionEffect =
|
||||
processor.cast<GrConfigConversionEffect>();
|
||||
fSwapRedAndBlue = configConversionEffect.swapsRedAndBlue();
|
||||
fPMConversion = configConversionEffect.pmConversion();
|
||||
}
|
||||
GrGLConfigConversionEffect() {}
|
||||
|
||||
virtual void emitCode(EmitArgs& args) override {
|
||||
const GrConfigConversionEffect& cce = args.fFp.cast<GrConfigConversionEffect>();
|
||||
const GrSwizzle& swizzle = cce.swizzle();
|
||||
GrConfigConversionEffect::PMConversion pmConversion = cce.pmConversion();
|
||||
|
||||
// Using highp for GLES here in order to avoid some precision issues on specific GPUs.
|
||||
GrGLSLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
|
||||
SkString tmpDecl;
|
||||
@ -38,16 +37,16 @@ public:
|
||||
args.fCoords[0].getType());
|
||||
fragBuilder->codeAppend(";");
|
||||
|
||||
if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
|
||||
SkASSERT(fSwapRedAndBlue);
|
||||
fragBuilder->codeAppendf("%s = %s.bgra;", args.fOutputColor, tmpVar.c_str());
|
||||
if (GrConfigConversionEffect::kNone_PMConversion == pmConversion) {
|
||||
SkASSERT(GrSwizzle::RGBA() != swizzle);
|
||||
fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
|
||||
swizzle.c_str());
|
||||
} else {
|
||||
const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
|
||||
switch (fPMConversion) {
|
||||
switch (pmConversion) {
|
||||
case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
|
||||
fragBuilder->codeAppendf(
|
||||
"%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
|
||||
"%s = vec4(ceil(%s.rgb * %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());
|
||||
break;
|
||||
case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
|
||||
// Add a compensation(0.001) here to avoid the side effect of the floor operation.
|
||||
@ -55,24 +54,28 @@ public:
|
||||
// is less than the integer value converted from %s.r by 1 when the %s.r is
|
||||
// converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
|
||||
fragBuilder->codeAppendf(
|
||||
"%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
|
||||
"%s = vec4(floor(%s.rgb * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str());
|
||||
|
||||
break;
|
||||
case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
|
||||
fragBuilder->codeAppendf(
|
||||
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
|
||||
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
|
||||
tmpVar.c_str());
|
||||
break;
|
||||
case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
|
||||
fragBuilder->codeAppendf(
|
||||
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
|
||||
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.rgb / %s.a * 255.0) / 255.0, %s.a);",
|
||||
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(),
|
||||
tmpVar.c_str());
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unknown conversion op.");
|
||||
break;
|
||||
}
|
||||
fragBuilder->codeAppendf("%s = %s;", args.fOutputColor, tmpVar.c_str());
|
||||
fragBuilder->codeAppendf("%s = %s.%s;", args.fOutputColor, tmpVar.c_str(),
|
||||
swizzle.c_str());
|
||||
}
|
||||
SkString modulate;
|
||||
GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
|
||||
@ -81,15 +84,12 @@ public:
|
||||
|
||||
static inline void GenKey(const GrProcessor& processor, const GrGLSLCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const GrConfigConversionEffect& conv = processor.cast<GrConfigConversionEffect>();
|
||||
uint32_t key = (conv.swapsRedAndBlue() ? 0 : 1) | (conv.pmConversion() << 1);
|
||||
const GrConfigConversionEffect& cce = processor.cast<GrConfigConversionEffect>();
|
||||
uint32_t key = (cce.swizzle().asKey()) | (cce.pmConversion() << 16);
|
||||
b->add32(key);
|
||||
}
|
||||
|
||||
private:
|
||||
bool fSwapRedAndBlue;
|
||||
GrConfigConversionEffect::PMConversion fPMConversion;
|
||||
|
||||
typedef GrGLSLFragmentProcessor INHERITED;
|
||||
|
||||
};
|
||||
@ -97,11 +97,11 @@ private:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
|
||||
bool swapRedAndBlue,
|
||||
const GrSwizzle& swizzle,
|
||||
PMConversion pmConversion,
|
||||
const SkMatrix& matrix)
|
||||
: INHERITED(texture, matrix)
|
||||
, fSwapRedAndBlue(swapRedAndBlue)
|
||||
, 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
|
||||
@ -110,12 +110,12 @@ GrConfigConversionEffect::GrConfigConversionEffect(GrTexture* texture,
|
||||
kBGRA_8888_GrPixelConfig == texture->config()) ||
|
||||
kNone_PMConversion == pmConversion);
|
||||
// Why did we pollute our texture cache instead of using a GrSingleTextureEffect?
|
||||
SkASSERT(swapRedAndBlue || kNone_PMConversion != pmConversion);
|
||||
SkASSERT(swizzle != GrSwizzle::RGBA() || kNone_PMConversion != pmConversion);
|
||||
}
|
||||
|
||||
bool GrConfigConversionEffect::onIsEqual(const GrFragmentProcessor& s) const {
|
||||
const GrConfigConversionEffect& other = s.cast<GrConfigConversionEffect>();
|
||||
return other.fSwapRedAndBlue == fSwapRedAndBlue &&
|
||||
return other.fSwizzle == fSwizzle &&
|
||||
other.fPMConversion == fPMConversion;
|
||||
}
|
||||
|
||||
@ -129,14 +129,12 @@ GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrConfigConversionEffect);
|
||||
|
||||
const GrFragmentProcessor* GrConfigConversionEffect::TestCreate(GrProcessorTestData* d) {
|
||||
PMConversion pmConv = static_cast<PMConversion>(d->fRandom->nextULessThan(kPMConversionCnt));
|
||||
bool swapRB;
|
||||
if (kNone_PMConversion == pmConv) {
|
||||
swapRB = true;
|
||||
} else {
|
||||
swapRB = d->fRandom->nextBool();
|
||||
}
|
||||
GrSwizzle swizzle;
|
||||
do {
|
||||
swizzle = GrSwizzle::CreateRandom(d->fRandom);
|
||||
} while (pmConv == kNone_PMConversion && swizzle == GrSwizzle::RGBA());
|
||||
return new GrConfigConversionEffect(d->fTextures[GrProcessorUnitTest::kSkiaPMTextureIdx],
|
||||
swapRB, pmConv, GrTest::TestMatrix(d->fRandom));
|
||||
swizzle, pmConv, GrTest::TestMatrix(d->fRandom));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -147,7 +145,7 @@ void GrConfigConversionEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* GrConfigConversionEffect::onCreateGLSLInstance() const {
|
||||
return new GrGLConfigConversionEffect(*this);
|
||||
return new GrGLConfigConversionEffect();
|
||||
}
|
||||
|
||||
|
||||
@ -215,11 +213,11 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
|
||||
GrPaint paint2;
|
||||
GrPaint paint3;
|
||||
SkAutoTUnref<GrFragmentProcessor> pmToUPM1(new GrConfigConversionEffect(
|
||||
dataTex, false, *pmToUPMRule, SkMatrix::I()));
|
||||
dataTex, GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
|
||||
SkAutoTUnref<GrFragmentProcessor> upmToPM(new GrConfigConversionEffect(
|
||||
readTex, false, *upmToPMRule, SkMatrix::I()));
|
||||
readTex, GrSwizzle::RGBA(), *upmToPMRule, SkMatrix::I()));
|
||||
SkAutoTUnref<GrFragmentProcessor> pmToUPM2(new GrConfigConversionEffect(
|
||||
tempTex, false, *pmToUPMRule, SkMatrix::I()));
|
||||
tempTex, GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I()));
|
||||
|
||||
paint1.addColorFragmentProcessor(pmToUPM1);
|
||||
paint1.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
|
||||
@ -289,10 +287,10 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context
|
||||
}
|
||||
|
||||
const GrFragmentProcessor* GrConfigConversionEffect::Create(GrTexture* texture,
|
||||
bool swapRedAndBlue,
|
||||
const GrSwizzle& swizzle,
|
||||
PMConversion pmConversion,
|
||||
const SkMatrix& matrix) {
|
||||
if (!swapRedAndBlue && kNone_PMConversion == pmConversion) {
|
||||
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.
|
||||
@ -304,6 +302,6 @@ const GrFragmentProcessor* GrConfigConversionEffect::Create(GrTexture* texture,
|
||||
// The PM conversions assume colors are 0..255
|
||||
return nullptr;
|
||||
}
|
||||
return new GrConfigConversionEffect(texture, swapRedAndBlue, pmConversion, matrix);
|
||||
return new GrConfigConversionEffect(texture, swizzle, pmConversion, matrix);
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,14 @@
|
||||
#define GrConfigConversionEffect_DEFINED
|
||||
|
||||
#include "GrSingleTextureEffect.h"
|
||||
#include "GrSwizzle.h"
|
||||
|
||||
class GrInvariantOutput;
|
||||
|
||||
/**
|
||||
* This class is used to perform config conversions. Clients may want to read/write data that is
|
||||
* unpremultiplied. Also on some systems reading/writing BGRA or RGBA is faster. In those cases we
|
||||
* read/write using the faster path and perform an R/B swap in the shader if the client data is in
|
||||
* the slower config.
|
||||
* unpremultiplied. Additionally, the channels may also be swizzled for optimal readback/upload
|
||||
* performance.
|
||||
*/
|
||||
class GrConfigConversionEffect : public GrSingleTextureEffect {
|
||||
public:
|
||||
@ -33,12 +33,12 @@ public:
|
||||
kPMConversionCnt
|
||||
};
|
||||
|
||||
static const GrFragmentProcessor* Create(GrTexture*, bool swapRedAndBlue, PMConversion,
|
||||
static const GrFragmentProcessor* Create(GrTexture*, const GrSwizzle&, PMConversion,
|
||||
const SkMatrix&);
|
||||
|
||||
const char* name() const override { return "Config Conversion"; }
|
||||
|
||||
bool swapsRedAndBlue() const { return fSwapRedAndBlue; }
|
||||
const GrSwizzle& swizzle() const { return fSwizzle; }
|
||||
PMConversion pmConversion() const { return fPMConversion; }
|
||||
|
||||
// This function determines whether it is possible to choose PM->UPM and UPM->PM conversions
|
||||
@ -52,7 +52,7 @@ public:
|
||||
|
||||
private:
|
||||
GrConfigConversionEffect(GrTexture*,
|
||||
bool swapRedAndBlue,
|
||||
const GrSwizzle&,
|
||||
PMConversion pmConversion,
|
||||
const SkMatrix& matrix);
|
||||
|
||||
@ -64,7 +64,7 @@ private:
|
||||
|
||||
void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
|
||||
|
||||
bool fSwapRedAndBlue;
|
||||
GrSwizzle fSwizzle;
|
||||
PMConversion fPMConversion;
|
||||
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
|
||||
|
@ -670,7 +670,9 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
tempDrawInfo->fSwapRAndB = false;
|
||||
// Start off assuming no swizzling
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fWriteConfig = srcConfig;
|
||||
|
||||
// These settings we will always want if a temp draw is performed. Initially set the config
|
||||
// to srcConfig, though that may be modified if we decide to do a R/G swap.
|
||||
@ -687,19 +689,22 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
|
||||
if (!this->caps()->isConfigTexturable(srcConfig)) {
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
} else if (this->glCaps().rgba8888PixelsOpsAreSlow() &&
|
||||
kRGBA_8888_GrPixelConfig == srcConfig) {
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
} else if (kGLES_GrGLStandard == this->glStandard() &&
|
||||
this->glCaps().bgraIsInternalFormat()) {
|
||||
// The internal format and external formats must match texture uploads so we can't
|
||||
// swizzle while uploading when BGRA is a distinct internal format.
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = dstSurface->config();
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fWriteConfig = dstSurface->config();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2077,7 +2082,8 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
tempDrawInfo->fSwapRAndB = false;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::RGBA();
|
||||
tempDrawInfo->fReadConfig = readConfig;
|
||||
|
||||
// These settings we will always want if a temp draw is performed. The config is set below
|
||||
// depending on whether we want to do a R/B swap or not.
|
||||
@ -2095,20 +2101,23 @@ bool GrGLGpu::onGetReadPixelsInfo(GrSurface* srcSurface, int width, int height,
|
||||
|
||||
if (this->glCaps().rgba8888PixelsOpsAreSlow() && kRGBA_8888_GrPixelConfig == readConfig) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kBGRA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kBGRA_8888_GrPixelConfig;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (kMesa_GrGLDriver == this->glContext().driver() &&
|
||||
GrBytesPerPixel(readConfig) == 4 &&
|
||||
GrPixelConfigSwapRAndB(readConfig) == srcConfig) {
|
||||
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
|
||||
// Mesa 3D takes a slow path on when reading back BGRA from an RGBA surface and vice-versa.
|
||||
// Better to do a draw with a R/B swap and then read as the original config.
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = srcConfig;
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = srcConfig;
|
||||
ElevateDrawPreference(drawPreference, kGpuPrefersDraw_DrawPreference);
|
||||
} else if (readConfig == kBGRA_8888_GrPixelConfig &&
|
||||
!this->glCaps().readPixelsSupported(this->glInterface(), readConfig, srcConfig)) {
|
||||
tempDrawInfo->fTempSurfaceDesc.fConfig = kRGBA_8888_GrPixelConfig;
|
||||
tempDrawInfo->fSwapRAndB = true;
|
||||
tempDrawInfo->fSwizzle = GrSwizzle::BGRA();
|
||||
tempDrawInfo->fReadConfig = kRGBA_8888_GrPixelConfig;
|
||||
ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference);
|
||||
}
|
||||
|
||||
@ -2160,8 +2169,7 @@ bool GrGLGpu::onReadPixels(GrSurface* surface,
|
||||
this->onResolveRenderTarget(tgt);
|
||||
// we don't track the state of the READ FBO ID.
|
||||
fStats.incRenderTargetBinds();
|
||||
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER,
|
||||
tgt->textureFBOID()));
|
||||
GL_CALL(BindFramebuffer(GR_GL_READ_FRAMEBUFFER, tgt->textureFBOID()));
|
||||
break;
|
||||
default:
|
||||
SkFAIL("Unknown resolve type");
|
||||
|
Loading…
Reference in New Issue
Block a user