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 // This test only works with the GPU backend. 9 10 #include "gm.h" 11 #include "sk_tool_utils.h" 12 13 #include "GrContext.h" 14 #include "GrRenderTargetContextPriv.h" 15 #include "SkGr.h" 16 #include "SkGradientShader.h" 17 #include "effects/GrConstColorProcessor.h" 18 #include "ops/GrDrawOp.h" 19 #include "ops/GrFillRectOp.h" 20 21 namespace skiagm { 22 /** 23 * This GM directly exercises GrConstColorProcessor. 24 */ 25 class ConstColorProcessor : public GpuGM { 26 public: ConstColorProcessor()27 ConstColorProcessor() { 28 this->setBGColor(0xFFDDDDDD); 29 } 30 31 protected: onShortName()32 SkString onShortName() override { 33 return SkString("const_color_processor"); 34 } 35 onISize()36 SkISize onISize() override { 37 return SkISize::Make(kWidth, kHeight); 38 } 39 onOnceBeforeDraw()40 void onOnceBeforeDraw() override { 41 SkColor colors[] = { 0xFFFF0000, 0x2000FF00, 0xFF0000FF}; 42 SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(kRectSize, kRectSize) }; 43 fShader = SkGradientShader::MakeLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), 44 SkShader::kClamp_TileMode); 45 } 46 onDraw(GrContext * context,GrRenderTargetContext * renderTargetContext,SkCanvas * canvas)47 void onDraw(GrContext* context, GrRenderTargetContext* renderTargetContext, 48 SkCanvas* canvas) override { 49 constexpr GrColor kColors[] = { 50 0xFFFFFFFF, 51 0xFFFF00FF, 52 0x80000000, 53 0x00000000, 54 }; 55 56 constexpr SkColor kPaintColors[] = { 57 0xFFFFFFFF, 58 0xFFFF0000, 59 0x80FF0000, 60 0x00000000, 61 }; 62 63 const char* kModeStrs[] { 64 "kIgnore", 65 "kModulateRGBA", 66 "kModulateA", 67 }; 68 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kModeStrs) == GrConstColorProcessor::kInputModeCnt); 69 70 SkScalar y = kPad; 71 SkScalar x = kPad; 72 SkScalar maxW = 0; 73 for (size_t paintType = 0; paintType < SK_ARRAY_COUNT(kPaintColors) + 1; ++paintType) { 74 for (size_t procColor = 0; procColor < SK_ARRAY_COUNT(kColors); ++procColor) { 75 for (int m = 0; m < GrConstColorProcessor::kInputModeCnt; ++m) { 76 // translate by x,y for the canvas draws and the test target draws. 77 canvas->save(); 78 canvas->translate(x, y); 79 const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y); 80 81 // rect to draw 82 SkRect renderRect = SkRect::MakeXYWH(0, 0, kRectSize, kRectSize); 83 84 GrPaint grPaint; 85 SkPaint skPaint; 86 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 87 skPaint.setShader(fShader); 88 } else { 89 skPaint.setColor(kPaintColors[paintType]); 90 } 91 SkAssertResult(SkPaintToGrPaint(context, renderTargetContext->colorSpaceInfo(), 92 skPaint, viewMatrix, &grPaint)); 93 94 GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; 95 SkPMColor4f color = SkPMColor4f::FromBytes_RGBA(kColors[procColor]); 96 auto fp = GrConstColorProcessor::Make(color, mode); 97 98 grPaint.addColorFragmentProcessor(std::move(fp)); 99 renderTargetContext->priv().testingOnly_addDrawOp( 100 GrFillRectOp::Make(context, std::move(grPaint), GrAAType::kNone, 101 viewMatrix, renderRect)); 102 103 // Draw labels for the input to the processor and the processor to the right of 104 // the test rect. The input label appears above the processor label. 105 SkFont labelFont; 106 labelFont.setTypeface(sk_tool_utils::create_portable_typeface()); 107 labelFont.setEdging(SkFont::Edging::kAntiAlias); 108 labelFont.setSize(10.f); 109 SkPaint labelPaint; 110 labelPaint.setAntiAlias(true); 111 SkString inputLabel; 112 inputLabel.set("Input: "); 113 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 114 inputLabel.append("gradient"); 115 } else { 116 inputLabel.appendf("0x%08x", kPaintColors[paintType]); 117 } 118 SkString procLabel; 119 procLabel.printf("Proc: [0x%08x, %s]", kColors[procColor], kModeStrs[m]); 120 121 SkRect inputLabelBounds; 122 // get the bounds of the text in order to position it 123 labelFont.measureText(inputLabel.c_str(), inputLabel.size(), 124 kUTF8_SkTextEncoding, &inputLabelBounds); 125 canvas->drawString(inputLabel, renderRect.fRight + kPad, -inputLabelBounds.fTop, 126 labelFont, labelPaint); 127 // update the bounds to reflect the offset we used to draw it. 128 inputLabelBounds.offset(renderRect.fRight + kPad, -inputLabelBounds.fTop); 129 130 SkRect procLabelBounds; 131 labelFont.measureText(procLabel.c_str(), procLabel.size(), 132 kUTF8_SkTextEncoding, &procLabelBounds); 133 canvas->drawString(procLabel, renderRect.fRight + kPad, 134 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop, 135 labelFont, labelPaint); 136 procLabelBounds.offset(renderRect.fRight + kPad, 137 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop); 138 139 labelPaint.setStrokeWidth(0); 140 labelPaint.setStyle(SkPaint::kStroke_Style); 141 canvas->drawRect(renderRect, labelPaint); 142 143 canvas->restore(); 144 145 // update x and y for the next test case. 146 SkScalar height = renderRect.height(); 147 SkScalar width = SkTMax(inputLabelBounds.fRight, procLabelBounds.fRight); 148 maxW = SkTMax(maxW, width); 149 y += height + kPad; 150 if (y + height > kHeight) { 151 y = kPad; 152 x += maxW + kPad; 153 maxW = 0; 154 } 155 } 156 } 157 } 158 } 159 160 private: 161 // Use this as a way of generating and input FP 162 sk_sp<SkShader> fShader; 163 164 static constexpr SkScalar kPad = 10.f; 165 static constexpr SkScalar kRectSize = 20.f; 166 static constexpr int kWidth = 820; 167 static constexpr int kHeight = 500; 168 169 typedef GM INHERITED; 170 }; 171 172 DEF_GM(return new ConstColorProcessor;) 173 } 174