LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu/ops - GrAtlasTextOp.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 135 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "GrAtlasTextOp.h"
       9             : 
      10             : #include "GrContext.h"
      11             : #include "GrOpFlushState.h"
      12             : #include "GrResourceProvider.h"
      13             : 
      14             : #include "SkGlyphCache.h"
      15             : #include "SkMathPriv.h"
      16             : 
      17             : #include "effects/GrBitmapTextGeoProc.h"
      18             : #include "effects/GrDistanceFieldGeoProc.h"
      19             : #include "text/GrAtlasGlyphCache.h"
      20             : 
      21             : ///////////////////////////////////////////////////////////////////////////////////////////////////
      22             : 
      23           0 : static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
      24           0 :     unsigned r = SkColorGetR(c);
      25           0 :     unsigned g = SkColorGetG(c);
      26           0 :     unsigned b = SkColorGetB(c);
      27           0 :     return GrColorPackRGBA(r, g, b, 0xff);
      28             : }
      29             : 
      30             : static const int kDistanceAdjustLumShift = 5;
      31             : 
      32           0 : SkString GrAtlasTextOp::dumpInfo() const {
      33           0 :     SkString str;
      34             : 
      35           0 :     for (int i = 0; i < fGeoCount; ++i) {
      36           0 :         str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n",
      37             :                     i,
      38           0 :                     fGeoData[i].fColor,
      39           0 :                     fGeoData[i].fX,
      40           0 :                     fGeoData[i].fY,
      41           0 :                     fGeoData[i].fBlob->runCount());
      42             :     }
      43             : 
      44           0 :     str.append(DumpPipelineInfo(*this->pipeline()));
      45           0 :     str.append(INHERITED::dumpInfo());
      46           0 :     return str;
      47             : }
      48             : 
      49           0 : void GrAtlasTextOp::getProcessorAnalysisInputs(GrProcessorAnalysisColor* color,
      50             :                                                GrProcessorAnalysisCoverage* coverage) const {
      51           0 :     if (kColorBitmapMask_MaskType == fMaskType) {
      52           0 :         color->setToUnknown();
      53             :     } else {
      54           0 :         color->setToConstant(fColor);
      55             :     }
      56           0 :     switch (fMaskType) {
      57             :         case kGrayscaleDistanceField_MaskType:
      58             :         case kGrayscaleCoverageMask_MaskType:
      59           0 :             *coverage = GrProcessorAnalysisCoverage::kSingleChannel;
      60           0 :             break;
      61             :         case kLCDCoverageMask_MaskType:
      62             :         case kLCDDistanceField_MaskType:
      63           0 :             *coverage = GrProcessorAnalysisCoverage::kLCD;
      64           0 :             break;
      65             :         case kColorBitmapMask_MaskType:
      66           0 :             *coverage = GrProcessorAnalysisCoverage::kNone;
      67           0 :             break;
      68             :     }
      69           0 : }
      70             : 
      71           0 : void GrAtlasTextOp::applyPipelineOptimizations(const PipelineOptimizations& optimizations) {
      72           0 :     optimizations.getOverrideColorIfSet(&fGeoData[0].fColor);
      73             : 
      74           0 :     fColor = fGeoData[0].fColor;
      75           0 :     fUsesLocalCoords = optimizations.readsLocalCoords();
      76           0 : }
      77             : 
      78           0 : void GrAtlasTextOp::onPrepareDraws(Target* target) const {
      79             :     // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
      80             :     // TODO actually only invert if we don't have RGBA
      81             :     SkMatrix localMatrix;
      82           0 :     if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
      83           0 :         SkDebugf("Cannot invert viewmatrix\n");
      84           0 :         return;
      85             :     }
      86             : 
      87           0 :     sk_sp<GrTextureProxy> proxy = fFontCache->getProxy(this->maskFormat());
      88           0 :     if (!proxy) {
      89           0 :         SkDebugf("Could not allocate backing texture for atlas\n");
      90           0 :         return;
      91             :     }
      92             : 
      93           0 :     GrMaskFormat maskFormat = this->maskFormat();
      94             : 
      95           0 :     FlushInfo flushInfo;
      96           0 :     if (this->usesDistanceFields()) {
      97             :         flushInfo.fGeometryProcessor =
      98           0 :                 this->setupDfProcessor(fFontCache->context()->resourceProvider(),
      99             :                                        this->viewMatrix(),
     100           0 :                                        fFilteredColor, this->color(), std::move(proxy));
     101             :     } else {
     102           0 :         GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kNone_FilterMode);
     103           0 :         flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
     104           0 :                 fFontCache->context()->resourceProvider(),
     105           0 :                 this->color(), std::move(proxy), params,
     106           0 :                 maskFormat, localMatrix, this->usesLocalCoords());
     107             :     }
     108             : 
     109           0 :     flushInfo.fGlyphsToFlush = 0;
     110           0 :     size_t vertexStride = flushInfo.fGeometryProcessor->getVertexStride();
     111           0 :     SkASSERT(vertexStride == GrAtlasTextBlob::GetVertexStride(maskFormat));
     112             : 
     113           0 :     int glyphCount = this->numGlyphs();
     114             :     const GrBuffer* vertexBuffer;
     115             : 
     116           0 :     void* vertices = target->makeVertexSpace(
     117           0 :             vertexStride, glyphCount * kVerticesPerGlyph, &vertexBuffer, &flushInfo.fVertexOffset);
     118           0 :     flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
     119           0 :     flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuffer());
     120           0 :     if (!vertices || !flushInfo.fVertexBuffer) {
     121           0 :         SkDebugf("Could not allocate vertices\n");
     122           0 :         return;
     123             :     }
     124             : 
     125           0 :     unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices);
     126             : 
     127           0 :     GrBlobRegenHelper helper(this, target, &flushInfo);
     128           0 :     SkAutoGlyphCache glyphCache;
     129           0 :     for (int i = 0; i < fGeoCount; i++) {
     130           0 :         const Geometry& args = fGeoData[i];
     131           0 :         Blob* blob = args.fBlob;
     132             :         size_t byteCount;
     133             :         void* blobVertices;
     134             :         int subRunGlyphCount;
     135           0 :         blob->regenInOp(target, fFontCache, &helper, args.fRun, args.fSubRun, &glyphCache,
     136           0 :                         vertexStride, args.fViewMatrix, args.fX, args.fY, args.fColor,
     137           0 :                         &blobVertices, &byteCount, &subRunGlyphCount);
     138             : 
     139             :         // now copy all vertices
     140           0 :         memcpy(currVertex, blobVertices, byteCount);
     141             : 
     142           0 :         currVertex += byteCount;
     143             :     }
     144             : 
     145           0 :     this->flush(target, &flushInfo);
     146             : }
     147             : 
     148           0 : void GrAtlasTextOp::flush(GrLegacyMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
     149           0 :     GrMesh mesh;
     150             :     int maxGlyphsPerDraw =
     151           0 :             static_cast<int>(flushInfo->fIndexBuffer->gpuMemorySize() / sizeof(uint16_t) / 6);
     152           0 :     mesh.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuffer.get(),
     153             :                        flushInfo->fIndexBuffer.get(), flushInfo->fVertexOffset, kVerticesPerGlyph,
     154           0 :                        kIndicesPerGlyph, flushInfo->fGlyphsToFlush, maxGlyphsPerDraw);
     155           0 :     target->draw(flushInfo->fGeometryProcessor.get(), this->pipeline(), mesh);
     156           0 :     flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlush;
     157           0 :     flushInfo->fGlyphsToFlush = 0;
     158           0 : }
     159             : 
     160           0 : bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
     161           0 :     GrAtlasTextOp* that = t->cast<GrAtlasTextOp>();
     162           0 :     if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
     163             :                                 that->bounds(), caps)) {
     164           0 :         return false;
     165             :     }
     166             : 
     167           0 :     if (fMaskType != that->fMaskType) {
     168           0 :         return false;
     169             :     }
     170             : 
     171           0 :     if (!this->usesDistanceFields()) {
     172           0 :         if (kColorBitmapMask_MaskType == fMaskType && this->color() != that->color()) {
     173           0 :             return false;
     174             :         }
     175           0 :         if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
     176           0 :             return false;
     177             :         }
     178             :     } else {
     179           0 :         if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
     180           0 :             return false;
     181             :         }
     182             : 
     183           0 :         if (fFilteredColor != that->fFilteredColor) {
     184           0 :             return false;
     185             :         }
     186             : 
     187           0 :         if (fUseBGR != that->fUseBGR) {
     188           0 :             return false;
     189             :         }
     190             :     }
     191             : 
     192           0 :     fNumGlyphs += that->numGlyphs();
     193             : 
     194             :     // Reallocate space for geo data if necessary and then import that's geo data.
     195           0 :     int newGeoCount = that->fGeoCount + fGeoCount;
     196             :     // We assume (and here enforce) that the allocation size is the smallest power of two that
     197             :     // is greater than or equal to the number of geometries (and at least
     198             :     // kMinGeometryAllocated).
     199           0 :     int newAllocSize = GrNextPow2(newGeoCount);
     200           0 :     int currAllocSize = SkTMax<int>(kMinGeometryAllocated, GrNextPow2(fGeoCount));
     201             : 
     202           0 :     if (newGeoCount > currAllocSize) {
     203           0 :         fGeoData.realloc(newAllocSize);
     204             :     }
     205             : 
     206             :     // We steal the ref on the blobs from the other AtlasTextOp and set its count to 0 so that
     207             :     // it doesn't try to unref them.
     208           0 :     memcpy(&fGeoData[fGeoCount], that->fGeoData.get(), that->fGeoCount * sizeof(Geometry));
     209             : #ifdef SK_DEBUG
     210           0 :     for (int i = 0; i < that->fGeoCount; ++i) {
     211           0 :         that->fGeoData.get()[i].fBlob = (Blob*)0x1;
     212             :     }
     213             : #endif
     214           0 :     that->fGeoCount = 0;
     215           0 :     fGeoCount = newGeoCount;
     216             : 
     217           0 :     this->joinBounds(*that);
     218           0 :     return true;
     219             : }
     220             : 
     221             : // TODO just use class params
     222             : // TODO trying to figure out why lcd is so whack
     223           0 : sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor(GrResourceProvider* resourceProvider,
     224             :                                                            const SkMatrix& viewMatrix,
     225             :                                                            SkColor filteredColor,
     226             :                                                            GrColor color,
     227             :                                                            sk_sp<GrTextureProxy> proxy) const {
     228           0 :     GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBilerp_FilterMode);
     229           0 :     bool isLCD = this->isLCD();
     230             :     // set up any flags
     231           0 :     uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
     232           0 :     flags |= viewMatrix.isScaleTranslate() ? kScaleOnly_DistanceFieldEffectFlag : 0;
     233           0 :     flags |= fUseGammaCorrectDistanceTable ? kGammaCorrect_DistanceFieldEffectFlag : 0;
     234             : 
     235             :     // see if we need to create a new effect
     236           0 :     if (isLCD) {
     237           0 :         flags |= kUseLCD_DistanceFieldEffectFlag;
     238           0 :         flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0;
     239             : 
     240           0 :         GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
     241             : 
     242             :         float redCorrection = fDistanceAdjustTable->getAdjustment(
     243           0 :                 GrColorUnpackR(colorNoPreMul) >> kDistanceAdjustLumShift,
     244           0 :                 fUseGammaCorrectDistanceTable);
     245             :         float greenCorrection = fDistanceAdjustTable->getAdjustment(
     246           0 :                 GrColorUnpackG(colorNoPreMul) >> kDistanceAdjustLumShift,
     247           0 :                 fUseGammaCorrectDistanceTable);
     248             :         float blueCorrection = fDistanceAdjustTable->getAdjustment(
     249           0 :                 GrColorUnpackB(colorNoPreMul) >> kDistanceAdjustLumShift,
     250           0 :                 fUseGammaCorrectDistanceTable);
     251             :         GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
     252             :                 GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(
     253           0 :                         redCorrection, greenCorrection, blueCorrection);
     254             : 
     255             :         return GrDistanceFieldLCDTextGeoProc::Make(resourceProvider,
     256           0 :                                                    color, viewMatrix, std::move(proxy),
     257             :                                                    params, widthAdjust, flags,
     258           0 :                                                    this->usesLocalCoords());
     259             :     } else {
     260             : #ifdef SK_GAMMA_APPLY_TO_A8
     261             :         U8CPU lum = SkColorSpaceLuminance::computeLuminance(SK_GAMMA_EXPONENT, filteredColor);
     262             :         float correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift,
     263             :                                                                fUseGammaCorrectDistanceTable);
     264             :         return GrDistanceFieldA8TextGeoProc::Make(resourceProvider, color,
     265             :                                                   viewMatrix, std::move(proxy),
     266             :                                                   params, correction, flags,
     267             :                                                   this->usesLocalCoords());
     268             : #else
     269             :         return GrDistanceFieldA8TextGeoProc::Make(resourceProvider, color,
     270           0 :                                                   viewMatrix, std::move(proxy),
     271           0 :                                                   params, flags, this->usesLocalCoords());
     272             : #endif
     273             :     }
     274             : }
     275             : 
     276           0 : void GrBlobRegenHelper::flush() { fOp->flush(fTarget, fFlushInfo); }

Generated by: LCOV version 1.13