blob: d730ed58a69258cdcfc0c724d10e765b5be64224 [file] [log] [blame]
Robert Phillipsa0971732017-10-31 12:26:35 -04001/*
2 * Copyright 2017 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#include "gm.h"
9#include "sk_tool_utils.h"
10
11#include "SkSurface.h"
12
13#if SK_SUPPORT_GPU
14
Robert Phillips1afd4cd2018-01-08 13:40:32 -050015#include "GrContextPriv.h"
Brian Salomon58389b92018-03-07 13:01:25 -050016#include "ProxyUtils.h"
Robert Phillipsa0971732017-10-31 12:26:35 -040017#include "SkImage_Gpu.h"
18
19static const int kNumMatrices = 6;
20static const int kImageSize = 128;
21static const int kLabelSize = 32;
22static const int kNumLabels = 4;
Robert Phillips206bda52017-11-01 09:26:06 -040023static const int kInset = 16;
Robert Phillipsa0971732017-10-31 12:26:35 -040024
25static const int kCellSize = kImageSize+2*kLabelSize;
26static const int kGMWidth = kNumMatrices*kCellSize;
Robert Phillips206bda52017-11-01 09:26:06 -040027static const int kGMHeight = 4*kCellSize;
Robert Phillipsa0971732017-10-31 12:26:35 -040028
29static const SkPoint kPoints[kNumLabels] = {
Robert Phillips206bda52017-11-01 09:26:06 -040030 { 0, kImageSize }, // LL
31 { kImageSize, kImageSize }, // LR
32 { 0, 0 }, // UL
33 { kImageSize, 0 }, // UR
Robert Phillipsa0971732017-10-31 12:26:35 -040034};
35
36static const SkMatrix kUVMatrices[kNumMatrices] = {
37 SkMatrix::MakeAll( 0, -1, 1,
38 -1, 0, 1,
39 0, 0, 1),
40 SkMatrix::MakeAll( 1, 0, 0,
41 0, -1, 1,
42 0, 0, 1),
43 // flip x
44 SkMatrix::MakeAll(-1, 0, 1,
45 0, 1, 0,
46 0, 0, 1),
47 SkMatrix::MakeAll( 0, 1, 0,
48 -1, 0, 1,
49 0, 0, 1),
50 // flip both x & y == rotate 180
51 SkMatrix::MakeAll(-1, 0, 1,
52 0, -1, 1,
53 0, 0, 1),
54 // identity
55 SkMatrix::MakeAll(1, 0, 0,
56 0, 1, 0,
57 0, 0, 1)
58};
59
Robert Phillips206bda52017-11-01 09:26:06 -040060
Robert Phillipsa0971732017-10-31 12:26:35 -040061// Create a fixed size text label like "LL" or "LR".
62static sk_sp<SkImage> make_text_image(GrContext* context, const char* text, SkColor color) {
63 SkPaint paint;
Robert Phillipsf0a30d72017-11-01 14:05:12 -040064 sk_tool_utils::set_portable_typeface(&paint);
Robert Phillipsa0971732017-10-31 12:26:35 -040065 paint.setAntiAlias(true);
66 paint.setTextSize(32);
67 paint.setColor(color);
68
69 SkRect bounds;
70 paint.measureText(text, strlen(text), &bounds);
71 const SkMatrix mat = SkMatrix::MakeRectToRect(bounds, SkRect::MakeWH(kLabelSize, kLabelSize),
72 SkMatrix::kFill_ScaleToFit);
73
74 const SkImageInfo ii = SkImageInfo::MakeN32Premul(kLabelSize, kLabelSize);
75 sk_sp<SkSurface> surf = SkSurface::MakeRaster(ii);
76
77 SkCanvas* canvas = surf->getCanvas();
78
79 canvas->clear(SK_ColorWHITE);
80 canvas->concat(mat);
81 canvas->drawText(text, strlen(text), 0, 0, paint);
82
83 sk_sp<SkImage> image = surf->makeImageSnapshot();
84
85 return image->makeTextureImage(context, nullptr);
86}
87
Robert Phillipsa0971732017-10-31 12:26:35 -040088// Create an image with each corner marked w/ "LL", "LR", etc., with the origin either bottom-left
89// or top-left.
Robert Phillips206bda52017-11-01 09:26:06 -040090static sk_sp<SkImage> make_reference_image(GrContext* context,
91 const SkTArray<sk_sp<SkImage>>& labels,
92 bool bottomLeftOrigin) {
Robert Phillipsa0971732017-10-31 12:26:35 -040093 SkASSERT(kNumLabels == labels.count());
94
Brian Salomon58389b92018-03-07 13:01:25 -050095 SkImageInfo ii =
96 SkImageInfo::Make(kImageSize, kImageSize, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
Robert Phillipsa0971732017-10-31 12:26:35 -040097 SkBitmap bm;
98 bm.allocPixels(ii);
99 SkCanvas canvas(bm);
100
101 canvas.clear(SK_ColorWHITE);
102 for (int i = 0; i < kNumLabels; ++i) {
103 canvas.drawImage(labels[i],
Robert Phillips206bda52017-11-01 09:26:06 -0400104 0.0 != kPoints[i].fX ? kPoints[i].fX-kLabelSize-kInset : kInset,
105 0.0 != kPoints[i].fY ? kPoints[i].fY-kLabelSize-kInset : kInset);
Robert Phillipsa0971732017-10-31 12:26:35 -0400106 }
107
Brian Salomon2a4f9832018-03-03 22:43:43 -0500108 auto origin = bottomLeftOrigin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
Robert Phillipsa0971732017-10-31 12:26:35 -0400109
Brian Salomon58389b92018-03-07 13:01:25 -0500110 auto proxy = sk_gpu_test::MakeTextureProxyFromData(context, false, kImageSize, kImageSize,
111 bm.colorType(), origin, bm.getPixels(),
112 bm.rowBytes());
Robert Phillipsa0971732017-10-31 12:26:35 -0400113 if (!proxy) {
114 return nullptr;
115 }
116
117 return sk_make_sp<SkImage_Gpu>(context, kNeedNewImageUniqueID, kOpaque_SkAlphaType,
118 std::move(proxy), nullptr, SkBudgeted::kYes);
119}
120
121// Here we're converting from a matrix that is intended for UVs to a matrix that is intended
122// for rect geometry used for a drawImage call. They are, in some sense, inverses of each
123// other but we also need a scale to map from the [0..1] uv range to the actual size of
124// image.
125static bool UVMatToGeomMatForImage(SkMatrix* geomMat, const SkMatrix& uvMat) {
Robert Phillips206bda52017-11-01 09:26:06 -0400126
127 const SkMatrix yFlip = SkMatrix::MakeAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
128
Robert Phillipsa0971732017-10-31 12:26:35 -0400129 SkMatrix tmp = uvMat;
Robert Phillips206bda52017-11-01 09:26:06 -0400130 tmp.preConcat(yFlip);
Robert Phillipsa0971732017-10-31 12:26:35 -0400131 tmp.preScale(1.0f/kImageSize, 1.0f/kImageSize);
Robert Phillips206bda52017-11-01 09:26:06 -0400132
133 tmp.postConcat(yFlip);
Robert Phillipsa0971732017-10-31 12:26:35 -0400134 tmp.postScale(kImageSize, kImageSize);
135
136 return tmp.invert(geomMat);
137}
138
139// This GM exercises drawImage with a set of matrices that use an unusual amount of flips and
140// rotates.
141class FlippityGM : public skiagm::GM {
142public:
143 FlippityGM() {
144 this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
145 }
146
147protected:
148
149 SkString onShortName() override {
150 return SkString("flippity");
151 }
152
153 SkISize onISize() override {
154 return SkISize::Make(kGMWidth, kGMHeight);
155 }
156
157 // Draw the reference image and the four corner labels in the matrix's coordinate space
Robert Phillips206bda52017-11-01 09:26:06 -0400158 void drawImageWithMatrixAndLabels(SkCanvas* canvas, SkImage* image, int matIndex,
159 bool drawSubset, bool drawScaled) {
160 static const SkRect kSubsets[kNumMatrices] = {
161 SkRect::MakeXYWH(kInset, 0, kImageSize-kInset, kImageSize),
162 SkRect::MakeXYWH(0, kInset, kImageSize, kImageSize-kInset),
163 SkRect::MakeXYWH(0, 0, kImageSize-kInset, kImageSize),
164 SkRect::MakeXYWH(0, 0, kImageSize, kImageSize-kInset),
165 SkRect::MakeXYWH(kInset/2, kInset/2, kImageSize-kInset, kImageSize-kInset),
166 SkRect::MakeXYWH(kInset, kInset, kImageSize-2*kInset, kImageSize-2*kInset),
167 };
168
Robert Phillipsa0971732017-10-31 12:26:35 -0400169 SkMatrix imageGeomMat;
170 SkAssertResult(UVMatToGeomMatForImage(&imageGeomMat, kUVMatrices[matIndex]));
171
172 canvas->save();
Robert Phillipsa0971732017-10-31 12:26:35 -0400173
174 // draw the reference image
Robert Phillips206bda52017-11-01 09:26:06 -0400175 canvas->concat(imageGeomMat);
176 if (drawSubset) {
177 canvas->drawImageRect(image, kSubsets[matIndex],
178 drawScaled ? SkRect::MakeWH(kImageSize, kImageSize)
179 : kSubsets[matIndex],
180 nullptr, SkCanvas::kFast_SrcRectConstraint);
181 } else {
182 canvas->drawImage(image, 0, 0);
183 }
Robert Phillipsa0971732017-10-31 12:26:35 -0400184
185 // draw the labels
186 for (int i = 0; i < kNumLabels; ++i) {
187 canvas->drawImage(fLabels[i],
188 0.0f == kPoints[i].fX ? -kLabelSize : kPoints[i].fX,
189 0.0f == kPoints[i].fY ? -kLabelSize : kPoints[i].fY);
190 }
191 canvas->restore();
192 }
193
Robert Phillips206bda52017-11-01 09:26:06 -0400194 void drawRow(GrContext* context, SkCanvas* canvas,
195 bool bottomLeftImage, bool drawSubset, bool drawScaled) {
196
197 sk_sp<SkImage> referenceImage = make_reference_image(context, fLabels, bottomLeftImage);
198
199 canvas->save();
200 canvas->translate(kLabelSize, kLabelSize);
201
202 for (int i = 0; i < kNumMatrices; ++i) {
203 this->drawImageWithMatrixAndLabels(canvas, referenceImage.get(), i,
204 drawSubset, drawScaled);
205 canvas->translate(kCellSize, 0);
206 }
207 canvas->restore();
208 }
209
Robert Phillipsa0971732017-10-31 12:26:35 -0400210 void makeLabels(GrContext* context) {
211 static const char* kLabelText[kNumLabels] = { "LL", "LR", "UL", "UR" };
212
213 static const SkColor kLabelColors[kNumLabels] = {
214 SK_ColorRED,
215 SK_ColorGREEN,
216 SK_ColorBLUE,
217 SK_ColorCYAN
218 };
219
220 SkASSERT(!fLabels.count());
221 for (int i = 0; i < kNumLabels; ++i) {
222 fLabels.push_back(make_text_image(context, kLabelText[i], kLabelColors[i]));
223 }
224 SkASSERT(kNumLabels == fLabels.count());
225 }
226
227 void onDraw(SkCanvas* canvas) override {
228 GrContext* context = canvas->getGrContext();
229 if (!context) {
230 skiagm::GM::DrawGpuOnlyMessage(canvas);
231 return;
232 }
233
234 this->makeLabels(context);
235
Robert Phillipsf0a30d72017-11-01 14:05:12 -0400236 canvas->save();
237
Robert Phillipsa0971732017-10-31 12:26:35 -0400238 // Top row gets TL image
Robert Phillips206bda52017-11-01 09:26:06 -0400239 this->drawRow(context, canvas, false, false, false);
Robert Phillipsa0971732017-10-31 12:26:35 -0400240
Robert Phillips206bda52017-11-01 09:26:06 -0400241 canvas->translate(0, kCellSize);
Robert Phillipsa0971732017-10-31 12:26:35 -0400242
243 // Bottom row gets BL image
Robert Phillips206bda52017-11-01 09:26:06 -0400244 this->drawRow(context, canvas, true, false, false);
Robert Phillipsa0971732017-10-31 12:26:35 -0400245
Robert Phillips206bda52017-11-01 09:26:06 -0400246 canvas->translate(0, kCellSize);
Robert Phillipsa0971732017-10-31 12:26:35 -0400247
Robert Phillips206bda52017-11-01 09:26:06 -0400248 // Third row gets subsets of BL images
249 this->drawRow(context, canvas, true, true, false);
250
251 canvas->translate(0, kCellSize);
252
253 // Fourth row gets scaled subsets of BL images
254 this->drawRow(context, canvas, true, true, true);
Robert Phillipsa0971732017-10-31 12:26:35 -0400255
Robert Phillipsf0a30d72017-11-01 14:05:12 -0400256 canvas->restore();
257
Robert Phillipsa0971732017-10-31 12:26:35 -0400258 // separator grid
Robert Phillipsf0a30d72017-11-01 14:05:12 -0400259 for (int i = 0; i < 4; ++i) {
260 canvas->drawLine(0, i * kCellSize, kGMWidth, i * kCellSize, SkPaint());
261 }
Robert Phillipsa0971732017-10-31 12:26:35 -0400262 for (int i = 0; i < kNumMatrices; ++i) {
263 canvas->drawLine(i * kCellSize, 0, i * kCellSize, kGMHeight, SkPaint());
264 }
265 }
266
267private:
268 SkTArray<sk_sp<SkImage>> fLabels;
269
270 typedef GM INHERITED;
271};
272
273DEF_GM(return new FlippityGM;)
274
275#endif