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