blob: 466e78cb2102c7a8cf0ff0a0393841667aba87c5 [file] [edit]
/*
* Copyright 2026 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkGradient.h"
#include "include/gpu/ganesh/SkImageGanesh.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "tests/Test.h"
namespace {
sk_sp<SkImage> make_gpu_src_img(GrDirectContext* dContext, float srcSize) {
SkImageInfo ii = SkImageInfo::Make(srcSize, srcSize,
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
SkBitmap srcBM;
srcBM.allocPixels(ii);
SkPaint p;
const SkPoint pts[] = { { 0, 0 }, { srcSize, srcSize } };
const SkColor4f colors[] = { SkColors::kWhite, SkColors::kBlue };
p.setShader(SkShaders::LinearGradient(pts, {{colors, {}, SkTileMode::kClamp}, {}}));
SkCanvas c(srcBM);
c.drawRect(SkRect::MakeWH(srcSize, srcSize), p);
sk_sp<SkImage> rasterImage = SkImages::RasterFromBitmap(srcBM);
return SkImages::TextureFromImage(dContext, rasterImage);
}
// This test will trigger an assert if the max quads/TextureOp limit overflows
void run_test(GrDirectContext* dContext, uint32_t numXSteps, uint32_t numYSteps, bool withAA) {
constexpr uint32_t kRectSize = 8;
constexpr float kHalfRectSize = kRectSize / 2.0f;
sk_sp<SkImage> srcImg = make_gpu_src_img(dContext, kRectSize);
SkImageInfo ii = SkImageInfo::Make(numXSteps*kRectSize, numYSteps*kRectSize,
kRGBA_8888_SkColorType, kPremul_SkAlphaType);
auto surface(SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, ii));
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorBLACK);
SkCanvas::ImageSetEntry* entries = new SkCanvas::ImageSetEntry[numXSteps*numYSteps];
SkMatrix* preViewMatrices = new SkMatrix[numXSteps*numYSteps];
SkMatrix perspMatrix;
perspMatrix.setPerspX(0.1f);
perspMatrix.setPerspY(0.1f);
for (uint32_t y = 0; y < numYSteps; ++y) {
for (uint32_t x = 0; x < numXSteps; x++) {
uint32_t entry = y*numXSteps+x;
// These matrices are arranged so every quad will be split due to
// perspective
preViewMatrices[entry].setTranslate(x*kRectSize+kHalfRectSize,
y*kRectSize+kHalfRectSize);
preViewMatrices[entry].preConcat(perspMatrix);
SkRect destRect = SkRect::MakeXYWH(-kHalfRectSize, -kHalfRectSize,
kRectSize, kRectSize);
entries[entry].fImage = srcImg;
entries[entry].fSrcRect = SkRect::MakeLTRB(0, 0, kRectSize, kRectSize);
entries[entry].fDstRect = destRect;
entries[entry].fMatrixIndex = entry;
entries[entry].fAlpha = 1.f;
entries[entry].fAAFlags = withAA ? SkCanvas::kAll_QuadAAFlags
: SkCanvas::kNone_QuadAAFlags;
entries[entry].fHasClip = false;
}
}
canvas->experimental_DrawEdgeAAImageSet(
entries,
numXSteps*numYSteps,
/* dstClips= */ nullptr,
preViewMatrices,
SkSamplingOptions());
dContext->flushAndSubmit(surface.get(), GrSyncCpu::kYes);
delete [] preViewMatrices;
delete [] entries;
}
} // anonymous namespace
// This checks that the perspective quad splitting doesn't overflow for AA draws
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(crbug_500172224_aa_double,
reporter,
ctxInfo,
CtsEnforcement::kNever) {
constexpr uint32_t kNumXSteps = 32;
constexpr uint32_t kNumYSteps = 32;
SkASSERT(kNumXSteps*kNumYSteps == 2*GrResourceProvider::MaxNumAAQuads());
run_test(ctxInfo.directContext(), kNumXSteps, kNumYSteps, /* withAA= */ true);
}
// This checks that the perspective quad splitting doesn't overflow for non-AA draws
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(crbug_500172224_non_aa_double,
reporter,
ctxInfo,
CtsEnforcement::kNever) {
constexpr uint32_t kNumXSteps = 128;
constexpr uint32_t kNumYSteps = 64;
SkASSERT(kNumXSteps*kNumYSteps == 2*GrResourceProvider::MaxNumNonAAQuads());
run_test(ctxInfo.directContext(), kNumXSteps, kNumYSteps, /* withAA= */ false);
}
// This tests the AA perspective fast-path blocking in TextureOp::AddTextureSetOps.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(crbug_500172224_aa,
reporter,
ctxInfo,
CtsEnforcement::kNever) {
constexpr uint32_t kNumXSteps = 32;
constexpr uint32_t kNumYSteps = 16;
SkASSERT(kNumXSteps*kNumYSteps == GrResourceProvider::MaxNumAAQuads());
run_test(ctxInfo.directContext(), kNumXSteps, kNumYSteps, /* withAA= */ true);
}