f05e6d3a46
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>
275 lines
9.1 KiB
C++
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;)
|