Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2016 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 "SkArenaAlloc.h"
      9 #include "SkOverdrawColorFilter.h"
     10 #include "SkPM4f.h"
     11 #include "SkRasterPipeline.h"
     12 #include "SkReadBuffer.h"
     13 #include "../jumper/SkJumper.h"
     14 
     15 void SkOverdrawColorFilter::onAppendStages(SkRasterPipeline* p,
     16                                            SkColorSpace* dstCS,
     17                                            SkArenaAlloc* alloc,
     18                                            bool shader_is_opaque) const {
     19     struct Ctx : public SkJumper_CallbackCtx {
     20         const SkPMColor* colors;
     21     };
     22     // TODO: do we care about transforming to dstCS?
     23     auto ctx = alloc->make<Ctx>();
     24     ctx->colors = fColors;
     25     ctx->fn = [](SkJumper_CallbackCtx* arg, int active_pixels) {
     26         auto ctx = (Ctx*)arg;
     27         auto pixels = (SkPM4f*)ctx->rgba;
     28         for (int i = 0; i < active_pixels; i++) {
     29             uint8_t alpha = (int)(pixels[i].a() * 255);
     30             if (alpha >= kNumColors) {
     31                 alpha = kNumColors - 1;
     32             }
     33             pixels[i] = SkPM4f::FromPMColor(ctx->colors[alpha]);
     34         }
     35     };
     36     p->append(SkRasterPipeline::callback, ctx);
     37 }
     38 
     39 void SkOverdrawColorFilter::toString(SkString* str) const {
     40     str->append("SkOverdrawColorFilter (");
     41     for (int i = 0; i < kNumColors; i++) {
     42         str->appendf("%d: %x\n", i, fColors[i]);
     43     }
     44     str->append(")");
     45 }
     46 
     47 void SkOverdrawColorFilter::flatten(SkWriteBuffer& buffer) const {
     48     buffer.writeByteArray(fColors, kNumColors * sizeof(SkPMColor));
     49 }
     50 
     51 sk_sp<SkFlattenable> SkOverdrawColorFilter::CreateProc(SkReadBuffer& buffer) {
     52     SkPMColor colors[kNumColors];
     53     size_t size = buffer.getArrayCount();
     54     if (!buffer.validate(size == sizeof(colors))) {
     55         return nullptr;
     56     }
     57     if (!buffer.readByteArray(colors, sizeof(colors))) {
     58         return nullptr;
     59     }
     60 
     61     return SkOverdrawColorFilter::Make(colors);
     62 }
     63 
     64 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkOverdrawColorFilter)
     65     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkOverdrawColorFilter)
     66 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
     67 
     68 #if SK_SUPPORT_GPU
     69 
     70 #include "GrFragmentProcessor.h"
     71 #include "glsl/GrGLSLFragmentProcessor.h"
     72 #include "glsl/GrGLSLFragmentShaderBuilder.h"
     73 
     74 class OverdrawFragmentProcessor : public GrFragmentProcessor {
     75 public:
     76     static sk_sp<GrFragmentProcessor> Make(const SkPMColor* colors);
     77 
     78     const char* name() const override { return "Overdraw"; }
     79 private:
     80     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
     81     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
     82     bool onIsEqual(const GrFragmentProcessor&) const override;
     83 
     84     OverdrawFragmentProcessor(const GrColor4f* colors);
     85 
     86     GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
     87 
     88     typedef GrFragmentProcessor INHERITED;
     89 };
     90 
     91 class GLOverdrawFragmentProcessor : public GrGLSLFragmentProcessor {
     92 public:
     93     GLOverdrawFragmentProcessor(const GrColor4f* colors);
     94 
     95     void emitCode(EmitArgs&) override;
     96 
     97 protected:
     98     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override {}
     99 
    100 private:
    101     GrColor4f fColors[SkOverdrawColorFilter::kNumColors];
    102 
    103     typedef GrGLSLFragmentProcessor INHERITED;
    104 };
    105 
    106 sk_sp<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(GrContext*,
    107                                                                       SkColorSpace*) const {
    108     return OverdrawFragmentProcessor::Make(fColors);
    109 }
    110 
    111 sk_sp<GrFragmentProcessor> OverdrawFragmentProcessor::Make(const SkPMColor* colors) {
    112     GrColor4f grColors[SkOverdrawColorFilter::kNumColors];
    113     for (int i = 0; i < SkOverdrawColorFilter::kNumColors; i++) {
    114         grColors[i] = GrColor4f::FromGrColor(GrColorPackRGBA(SkGetPackedR32(colors[i]),
    115                                                              SkGetPackedG32(colors[i]),
    116                                                              SkGetPackedB32(colors[i]),
    117                                                              SkGetPackedA32(colors[i])));
    118     }
    119 
    120     return sk_sp<OverdrawFragmentProcessor>(new OverdrawFragmentProcessor(grColors));
    121 }
    122 
    123 // This could implement the constant input -> constant output optimization, but we don't really
    124 // care given how this is used.
    125 OverdrawFragmentProcessor::OverdrawFragmentProcessor(const GrColor4f* colors)
    126         : INHERITED(kNone_OptimizationFlags) {
    127     this->initClassID<OverdrawFragmentProcessor>();
    128     memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
    129 }
    130 
    131 GrGLSLFragmentProcessor* OverdrawFragmentProcessor::onCreateGLSLInstance() const {
    132     return new GLOverdrawFragmentProcessor(fColors);
    133 }
    134 
    135 bool OverdrawFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
    136     const OverdrawFragmentProcessor& that = other.cast<OverdrawFragmentProcessor>();
    137     return 0 == memcmp(fColors, that.fColors,
    138                        sizeof(GrColor4f) * SkOverdrawColorFilter::kNumColors);
    139 }
    140 
    141 GLOverdrawFragmentProcessor::GLOverdrawFragmentProcessor(const GrColor4f* colors) {
    142     memcpy(fColors, colors, SkOverdrawColorFilter::kNumColors * sizeof(GrColor4f));
    143 }
    144 
    145 void GLOverdrawFragmentProcessor::emitCode(EmitArgs& args) {
    146     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
    147     if (nullptr == args.fInputColor) {
    148         fragBuilder->codeAppendf("%s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    149                                                                     fColors[5].fRGBA[0],
    150                                                                     fColors[5].fRGBA[1],
    151                                                                     fColors[5].fRGBA[2],
    152                                                                     fColors[5].fRGBA[3]);
    153     } else {
    154         fragBuilder->codeAppendf("float alpha = 255.0 * %s.a;", args.fInputColor);
    155         fragBuilder->codeAppendf("if (alpha < 0.5) {");
    156         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    157                                                                         fColors[0].fRGBA[0],
    158                                                                         fColors[0].fRGBA[1],
    159                                                                         fColors[0].fRGBA[2],
    160                                                                         fColors[0].fRGBA[3]);
    161         fragBuilder->codeAppendf("} else if (alpha < 1.5) {");
    162         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    163                                                                         fColors[1].fRGBA[0],
    164                                                                         fColors[1].fRGBA[1],
    165                                                                         fColors[1].fRGBA[2],
    166                                                                         fColors[1].fRGBA[3]);
    167         fragBuilder->codeAppendf("} else if (alpha < 2.5) {");
    168         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    169                                                                         fColors[2].fRGBA[0],
    170                                                                         fColors[2].fRGBA[1],
    171                                                                         fColors[2].fRGBA[2],
    172                                                                         fColors[2].fRGBA[3]);
    173         fragBuilder->codeAppendf("} else if (alpha < 3.5) {");
    174         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    175                                                                         fColors[3].fRGBA[0],
    176                                                                         fColors[3].fRGBA[1],
    177                                                                         fColors[3].fRGBA[2],
    178                                                                         fColors[3].fRGBA[3]);
    179         fragBuilder->codeAppendf("} else if (alpha < 4.5) {");
    180         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    181                                                                         fColors[4].fRGBA[0],
    182                                                                         fColors[4].fRGBA[1],
    183                                                                         fColors[4].fRGBA[2],
    184                                                                         fColors[4].fRGBA[3]);
    185         fragBuilder->codeAppendf("} else {");
    186         fragBuilder->codeAppendf("    %s.rgba = vec4(%f, %f, %f, %f);", args.fOutputColor,
    187                                                                         fColors[5].fRGBA[0],
    188                                                                         fColors[5].fRGBA[1],
    189                                                                         fColors[5].fRGBA[2],
    190                                                                         fColors[5].fRGBA[3]);
    191         fragBuilder->codeAppendf("}");
    192     }
    193 }
    194 
    195 #endif
    196