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 "GrTest.h" 17#include "effects/GrConstColorProcessor.h" 18#include "SkGr.h" 19#include "SkGradientShader.h" 20 21namespace skiagm { 22/** 23 * This GM directly exercises GrConstColorProcessor. 24 */ 25class ConstColorProcessor : public GM { 26public: 27 ConstColorProcessor() { 28 this->setBGColor(0xFFDDDDDD); 29 } 30 31protected: 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.reset(SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors), 44 SkShader::kClamp_TileMode)); 45 } 46 47 void onDraw(SkCanvas* canvas) override { 48 GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget(); 49 if (NULL == rt) { 50 return; 51 } 52 GrContext* context = rt->getContext(); 53 if (NULL == context) { 54 this->drawGpuOnlyMessage(canvas); 55 return; 56 } 57 58 static const GrColor kColors[] = { 59 0xFFFFFFFF, 60 0xFFFF00FF, 61 0x80000000, 62 0x00000000, 63 }; 64 65 static const SkColor kPaintColors[] = { 66 0xFFFFFFFF, 67 0xFFFF0000, 68 0x80FF0000, 69 0x00000000, 70 }; 71 72 static const char* kModeStrs[] { 73 "kIgnore", 74 "kModulateRGBA", 75 "kModulateA", 76 }; 77 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kModeStrs) == GrConstColorProcessor::kInputModeCnt); 78 79 SkScalar y = kPad; 80 SkScalar x = kPad; 81 SkScalar maxW = 0; 82 for (size_t paintType = 0; paintType < SK_ARRAY_COUNT(kPaintColors) + 1; ++paintType) { 83 for (size_t procColor = 0; procColor < SK_ARRAY_COUNT(kColors); ++procColor) { 84 for (int m = 0; m < GrConstColorProcessor::kInputModeCnt; ++m) { 85 // translate by x,y for the canvas draws and the test target draws. 86 canvas->save(); 87 canvas->translate(x, y); 88 const SkMatrix viewMatrix = SkMatrix::MakeTrans(x, y); 89 90 // rect to draw 91 SkRect renderRect = SkRect::MakeXYWH(0, 0, kRectSize, kRectSize); 92 93 GrTestTarget tt; 94 context->getTestTarget(&tt); 95 if (NULL == tt.target()) { 96 SkDEBUGFAIL("Couldn't get Gr test target."); 97 return; 98 } 99 100 GrPaint grPaint; 101 SkPaint skPaint; 102 if (paintType >= SK_ARRAY_COUNT(kPaintColors)) { 103 skPaint.setShader(fShader); 104 } else { 105 skPaint.setColor(kPaintColors[paintType]); 106 } 107 SkAssertResult(SkPaint2GrPaint(context, rt, skPaint, viewMatrix, false, 108 &grPaint)); 109 110 GrConstColorProcessor::InputMode mode = (GrConstColorProcessor::InputMode) m; 111 GrColor color = kColors[procColor]; 112 SkAutoTUnref<GrFragmentProcessor> fp(GrConstColorProcessor::Create(color, mode)); 113 114 GrPipelineBuilder pipelineBuilder; 115 GrClip clip; 116 pipelineBuilder.setFromPaint(grPaint, rt, clip); 117 pipelineBuilder.addColorProcessor(fp); 118 119 tt.target()->drawSimpleRect(&pipelineBuilder, 120 grPaint.getColor(), 121 viewMatrix, 122 renderRect); 123 124 // Draw labels for the input to the processor and the processor to the right of 125 // the test rect. The input label appears above the processor label. 126 SkPaint 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 180private: 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 192const SkScalar ConstColorProcessor::kPad = 10.f; 193const SkScalar ConstColorProcessor::kRectSize = 20.f; 194 195DEF_GM( return SkNEW(ConstColorProcessor); ) 196} 197 198#endif 199