1 2 /* 3 * Copyright 2015 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 // This test only works with the GPU backend. 10 11 #include "gm.h" 12 13 #if SK_SUPPORT_GPU 14 15 #include "GrContext.h" 16 #include "GrDrawContext.h" 17 #include "GrPipelineBuilder.h" 18 #include "SkGrPriv.h" 19 #include "SkGradientShader.h" 20 #include "batches/GrDrawBatch.h" 21 #include "batches/GrRectBatchFactory.h" 22 #include "effects/GrConstColorProcessor.h" 23 24 namespace skiagm { 25 /** 26 * This GM directly exercises GrConstColorProcessor. 27 */ 28 class ConstColorProcessor : public GM { 29 public: ConstColorProcessor()30 ConstColorProcessor() { 31 this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD)); 32 } 33 34 protected: onShortName()35 SkString onShortName() override { 36 return SkString("const_color_processor"); 37 } 38 onISize()39 SkISize onISize() override { 40 return SkISize::Make(kWidth, kHeight); 41 } 42 onOnceBeforeDraw()43 void onOnceBeforeDraw() override { 44 SkColor colors[] = { 0xFFFF0000, 0x2000FF00, 0xFF0000FF}; 45 SkPoint pts[] = { SkPoint::Make(0, 0), SkPoint::Make(kRectSize, kRectSize) }; 46 fShader.reset(SkGradientShader::CreateLinear(pts, colors, nullptr, SK_ARRAY_COUNT(colors), 47 SkShader::kClamp_TileMode)); 48 } 49 onDraw(SkCanvas * canvas)50 void onDraw(SkCanvas* canvas) override { 51 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 52 if (nullptr == rt) { 53 return; 54 } 55 GrContext* context = rt->getContext(); 56 if (nullptr == context) { 57 skiagm::GM::DrawGpuOnlyMessage(canvas); 58 return; 59 } 60 61 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(rt)); 62 if (!drawContext) { 63 return; 64 } 65 66 static const GrColor kColors[] = { 67 0xFFFFFFFF, 68 0xFFFF00FF, 69 0x80000000, 70 0x00000000, 71 }; 72 73 static const SkColor kPaintColors[] = { 74 0xFFFFFFFF, 75 0xFFFF0000, 76 0x80FF0000, 77 0x00000000, 78 }; 79 80 static const char* kModeStrs[] { 81 "kIgnore", 82 "kModulateRGBA", 83 "kModulateA", 84 }; 85 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kModeStrs) == GrConstColorProcessor::kInputModeCnt); 86 87 SkScalar y = kPad; 88 SkScalar x = kPad; 89 SkScalar maxW = 0; 90 for (size_t paintType = 0; paintType < SK_ARRAY_COUNT(kPaintColors) + 1; ++paintType) { 91 for (size_t procColor = 0; procColor < SK_ARRAY_COUNT(kColors); ++procColor) { 92 for (int m = 0; m < GrConstColorProcessor::kInputModeCnt; ++m) { 93 // translate by x,y for the canvas draws and the test target draws. 94 canvas->save(); 95 canvas->translate(x, y); 96 const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y); 97 98 // rect to draw 99 SkRect renderRect = SkRect::MakeXYWH(0, 0, kRectSize, kRectSize); 100 101 GrPaint grPaint; 102 SkPaint skPaint; 103 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 104 skPaint.setShader(fShader); 105 } else { 106 skPaint.setColor(kPaintColors[paintType]); 107 } 108 SkAssertResult(SkPaintToGrPaint(context, skPaint, viewMatrix, &grPaint)); 109 110 GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; 111 GrColor color = kColors[procColor]; 112 SkAutoTUnref<GrFragmentProcessor> fp(GrConstColorProcessor::Create(color, mode)); 113 114 GrClip clip; 115 GrPipelineBuilder pipelineBuilder(grPaint, rt, clip); 116 pipelineBuilder.addColorFragmentProcessor(fp); 117 118 SkAutoTUnref<GrDrawBatch> batch( 119 GrRectBatchFactory::CreateNonAAFill(grPaint.getColor(), viewMatrix, 120 renderRect, nullptr, nullptr)); 121 drawContext->internal_drawBatch(pipelineBuilder, batch); 122 123 // Draw labels for the input to the processor and the processor to the right of 124 // the test rect. The input label appears above the processor label. 125 SkPaint labelPaint; 126 sk_tool_utils::set_portable_typeface(&labelPaint); 127 labelPaint.setAntiAlias(true); 128 labelPaint.setTextSize(10.f); 129 SkString inputLabel; 130 inputLabel.set("Input: "); 131 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 132 inputLabel.append("gradient"); 133 } else { 134 inputLabel.appendf("0x%08x", kPaintColors[paintType]); 135 } 136 SkString procLabel; 137 procLabel.printf("Proc: [0x%08x, %s]", kColors[procColor], kModeStrs[m]); 138 139 SkRect inputLabelBounds; 140 // get the bounds of the text in order to position it 141 labelPaint.measureText(inputLabel.c_str(), inputLabel.size(), 142 &inputLabelBounds); 143 canvas->drawText(inputLabel.c_str(), inputLabel.size(), 144 renderRect.fRight + kPad, 145 -inputLabelBounds.fTop, labelPaint); 146 // update the bounds to reflect the offset we used to draw it. 147 inputLabelBounds.offset(renderRect.fRight + kPad, -inputLabelBounds.fTop); 148 149 SkRect procLabelBounds; 150 labelPaint.measureText(procLabel.c_str(), procLabel.size(), 151 &procLabelBounds); 152 canvas->drawText(procLabel.c_str(), procLabel.size(), 153 renderRect.fRight + kPad, 154 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop, 155 labelPaint); 156 procLabelBounds.offset(renderRect.fRight + kPad, 157 inputLabelBounds.fBottom + 2.f - procLabelBounds.fTop); 158 159 labelPaint.setStrokeWidth(0); 160 labelPaint.setStyle(SkPaint::kStroke_Style); 161 canvas->drawRect(renderRect, labelPaint); 162 163 canvas->restore(); 164 165 // update x and y for the next test case. 166 SkScalar height = renderRect.height(); 167 SkScalar width = SkTMax(inputLabelBounds.fRight, procLabelBounds.fRight); 168 maxW = SkTMax(maxW, width); 169 y += height + kPad; 170 if (y + height > kHeight) { 171 y = kPad; 172 x += maxW + kPad; 173 maxW = 0; 174 } 175 } 176 } 177 } 178 } 179 180 private: 181 // Use this as a way of generating and input FP 182 SkAutoTUnref<SkShader> fShader; 183 184 static const SkScalar kPad; 185 static const SkScalar kRectSize; 186 static const int kWidth = 820; 187 static const int kHeight = 500; 188 189 typedef GM INHERITED; 190 }; 191 192 const SkScalar ConstColorProcessor::kPad = 10.f; 193 const SkScalar ConstColorProcessor::kRectSize = 20.f; 194 195 DEF_GM(return new ConstColorProcessor;) 196 } 197 198 #endif 199