| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrAtlasTextBatch.h" | 8 #include "GrAtlasTextBatch.h" |
| 9 | 9 |
| 10 #include "GrBatchFlushState.h" | 10 #include "GrBatchFlushState.h" |
| 11 #include "GrBatchTest.h" | |
| 12 #include "GrResourceProvider.h" | 11 #include "GrResourceProvider.h" |
| 13 | 12 |
| 14 #include "SkDistanceFieldGen.h" | |
| 15 #include "SkGlyphCache.h" | 13 #include "SkGlyphCache.h" |
| 16 | 14 |
| 17 #include "effects/GrBitmapTextGeoProc.h" | 15 #include "effects/GrBitmapTextGeoProc.h" |
| 18 #include "effects/GrDistanceFieldGeoProc.h" | 16 #include "effects/GrDistanceFieldGeoProc.h" |
| 19 #include "text/GrBatchFontCache.h" | 17 #include "text/GrBatchFontCache.h" |
| 20 | 18 |
| 21 ////////////////////////////////////////////////////////////////////////////////
//////////////////// | |
| 22 // A large template to handle regenerating the vertices of a textblob with as fe
w branches as | |
| 23 // possible | |
| 24 template <bool regenPos, bool regenCol, bool regenTexCoords> | |
| 25 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
tride, | |
| 26 bool useDistanceFields, SkScalar transX, SkScalar tra
nsY, | |
| 27 GrColor color) { | |
| 28 int u0, v0, u1, v1; | |
| 29 if (regenTexCoords) { | |
| 30 SkASSERT(glyph); | |
| 31 int width = glyph->fBounds.width(); | |
| 32 int height = glyph->fBounds.height(); | |
| 33 | |
| 34 if (useDistanceFields) { | |
| 35 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset; | |
| 36 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset; | |
| 37 u1 = u0 + width - 2 * SK_DistanceFieldInset; | |
| 38 v1 = v0 + height - 2 * SK_DistanceFieldInset; | |
| 39 } else { | |
| 40 u0 = glyph->fAtlasLocation.fX; | |
| 41 v0 = glyph->fAtlasLocation.fY; | |
| 42 u1 = u0 + width; | |
| 43 v1 = v0 + height; | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 // This is a bit wonky, but sometimes we have LCD text, in which case we won
't have color | |
| 48 // vertices, hence vertexStride - sizeof(SkIPoint16) | |
| 49 intptr_t colorOffset = sizeof(SkPoint); | |
| 50 intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16); | |
| 51 | |
| 52 // V0 | |
| 53 if (regenPos) { | |
| 54 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | |
| 55 point->fX += transX; | |
| 56 point->fY += transY; | |
| 57 } | |
| 58 | |
| 59 if (regenCol) { | |
| 60 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | |
| 61 *vcolor = color; | |
| 62 } | |
| 63 | |
| 64 if (regenTexCoords) { | |
| 65 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); | |
| 66 textureCoords->set(u0, v0); | |
| 67 } | |
| 68 vertex += vertexStride; | |
| 69 | |
| 70 // V1 | |
| 71 if (regenPos) { | |
| 72 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | |
| 73 point->fX += transX; | |
| 74 point->fY += transY; | |
| 75 } | |
| 76 | |
| 77 if (regenCol) { | |
| 78 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | |
| 79 *vcolor = color; | |
| 80 } | |
| 81 | |
| 82 if (regenTexCoords) { | |
| 83 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); | |
| 84 textureCoords->set(u0, v1); | |
| 85 } | |
| 86 vertex += vertexStride; | |
| 87 | |
| 88 // V2 | |
| 89 if (regenPos) { | |
| 90 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | |
| 91 point->fX += transX; | |
| 92 point->fY += transY; | |
| 93 } | |
| 94 | |
| 95 if (regenCol) { | |
| 96 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | |
| 97 *vcolor = color; | |
| 98 } | |
| 99 | |
| 100 if (regenTexCoords) { | |
| 101 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); | |
| 102 textureCoords->set(u1, v1); | |
| 103 } | |
| 104 vertex += vertexStride; | |
| 105 | |
| 106 // V3 | |
| 107 if (regenPos) { | |
| 108 SkPoint* point = reinterpret_cast<SkPoint*>(vertex); | |
| 109 point->fX += transX; | |
| 110 point->fY += transY; | |
| 111 } | |
| 112 | |
| 113 if (regenCol) { | |
| 114 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset); | |
| 115 *vcolor = color; | |
| 116 } | |
| 117 | |
| 118 if (regenTexCoords) { | |
| 119 SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCo
ordOffset); | |
| 120 textureCoords->set(u1, v0); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs> | |
| 125 inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl
ob* blob, Run* run, | |
| 126 TextInfo* info, SkGlyphCache** cache, | |
| 127 SkTypeface** typeface, GrFontScaler** sc
aler, | |
| 128 const SkDescriptor** desc, const GrGeome
tryProcessor* gp, | |
| 129 int glyphCount, size_t vertexStride, | |
| 130 GrColor color, SkScalar transX, SkScalar
transY) const { | |
| 131 static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along reg
enGlyphs"); | |
| 132 GrBatchTextStrike* strike = nullptr; | |
| 133 if (regenTexCoords) { | |
| 134 info->resetBulkUseToken(); | |
| 135 | |
| 136 // We can reuse if we have a valid strike and our descriptors / typeface
are the | |
| 137 // same. The override descriptor is only for the non distance field tex
t within | |
| 138 // a run | |
| 139 const SkDescriptor* newDesc = (run->fOverrideDescriptor && !this->usesDi
stanceFields()) ? | |
| 140 run->fOverrideDescriptor->getDesc() : | |
| 141 run->fDescriptor.getDesc(); | |
| 142 if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) || | |
| 143 !((*desc)->equals(*newDesc))) { | |
| 144 if (*cache) { | |
| 145 SkGlyphCache::AttachCache(*cache); | |
| 146 } | |
| 147 *desc = newDesc; | |
| 148 *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc); | |
| 149 *scaler = GrTextContext::GetGrFontScaler(*cache); | |
| 150 *typeface = run->fTypeface; | |
| 151 } | |
| 152 | |
| 153 if (regenGlyphs) { | |
| 154 strike = fFontCache->getStrike(*scaler); | |
| 155 } else { | |
| 156 strike = info->strike(); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 bool brokenRun = false; | |
| 161 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { | |
| 162 GrGlyph* glyph = nullptr; | |
| 163 if (regenTexCoords) { | |
| 164 size_t glyphOffset = glyphIdx + info->glyphStartIndex(); | |
| 165 | |
| 166 if (regenGlyphs) { | |
| 167 // Get the id from the old glyph, and use the new strike to look
up | |
| 168 // the glyph. | |
| 169 GrGlyph::PackedID id = blob->fGlyphs[glyphOffset]->fPackedID; | |
| 170 blob->fGlyphs[glyphOffset] = strike->getGlyph(id, this->maskForm
at(), *scaler); | |
| 171 SkASSERT(id == blob->fGlyphs[glyphOffset]->fPackedID); | |
| 172 } | |
| 173 glyph = blob->fGlyphs[glyphOffset]; | |
| 174 SkASSERT(glyph && glyph->fMaskFormat == this->maskFormat()); | |
| 175 | |
| 176 if (!fFontCache->hasGlyph(glyph) && | |
| 177 !strike->addGlyphToAtlas(target, glyph, *scaler, this->maskForma
t())) { | |
| 178 this->flush(target, flushInfo); | |
| 179 target->initDraw(gp, this->pipeline()); | |
| 180 brokenRun = glyphIdx > 0; | |
| 181 | |
| 182 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, | |
| 183 glyph, | |
| 184 *scaler, | |
| 185 this->maskFo
rmat()); | |
| 186 SkASSERT(success); | |
| 187 } | |
| 188 fFontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph
, | |
| 189 target->currentToken()); | |
| 190 } | |
| 191 | |
| 192 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices); | |
| 193 vertex += info->vertexStartIndex(); | |
| 194 vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; | |
| 195 regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertex
Stride, | |
| 196 this->usesDistanceFie
lds(), transX, | |
| 197 transY, color); | |
| 198 flushInfo->fGlyphsToFlush++; | |
| 199 } | |
| 200 | |
| 201 // We may have changed the color so update it here | |
| 202 info->setColor(color); | |
| 203 if (regenTexCoords) { | |
| 204 if (regenGlyphs) { | |
| 205 info->setStrike(strike); | |
| 206 } | |
| 207 info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGenerati
on : | |
| 208 fFontCache->atlasGeneration(this->m
askFormat())); | |
| 209 } | |
| 210 } | |
| 211 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 19 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 212 | 20 |
| 213 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { | 21 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) { |
| 214 unsigned r = SkColorGetR(c); | 22 unsigned r = SkColorGetR(c); |
| 215 unsigned g = SkColorGetG(c); | 23 unsigned g = SkColorGetG(c); |
| 216 unsigned b = SkColorGetB(c); | 24 unsigned b = SkColorGetB(c); |
| 217 return GrColorPackRGBA(r, g, b, 0xff); | 25 return GrColorPackRGBA(r, g, b, 0xff); |
| 218 } | 26 } |
| 219 | 27 |
| 220 static const int kDistanceAdjustLumShift = 5; | 28 static const int kDistanceAdjustLumShift = 5; |
| 221 | 29 |
| 222 SkString GrAtlasTextBatch::dumpInfo() const { | 30 SkString GrAtlasTextBatch::dumpInfo() const { |
| 223 SkString str; | 31 SkString str; |
| 224 | 32 |
| 225 for (int i = 0; i < fGeoCount; ++i) { | 33 for (int i = 0; i < fGeoCount; ++i) { |
| 226 str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n", | 34 str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n", |
| 227 i, | 35 i, |
| 228 fGeoData[i].fColor, | 36 fGeoData[i].fColor, |
| 229 fGeoData[i].fTransX, | 37 fGeoData[i].fTransX, |
| 230 fGeoData[i].fTransY, | 38 fGeoData[i].fTransY, |
| 231 fGeoData[i].fBlob->fRunCount); | 39 fGeoData[i].fBlob->runCount()); |
| 232 } | 40 } |
| 233 | 41 |
| 234 str.append(INHERITED::dumpInfo()); | 42 str.append(INHERITED::dumpInfo()); |
| 235 return str; | 43 return str; |
| 236 } | 44 } |
| 237 | 45 |
| 238 void GrAtlasTextBatch::computePipelineOptimizations(GrInitInvariantOutput* color
, | 46 void GrAtlasTextBatch::computePipelineOptimizations(GrInitInvariantOutput* color
, |
| 239 GrInitInvariantOutput* cover
age, | 47 GrInitInvariantOutput* cover
age, |
| 240 GrBatchToXPOverrides* overri
des) const { | 48 GrBatchToXPOverrides* overri
des) const { |
| 241 if (kColorBitmapMask_MaskType == fMaskType) { | 49 if (kColorBitmapMask_MaskType == fMaskType) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 265 } | 73 } |
| 266 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); | 74 overrides.getOverrideColorIfSet(&fGeoData[0].fColor); |
| 267 | 75 |
| 268 // setup batch properties | 76 // setup batch properties |
| 269 fBatch.fColorIgnored = !overrides.readsColor(); | 77 fBatch.fColorIgnored = !overrides.readsColor(); |
| 270 fBatch.fColor = fGeoData[0].fColor; | 78 fBatch.fColor = fGeoData[0].fColor; |
| 271 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); | 79 fBatch.fUsesLocalCoords = overrides.readsLocalCoords(); |
| 272 fBatch.fCoverageIgnored = !overrides.readsCoverage(); | 80 fBatch.fCoverageIgnored = !overrides.readsCoverage(); |
| 273 } | 81 } |
| 274 | 82 |
| 275 enum RegenMask { | |
| 276 kNoRegen = 0x0, | |
| 277 kRegenPos = 0x1, | |
| 278 kRegenCol = 0x2, | |
| 279 kRegenTex = 0x4, | |
| 280 kRegenGlyph = 0x8 | kRegenTex, // we have to regenerate the texture coords w
hen we regen glyphs | |
| 281 | |
| 282 // combinations | |
| 283 kRegenPosCol = kRegenPos | kRegenCol, | |
| 284 kRegenPosTex = kRegenPos | kRegenTex, | |
| 285 kRegenPosTexGlyph = kRegenPos | kRegenGlyph, | |
| 286 kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex, | |
| 287 kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph, | |
| 288 kRegenColTex = kRegenCol | kRegenTex, | |
| 289 kRegenColTexGlyph = kRegenCol | kRegenGlyph, | |
| 290 }; | |
| 291 | |
| 292 #define REGEN_ARGS target, &flushInfo, blob, &run, &info, &cache, &typeface, &sc
aler, &desc, gp, \ | |
| 293 glyphCount, vertexStride, args.fColor, args.fTransX, args.fTr
ansY | |
| 294 | |
| 295 void GrAtlasTextBatch::onPrepareDraws(Target* target) const { | 83 void GrAtlasTextBatch::onPrepareDraws(Target* target) const { |
| 296 // if we have RGB, then we won't have any SkShaders so no need to use a loca
lmatrix. | 84 // if we have RGB, then we won't have any SkShaders so no need to use a loca
lmatrix. |
| 297 // TODO actually only invert if we don't have RGBA | 85 // TODO actually only invert if we don't have RGBA |
| 298 SkMatrix localMatrix; | 86 SkMatrix localMatrix; |
| 299 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) { | 87 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) { |
| 300 SkDebugf("Cannot invert viewmatrix\n"); | 88 SkDebugf("Cannot invert viewmatrix\n"); |
| 301 return; | 89 return; |
| 302 } | 90 } |
| 303 | 91 |
| 304 GrTexture* texture = fFontCache->getTexture(this->maskFormat()); | 92 GrTexture* texture = fFontCache->getTexture(this->maskFormat()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 | 134 |
| 347 unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices); | 135 unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices); |
| 348 | 136 |
| 349 // We cache some values to avoid going to the glyphcache for the same fontSc
aler twice | 137 // We cache some values to avoid going to the glyphcache for the same fontSc
aler twice |
| 350 // in a row | 138 // in a row |
| 351 const SkDescriptor* desc = nullptr; | 139 const SkDescriptor* desc = nullptr; |
| 352 SkGlyphCache* cache = nullptr; | 140 SkGlyphCache* cache = nullptr; |
| 353 GrFontScaler* scaler = nullptr; | 141 GrFontScaler* scaler = nullptr; |
| 354 SkTypeface* typeface = nullptr; | 142 SkTypeface* typeface = nullptr; |
| 355 | 143 |
| 144 GrBlobRegenHelper helper(this, target, &flushInfo, gp); |
| 145 |
| 356 for (int i = 0; i < fGeoCount; i++) { | 146 for (int i = 0; i < fGeoCount; i++) { |
| 357 const Geometry& args = fGeoData[i]; | 147 const Geometry& args = fGeoData[i]; |
| 358 Blob* blob = args.fBlob; | 148 Blob* blob = args.fBlob; |
| 359 Run& run = blob->fRuns[args.fRun]; | 149 size_t byteCount; |
| 360 TextInfo& info = run.fSubRunInfo[args.fSubRun]; | 150 void* blobVertices; |
| 361 | 151 int glyphCount; |
| 362 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat); | 152 blob->regenInBatch(target, fFontCache, &helper, args.fRun, args.fSubRun,
&cache, |
| 363 | 153 &typeface, &scaler, &desc, vertexStride, args.fColor,
args.fTransX, |
| 364 // Because the GrBatchFontCache may evict the strike a blob depends on u
sing for | 154 args.fTransY, &blobVertices, &byteCount, &glyphCount)
; |
| 365 // generating its texture coords, we have to track whether or not the st
rike has | |
| 366 // been abandoned. If it hasn't been abandoned, then we can use the GrG
lyph*s as is | |
| 367 // otherwise we have to get the new strike, and use that to get the corr
ect glyphs. | |
| 368 // Because we do not have the packed ids, and thus can't look up our gly
phs in the | |
| 369 // new strike, we instead keep our ref to the old strike and use the pac
ked ids from | |
| 370 // it. These ids will still be valid as long as we hold the ref. When
we are done | |
| 371 // updating our cache of the GrGlyph*s, we drop our ref on the old strik
e | |
| 372 bool regenerateGlyphs = info.strike()->isAbandoned(); | |
| 373 bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen
|| | |
| 374 regenerateGlyphs; | |
| 375 bool regenerateColors = kARGB_GrMaskFormat != maskFormat && | |
| 376 info.color() != args.fColor; | |
| 377 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f; | |
| 378 int glyphCount = info.glyphCount(); | |
| 379 | |
| 380 uint32_t regenMaskBits = kNoRegen; | |
| 381 regenMaskBits |= regeneratePositions ? kRegenPos : 0; | |
| 382 regenMaskBits |= regenerateColors ? kRegenCol : 0; | |
| 383 regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0; | |
| 384 regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0; | |
| 385 RegenMask regenMask = (RegenMask)regenMaskBits; | |
| 386 | |
| 387 switch (regenMask) { | |
| 388 case kRegenPos: this->regenBlob<true, false, false, false>(REGEN_ARG
S); break; | |
| 389 case kRegenCol: this->regenBlob<false, true, false, false>(REGEN_ARG
S); break; | |
| 390 case kRegenTex: this->regenBlob<false, false, true, false>(REGEN_ARG
S); break; | |
| 391 case kRegenGlyph: this->regenBlob<false, false, true, true>(REGEN_AR
GS); break; | |
| 392 | |
| 393 // combinations | |
| 394 case kRegenPosCol: this->regenBlob<true, true, false, false>(REGEN_A
RGS); break; | |
| 395 case kRegenPosTex: this->regenBlob<true, false, true, false>(REGEN_A
RGS); break; | |
| 396 case kRegenPosTexGlyph: this->regenBlob<true, false, true, true>(REG
EN_ARGS); break; | |
| 397 case kRegenPosColTex: this->regenBlob<true, true, true, false>(REGEN
_ARGS); break; | |
| 398 case kRegenPosColTexGlyph: this->regenBlob<true, true, true, true>(R
EGEN_ARGS); break; | |
| 399 case kRegenColTex: this->regenBlob<false, true, true, false>(REGEN_A
RGS); break; | |
| 400 case kRegenColTexGlyph: this->regenBlob<false, true, true, true>(REG
EN_ARGS); break; | |
| 401 case kNoRegen: | |
| 402 flushInfo.fGlyphsToFlush += glyphCount; | |
| 403 | |
| 404 // set use tokens for all of the glyphs in our subrun. This is
only valid if we | |
| 405 // have a valid atlas generation | |
| 406 fFontCache->setUseTokenBulk(*info.bulkUseToken(), target->curren
tToken(), | |
| 407 maskFormat); | |
| 408 break; | |
| 409 } | |
| 410 | 155 |
| 411 // now copy all vertices | 156 // now copy all vertices |
| 412 size_t byteCount = info.byteCount(); | 157 memcpy(currVertex, blobVertices, byteCount); |
| 413 memcpy(currVertex, blob->fVertices + info.vertexStartIndex(), byteCount)
; | |
| 414 | 158 |
| 415 #ifdef SK_DEBUG | 159 #ifdef SK_DEBUG |
| 416 // bounds sanity check | 160 // bounds sanity check |
| 417 SkRect rect; | 161 SkRect rect; |
| 418 rect.setLargestInverted(); | 162 rect.setLargestInverted(); |
| 419 SkPoint* vertex = (SkPoint*) ((char*)blob->fVertices + info.vertexStartI
ndex()); | 163 SkPoint* vertex = (SkPoint*) ((char*)blobVertices); |
| 420 rect.growToInclude(vertex, vertexStride, kVerticesPerGlyph * info.glyphC
ount()); | 164 rect.growToInclude(vertex, vertexStride, kVerticesPerGlyph * glyphCount)
; |
| 421 | 165 |
| 422 if (this->usesDistanceFields()) { | 166 if (this->usesDistanceFields()) { |
| 423 fBatch.fViewMatrix.mapRect(&rect); | 167 fBatch.fViewMatrix.mapRect(&rect); |
| 424 } | 168 } |
| 425 SkASSERT(fBounds.contains(rect)); | 169 SkASSERT(fBounds.contains(rect)); |
| 426 #endif | 170 #endif |
| 427 | 171 |
| 428 currVertex += byteCount; | 172 currVertex += byteCount; |
| 429 } | 173 } |
| 430 | 174 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 return GrDistanceFieldA8TextGeoProc::Create(color, | 303 return GrDistanceFieldA8TextGeoProc::Create(color, |
| 560 viewMatrix, | 304 viewMatrix, |
| 561 texture, | 305 texture, |
| 562 params, | 306 params, |
| 563 flags, | 307 flags, |
| 564 this->usesLocalCoords()); | 308 this->usesLocalCoords()); |
| 565 #endif | 309 #endif |
| 566 } | 310 } |
| 567 | 311 |
| 568 } | 312 } |
| 313 |
| 314 void GrBlobRegenHelper::flush() { |
| 315 fBatch->flush(fTarget, fFlushInfo); |
| 316 fTarget->initDraw(fGP, fBatch->pipeline()); |
| 317 } |
| OLD | NEW |