Distance field fixes for Android
- Expand glyph size by 2 on each side to compensate for bilerp lookup - Correct for Adreno tendency to drop entire tile if any pixel has divide-by-0 - Fix blurriness on Adreno by using uv coords to compute gradient instead of st coords - Add faster version for uniform scale BUG=skia:2173 R=bsalomon@google.com Author: jvanverth@google.com Review URL: https://codereview.chromium.org/205343008 git-svn-id: http://skia.googlecode.com/svn/trunk@13955 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
3fcab54c7f
commit
8fe2ee1cf3
@ -336,10 +336,10 @@ bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField,
|
|||||||
SkASSERT(NULL != image);
|
SkASSERT(NULL != image);
|
||||||
|
|
||||||
// the final distance field will have additional texels on each side to handle
|
// the final distance field will have additional texels on each side to handle
|
||||||
// the maximum distance
|
// the maximum distance + 1 for bilerp
|
||||||
// we expand our temp data by one more on each side to simplify
|
// we expand our temp data by one more on each side to simplify
|
||||||
// the scanning code -- will always be treated as infinitely far away
|
// the scanning code -- will always be treated as infinitely far away
|
||||||
int pad = distanceMagnitude+1;
|
int pad = distanceMagnitude+2;
|
||||||
|
|
||||||
// set params for distance field data
|
// set params for distance field data
|
||||||
int dataWidth = width + 2*pad;
|
int dataWidth = width + 2*pad;
|
||||||
|
@ -209,7 +209,3 @@ GrPlot* GrAtlasMgr::getUnusedPlot() {
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkISize GrAtlas::getSize() const {
|
|
||||||
return SkISize::Make(GR_ATLAS_TEXTURE_WIDTH, GR_ATLAS_TEXTURE_HEIGHT);
|
|
||||||
}
|
|
||||||
|
@ -103,8 +103,6 @@ public:
|
|||||||
|
|
||||||
bool isEmpty() { return 0 == fPlots.count(); }
|
bool isEmpty() { return 0 == fPlots.count(); }
|
||||||
|
|
||||||
SkISize getSize() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SkTDArray<GrPlot*> fPlots;
|
SkTDArray<GrPlot*> fPlots;
|
||||||
|
|
||||||
|
@ -81,10 +81,10 @@ void GrDistanceFieldTextContext::flushGlyphs() {
|
|||||||
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
|
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
|
||||||
|
|
||||||
// This effect could be stored with one of the cache objects (atlas?)
|
// This effect could be stored with one of the cache objects (atlas?)
|
||||||
SkISize size = fStrike->getAtlasSize();
|
|
||||||
drawState->addCoverageEffect(
|
drawState->addCoverageEffect(
|
||||||
GrDistanceFieldTextureEffect::Create(fCurrTexture, params, size),
|
GrDistanceFieldTextureEffect::Create(fCurrTexture, params,
|
||||||
kGlyphCoordsAttributeIndex)->unref();
|
fContext->getMatrix().isSimilarity()),
|
||||||
|
kGlyphCoordsAttributeIndex)->unref();
|
||||||
|
|
||||||
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
|
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
|
||||||
if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
|
if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
|
||||||
|
@ -232,8 +232,9 @@ public:
|
|||||||
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
|
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
|
||||||
// we need to clamp the length^2 of the gradiant vector to a non-zero value, because
|
// we need to clamp the length^2 of the gradiant vector to a non-zero value, because
|
||||||
// on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
|
// on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
|
||||||
// TODO: restrict this to Adreno-only
|
if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
|
||||||
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
|
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
|
||||||
|
}
|
||||||
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
|
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
|
||||||
builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n");
|
builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n");
|
||||||
|
|
||||||
@ -380,8 +381,9 @@ public:
|
|||||||
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
|
builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
|
||||||
// we need to clamp the length^2 of the gradiant vector to a non-zero value, because
|
// we need to clamp the length^2 of the gradiant vector to a non-zero value, because
|
||||||
// on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
|
// on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile
|
||||||
// TODO: restrict this to Adreno-only
|
if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
|
||||||
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
|
builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
|
||||||
|
}
|
||||||
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
|
builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
|
||||||
if (kHairline == ellipseEffect.getMode()) {
|
if (kHairline == ellipseEffect.getMode()) {
|
||||||
// can probably do this with one step
|
// can probably do this with one step
|
||||||
|
@ -181,7 +181,11 @@ void GrFontCache::dump() const {
|
|||||||
GrTexture* texture = fAtlasMgr[i]->getTexture();
|
GrTexture* texture = fAtlasMgr[i]->getTexture();
|
||||||
if (NULL != texture) {
|
if (NULL != texture) {
|
||||||
SkString filename;
|
SkString filename;
|
||||||
|
#ifdef SK_BUILD_FOR_ANDROID
|
||||||
|
filename.printf("/sdcard/fontcache_%d%d.png", gDumpCount, i);
|
||||||
|
#else
|
||||||
filename.printf("fontcache_%d%d.png", gDumpCount, i);
|
filename.printf("fontcache_%d%d.png", gDumpCount, i);
|
||||||
|
#endif
|
||||||
texture->savePixels(filename.c_str());
|
texture->savePixels(filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,11 +252,13 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed,
|
|||||||
|
|
||||||
GrGlyph* glyph = fPool.alloc();
|
GrGlyph* glyph = fPool.alloc();
|
||||||
// expand bounds to hold full distance field data
|
// expand bounds to hold full distance field data
|
||||||
|
// + room for bilerp
|
||||||
|
int pad = DISTANCE_FIELD_RANGE+1;
|
||||||
if (fUseDistanceField) {
|
if (fUseDistanceField) {
|
||||||
bounds.fLeft -= DISTANCE_FIELD_RANGE;
|
bounds.fLeft -= pad;
|
||||||
bounds.fRight += DISTANCE_FIELD_RANGE;
|
bounds.fRight += pad;
|
||||||
bounds.fTop -= DISTANCE_FIELD_RANGE;
|
bounds.fTop -= pad;
|
||||||
bounds.fBottom += DISTANCE_FIELD_RANGE;
|
bounds.fBottom += pad;
|
||||||
}
|
}
|
||||||
glyph->init(packed, bounds);
|
glyph->init(packed, bounds);
|
||||||
fCache.insert(packed, glyph);
|
fCache.insert(packed, glyph);
|
||||||
@ -292,8 +298,9 @@ bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) {
|
|||||||
// but must shrink back down to get the packed glyph data
|
// but must shrink back down to get the packed glyph data
|
||||||
int dfWidth = glyph->width();
|
int dfWidth = glyph->width();
|
||||||
int dfHeight = glyph->height();
|
int dfHeight = glyph->height();
|
||||||
int width = dfWidth - 2*DISTANCE_FIELD_RANGE;
|
int pad = DISTANCE_FIELD_RANGE+1;
|
||||||
int height = dfHeight - 2*DISTANCE_FIELD_RANGE;
|
int width = dfWidth - 2*pad;
|
||||||
|
int height = dfHeight - 2*pad;
|
||||||
int stride = width*bytesPerPixel;
|
int stride = width*bytesPerPixel;
|
||||||
|
|
||||||
size_t size = width * height * bytesPerPixel;
|
size_t size = width * height * bytesPerPixel;
|
||||||
|
@ -39,8 +39,6 @@ public:
|
|||||||
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
|
inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
|
||||||
bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
|
bool addGlyphToAtlas(GrGlyph*, GrFontScaler*);
|
||||||
|
|
||||||
SkISize getAtlasSize() const { return fAtlas.getSize(); }
|
|
||||||
|
|
||||||
// testing
|
// testing
|
||||||
int countGlyphs() const { return fCache.getArray().count(); }
|
int countGlyphs() const { return fCache.getArray().count(); }
|
||||||
const GrGlyph* glyphAt(int index) const {
|
const GrGlyph* glyphAt(int index) const {
|
||||||
|
@ -35,6 +35,8 @@ public:
|
|||||||
SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs());
|
SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numVertexAttribs());
|
||||||
|
|
||||||
SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
|
SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
|
||||||
|
const GrDistanceFieldTextureEffect& dfTexEffect =
|
||||||
|
drawEffect.castEffect<GrDistanceFieldTextureEffect>();
|
||||||
|
|
||||||
SkString fsCoordName;
|
SkString fsCoordName;
|
||||||
const char* vsCoordName;
|
const char* vsCoordName;
|
||||||
@ -61,16 +63,37 @@ public:
|
|||||||
// we adjust for the effect of the transformation on the distance by using
|
// we adjust for the effect of the transformation on the distance by using
|
||||||
// the length of the gradient of the texture coordinates. We use st coordinates
|
// the length of the gradient of the texture coordinates. We use st coordinates
|
||||||
// to ensure we're mapping 1:1 from texel space to pixel space.
|
// to ensure we're mapping 1:1 from texel space to pixel space.
|
||||||
builder->fsCodeAppendf("\tvec2 st = %s*%s;\n", fsCoordName.c_str(), textureSizeUniName);
|
builder->fsCodeAppendf("\tvec2 uv = %s;\n", fsCoordName.c_str());
|
||||||
builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
|
builder->fsCodeAppendf("\tvec2 st = uv*%s;\n", textureSizeUniName);
|
||||||
builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
|
builder->fsCodeAppend("\tfloat afwidth;\n");
|
||||||
builder->fsCodeAppend("\tvec2 st_grad = normalize(st);\n");
|
if (dfTexEffect.isUniformScale()) {
|
||||||
builder->fsCodeAppend("\tvec2 grad = vec2(st_grad.x*Jdx.x + st_grad.y*Jdy.x,\n");
|
// this gives us a smooth step across approximately one fragment
|
||||||
builder->fsCodeAppend("\t st_grad.x*Jdx.y + st_grad.y*Jdy.y);\n");
|
// (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2)
|
||||||
|
builder->fsCodeAppend("\tafwidth = 0.7071*dFdx(st.x);\n");
|
||||||
|
} else {
|
||||||
|
builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n");
|
||||||
|
builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n");
|
||||||
|
|
||||||
|
builder->fsCodeAppend("\tvec2 uv_grad;\n");
|
||||||
|
if (builder->ctxInfo().caps()->dropsTileOnZeroDivide()) {
|
||||||
|
// this is to compensate for the Adreno, which likes to drop tiles on division by 0
|
||||||
|
builder->fsCodeAppend("\tfloat uv_len2 = dot(uv, uv);\n");
|
||||||
|
builder->fsCodeAppend("\tif (uv_len2 < 0.0001) {\n");
|
||||||
|
builder->fsCodeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n");
|
||||||
|
builder->fsCodeAppend("\t} else {\n");
|
||||||
|
builder->fsCodeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n");
|
||||||
|
builder->fsCodeAppend("\t}\n");
|
||||||
|
} else {
|
||||||
|
builder->fsCodeAppend("\tuv_grad = normalize(uv);\n");
|
||||||
|
}
|
||||||
|
builder->fsCodeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n");
|
||||||
|
builder->fsCodeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n");
|
||||||
|
|
||||||
|
// this gives us a smooth step across approximately one fragment
|
||||||
|
// (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2)
|
||||||
|
builder->fsCodeAppend("\tafwidth = 0.7071*length(grad);\n");
|
||||||
|
}
|
||||||
|
|
||||||
// this gives us a smooth step across approximately one fragment
|
|
||||||
// (assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2)
|
|
||||||
builder->fsCodeAppend("\tfloat afwidth = 0.7071*length(grad);\n");
|
|
||||||
builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
|
builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n");
|
||||||
|
|
||||||
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
|
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
|
||||||
@ -80,17 +103,24 @@ public:
|
|||||||
virtual void setData(const GrGLUniformManager& uman,
|
virtual void setData(const GrGLUniformManager& uman,
|
||||||
const GrDrawEffect& drawEffect) SK_OVERRIDE {
|
const GrDrawEffect& drawEffect) SK_OVERRIDE {
|
||||||
SkASSERT(fTextureSizeUni.isValid());
|
SkASSERT(fTextureSizeUni.isValid());
|
||||||
const GrDistanceFieldTextureEffect& distanceFieldEffect =
|
|
||||||
drawEffect.castEffect<GrDistanceFieldTextureEffect>();
|
GrTexture* texture = drawEffect.effect()->get()->texture(0);
|
||||||
if (distanceFieldEffect.getSize().width() != fTextureSize.width() ||
|
if (texture->width() != fTextureSize.width() ||
|
||||||
distanceFieldEffect.getSize().height() != fTextureSize.height()) {
|
texture->height() != fTextureSize.height()) {
|
||||||
fTextureSize = distanceFieldEffect.getSize();
|
fTextureSize = SkSize::Make(texture->width(), texture->height());
|
||||||
uman.set2f(fTextureSizeUni,
|
uman.set2f(fTextureSizeUni,
|
||||||
distanceFieldEffect.getSize().width(),
|
fTextureSize.width(),
|
||||||
distanceFieldEffect.getSize().height());
|
fTextureSize.height());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
|
||||||
|
const GrDistanceFieldTextureEffect& dfTexEffect =
|
||||||
|
drawEffect.castEffect<GrDistanceFieldTextureEffect>();
|
||||||
|
|
||||||
|
return dfTexEffect.isUniformScale() ? 0x1 : 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrGLUniformManager::UniformHandle fTextureSizeUni;
|
GrGLUniformManager::UniformHandle fTextureSizeUni;
|
||||||
SkSize fTextureSize;
|
SkSize fTextureSize;
|
||||||
@ -102,9 +132,9 @@ private:
|
|||||||
|
|
||||||
GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
|
GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture,
|
||||||
const GrTextureParams& params,
|
const GrTextureParams& params,
|
||||||
const SkISize& size)
|
bool uniformScale)
|
||||||
: fTextureAccess(texture, params)
|
: fTextureAccess(texture, params)
|
||||||
, fSize(SkSize::Make(SkIntToScalar(size.width()), SkIntToScalar(size.height()))) {
|
, fUniformScale(uniformScale) {
|
||||||
this->addTextureAccess(&fTextureAccess);
|
this->addTextureAccess(&fTextureAccess);
|
||||||
this->addVertexAttrib(kVec2f_GrSLType);
|
this->addVertexAttrib(kVec2f_GrSLType);
|
||||||
}
|
}
|
||||||
@ -149,7 +179,6 @@ GrEffectRef* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
|
|||||||
};
|
};
|
||||||
GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
|
GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBilerp_FilterMode :
|
||||||
GrTextureParams::kNone_FilterMode);
|
GrTextureParams::kNone_FilterMode);
|
||||||
SkISize size = SkISize::Make(1024, 2048);
|
|
||||||
|
|
||||||
return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, size);
|
return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, random->nextBool());
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ class GrGLDistanceFieldTextureEffect;
|
|||||||
*/
|
*/
|
||||||
class GrDistanceFieldTextureEffect : public GrVertexEffect {
|
class GrDistanceFieldTextureEffect : public GrVertexEffect {
|
||||||
public:
|
public:
|
||||||
static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& p, const SkISize& s) {
|
static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& para, bool uniformScale) {
|
||||||
AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, p, s)));
|
AutoEffectUnref effect(SkNEW_ARGS(GrDistanceFieldTextureEffect, (tex, para, uniformScale)));
|
||||||
return CreateEffectRef(effect);
|
return CreateEffectRef(effect);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ public:
|
|||||||
static const char* Name() { return "DistanceFieldTexture"; }
|
static const char* Name() { return "DistanceFieldTexture"; }
|
||||||
|
|
||||||
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
|
virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
|
||||||
const SkSize& getSize() const { return fSize; }
|
bool isUniformScale() const { return fUniformScale; }
|
||||||
|
|
||||||
typedef GrGLDistanceFieldTextureEffect GLEffect;
|
typedef GrGLDistanceFieldTextureEffect GLEffect;
|
||||||
|
|
||||||
@ -39,12 +39,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params,
|
GrDistanceFieldTextureEffect(GrTexture* texture, const GrTextureParams& params,
|
||||||
const SkISize& textureSize);
|
bool uniformScale);
|
||||||
|
|
||||||
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
|
virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE;
|
||||||
|
|
||||||
GrTextureAccess fTextureAccess;
|
GrTextureAccess fTextureAccess;
|
||||||
SkSize fSize;
|
bool fUniformScale;
|
||||||
|
|
||||||
GR_DECLARE_EFFECT_TEST;
|
GR_DECLARE_EFFECT_TEST;
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ void GrGLCaps::reset() {
|
|||||||
fFixedFunctionSupport = false;
|
fFixedFunctionSupport = false;
|
||||||
fDiscardFBSupport = false;
|
fDiscardFBSupport = false;
|
||||||
fFullClearIsFree = false;
|
fFullClearIsFree = false;
|
||||||
|
fDropsTileOnZeroDivide = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
|
GrGLCaps::GrGLCaps(const GrGLCaps& caps) : GrDrawTargetCaps() {
|
||||||
@ -84,6 +85,7 @@ GrGLCaps& GrGLCaps::operator = (const GrGLCaps& caps) {
|
|||||||
fFixedFunctionSupport = caps.fFixedFunctionSupport;
|
fFixedFunctionSupport = caps.fFixedFunctionSupport;
|
||||||
fDiscardFBSupport = caps.fDiscardFBSupport;
|
fDiscardFBSupport = caps.fDiscardFBSupport;
|
||||||
fFullClearIsFree = caps.fFullClearIsFree;
|
fFullClearIsFree = caps.fFullClearIsFree;
|
||||||
|
fDropsTileOnZeroDivide = caps.fDropsTileOnZeroDivide;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -244,6 +246,9 @@ void GrGLCaps::init(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adreno GPUs have a tendency to drop tiles when there is a divide-by-zero in a shader
|
||||||
|
fDropsTileOnZeroDivide = kQualcomm_GrGLVendor == ctxInfo.vendor();
|
||||||
|
|
||||||
this->initFSAASupport(ctxInfo, gli);
|
this->initFSAASupport(ctxInfo, gli);
|
||||||
this->initStencilFormats(ctxInfo);
|
this->initStencilFormats(ctxInfo);
|
||||||
|
|
||||||
@ -661,5 +666,6 @@ SkString GrGLCaps::dump() const {
|
|||||||
(fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
|
(fUseNonVBOVertexAndIndexDynamicData ? "YES" : "NO"));
|
||||||
r.appendf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO"));
|
r.appendf("Discard FrameBuffer support: %s\n", (fDiscardFBSupport ? "YES" : "NO"));
|
||||||
r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
|
r.appendf("Full screen clear is free: %s\n", (fFullClearIsFree ? "YES" : "NO"));
|
||||||
|
r.appendf("Drops tile on zero divide: %s\n", (fDropsTileOnZeroDivide ? "YES" : "NO"));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,8 @@ public:
|
|||||||
|
|
||||||
bool fullClearIsFree() const { return fFullClearIsFree; }
|
bool fullClearIsFree() const { return fFullClearIsFree; }
|
||||||
|
|
||||||
|
bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
|
* Maintains a bit per GrPixelConfig. It is used to avoid redundantly
|
||||||
@ -332,6 +334,7 @@ private:
|
|||||||
bool fFixedFunctionSupport : 1;
|
bool fFixedFunctionSupport : 1;
|
||||||
bool fDiscardFBSupport : 1;
|
bool fDiscardFBSupport : 1;
|
||||||
bool fFullClearIsFree : 1;
|
bool fFullClearIsFree : 1;
|
||||||
|
bool fDropsTileOnZeroDivide : 1;
|
||||||
|
|
||||||
typedef GrDrawTargetCaps INHERITED;
|
typedef GrDrawTargetCaps INHERITED;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user