skia2/gm/flippity.cpp
Brian Salomon f05e6d3a46 Remove superfluous budgeted params and member related to SkImage_GpuBase
The proxy/proxies in the SkImage_GpuBase subclasses already track
whether they're budgeted.

The parameters are sometimes redundantly stating the known budgeted
status of the proxy. Other times they are an illusion of control as
the value doesn't actually affected the budgeting of the proxy/proxies.

Change-Id: Ic2b12fbbed653fca1ec1910eeab686de69782834
Reviewed-on: https://skia-review.googlesource.com/c/179402
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2018-12-20 15:58:55 +00:00

275 lines
9.1 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;
paint.setAntiAlias(true);
paint.setColor(color);
SkFont font;
font.setEdging(SkFont::Edging::kAntiAlias);
font.setTypeface(sk_tool_utils::create_portable_typeface());
font.setSize(32);
SkRect bounds;
font.measureText(text, strlen(text), kUTF8_SkTextEncoding, &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->drawSimpleText(text, strlen(text), kUTF8_SkTextEncoding, 0, 0, font, 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);
}
// 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(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;)