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 "SkRasterPipeline.h"
11 #include "SkReadBuffer.h"
12
13 #if SK_SUPPORT_GPU
14 #include "effects/GrSkSLFP.h"
15
16 GR_FP_SRC_STRING SKSL_OVERDRAW_SRC = R"(
17 layout(ctype=SkPMColor) in uniform half4 color0;
18 layout(ctype=SkPMColor) in uniform half4 color1;
19 layout(ctype=SkPMColor) in uniform half4 color2;
20 layout(ctype=SkPMColor) in uniform half4 color3;
21 layout(ctype=SkPMColor) in uniform half4 color4;
22 layout(ctype=SkPMColor) in uniform half4 color5;
23
24 void main(int x, int y, inout half4 color) {
25 half alpha = 255.0 * color.a;
26 if (alpha < 0.5) {
27 color = color0;
28 } else if (alpha < 1.5) {
29 color = color1;
30 } else if (alpha < 2.5) {
31 color = color2;
32 } else if (alpha < 3.5) {
33 color = color3;
34 } else if (alpha < 4.5) {
35 color = color4;
36 } else {
37 color = color5;
38 }
39 }
40 )";
41 #endif
42
onAppendStages(SkRasterPipeline * p,SkColorSpace * dstCS,SkArenaAlloc * alloc,bool shader_is_opaque) const43 void SkOverdrawColorFilter::onAppendStages(SkRasterPipeline* p,
44 SkColorSpace* dstCS,
45 SkArenaAlloc* alloc,
46 bool shader_is_opaque) const {
47 struct Ctx : public SkRasterPipeline_CallbackCtx {
48 const SkPMColor* colors;
49 };
50 // TODO: do we care about transforming to dstCS?
51 auto ctx = alloc->make<Ctx>();
52 ctx->colors = fColors;
53 ctx->fn = [](SkRasterPipeline_CallbackCtx* arg, int active_pixels) {
54 auto ctx = (Ctx*)arg;
55 auto pixels = (SkPMColor4f*)ctx->rgba;
56 for (int i = 0; i < active_pixels; i++) {
57 uint8_t alpha = (int)(pixels[i].fA * 255);
58 if (alpha >= kNumColors) {
59 alpha = kNumColors - 1;
60 }
61 pixels[i] = SkPMColor4f::FromPMColor(ctx->colors[alpha]);
62 }
63 };
64 p->append(SkRasterPipeline::callback, ctx);
65 }
66
flatten(SkWriteBuffer & buffer) const67 void SkOverdrawColorFilter::flatten(SkWriteBuffer& buffer) const {
68 buffer.writeByteArray(fColors, kNumColors * sizeof(SkPMColor));
69 }
70
CreateProc(SkReadBuffer & buffer)71 sk_sp<SkFlattenable> SkOverdrawColorFilter::CreateProc(SkReadBuffer& buffer) {
72 SkPMColor colors[kNumColors];
73 size_t size = buffer.getArrayCount();
74 if (!buffer.validate(size == sizeof(colors))) {
75 return nullptr;
76 }
77 if (!buffer.readByteArray(colors, sizeof(colors))) {
78 return nullptr;
79 }
80
81 return SkOverdrawColorFilter::Make(colors);
82 }
83
RegisterFlattenables()84 void SkOverdrawColorFilter::RegisterFlattenables() {
85 SK_REGISTER_FLATTENABLE(SkOverdrawColorFilter);
86 }
87 #if SK_SUPPORT_GPU
88
asFragmentProcessor(GrContext * context,const GrColorSpaceInfo &) const89 std::unique_ptr<GrFragmentProcessor> SkOverdrawColorFilter::asFragmentProcessor(
90 GrContext* context, const GrColorSpaceInfo&) const {
91 static int overdrawIndex = GrSkSLFP::NewIndex();
92 return GrSkSLFP::Make(context, overdrawIndex, "Overdraw", SKSL_OVERDRAW_SRC, fColors,
93 sizeof(fColors));
94 }
95
96 #endif
97