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: ConstColorProcessor()29 ConstColorProcessor() { 30 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); 31 } 32 33 protected: onShortName()34 SkString onShortName() override { 35 return SkString("const_color_processor"); 36 } 37 onISize()38 SkISize onISize() override { 39 return SkISize::Make(kWidth, kHeight); 40 } 41 onOnceBeforeDraw()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 onDraw(SkCanvas * canvas)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, skPaint, 105 viewMatrix, &grPaint)); 106 107 GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; 108 GrColor4f color = GrColor4f::FromGrColor(kColors[procColor]); 109 sk_sp<GrFragmentProcessor> fp(GrConstColorProcessor::Make(color, mode)); 110 111 grPaint.addColorFragmentProcessor(std::move(fp)); 112 113 std::unique_ptr<GrMeshDrawOp> op(GrRectOpFactory::MakeNonAAFill( 114 grPaint.getColor(), viewMatrix, renderRect, nullptr, nullptr)); 115 renderTargetContext->priv().testingOnly_addMeshDrawOp( 116 std::move(grPaint), GrAAType::kNone, std::move(op)); 117 118 // Draw labels for the input to the processor and the processor to the right of 119 // the test rect. The input label appears above the processor label. 120 SkPaint labelPaint; 121 sk_tool_utils::set_portable_typeface(&labelPaint); 122 labelPaint.setAntiAlias(true); 123 labelPaint.setTextSize(10.f); 124 SkString inputLabel; 125 inputLabel.set("Input: "); 126 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 127 inputLabel.append("gradient"); 128 } else { 129 inputLabel.appendf("0x%08x", kPaintColors[paintType]); 130 } 131 SkString procLabel; 132 procLabel.printf("Proc: [0x%08x, %s]", kColors[procColor], kModeStrs[m]); 133 134 SkRect inputLabelBounds; 135 // get the bounds of the text in order to position it 136 labelPaint.measureText(inputLabel.c_str(), inputLabel.size(), 137 &inputLabelBounds); 138 canvas->drawText(inputLabel.c_str(), inputLabel.size(), 139 renderRect.fRight + kPad, 140 -inputLabelBounds.fTop, labelPaint); 141 // update the bounds to reflect the offset we used to draw it. 142 inputLabelBounds.offset(renderRect.fRight + kPad, -inputLabelBounds.fTop); 143 144 SkRect procLabelBounds; 145 labelPaint.measureText(procLabel.c_str(), procLabel.size(), 146 &procLabelBounds); 147 canvas->drawText(procLabel.c_str(), procLabel.size(), 148 renderRect.fRight + kPad, 149 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop, 150 labelPaint); 151 procLabelBounds.offset(renderRect.fRight + kPad, 152 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop); 153 154 labelPaint.setStrokeWidth(0); 155 labelPaint.setStyle(SkPaint::kStroke_Style); 156 canvas->drawRect(renderRect, labelPaint); 157 158 canvas->restore(); 159 160 // update x and y for the next test case. 161 SkScalar height = renderRect.height(); 162 SkScalar width = SkTMax(inputLabelBounds.fRight, procLabelBounds.fRight); 163 maxW = SkTMax(maxW, width); 164 y += height + kPad; 165 if (y + height > kHeight) { 166 y = kPad; 167 x += maxW + kPad; 168 maxW = 0; 169 } 170 } 171 } 172 } 173 } 174 175 private: 176 // Use this as a way of generating and input FP 177 sk_sp<SkShader> fShader; 178 179 static constexpr SkScalar kPad = 10.f; 180 static constexpr SkScalar kRectSize = 20.f; 181 static constexpr int kWidth = 820; 182 static constexpr int kHeight = 500; 183 184 typedef GM INHERITED; 185 }; 186 187 DEF_GM(return new ConstColorProcessor;) 188 } 189 190 #endif 191