c7ad40f76f
Most of this is (obviously) not necessary to do, but once I started, I figured I'd just get it all. Tools (nanobench, DM, skiaserve), all GMs, benches, and unit tests, plus support code (command line parsing and config stuff). This is almost entirely mechanical. Bug: skia: Change-Id: I209500f8df8c5bd43f8298ff26440d1c4d7425fb Reviewed-on: https://skia-review.googlesource.com/131153 Reviewed-by: Mike Klein <mtklein@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
272 lines
9.0 KiB
C++
272 lines
9.0 KiB
C++
/*
|
|
* Copyright 2017 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm.h"
|
|
#include "sk_tool_utils.h"
|
|
|
|
#include "SkSurface.h"
|
|
|
|
#include "GrContextPriv.h"
|
|
#include "ProxyUtils.h"
|
|
#include "SkImage_Gpu.h"
|
|
|
|
static const int kNumMatrices = 6;
|
|
static const int kImageSize = 128;
|
|
static const int kLabelSize = 32;
|
|
static const int kNumLabels = 4;
|
|
static const int kInset = 16;
|
|
|
|
static const int kCellSize = kImageSize+2*kLabelSize;
|
|
static const int kGMWidth = kNumMatrices*kCellSize;
|
|
static const int kGMHeight = 4*kCellSize;
|
|
|
|
static const SkPoint kPoints[kNumLabels] = {
|
|
{ 0, kImageSize }, // LL
|
|
{ kImageSize, kImageSize }, // LR
|
|
{ 0, 0 }, // UL
|
|
{ kImageSize, 0 }, // UR
|
|
};
|
|
|
|
static const SkMatrix kUVMatrices[kNumMatrices] = {
|
|
SkMatrix::MakeAll( 0, -1, 1,
|
|
-1, 0, 1,
|
|
0, 0, 1),
|
|
SkMatrix::MakeAll( 1, 0, 0,
|
|
0, -1, 1,
|
|
0, 0, 1),
|
|
// flip x
|
|
SkMatrix::MakeAll(-1, 0, 1,
|
|
0, 1, 0,
|
|
0, 0, 1),
|
|
SkMatrix::MakeAll( 0, 1, 0,
|
|
-1, 0, 1,
|
|
0, 0, 1),
|
|
// flip both x & y == rotate 180
|
|
SkMatrix::MakeAll(-1, 0, 1,
|
|
0, -1, 1,
|
|
0, 0, 1),
|
|
// identity
|
|
SkMatrix::MakeAll(1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, 1)
|
|
};
|
|
|
|
|
|
// Create a fixed size text label like "LL" or "LR".
|
|
static sk_sp<SkImage> make_text_image(GrContext* context, const char* text, SkColor color) {
|
|
SkPaint paint;
|
|
sk_tool_utils::set_portable_typeface(&paint);
|
|
paint.setAntiAlias(true);
|
|
paint.setTextSize(32);
|
|
paint.setColor(color);
|
|
|
|
SkRect bounds;
|
|
paint.measureText(text, strlen(text), &bounds);
|
|
const SkMatrix mat = SkMatrix::MakeRectToRect(bounds, SkRect::MakeWH(kLabelSize, kLabelSize),
|
|
SkMatrix::kFill_ScaleToFit);
|
|
|
|
const SkImageInfo ii = SkImageInfo::MakeN32Premul(kLabelSize, kLabelSize);
|
|
sk_sp<SkSurface> surf = SkSurface::MakeRaster(ii);
|
|
|
|
SkCanvas* canvas = surf->getCanvas();
|
|
|
|
canvas->clear(SK_ColorWHITE);
|
|
canvas->concat(mat);
|
|
canvas->drawText(text, strlen(text), 0, 0, paint);
|
|
|
|
sk_sp<SkImage> image = surf->makeImageSnapshot();
|
|
|
|
return image->makeTextureImage(context, nullptr);
|
|
}
|
|
|
|
// Create an image with each corner marked w/ "LL", "LR", etc., with the origin either bottom-left
|
|
// or top-left.
|
|
static sk_sp<SkImage> make_reference_image(GrContext* context,
|
|
const SkTArray<sk_sp<SkImage>>& labels,
|
|
bool bottomLeftOrigin) {
|
|
SkASSERT(kNumLabels == labels.count());
|
|
|
|
SkImageInfo ii =
|
|
SkImageInfo::Make(kImageSize, kImageSize, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
|
|
SkBitmap bm;
|
|
bm.allocPixels(ii);
|
|
SkCanvas canvas(bm);
|
|
|
|
canvas.clear(SK_ColorWHITE);
|
|
for (int i = 0; i < kNumLabels; ++i) {
|
|
canvas.drawImage(labels[i],
|
|
0.0 != kPoints[i].fX ? kPoints[i].fX-kLabelSize-kInset : kInset,
|
|
0.0 != kPoints[i].fY ? kPoints[i].fY-kLabelSize-kInset : kInset);
|
|
}
|
|
|
|
auto origin = bottomLeftOrigin ? kBottomLeft_GrSurfaceOrigin : kTopLeft_GrSurfaceOrigin;
|
|
|
|
auto proxy = sk_gpu_test::MakeTextureProxyFromData(context, false, kImageSize, kImageSize,
|
|
bm.colorType(), origin, bm.getPixels(),
|
|
bm.rowBytes());
|
|
if (!proxy) {
|
|
return nullptr;
|
|
}
|
|
|
|
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID, kOpaque_SkAlphaType,
|
|
std::move(proxy), nullptr, SkBudgeted::kYes);
|
|
}
|
|
|
|
// Here we're converting from a matrix that is intended for UVs to a matrix that is intended
|
|
// for rect geometry used for a drawImage call. They are, in some sense, inverses of each
|
|
// other but we also need a scale to map from the [0..1] uv range to the actual size of
|
|
// image.
|
|
static bool UVMatToGeomMatForImage(SkMatrix* geomMat, const SkMatrix& uvMat) {
|
|
|
|
const SkMatrix yFlip = SkMatrix::MakeAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
|
|
|
|
SkMatrix tmp = uvMat;
|
|
tmp.preConcat(yFlip);
|
|
tmp.preScale(1.0f/kImageSize, 1.0f/kImageSize);
|
|
|
|
tmp.postConcat(yFlip);
|
|
tmp.postScale(kImageSize, kImageSize);
|
|
|
|
return tmp.invert(geomMat);
|
|
}
|
|
|
|
// This GM exercises drawImage with a set of matrices that use an unusual amount of flips and
|
|
// rotates.
|
|
class FlippityGM : public skiagm::GM {
|
|
public:
|
|
FlippityGM() {
|
|
this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
|
|
}
|
|
|
|
protected:
|
|
|
|
SkString onShortName() override {
|
|
return SkString("flippity");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(kGMWidth, kGMHeight);
|
|
}
|
|
|
|
// Draw the reference image and the four corner labels in the matrix's coordinate space
|
|
void drawImageWithMatrixAndLabels(SkCanvas* canvas, SkImage* image, int matIndex,
|
|
bool drawSubset, bool drawScaled) {
|
|
static const SkRect kSubsets[kNumMatrices] = {
|
|
SkRect::MakeXYWH(kInset, 0, kImageSize-kInset, kImageSize),
|
|
SkRect::MakeXYWH(0, kInset, kImageSize, kImageSize-kInset),
|
|
SkRect::MakeXYWH(0, 0, kImageSize-kInset, kImageSize),
|
|
SkRect::MakeXYWH(0, 0, kImageSize, kImageSize-kInset),
|
|
SkRect::MakeXYWH(kInset/2, kInset/2, kImageSize-kInset, kImageSize-kInset),
|
|
SkRect::MakeXYWH(kInset, kInset, kImageSize-2*kInset, kImageSize-2*kInset),
|
|
};
|
|
|
|
SkMatrix imageGeomMat;
|
|
SkAssertResult(UVMatToGeomMatForImage(&imageGeomMat, kUVMatrices[matIndex]));
|
|
|
|
canvas->save();
|
|
|
|
// draw the reference image
|
|
canvas->concat(imageGeomMat);
|
|
if (drawSubset) {
|
|
canvas->drawImageRect(image, kSubsets[matIndex],
|
|
drawScaled ? SkRect::MakeWH(kImageSize, kImageSize)
|
|
: kSubsets[matIndex],
|
|
nullptr, SkCanvas::kFast_SrcRectConstraint);
|
|
} else {
|
|
canvas->drawImage(image, 0, 0);
|
|
}
|
|
|
|
// draw the labels
|
|
for (int i = 0; i < kNumLabels; ++i) {
|
|
canvas->drawImage(fLabels[i],
|
|
0.0f == kPoints[i].fX ? -kLabelSize : kPoints[i].fX,
|
|
0.0f == kPoints[i].fY ? -kLabelSize : kPoints[i].fY);
|
|
}
|
|
canvas->restore();
|
|
}
|
|
|
|
void drawRow(GrContext* context, SkCanvas* canvas,
|
|
bool bottomLeftImage, bool drawSubset, bool drawScaled) {
|
|
|
|
sk_sp<SkImage> referenceImage = make_reference_image(context, fLabels, bottomLeftImage);
|
|
|
|
canvas->save();
|
|
canvas->translate(kLabelSize, kLabelSize);
|
|
|
|
for (int i = 0; i < kNumMatrices; ++i) {
|
|
this->drawImageWithMatrixAndLabels(canvas, referenceImage.get(), i,
|
|
drawSubset, drawScaled);
|
|
canvas->translate(kCellSize, 0);
|
|
}
|
|
canvas->restore();
|
|
}
|
|
|
|
void makeLabels(GrContext* context) {
|
|
static const char* kLabelText[kNumLabels] = { "LL", "LR", "UL", "UR" };
|
|
|
|
static const SkColor kLabelColors[kNumLabels] = {
|
|
SK_ColorRED,
|
|
SK_ColorGREEN,
|
|
SK_ColorBLUE,
|
|
SK_ColorCYAN
|
|
};
|
|
|
|
SkASSERT(!fLabels.count());
|
|
for (int i = 0; i < kNumLabels; ++i) {
|
|
fLabels.push_back(make_text_image(context, kLabelText[i], kLabelColors[i]));
|
|
}
|
|
SkASSERT(kNumLabels == fLabels.count());
|
|
}
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
GrContext* context = canvas->getGrContext();
|
|
if (!context) {
|
|
skiagm::GM::DrawGpuOnlyMessage(canvas);
|
|
return;
|
|
}
|
|
|
|
this->makeLabels(context);
|
|
|
|
canvas->save();
|
|
|
|
// Top row gets TL image
|
|
this->drawRow(context, canvas, false, false, false);
|
|
|
|
canvas->translate(0, kCellSize);
|
|
|
|
// Bottom row gets BL image
|
|
this->drawRow(context, canvas, true, false, false);
|
|
|
|
canvas->translate(0, kCellSize);
|
|
|
|
// Third row gets subsets of BL images
|
|
this->drawRow(context, canvas, true, true, false);
|
|
|
|
canvas->translate(0, kCellSize);
|
|
|
|
// Fourth row gets scaled subsets of BL images
|
|
this->drawRow(context, canvas, true, true, true);
|
|
|
|
canvas->restore();
|
|
|
|
// separator grid
|
|
for (int i = 0; i < 4; ++i) {
|
|
canvas->drawLine(0, i * kCellSize, kGMWidth, i * kCellSize, SkPaint());
|
|
}
|
|
for (int i = 0; i < kNumMatrices; ++i) {
|
|
canvas->drawLine(i * kCellSize, 0, i * kCellSize, kGMHeight, SkPaint());
|
|
}
|
|
}
|
|
|
|
private:
|
|
SkTArray<sk_sp<SkImage>> fLabels;
|
|
|
|
typedef GM INHERITED;
|
|
};
|
|
|
|
DEF_GM(return new FlippityGM;)
|