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