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