a696f8a925
In this CL, GrResourceProvider's functions, like createTexture etc, get label string passed to it which are called from GrGpu which then passes the label to setLabel method of GrGpuResource. Bug: chromium:1164111 Change-Id: Icfd88279c0729e36c105c62c05f382aab0a89310 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/534778 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
276 lines
11 KiB
C++
276 lines
11 KiB
C++
/*
|
|
* Copyright 2021 Google LLC
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/core/SkBitmap.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkRect.h"
|
|
#include "include/core/SkSize.h"
|
|
#include "include/core/SkString.h"
|
|
#include "include/gpu/GrDirectContext.h"
|
|
#include "src/core/SkCanvasPriv.h"
|
|
#include "src/core/SkConvertPixels.h"
|
|
#include "src/gpu/ganesh/GrDirectContextPriv.h"
|
|
#include "src/gpu/ganesh/GrPaint.h"
|
|
#include "src/gpu/ganesh/GrProxyProvider.h"
|
|
#include "src/gpu/ganesh/GrResourceProvider.h"
|
|
#include "src/gpu/ganesh/SkGr.h"
|
|
#include "src/gpu/ganesh/effects/GrTextureEffect.h"
|
|
#include "src/gpu/ganesh/v1/SurfaceDrawContext_v1.h"
|
|
#include "tools/gpu/ProxyUtils.h"
|
|
|
|
static GrSurfaceProxyView create_view(GrDirectContext* dContext,
|
|
const SkBitmap& src,
|
|
GrSurfaceOrigin origin) {
|
|
SkASSERT(src.colorType() == kRGBA_8888_SkColorType);
|
|
|
|
#define USE_LAZY_PROXIES 1 // Toggle this to generate the reference images
|
|
|
|
if (USE_LAZY_PROXIES) {
|
|
auto format = dContext->priv().caps()->getDefaultBackendFormat(GrColorType::kRGBA_8888,
|
|
GrRenderable::kNo);
|
|
if (!format.isValid()) {
|
|
return {};
|
|
}
|
|
|
|
sk_sp<GrTextureProxy> proxy = GrProxyProvider::MakeFullyLazyProxy(
|
|
[src](GrResourceProvider* rp,
|
|
const GrSurfaceProxy::LazySurfaceDesc& desc)
|
|
-> GrSurfaceProxy::LazyCallbackResult {
|
|
SkASSERT(desc.fMipmapped == GrMipmapped::kNo);
|
|
GrMipLevel mipLevel = {src.getPixels(), src.rowBytes(), nullptr};
|
|
auto colorType = SkColorTypeToGrColorType(src.colorType());
|
|
|
|
return rp->createTexture(src.dimensions(),
|
|
desc.fFormat,
|
|
desc.fTextureType,
|
|
colorType,
|
|
desc.fRenderable,
|
|
desc.fSampleCnt,
|
|
desc.fBudgeted,
|
|
desc.fFit,
|
|
desc.fProtected,
|
|
mipLevel,
|
|
desc.fLabel);
|
|
},
|
|
format, GrRenderable::kNo, 1, GrProtected::kNo, *dContext->priv().caps(),
|
|
GrSurfaceProxy::UseAllocator::kYes);
|
|
|
|
if (!proxy) {
|
|
return {};
|
|
}
|
|
|
|
auto swizzle = dContext->priv().caps()->getReadSwizzle(proxy->backendFormat(),
|
|
GrColorType::kRGBA_8888);
|
|
return GrSurfaceProxyView(std::move(proxy), origin, swizzle);
|
|
}
|
|
|
|
return sk_gpu_test::MakeTextureProxyViewFromData(dContext,
|
|
GrRenderable::kNo,
|
|
origin,
|
|
src.pixmap());
|
|
}
|
|
|
|
// Create an over large texture which is initialized to opaque black outside of the content
|
|
// rect. The inside of the content rect consists of a grey coordinate frame lacking the -Y axis.
|
|
// The -X and +X axes have a red and green dot at their ends (respectively). Finally, the content
|
|
// rect has a 1-pixel wide blue border.
|
|
static SkBitmap create_bitmap(SkIRect contentRect, SkISize fullSize, GrSurfaceOrigin origin) {
|
|
|
|
const int kContentSize = contentRect.width();
|
|
SkBitmap contentBM;
|
|
|
|
{
|
|
SkImageInfo contentInfo = SkImageInfo::Make(kContentSize, kContentSize,
|
|
kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
|
|
contentBM.allocPixels(contentInfo);
|
|
|
|
contentBM.eraseColor(SK_ColorWHITE);
|
|
|
|
const int halfM1 = kContentSize/2 - 1;
|
|
|
|
// The coordinate frame
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(halfM1, 2,2, halfM1), SK_ColorGRAY);
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(2, halfM1, kContentSize-4, 2), SK_ColorGRAY);
|
|
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(2, halfM1, 2, 2), SK_ColorRED);
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(kContentSize-4, halfM1, 2, 2), SK_ColorGREEN);
|
|
|
|
// The 1-pixel wide rim around the content rect
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(0, 0, kContentSize, 1), SK_ColorBLUE);
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(0, 0, 1, kContentSize), SK_ColorBLUE);
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(kContentSize-1, 0, 1, kContentSize), SK_ColorBLUE);
|
|
contentBM.eraseArea(SkIRect::MakeXYWH(0, kContentSize-1, kContentSize, 1), SK_ColorBLUE);
|
|
}
|
|
|
|
SkBitmap bigBM;
|
|
|
|
{
|
|
const int kLeft = contentRect.fLeft;
|
|
const int kTop = contentRect.fTop;
|
|
|
|
SkImageInfo bigInfo = SkImageInfo::Make(fullSize.fWidth, fullSize.fHeight,
|
|
kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
|
|
|
|
bigBM.allocPixels(bigInfo);
|
|
|
|
bigBM.eraseColor(SK_ColorBLACK);
|
|
|
|
const char* src = static_cast<const char*>(contentBM.getPixels());
|
|
size_t srcRB = contentBM.rowBytes();
|
|
size_t dstRB = bigBM.rowBytes();
|
|
|
|
if (USE_LAZY_PROXIES && origin == kBottomLeft_GrSurfaceOrigin) {
|
|
char* dst = static_cast<char*>(bigBM.getAddr(kLeft, fullSize.height() - kTop - 1));
|
|
for (int y = 0; y < contentBM.height(); ++y) {
|
|
memcpy(dst, src, srcRB);
|
|
src = src + srcRB;
|
|
dst = dst - dstRB;
|
|
}
|
|
} else {
|
|
char* dst = static_cast<char*>(bigBM.getAddr(kLeft, kTop));
|
|
SkRectMemcpy(dst, dstRB, src, srcRB,
|
|
contentBM.rowBytes(), contentBM.height());
|
|
}
|
|
|
|
bigBM.setAlphaType(kOpaque_SkAlphaType);
|
|
bigBM.setImmutable();
|
|
}
|
|
|
|
return bigBM;
|
|
}
|
|
|
|
static void draw_texture(const GrCaps* caps,
|
|
skgpu::v1::SurfaceDrawContext* sdc,
|
|
const GrSurfaceProxyView& src,
|
|
const SkIRect& srcRect,
|
|
const SkIRect& drawRect,
|
|
const SkMatrix& mat,
|
|
GrSamplerState::WrapMode xTileMode,
|
|
GrSamplerState::WrapMode yTileMode) {
|
|
GrSamplerState sampler(xTileMode, yTileMode, SkFilterMode::kNearest);
|
|
|
|
auto fp = GrTextureEffect::MakeSubset(src, kOpaque_SkAlphaType, mat,
|
|
sampler, SkRect::Make(srcRect), *caps);
|
|
GrPaint paint;
|
|
paint.setColorFragmentProcessor(std::move(fp));
|
|
|
|
sdc->drawRect(nullptr, std::move(paint), GrAA::kNo, SkMatrix::I(), SkRect::Make(drawRect));
|
|
}
|
|
|
|
namespace skiagm {
|
|
|
|
// This GM exercises all the different tile modes for a texture that cannot be normalized
|
|
// early (i.e., rectangle or fully-lazy).
|
|
// TODO: should we also test w/ mipmapping?
|
|
class LazyTilingGM : public GpuGM {
|
|
public:
|
|
LazyTilingGM(GrSurfaceOrigin origin)
|
|
: fOrigin(origin)
|
|
, fContentRect(SkIRect::MakeXYWH(kLeftContentOffset, kTopContentOffset,
|
|
kContentSize, kContentSize)) {
|
|
this->setBGColor(0xFFCCCCCC);
|
|
}
|
|
|
|
protected:
|
|
|
|
SkString onShortName() override {
|
|
return SkStringPrintf("lazytiling_%s", fOrigin == kTopLeft_GrSurfaceOrigin ? "tl" : "bl");
|
|
}
|
|
|
|
SkISize onISize() override {
|
|
return SkISize::Make(kTotalWidth, kTotalHeight);
|
|
}
|
|
|
|
DrawResult onGpuSetup(GrDirectContext* dContext, SkString* errorMsg) override {
|
|
if (!dContext || dContext->abandoned()) {
|
|
return DrawResult::kSkip;
|
|
}
|
|
|
|
auto bm = create_bitmap(fContentRect,
|
|
{ kLeftContentOffset + kContentSize + kRightContentPadding,
|
|
kTopContentOffset + kContentSize + kBottomContentPadding },
|
|
fOrigin);
|
|
|
|
fView = create_view(dContext, bm, fOrigin);
|
|
if (!fView.proxy()) {
|
|
*errorMsg = "Failed to create proxy";
|
|
return DrawResult::kFail;
|
|
}
|
|
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
|
|
SkSamplingOptions sampling(SkFilterMode::kNearest, SkMipmapMode::kNone);
|
|
SkPaint p;
|
|
|
|
auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
|
|
if (!sdc) {
|
|
*errorMsg = kErrorMsg_DrawSkippedGpuOnly;
|
|
return DrawResult::kSkip;
|
|
}
|
|
|
|
int y = kPad;
|
|
for (auto yMode : { SkTileMode::kClamp, SkTileMode::kRepeat,
|
|
SkTileMode::kMirror, SkTileMode::kDecal }) {
|
|
int x = kPad;
|
|
for (auto xMode : { SkTileMode::kClamp, SkTileMode::kRepeat,
|
|
SkTileMode::kMirror, SkTileMode::kDecal }) {
|
|
SkIRect cellRect = SkIRect::MakeXYWH(x, y, 2*kContentSize, 2*kContentSize);
|
|
SkRect contentRect = SkRect::MakeXYWH(x+kContentSize/2, y+kContentSize/2,
|
|
kContentSize, kContentSize);
|
|
|
|
SkMatrix texMatrix = SkMatrix::RectToRect(contentRect, SkRect::Make(fContentRect));
|
|
|
|
draw_texture(rContext->priv().caps(),
|
|
sdc,
|
|
fView,
|
|
fContentRect,
|
|
cellRect,
|
|
texMatrix,
|
|
SkTileModeToWrapMode(xMode),
|
|
SkTileModeToWrapMode(yMode));
|
|
|
|
x += 2*kContentSize+kPad;
|
|
}
|
|
|
|
y += 2*kContentSize+kPad;
|
|
}
|
|
|
|
return DrawResult::kOk;
|
|
}
|
|
|
|
private:
|
|
inline static constexpr int kLeftContentOffset = 8;
|
|
inline static constexpr int kTopContentOffset = 16;
|
|
inline static constexpr int kRightContentPadding = 24;
|
|
inline static constexpr int kBottomContentPadding = 80;
|
|
|
|
inline static constexpr int kPad = 4; // on-screen padding between cells
|
|
|
|
inline static constexpr int kContentSize = 32;
|
|
|
|
// Each cell in this GM's grid is a square - 2*kContentSize on a side
|
|
inline static constexpr int kTotalWidth = (2*kContentSize+kPad) * kSkTileModeCount + kPad;
|
|
inline static constexpr int kTotalHeight = (2*kContentSize+kPad) * kSkTileModeCount + kPad;
|
|
|
|
GrSurfaceOrigin fOrigin;
|
|
SkIRect fContentRect;
|
|
GrSurfaceProxyView fView;
|
|
|
|
using INHERITED = GM;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
DEF_GM(return new LazyTilingGM(kTopLeft_GrSurfaceOrigin);)
|
|
DEF_GM(return new LazyTilingGM(kBottomLeft_GrSurfaceOrigin);)
|
|
|
|
} // namespace skiagm
|