Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2014 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 "GrGpu.h"
      9 #include "GrPathRendering.h"
     10 #include "SkDescriptor.h"
     11 #include "SkGlyph.h"
     12 #include "SkMatrix.h"
     13 #include "SkTypeface.h"
     14 #include "GrPathRange.h"
     15 
     16 const GrUserStencilSettings& GrPathRendering::GetStencilPassSettings(FillType fill) {
     17     switch (fill) {
     18         default:
     19             SkFAIL("Unexpected path fill.");
     20         case GrPathRendering::kWinding_FillType: {
     21             constexpr static GrUserStencilSettings kWindingStencilPass(
     22                 GrUserStencilSettings::StaticInit<
     23                     0xffff,
     24                     GrUserStencilTest::kAlwaysIfInClip,
     25                     0xffff,
     26                     GrUserStencilOp::kIncWrap,
     27                     GrUserStencilOp::kIncWrap,
     28                     0xffff>()
     29             );
     30             return kWindingStencilPass;
     31         }
     32         case GrPathRendering::kEvenOdd_FillType: {
     33             constexpr static GrUserStencilSettings kEvenOddStencilPass(
     34                 GrUserStencilSettings::StaticInit<
     35                     0xffff,
     36                     GrUserStencilTest::kAlwaysIfInClip,
     37                     0xffff,
     38                     GrUserStencilOp::kInvert,
     39                     GrUserStencilOp::kInvert,
     40                     0xffff>()
     41             );
     42             return kEvenOddStencilPass;
     43         }
     44     }
     45 }
     46 
     47 class GlyphGenerator : public GrPathRange::PathGenerator {
     48 public:
     49     GlyphGenerator(const SkTypeface& typeface, const SkScalerContextEffects& effects,
     50                    const SkDescriptor& desc)
     51         : fScalerContext(typeface.createScalerContext(effects, &desc))
     52 #ifdef SK_DEBUG
     53         , fDesc(desc.copy())
     54 #endif
     55     {}
     56 
     57     int getNumPaths() override {
     58         return fScalerContext->getGlyphCount();
     59     }
     60 
     61     void generatePath(int glyphID, SkPath* out) override {
     62         fScalerContext->getPath(glyphID, out);
     63     }
     64 #ifdef SK_DEBUG
     65     bool isEqualTo(const SkDescriptor& desc) const override { return *fDesc == desc; }
     66 #endif
     67 private:
     68     const std::unique_ptr<SkScalerContext> fScalerContext;
     69 #ifdef SK_DEBUG
     70     const std::unique_ptr<SkDescriptor> fDesc;
     71 #endif
     72 };
     73 
     74 sk_sp<GrPathRange> GrPathRendering::createGlyphs(const SkTypeface* typeface,
     75                                                  const SkScalerContextEffects& effects,
     76                                                  const SkDescriptor* desc,
     77                                                  const GrStyle& style) {
     78     if (nullptr == typeface) {
     79         typeface = SkTypeface::GetDefaultTypeface();
     80         SkASSERT(nullptr != typeface);
     81     }
     82 
     83     if (desc) {
     84         sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, effects, *desc));
     85         return this->createPathRange(generator.get(), style);
     86     }
     87 
     88     SkScalerContextRec rec;
     89     memset(&rec, 0, sizeof(rec));
     90     rec.fFontID = typeface->uniqueID();
     91     rec.fTextSize = SkPaint::kCanonicalTextSizeForPaths;
     92     rec.fPreScaleX = rec.fPost2x2[0][0] = rec.fPost2x2[1][1] = SK_Scalar1;
     93     // Don't bake stroke information into the glyphs, we'll let the GPU do the stroking.
     94 
     95     SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
     96     SkDescriptor*    genericDesc = ad.getDesc();
     97 
     98     genericDesc->init();
     99     genericDesc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    100     genericDesc->computeChecksum();
    101 
    102     // No effects, so we make a dummy struct
    103     SkScalerContextEffects noEffects;
    104 
    105     sk_sp<GlyphGenerator> generator(new GlyphGenerator(*typeface, noEffects, *genericDesc));
    106     return this->createPathRange(generator.get(), style);
    107 }
    108 
    109 void GrPathRendering::stencilPath(const StencilPathArgs& args, const GrPath* path) {
    110     fGpu->handleDirtyContext();
    111     this->onStencilPath(args, path);
    112 }
    113 
    114 void GrPathRendering::drawPath(const GrPipeline& pipeline,
    115                                const GrPrimitiveProcessor& primProc,
    116                                // Cover pass settings in pipeline.
    117                                const GrStencilSettings& stencilPassSettings,
    118                                const GrPath* path) {
    119     fGpu->handleDirtyContext();
    120     if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
    121         fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType);
    122     }
    123     this->onDrawPath(pipeline, primProc, stencilPassSettings, path);
    124 }
    125 
    126 void GrPathRendering::drawPaths(const GrPipeline& pipeline,
    127                                 const GrPrimitiveProcessor& primProc,
    128                                 // Cover pass settings in pipeline.
    129                                 const GrStencilSettings& stencilPassSettings,
    130                                 const GrPathRange* pathRange,
    131                                 const void* indices,
    132                                 PathIndexType indexType,
    133                                 const float transformValues[],
    134                                 PathTransformType transformType,
    135                                 int count) {
    136     fGpu->handleDirtyContext();
    137     if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*fGpu->caps())) {
    138         fGpu->xferBarrier(pipeline.getRenderTarget(), barrierType);
    139     }
    140 #ifdef SK_DEBUG
    141     pathRange->assertPathsLoaded(indices, indexType, count);
    142 #endif
    143     this->onDrawPaths(pipeline, primProc, stencilPassSettings, pathRange, indices, indexType,
    144                       transformValues, transformType, count);
    145 }
    146