blob: c852c47ad0a89a316f4e1f58d340ff6a45e3949e [file]
/*
* 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/SkFont.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkSurface.h"
#include "include/utils/SkCustomTypeface.h"
#include "tests/CtsEnforcement.h"
#include "tests/Test.h"
#include <functional>
#include <type_traits>
#if defined(SK_GANESH)
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#endif
#if defined(SK_GRAPHITE)
#include "include/gpu/graphite/Context.h"
#include "include/gpu/graphite/ContextOptions.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/gpu/graphite/Surface.h"
#include "src/gpu/graphite/ContextOptionsPriv.h"
#endif
template <typename T>
static void disable_sdft_options(T* options) {
options->fMinDistanceFieldFontSize = 384.f;
options->fGlyphsAsPathsFontSize = 384.f;
options->fSupportBilerpFromGlyphAtlas = true;
if constexpr (std::is_same_v<T, GrContextOptions>) {
options->fMaxTextureSizeOverride = 1024;
} else {
options->fOptionsPriv->fMaxTextureSizeOverride = 1024;
}
}
static void test_direct_mask_limit(skiatest::Reporter* reporter,
SkSurface* surface,
const std::function<void()>& submit) {
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorBLACK);
SkCustomTypefaceBuilder builder;
SkPath path = SkPath::Rect(SkRect::MakeLTRB(0.f, -1.f, 1.f, 0.f));
builder.setGlyph(1, 1.0f, path);
SkFont font(builder.detach(), 253);
font.setEdging(SkFont::Edging::kSubpixelAntiAlias);
SkPaint paint;
paint.setColor(SK_ColorWHITE);
SkGlyphID glyph = 1;
SkPoint position = {0, 0};
canvas->drawGlyphs({&glyph, 1}, {&position, 1}, {100, 300}, font, paint);
submit();
SkBitmap bitmap;
bitmap.allocN32Pixels(512, 512);
REPORTER_ASSERT(reporter, surface->readPixels(bitmap, 0, 0));
bool hasWhitePixel = false;
for (int y = 0; y < 512; ++y) {
for (int x = 0; x < 512; ++x) {
if (bitmap.getColor(x, y) != SK_ColorBLACK) {
hasWhitePixel = true;
break;
}
}
if (hasWhitePixel) {
break;
}
}
REPORTER_ASSERT(reporter, hasWhitePixel, "Draw failed (all pixels are black)");
}
#if defined(SK_GANESH)
DEF_GANESH_TEST_FOR_CONTEXTS(DirectMaskLimitTest_Ganesh,
skgpu::IsRenderingContext,
reporter,
ctxInfo,
disable_sdft_options<GrContextOptions>,
CtsEnforcement::kNever) {
auto dContext = ctxInfo.directContext();
if (dContext->supportsProtectedContent()) {
return;
}
auto surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo,
SkImageInfo::MakeN32Premul(512, 512));
if (!surface) {
return;
}
test_direct_mask_limit(reporter, surface.get(), [&] { dContext->flushAndSubmit(); });
}
#endif // SK_GANESH
#if defined(SK_GRAPHITE)
DEF_CONDITIONAL_GRAPHITE_TEST_FOR_CONTEXTS(DirectMaskLimitTest_Graphite,
skgpu::IsRenderingContext,
reporter,
context,
testContext,
/* anonymous options */,
disable_sdft_options<skgpu::graphite::ContextOptions>,
/* condition= */ true,
CtsEnforcement::kNever) {
if (context->supportsProtectedContent()) {
return;
}
auto recorder = context->makeRecorder();
if (!recorder) {
return;
}
auto surface = SkSurfaces::RenderTarget(recorder.get(),
SkImageInfo::MakeN32Premul(512, 512));
if (!surface) {
return;
}
test_direct_mask_limit(reporter, surface.get(), [&] {
auto recording = recorder->snap();
context->insertRecording({recording.get()});
context->submit(skgpu::graphite::SyncToCpu::kYes);
});
}
#endif // SK_GRAPHITE