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