88#include <initializer_list>
108#if defined(SK_GRAPHITE)
116#include "misc/cpp/imgui_stdlib.h"
118#if defined(SK_VULKAN)
119#include "spirv-tools/libspirv.hpp"
122#if defined(SK_ENABLE_SKOTTIE)
126#if defined(SK_ENABLE_SVG)
131#ifdef SK_CODEC_DECODES_AVIF
135#ifdef SK_HAS_HEIF_LIBRARY
139#ifdef SK_CODEC_DECODES_JPEGXL
143#ifdef SK_CODEC_DECODES_RAW
183#define GL_BACKEND_STR ", \"gl\""
185#define GL_BACKEND_STR
188#define VK_BACKEND_STR ", \"vk\""
190#define VK_BACKEND_STR
193#define MTL_BACKEND_STR ", \"mtl\""
195#define MTL_BACKEND_STR
198#define D3D_BACKEND_STR ", \"d3d\""
200#define D3D_BACKEND_STR
203#define DAWN_BACKEND_STR ", \"dawn\""
205#define DAWN_BACKEND_STR
207#define BACKENDS_STR_EVALUATOR(sw, gl, vk, mtl, d3d, dawn) sw gl vk mtl d3d dawn
208#define BACKENDS_STR BACKENDS_STR_EVALUATOR( \
209 "\"sw\"", GL_BACKEND_STR, VK_BACKEND_STR, MTL_BACKEND_STR, D3D_BACKEND_STR, DAWN_BACKEND_STR)
213static DEFINE_int(msaa, 1,
"Number of subpixel samples. 0 for no HW antialiasing.");
214static DEFINE_bool(dmsaa,
false,
"Use internal MSAA to render to non-MSAA surfaces?");
221 "[~][^]substring[$] [...] of name to run.\n"
222 "Multiple matches may be separated by spaces.\n"
223 "~ causes a matching name to always be skipped\n"
224 "^ requires the start of the name to match\n"
225 "$ requires the end of the name to match\n"
226 "^ and $ requires an exact match\n"
227 "If a name does not match any list entry,\n"
228 "it is skipped unless some list entry starts with ~");
230#if defined(SK_GRAPHITE)
231#ifdef SK_ENABLE_VELLO_SHADERS
232#define COMPUTE_ANALYTIC_PATHSTRATEGY_STR ", \"compute-analytic\""
233#define COMPUTE_MSAA16_PATHSTRATEGY_STR ", \"compute-msaa16\""
234#define COMPUTE_MSAA8_PATHSTRATEGY_STR ", \"compute-msaa8\""
236#define COMPUTE_ANALYTIC_PATHSTRATEGY_STR
237#define COMPUTE_MSAA16_PATHSTRATEGY_STR
238#define COMPUTE_MSAA8_PATHSTRATEGY_STR
240#define PATHSTRATEGY_STR_EVALUATOR( \
241 default, raster, compute_analytic, compute_msaa16, compute_msaa8, tess) \
242 default raster compute_analytic compute_msaa16 tess
243#define PATHSTRATEGY_STR \
244 PATHSTRATEGY_STR_EVALUATOR("\"default\"", \
246 COMPUTE_ANALYTIC_PATHSTRATEGY_STR, \
247 COMPUTE_MSAA16_PATHSTRATEGY_STR, \
248 COMPUTE_MSAA8_PATHSTRATEGY_STR, \
252 "Path renderer strategy to use. Allowed values are " PATHSTRATEGY_STR
".");
256 "Disable Tint WGSL symbol renaming when using Dawn");
260#if defined(SK_BUILD_FOR_ANDROID)
261# define PATH_PREFIX "/data/local/tmp/"
263# define PATH_PREFIX ""
273static DEFINE_string(svgs,
"",
"Directory to read SVGs from, or a single SVG file.");
275static DEFINE_string(rives,
"",
"Directory to read RIVs from, or a single .riv file.");
278 "Run threadsafe tests on a threadpool with this many extra threads, "
279 "defaulting to one extra thread per core.");
283static DEFINE_bool(offscreen,
false,
"Force rendering to an offscreen surface.");
285static DEFINE_bool(createProtected,
false,
"Create a protected native backend (e.g., in EGL).");
288static_assert(
false,
"viewer requires GL backend for raster.")
292#if defined(SK_GRAPHITE)
295 case sk_app::Window::kGraphiteDawn_BackendType:
298 case sk_app::Window::kGraphiteMetal_BackendType:
301 case sk_app::Window::kGraphiteVulkan_BackendType:
311#if defined(SK_GRAPHITE)
318 case Strategy::kComputeAnalyticAA:
319 return "GPU Compute AA (Analytic)";
320 case Strategy::kComputeMSAA16:
321 return "GPU Compute AA (16xMSAA)";
322 case Strategy::kComputeMSAA8:
323 return "GPU Compute AA (8xMSAA)";
324 case Strategy::kRasterAA:
325 return "CPU Raster AA";
326 case Strategy::kTessellation:
327 return "Tessellation";
334 if (0 == strcmp(str,
"default")) {
336 }
else if (0 == strcmp(str,
"raster")) {
337 return Strategy::kRasterAA;
338#ifdef SK_ENABLE_VELLO_SHADERS
339 }
else if (0 == strcmp(str,
"compute-analytic")) {
340 return Strategy::kComputeAnalyticAA;
341 }
else if (0 == strcmp(str,
"compute-msaa16")) {
342 return Strategy::kComputeMSAA16;
343 }
else if (0 == strcmp(str,
"compute-msaa8")) {
344 return Strategy::kComputeMSAA8;
346 }
else if (0 == strcmp(str,
"tessellation")) {
347 return Strategy::kTessellation;
349 SkDebugf(
"Unknown path renderer strategy type, %s, defaulting to default.", str);
357 case sk_app::Window::kNativeGL_BackendType:
return "OpenGL";
358#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
359 case sk_app::Window::kANGLE_BackendType:
return "ANGLE";
362#if defined(SK_GRAPHITE)
363 case sk_app::Window::kGraphiteDawn_BackendType:
return "Dawn (Graphite)";
367 case sk_app::Window::kVulkan_BackendType:
return "Vulkan";
368#if defined(SK_GRAPHITE)
369 case sk_app::Window::kGraphiteVulkan_BackendType:
return "Vulkan (Graphite)";
373 case sk_app::Window::kMetal_BackendType:
return "Metal";
374#if defined(SK_GRAPHITE)
375 case sk_app::Window::kGraphiteMetal_BackendType:
return "Metal (Graphite)";
379 case sk_app::Window::kDirect3D_BackendType:
return "Direct3D";
389#if defined(SK_GRAPHITE)
390 if (0 == strcmp(str,
"grdawn")) {
391 return sk_app::Window::kGraphiteDawn_BackendType;
396 if (0 == strcmp(str,
"vk")) {
397 return sk_app::Window::kVulkan_BackendType;
399#if defined(SK_GRAPHITE)
400 if (0 == strcmp(str,
"grvk")) {
401 return sk_app::Window::kGraphiteVulkan_BackendType;
405#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
406 if (0 == strcmp(str,
"angle")) {
407 return sk_app::Window::kANGLE_BackendType;
411 if (0 == strcmp(str,
"mtl")) {
412 return sk_app::Window::kMetal_BackendType;
414#if defined(SK_GRAPHITE)
415 if (0 == strcmp(str,
"grmtl")) {
416 return sk_app::Window::kGraphiteMetal_BackendType;
421 if (0 == strcmp(str,
"d3d")) {
422 return sk_app::Window::kDirect3D_BackendType;
426 if (0 == strcmp(str,
"gl")) {
427 return sk_app::Window::kNativeGL_BackendType;
428 }
else if (0 == strcmp(str,
"sw")) {
431 SkDebugf(
"Unknown backend type, %s, defaulting to sw.", str);
482 canvas->
clear(0xffff11ff);
495static const char kON[] =
"ON";
502 , fShowSlideDimensions(
false)
503 , fShowImGuiDebugWindow(
false)
504 , fShowSlidePicker(
false)
505 , fShowImGuiTestWindow(
false)
506 , fShowHistogramWindow(
false)
507 , fShowZoomWindow(
false)
508 , fZoomWindowFixed(
false)
509 , fZoomWindowLocation{0.0f, 0.0f}
510 , fLastImage(nullptr)
513 , fColorMode(ColorMode::kLegacy)
517 , fApplyBackingScale(
true)
520 , fOffset{0.5f, 0.5f}
521 , fGestureDevice(GestureDevice::kNone)
523 , fDrawTileBoundaries(
false)
524 , fTileScale{0.25f, 0.25f}
525 , fPerspectiveMode(kPerspective_Off)
528#if defined(SK_ENABLE_SVG)
540 SkDebugf(
"Command line arguments: ");
541 for (
int i = 1;
i < argc; ++
i) {
547#ifdef SK_BUILD_FOR_ANDROID
555 fWindow = Window::CreateNativeWindow(platformData);
572#if defined(SK_GRAPHITE)
573 displayParams.fGraphiteContextOptions.fPriv.fPathRendererStrategy =
574 get_path_renderer_strategy_type(FLAGS_pathstrategy[0]);
576 displayParams.fDisableTintSymbolRenaming = FLAGS_disable_tint_symbol_renaming;
581 fRefresh = FLAGS_redraw;
593 fCommands.
attach(fWindow);
599 fCommands.
addCommand(
' ',
"GUI",
"Toggle Debug GUI", [
this]() {
600 this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
604 fCommands.
addCommand(
'/',
"GUI",
"Jump to slide picker", [
this]() {
605 this->fShowImGuiDebugWindow =
true;
606 this->fShowSlidePicker =
true;
611 this->fShowImGuiDebugWindow =
true;
612 this->fShowSlidePicker =
true;
615 fCommands.
addCommand(
'g',
"GUI",
"Toggle GUI Demo", [
this]() {
616 this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
619 fCommands.
addCommand(
'z',
"GUI",
"Toggle zoom window", [
this]() {
620 this->fShowZoomWindow = !this->fShowZoomWindow;
623 fCommands.
addCommand(
'Z',
"GUI",
"Toggle zoom window state", [
this]() {
624 this->fZoomWindowFixed = !this->fZoomWindowFixed;
627 fCommands.
addCommand(
'v',
"Swapchain",
"Toggle vsync on/off", [
this]() {
634 fCommands.
addCommand(
'V',
"Swapchain",
"Toggle delayed acquire on/off (Metal only)", [
this]() {
636 params.fDelayDrawableAcquisition = !
params.fDelayDrawableAcquisition;
641 fCommands.
addCommand(
'r',
"Redraw",
"Toggle redraw", [
this]() {
642 fRefresh = !fRefresh;
645 fCommands.
addCommand(
's',
"Overlays",
"Toggle stats display", [
this]() {
649 fCommands.
addCommand(
'0',
"Overlays",
"Reset stats", [
this]() {
654 fCommands.
addCommand(
'C',
"GUI",
"Toggle color histogram", [
this]() {
655 this->fShowHistogramWindow = !this->fShowHistogramWindow;
658 fCommands.
addCommand(
'c',
"Modes",
"Cycle color mode", [
this]() {
659 switch (fColorMode) {
660 case ColorMode::kLegacy:
661 this->setColorMode(ColorMode::kColorManaged8888);
663 case ColorMode::kColorManaged8888:
664 this->setColorMode(ColorMode::kColorManagedF16);
666 case ColorMode::kColorManagedF16:
667 this->setColorMode(ColorMode::kColorManagedF16Norm);
669 case ColorMode::kColorManagedF16Norm:
670 this->setColorMode(ColorMode::kLegacy);
674 fCommands.
addCommand(
'w',
"Modes",
"Toggle wireframe", [
this]() {
676 params.fGrContextOptions.fWireframeMode = !
params.fGrContextOptions.fWireframeMode;
680 fCommands.
addCommand(
'w',
"Modes",
"Toggle reduced shaders", [
this]() {
682 params.fGrContextOptions.fReducedShaderVariations =
683 !
params.fGrContextOptions.fReducedShaderVariations;
688 this->setCurrentSlide(fCurrentSlide < fSlides.
size() - 1 ? fCurrentSlide + 1 : 0);
691 this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.
size() - 1);
694 this->changeZoomLevel(1.f / 32.f);
698 this->changeZoomLevel(-1.f / 32.f);
701 fCommands.
addCommand(
'd',
"Modes",
"Change rendering backend", [
this]() {
705#if defined(SK_BUILD_FOR_UNIX) && defined(SK_VULKAN)
706 if (newBackend == sk_app::Window::kVulkan_BackendType) {
709 }
else if (fBackendType == sk_app::Window::kVulkan_BackendType) {
710 newBackend = sk_app::Window::kVulkan_BackendType;
713 this->setBackend(newBackend);
715 fCommands.
addCommand(
'K',
"IO",
"Save slide to SKP", [
this]() {
719 fCommands.
addCommand(
'&',
"Overlays",
"Show slide dimensios", [
this]() {
720 fShowSlideDimensions = !fShowSlideDimensions;
723 fCommands.
addCommand(
'G',
"Modes",
"Geometry", [
this]() {
731 switch (
params.fSurfaceProps.pixelGeometry()) {
754 fCommands.
addCommand(
'H',
"Font",
"Hinting mode", [
this]() {
778 fCommands.
addCommand(
'D',
"Modes",
"DFT", [
this]() {
787 fCommands.
addCommand(
'L',
"Font",
"Subpixel Antialias Mode", [
this]() {
801 fFontOverrides.
fEdging =
false;
808 fCommands.
addCommand(
'S',
"Font",
"Subpixel Position Mode", [
this]() {
822 fCommands.
addCommand(
'B',
"Font",
"Baseline Snapping", [
this]() {
836 fCommands.
addCommand(
'p',
"Transform",
"Toggle Perspective Mode", [
this]() {
837 fPerspectiveMode = (kPerspective_Real == fPerspectiveMode) ? kPerspective_Fake
842 fCommands.
addCommand(
'P',
"Transform",
"Toggle Perspective", [
this]() {
843 fPerspectiveMode = (kPerspective_Off == fPerspectiveMode) ? kPerspective_Real
848 fCommands.
addCommand(
'a',
"Transform",
"Toggle Animation", [
this]() {
851 fCommands.
addCommand(
'u',
"GUI",
"Zoom UI", [
this]() {
856 fCommands.
addCommand(
'=',
"Transform",
"Apply Backing Scale", [
this]() {
857 fApplyBackingScale = !fApplyBackingScale;
860 fCommands.
addCommand(
'$',
"ViaSerialize",
"Toggle ViaSerialize", [
this]() {
861 fDrawViaSerialize = !fDrawViaSerialize;
872 fPerspectivePoints[0].
set(0, 0);
873 fPerspectivePoints[1].
set(1, 0);
874 fPerspectivePoints[2].
set(0, 1);
875 fPerspectivePoints[3].
set(1, 1);
885 this->setCurrentSlide(this->startupSlide());
891 while (
size_t bytesRead = fread(buf, 1, 4096,
fp)) {
892 stream.write(buf, bytesRead);
894 return stream.detachAsData();
913 std::string str(
reinterpret_cast<const char*
>(
data->data()),
data->size());
914 std::regex re(
"data:image/png;base64,([a-zA-Z0-9+/=]+)");
915 std::sregex_iterator images_begin(str.begin(), str.end(), re);
916 std::sregex_iterator images_end;
917 std::vector<sk_sp<SkImage>>
images;
919 for (
auto iter = images_begin; iter != images_end; ++iter) {
920 const std::smatch&
match = *iter;
934void Viewer::initSlides() {
936 static const struct {
937 const char* fExtension;
938 const char* fDirName;
940 const SlideMaker fFactory;
941 } gExternalSlidesInfo[] = {
942 {
".mskp",
"mskp-dir", FLAGS_mskps,
944 return sk_make_sp<MSKPSlide>(
name,
path);}
946 {
".skp",
"skp-dir", FLAGS_skps,
948 return sk_make_sp<SKPSlide>(
name,
path);}
950 {
".jpg",
"jpg-dir", FLAGS_jpgs,
952 return sk_make_sp<ImageSlide>(
name,
path);}
954 {
".jxl",
"jxl-dir", FLAGS_jxls,
956 return sk_make_sp<ImageSlide>(
name,
path);}
958#if defined(SK_ENABLE_SKOTTIE)
959 {
".json",
"skottie-dir", FLAGS_lotties,
961 return sk_make_sp<SkottieSlide>(
name,
path);}
965#if defined(SK_ENABLE_SVG)
966 {
".svg",
"svg-dir", FLAGS_svgs,
968 return sk_make_sp<SvgSlide>(
name,
path);}
980 if (
auto slide = fact(
name,
path)) {
986 if (!FLAGS_file.isEmpty()) {
991 if (
file.equals(
"stdin")) {
997 char imageID =
'A' + fSlides.
size();
1001 if (!fSlides.
empty()) {
1002 fShowZoomWindow =
true;
1008 for (
const auto& sinfo : gExternalSlidesInfo) {
1009 if (
file.endsWith(sinfo.fExtension)) {
1015 fprintf(stderr,
"Unsupported file type \"%s\"\n",
file.c_str());
1017 fprintf(stderr,
"Cannot read \"%s\"\n",
file.c_str());
1024 if (!FLAGS_bisect.isEmpty()) {
1027 if (FLAGS_bisect.size() >= 2) {
1028 for (
const char* ch = FLAGS_bisect[1]; *ch; ++ch) {
1029 bisect->onChar(*ch);
1037 int firstGM = fSlides.
size();
1039 std::unique_ptr<skiagm::GM> gm = gmFactory();
1041 auto slide = sk_make_sp<GMSlide>(std::move(gm));
1051 int firstRegisteredSlide = fSlides.
size();
1061 std::sort(fSlides.
begin() + firstRegisteredSlide, fSlides.
end(), orderBySlideName);
1065 auto slide = sk_make_sp<SkSLSlide>();
1073 auto slide = sk_make_sp<SkSLDebuggerSlide>();
1079 for (
const auto&
info : gExternalSlidesInfo) {
1080 for (
const auto&
flag :
info.fFlags) {
1089 while (it.next(&
name)) {
1092 if (sortedFilenames.
size()) {
1095 return strcmp(a.c_str(), b.c_str()) < 0;
1098 for (
const SkString& filename : sortedFilenames) {
1103 if (!dirSlides.
empty()) {
1106 std::move(dirSlides)));
1112 if (fSlides.
empty()) {
1113 auto slide = sk_make_sp<NullSlide>();
1120 for(
auto& slide : fSlides) {
1121 slide->gpuTeardown();
1148void Viewer::updateTitle() {
1157 title.append(fSlides[fCurrentSlide]->getName());
1159 if (fDrawViaSerialize) {
1160 title.append(
" <serialize>");
1164 auto paintFlag = [
this, &paintTitle](
bool SkPaintFields::*
flag,
1165 bool (
SkPaint::* isFlag)()
const,
1166 const char* on,
const char* off)
1168 if (fPaintOverrides.*
flag) {
1169 paintTitle.append((fPaint.*isFlag)() ? on : off);
1173 auto fontFlag = [
this, &paintTitle](
bool SkFontFields::*
flag, bool (
SkFont::* isFlag)()
const,
1174 const char* on,
const char* off)
1176 if (fFontOverrides.*
flag) {
1177 paintTitle.append((fFont.*isFlag)() ? on : off);
1185 "Force Autohint",
"No Force Autohint");
1189 "Linear Metrics",
"Non-Linear Metrics");
1191 "Bitmap Text",
"No Bitmap Text");
1197 paintTitle.append(
"Alias Text");
1200 paintTitle.append(
"Antialias Text");
1203 paintTitle.append(
"Subpixel Antialias Text");
1211 paintTitle.append(
"No Hinting");
1214 paintTitle.append(
"Slight Hinting");
1217 paintTitle.append(
"Normal Hinting");
1220 paintTitle.append(
"Full Hinting");
1226 switch (fColorMode) {
1227 case ColorMode::kLegacy:
1228 title.append(
" Legacy 8888");
1230 case ColorMode::kColorManaged8888:
1231 title.append(
" ColorManaged 8888");
1233 case ColorMode::kColorManagedF16:
1234 title.append(
" ColorManaged F16");
1236 case ColorMode::kColorManagedF16Norm:
1237 title.append(
" ColorManaged F16 Norm");
1241 if (ColorMode::kLegacy != fColorMode) {
1242 int curPrimaries = -1;
1249 title.appendf(
" %s Gamma %f",
1251 fColorSpaceTransferFn.
g);
1256 switch (
params.fSurfaceProps.pixelGeometry()) {
1258 title.append(
" Flat");
1261 title.append(
" RGB");
1264 title.append(
" BGR");
1267 title.append(
" RGBV");
1270 title.append(
" BGRV");
1275 if (
params.fSurfaceProps.isUseDeviceIndependentFonts()) {
1276 title.append(
" DFT");
1283 title.appendf(
" MSAA: %i", msaa);
1288#if defined(SK_GRAPHITE)
1291 .fGraphiteContextOptions.fPriv.fPathRendererStrategy;
1293 title.appendf(
" [Path renderer strategy: %s]",
1294 get_path_renderer_strategy_string(strategy));
1305 if (kPerspective_Real == fPerspectiveMode) {
1306 title.append(
" Perspective (Real)");
1307 }
else if (kPerspective_Fake == fPerspectiveMode) {
1308 title.append(
" Perspective (Fake)");
1314int Viewer::startupSlide()
const {
1316 if (!FLAGS_slide.isEmpty()) {
1319 if (fSlides[
i]->getName().
equals(FLAGS_slide[0])) {
1324 fprintf(stderr,
"Unknown slide \"%s\"\n", FLAGS_slide[0]);
1331void Viewer::listNames()
const {
1333 for (
const auto& slide : fSlides) {
1334 SkDebugf(
" %s\n", slide->getName().c_str());
1338void Viewer::setCurrentSlide(
int slide) {
1341 if (slide == fCurrentSlide) {
1345 if (fCurrentSlide >= 0) {
1346 fSlides[fCurrentSlide]->unload();
1350 if (fApplyBackingScale) {
1355 fCurrentSlide = slide;
1356 this->setupCurrentSlide();
1359SkISize Viewer::currentSlideSize()
const {
1360 if (
auto size = fSlides[fCurrentSlide]->getDimensions(); !
size.isEmpty()) {
1366void Viewer::setupCurrentSlide() {
1367 if (fCurrentSlide >= 0) {
1370 fDefaultMatrix.
reset();
1377 if (windowRect.
width() > 0 && windowRect.
height() > 0) {
1384 fGesture.
setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
1386 this->updateTitle();
1387 this->updateUIState();
1395#define MAX_ZOOM_LEVEL 8.0f
1396#define MIN_ZOOM_LEVEL -8.0f
1398void Viewer::changeZoomLevel(
float delta) {
1399 fZoomLevel +=
delta;
1401 this->updateGestureTransLimit();
1404void Viewer::updateGestureTransLimit() {
1408 fGesture.
setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
1411SkMatrix Viewer::computePerspectiveMatrix() {
1413 SkPoint orthoPts[4] = { { 0, 0 }, {
w, 0 }, { 0,
h }, {
w,
h } };
1415 { fPerspectivePoints[0].
fX *
w, fPerspectivePoints[0].
fY *
h },
1416 { fPerspectivePoints[1].
fX *
w, fPerspectivePoints[1].
fY *
h },
1417 { fPerspectivePoints[2].
fX *
w, fPerspectivePoints[2].
fY *
h },
1418 { fPerspectivePoints[3].
fX *
w, fPerspectivePoints[3].
fY *
h }
1421 m.setPolyToPoly(orthoPts, perspPts, 4);
1425SkMatrix Viewer::computePreTouchMatrix() {
1428 SkScalar zoomScale = exp(fZoomLevel);
1429 if (fApplyBackingScale) {
1432 m.preTranslate((fOffset.
x() - 0.5f) * 2.0f, (fOffset.
y() - 0.5f) * 2.0f);
1433 m.preScale(zoomScale, zoomScale);
1435 const SkISize slideSize = this->currentSlideSize();
1436 m.preRotate(fRotation, slideSize.
width() * 0.5f, slideSize.
height() * 0.5f);
1438 if (kPerspective_Real == fPerspectiveMode) {
1439 SkMatrix persp = this->computePerspectiveMatrix();
1440 m.postConcat(persp);
1449 m.preConcat(this->computePreTouchMatrix());
1454 fPersistentCache.
reset();
1455 fCachedShaders.
clear();
1456 fBackendType = backendType;
1459 for(
auto& slide : fSlides) {
1460 slide->gpuTeardown();
1465#if defined(SK_BUILD_FOR_WIN)
1470 fWindow = Window::CreateNativeWindow(
nullptr);
1473 fCommands.
attach(fWindow);
1490void Viewer::setColorMode(ColorMode colorMode) {
1491 fColorMode = colorMode;
1492 this->updateTitle();
1511 bool blobWillChange =
false;
1514 bool shouldDraw = this->
filterFont(&filteredFont);
1515 if (it.font() != *filteredFont || !shouldDraw) {
1516 blobWillChange =
true;
1520 if (!blobWillChange) {
1527 bool shouldDraw = this->
filterFont(&filteredFont);
1536 ?
builder.allocRunText(
font, it.glyphCount(), it.offset().x(),it.offset().y(),
1539 ?
builder.allocRunTextPosH(
font, it.glyphCount(), it.offset().y(),
1542 ?
builder.allocRunTextPos(
font, it.glyphCount(), it.textSize())
1544 ?
builder.allocRunTextRSXform(
font, it.glyphCount(), it.textSize())
1546 uint32_t glyphCount = it.glyphCount();
1548 size_t glyphSize =
sizeof(
decltype(*it.glyphs()));
1549 memcpy(runBuffer.
glyphs, it.glyphs(), glyphCount * glyphSize);
1552 size_t posSize =
sizeof(
decltype(*it.pos()));
1553 unsigned posPerGlyph = it.scalarsPerGlyph();
1554 memcpy(runBuffer.
pos, it.pos(), glyphCount * posPerGlyph * posSize);
1557 size_t textSize =
sizeof(
decltype(*it.text()));
1558 uint32_t textCount = it.textSize();
1559 memcpy(runBuffer.
utf8text, it.text(), textCount * textSize);
1561 if (it.clusters()) {
1562 size_t clusterSize =
sizeof(
decltype(*it.clusters()));
1563 memcpy(runBuffer.
clusters, it.clusters(), glyphCount * clusterSize);
1567 return cache->get();
1667 if (std::optional<SkBlendMode>
mode =
paint.asBlendMode()) {
1697 if (fCurrentSlide < 0) {
1710 if (ColorMode::kLegacy != fColorMode) {
1719 fSlides[fCurrentSlide]->draw(recorderCanvas);
1729 switch (fColorMode) {
1730 case ColorMode::kLegacy:
1731 case ColorMode::kColorManaged8888:
1734 case ColorMode::kColorManagedF16:
1737 case ColorMode::kColorManagedF16Norm:
1748 if (kPerspective_Fake == fPerspectiveMode ||
1750 fShowHistogramWindow ||
1751 Window::kRaster_BackendType == fBackendType ||
1752 colorSpace !=
nullptr ||
1759 offscreenSurface = Window::kRaster_BackendType == this->fBackendType
1763 slideSurface = offscreenSurface.
get();
1764 slideCanvas = offscreenSurface->
getCanvas();
1768 SkCanvas* recorderRestoreCanvas =
nullptr;
1769 if (fDrawViaSerialize) {
1770 recorderRestoreCanvas = slideCanvas;
1781 for (
int y = 0;
y < fWindow->
height();
y += tileH) {
1782 for (
int x = 0;
x < fWindow->
width();
x += tileW) {
1785 fSlides[fCurrentSlide]->draw(slideCanvas);
1790 if (fDrawTileBoundaries) {
1794 for (
int y = 0;
y < fWindow->
height();
y += tileH) {
1795 for (
int x = 0;
x < fWindow->
width();
x += tileW) {
1801 slideCanvas->
concat(this->computeMatrix());
1802 if (kPerspective_Real == fPerspectiveMode) {
1807 &fPaint, &fPaintOverrides,
1808 &fFont, &fFontOverrides);
1809 fSlides[fCurrentSlide]->draw(&filterCanvas);
1811 fSlides[fCurrentSlide]->draw(slideCanvas);
1814#if defined(SK_GRAPHITE)
1821 if (recorderRestoreCanvas) {
1825 slideCanvas = recorderRestoreCanvas;
1831#if defined(SK_GANESH)
1834#if defined(SK_GRAPHITE)
1835 fWindow->snapRecordingAndSubmit();
1840 if (offscreenSurface) {
1847 int prePerspectiveCount = canvas->
save();
1848 if (kPerspective_Fake == fPerspectiveMode) {
1851 canvas->
concat(this->computePerspectiveMatrix());
1857 if (fShowSlideDimensions) {
1860 canvas->
concat(this->computeMatrix());
1863 paint.setColor(0x40FFFF00);
1868 this->updateGestureTransLimit();
1872 this->setupCurrentSlide();
1887 direct->performDeferredCleanup(std::chrono::seconds(10));
1892 if (fCurrentSlide >= 0) {
1895 fSlides[fCurrentSlide]->gpuTeardown();
1898 if (fApplyBackingScale) {
1901 fSlides[fCurrentSlide]->resize(
width / scaleFactor,
height / scaleFactor);
1905SkPoint Viewer::mapEvent(
float x,
float y) {
1906 const auto m = this->computeMatrix();
1911 return inv.mapXY(
x,
y);
1915 if (GestureDevice::kMouse == fGestureDevice) {
1919 const auto slidePt = this->mapEvent(
x,
y);
1925 void* castedOwner =
reinterpret_cast<void*
>(owner);
1929#if defined(SK_BUILD_FOR_IOS)
1936 this->setCurrentSlide(fCurrentSlide < fSlides.size() - 1 ?
1937 fCurrentSlide + 1 : 0);
1939 this->setCurrentSlide(fCurrentSlide > 0 ?
1940 fCurrentSlide - 1 : fSlides.size() - 1);
1962 fGestureDevice = fGesture.
isBeingTouched() ? GestureDevice::kTouch : GestureDevice::kNone;
1968 if (GestureDevice::kTouch == fGestureDevice) {
1972 const auto slidePt = this->mapEvent(
x,
y);
1973 if (fSlides[fCurrentSlide]->
onMouse(slidePt.x(), slidePt.y(),
state, modifiers)) {
1996 fGestureDevice = fGesture.
isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
2018 this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.size() - 1);
2021 this->setCurrentSlide(fCurrentSlide < fSlides.size() - 1 ? fCurrentSlide + 1 : 0);
2053 dc.
fDrawList->AddImage(gamutPaint, dc.fPos,
2054 ImVec2(dc.fPos.x + dc.fSize.x, dc.fPos.y + dc.fSize.y),
2055 ImVec2(242, 61), ImVec2(1897, 1922));
2057 dc.dragPoint((
SkPoint*)(&primaries->
fRX),
true, 0xFF000040);
2058 dc.dragPoint((
SkPoint*)(&primaries->
fGX),
true, 0xFF004000);
2059 dc.dragPoint((
SkPoint*)(&primaries->
fBX),
true, 0xFF400000);
2060 dc.dragPoint((
SkPoint*)(&primaries->
fWX),
true);
2061 dc.fDrawList->AddPolyline(dc.fScreenPoints.begin(), 3, 0xFFFFFFFF,
true, 1.5f);
2075 for (
int i = 0;
i < 4; ++
i) {
2088 return std::string(
"void main() { sk_FragColor = half4(1, 0, 1, 0.5); }");
2094 size_t pos = inShader.rfind(
"return _out;\n");
2095 if (
pos == std::string::npos) {
2099 std::string replacementShader = inShader;
2100 replacementShader.insert(
pos,
"_out.sk_FragColor = float4(1.0, 0.0, 1.0, 0.5); ");
2101 return replacementShader;
2106 std::string highlight = versionDecl ? versionDecl :
"";
2108 highlight.append(
"precision mediump float;\n");
2111 "void main() { sk_FragColor = vec4(1, 0, 1, 0.5); }");
2115void Viewer::drawImGui() {
2117 if (fShowImGuiTestWindow) {
2118 ImGui::ShowDemoWindow(&fShowImGuiTestWindow);
2121 if (fShowImGuiDebugWindow) {
2124 ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
2126 bool displayParamsChanged =
false;
2127 bool uiParamsChanged =
false;
2130 if (ImGui::Begin(
"Tools", &fShowImGuiDebugWindow,
2131 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
2132 if (ImGui::CollapsingHeader(
"Backend")) {
2133 int newBackend =
static_cast<int>(fBackendType);
2136 ImGui::RadioButton(
"OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
2137#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
2139 ImGui::RadioButton(
"ANGLE", &newBackend, sk_app::Window::kANGLE_BackendType);
2142#if defined(SK_GRAPHITE)
2144 ImGui::RadioButton(
"Dawn (Graphite)", &newBackend,
2145 sk_app::Window::kGraphiteDawn_BackendType);
2148#if defined(SK_VULKAN) && !defined(SK_BUILD_FOR_MAC)
2150 ImGui::RadioButton(
"Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);
2151#if defined(SK_GRAPHITE)
2153 ImGui::RadioButton(
"Vulkan (Graphite)", &newBackend,
2154 sk_app::Window::kGraphiteVulkan_BackendType);
2157#if defined(SK_METAL)
2159 ImGui::RadioButton(
"Metal", &newBackend, sk_app::Window::kMetal_BackendType);
2160#if defined(SK_GRAPHITE)
2162 ImGui::RadioButton(
"Metal (Graphite)", &newBackend,
2163 sk_app::Window::kGraphiteMetal_BackendType);
2166#if defined(SK_DIRECT3D)
2168 ImGui::RadioButton(
"Direct3D", &newBackend, sk_app::Window::kDirect3D_BackendType);
2170 if (newBackend != fBackendType) {
2171 fDeferredActions.
push_back([newBackend,
this]() {
2177 bool* wire = &
params.fGrContextOptions.fWireframeMode;
2178 if (ImGui::Checkbox(
"Wireframe Mode", wire)) {
2179 displayParamsChanged =
true;
2182 bool* reducedShaders = &
params.fGrContextOptions.fReducedShaderVariations;
2183 if (ImGui::Checkbox(
"Reduced shaders", reducedShaders)) {
2184 displayParamsChanged =
true;
2195 ImGui::Text(
"MSAA: ");
2197 for (
int curMSAA = 1; curMSAA <= maxMSAA; curMSAA *= 2) {
2205 &sampleCount, curMSAA);
2209 if (sampleCount !=
params.fMSAASampleCount) {
2210 params.fMSAASampleCount = sampleCount;
2211 displayParamsChanged =
true;
2215 int pixelGeometryIdx = 0;
2217 pixelGeometryIdx =
params.fSurfaceProps.pixelGeometry() + 1;
2219 if (ImGui::Combo(
"Pixel Geometry", &pixelGeometryIdx,
2220 "Default\0Flat\0RGB\0BGR\0RGBV\0BGRV\0\0"))
2223 if (pixelGeometryIdx == 0) {
2229 SkPixelGeometry pixelGeometry = SkTo<SkPixelGeometry>(pixelGeometryIdx - 1);
2232 displayParamsChanged =
true;
2235 bool useDFT =
params.fSurfaceProps.isUseDeviceIndependentFonts();
2236 if (ImGui::Checkbox(
"DFT", &useDFT)) {
2245 displayParamsChanged =
true;
2248 if (ImGui::TreeNode(
"Path Renderers")) {
2251#if defined(SK_GRAPHITE)
2254 &
params.fGraphiteContextOptions.fPriv;
2257 if (ImGui::RadioButton(get_path_renderer_strategy_string(
s),
2261 displayParamsChanged =
true;
2269 PathRendererStrategy::kComputeAnalyticAA,
2270 PathRendererStrategy::kComputeMSAA16,
2271 PathRendererStrategy::kComputeMSAA8,
2272 PathRendererStrategy::kRasterAA,
2273 PathRendererStrategy::kTessellation,
2276 if (gctx->
priv().supportsPathRendererStrategy(strategies[
i])) {
2277 prsButton(strategies[
i]);
2286 if (
x !=
params.fGrContextOptions.fGpuPathRenderers) {
2287 params.fGrContextOptions.fGpuPathRenderers =
x;
2288 displayParamsChanged =
true;
2294#if defined(SK_GANESH)
2296 const auto* caps = ctx->
priv().
caps();
2311 ImGui::RadioButton(
"Software",
true);
2317 if (ImGui::CollapsingHeader(
"Tiling")) {
2318 ImGui::Checkbox(
"Enable", &fTiled);
2319 ImGui::Checkbox(
"Draw Boundaries", &fDrawTileBoundaries);
2320 ImGui::SliderFloat(
"Horizontal", &fTileScale.
fWidth, 0.1f, 1.0f);
2321 ImGui::SliderFloat(
"Vertical", &fTileScale.
fHeight, 0.1f, 1.0f);
2324 if (ImGui::CollapsingHeader(
"Transform")) {
2325 if (ImGui::Checkbox(
"Apply Backing Scale", &fApplyBackingScale)) {
2326 this->updateGestureTransLimit();
2330 uiParamsChanged =
true;
2333 float zoom = fZoomLevel;
2336 this->updateGestureTransLimit();
2337 uiParamsChanged =
true;
2339 float deg = fRotation;
2340 if (ImGui::SliderFloat(
"Rotate", °, -30, 360,
"%.3f deg")) {
2342 this->updateGestureTransLimit();
2343 uiParamsChanged =
true;
2345 if (ImGui::CollapsingHeader(
"Subpixel offset", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
2347 this->updateGestureTransLimit();
2348 uiParamsChanged =
true;
2350 }
else if (fOffset !=
SkVector{0.5f, 0.5f}) {
2351 this->updateGestureTransLimit();
2352 uiParamsChanged =
true;
2353 fOffset = {0.5f, 0.5f};
2355 int perspectiveMode =
static_cast<int>(fPerspectiveMode);
2356 if (ImGui::Combo(
"Perspective", &perspectiveMode,
"Off\0Real\0Fake\0\0")) {
2357 fPerspectiveMode =
static_cast<PerspectiveMode
>(perspectiveMode);
2358 this->updateGestureTransLimit();
2359 uiParamsChanged =
true;
2361 if (perspectiveMode != kPerspective_Off &&
ImGui_DragQuad(fPerspectivePoints)) {
2362 this->updateGestureTransLimit();
2363 uiParamsChanged =
true;
2367 if (ImGui::CollapsingHeader(
"Paint")) {
2368 auto paintFlag = [
this, &uiParamsChanged](
const char* label,
const char* items,
2369 bool SkPaintFields::*
flag,
2370 bool (
SkPaint::* isFlag)()
const,
2371 void (
SkPaint::* setFlag)(bool) )
2374 if (fPaintOverrides.*
flag) {
2375 itemIndex = (fPaint.*isFlag)() ? 2 : 1;
2377 if (ImGui::Combo(label, &itemIndex, items)) {
2378 if (itemIndex == 0) {
2379 fPaintOverrides.*
flag =
false;
2381 fPaintOverrides.*
flag =
true;
2382 (fPaint.*setFlag)(itemIndex == 2);
2384 uiParamsChanged =
true;
2388 paintFlag(
"Antialias",
2389 "Default\0No AA\0AA\0\0",
2394 "Default\0No Dither\0Dither\0\0",
2399 if (fPaintOverrides.
fStyle) {
2400 styleIdx = SkTo<int>(fPaint.
getStyle()) + 1;
2402 if (ImGui::Combo(
"Style", &styleIdx,
2403 "Default\0Fill\0Stroke\0Stroke and Fill\0\0"))
2405 if (styleIdx == 0) {
2406 fPaintOverrides.
fStyle =
false;
2409 fPaint.
setStyle(SkTo<SkPaint::Style>(styleIdx - 1));
2410 fPaintOverrides.
fStyle =
true;
2412 uiParamsChanged =
true;
2417 ImGui::Checkbox(
"Override Stroke Width", &fPaintOverrides.
fStrokeWidth);
2420 if (ImGui::SliderFloat(
"Stroke Width", &
width, 0, 20)) {
2422 uiParamsChanged =
true;
2426 ImGui::Checkbox(
"Override Miter Limit", &fPaintOverrides.
fMiterLimit);
2429 if (ImGui::SliderFloat(
"Miter Limit", &miterLimit, 0, 20)) {
2431 uiParamsChanged =
true;
2439 if (ImGui::Combo(
"Cap Type", &capIdx,
2440 "Default\0Butt\0Round\0Square\0\0"))
2449 uiParamsChanged =
true;
2456 if (ImGui::Combo(
"Join Type", &joinIdx,
2457 "Default\0Miter\0Round\0Bevel\0\0"))
2466 uiParamsChanged =
true;
2470 if (ImGui::CollapsingHeader(
"Font")) {
2473 hintingIdx = SkTo<int>(fFont.
getHinting()) + 1;
2475 if (ImGui::Combo(
"Hinting", &hintingIdx,
2476 "Default\0None\0Slight\0Normal\0Full\0\0"))
2478 if (hintingIdx == 0) {
2482 fFont.
setHinting(SkTo<SkFontHinting>(hintingIdx - 1));
2485 uiParamsChanged =
true;
2488 auto fontFlag = [
this, &uiParamsChanged](
const char* label,
const char* items,
2489 bool SkFontFields::*
flag,
2490 bool (
SkFont::* isFlag)()
const,
2491 void (
SkFont::* setFlag)(bool) )
2494 if (fFontOverrides.*
flag) {
2495 itemIndex = (fFont.*isFlag)() ? 2 : 1;
2497 if (ImGui::Combo(label, &itemIndex, items)) {
2498 if (itemIndex == 0) {
2499 fFontOverrides.*
flag =
false;
2501 fFontOverrides.*
flag =
true;
2502 (fFont.*setFlag)(itemIndex == 2);
2504 uiParamsChanged =
true;
2508 fontFlag(
"Fake Bold Glyphs",
2509 "Default\0No Fake Bold\0Fake Bold\0\0",
2513 fontFlag(
"Baseline Snapping",
2514 "Default\0No Baseline Snapping\0Baseline Snapping\0\0",
2518 fontFlag(
"Linear Text",
2519 "Default\0No Linear Text\0Linear Text\0\0",
2523 fontFlag(
"Subpixel Position Glyphs",
2524 "Default\0Pixel Text\0Subpixel Text\0\0",
2528 fontFlag(
"Embedded Bitmap Text",
2529 "Default\0No Embedded Bitmaps\0Embedded Bitmaps\0\0",
2533 fontFlag(
"Force Auto-Hinting",
2534 "Default\0No Force Auto-Hinting\0Force Auto-Hinting\0\0",
2540 edgingIdx = SkTo<int>(fFont.
getEdging()) + 1;
2542 if (ImGui::Combo(
"Edging", &edgingIdx,
2543 "Default\0Alias\0Antialias\0Subpixel Antialias\0\0"))
2545 if (edgingIdx == 0) {
2546 fFontOverrides.
fEdging =
false;
2549 fFont.
setEdging(SkTo<SkFont::Edging>(edgingIdx-1));
2550 fFontOverrides.
fEdging =
true;
2552 uiParamsChanged =
true;
2555 ImGui::Checkbox(
"Override Size", &fFontOverrides.
fSize);
2556 if (fFontOverrides.
fSize) {
2557 ImGui::DragFloat2(
"TextRange", fFontOverrides.
fSizeRange,
2558 0.001f, -10.0f, 300.0f,
"%.6f", ImGuiSliderFlags_Logarithmic);
2559 float textSize = fFont.
getSize();
2560 if (ImGui::DragFloat(
"TextSize", &textSize, 0.001f,
2563 "%.6f", ImGuiSliderFlags_Logarithmic))
2566 uiParamsChanged =
true;
2570 ImGui::Checkbox(
"Override ScaleX", &fFontOverrides.
fScaleX);
2575 uiParamsChanged =
true;
2579 ImGui::Checkbox(
"Override SkewX", &fFontOverrides.
fSkewX);
2580 if (fFontOverrides.
fSkewX) {
2584 uiParamsChanged =
true;
2591 if (fSlides[fCurrentSlide]->onGetControls(&controls)) {
2592 if (ImGui::CollapsingHeader(
"Current Slide")) {
2602 if (ImGui::SliderFloat(
name, &val[0], val[1], val[2])) {
2609 if (ImGui::Checkbox(
name, &val)) {
2614 fSlides[fCurrentSlide]->onSetControls(controls);
2619 if (fShowSlidePicker) {
2620 ImGui::SetNextTreeNodeOpen(
true);
2622 if (ImGui::CollapsingHeader(
"Slide")) {
2623 static ImGuiTextFilter filter;
2624 static ImVector<const char*> filteredSlideNames;
2625 static ImVector<int> filteredSlideIndices;
2627 if (fShowSlidePicker) {
2628 ImGui::SetKeyboardFocusHere();
2629 fShowSlidePicker =
false;
2633 filteredSlideNames.clear();
2634 filteredSlideIndices.clear();
2635 int filteredIndex = 0;
2636 for (
int i = 0;
i < fSlides.size(); ++
i) {
2637 const char* slideName = fSlides[
i]->getName().c_str();
2638 if (filter.PassFilter(slideName) ||
i == fCurrentSlide) {
2639 if (
i == fCurrentSlide) {
2640 filteredIndex = filteredSlideIndices.size();
2642 filteredSlideNames.push_back(slideName);
2643 filteredSlideIndices.push_back(
i);
2647 if (ImGui::ListBox(
"", &filteredIndex, filteredSlideNames.begin(),
2648 filteredSlideNames.size(), 20)) {
2649 this->setCurrentSlide(filteredSlideIndices[filteredIndex]);
2653 if (ImGui::CollapsingHeader(
"Color Mode")) {
2654 ColorMode newMode = fColorMode;
2655 auto cmButton = [&](ColorMode
mode,
const char* label) {
2656 if (ImGui::RadioButton(label,
mode == fColorMode)) {
2661 cmButton(ColorMode::kLegacy,
"Legacy 8888");
2662 cmButton(ColorMode::kColorManaged8888,
"Color Managed 8888");
2663 cmButton(ColorMode::kColorManagedF16,
"Color Managed F16");
2664 cmButton(ColorMode::kColorManagedF16Norm,
"Color Managed F16 Norm");
2666 if (newMode != fColorMode) {
2667 this->setColorMode(newMode);
2671 int primariesIdx = 4;
2680 ImGui::SliderFloat(
"Gamma", &fColorSpaceTransferFn.
g, 0.5f, 3.5f);
2682 if (ImGui::Combo(
"Primaries", &primariesIdx,
2683 "sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
2684 if (primariesIdx >= 0 && primariesIdx <= 3) {
2689 if (ImGui::Button(
"Spin")) {
2690 float rx = fColorSpacePrimaries.
fRX,
2691 ry = fColorSpacePrimaries.
fRY;
2692 fColorSpacePrimaries.
fRX = fColorSpacePrimaries.
fGX;
2693 fColorSpacePrimaries.
fRY = fColorSpacePrimaries.
fGY;
2694 fColorSpacePrimaries.
fGX = fColorSpacePrimaries.
fBX;
2695 fColorSpacePrimaries.
fGY = fColorSpacePrimaries.
fBY;
2696 fColorSpacePrimaries.
fBX = rx;
2697 fColorSpacePrimaries.
fBY = ry;
2704 if (ImGui::CollapsingHeader(
"Animation")) {
2706 if (ImGui::Checkbox(
"Pause", &isPaused)) {
2710 float speed = fAnimTimer.
getSpeed();
2711 if (ImGui::DragFloat(
"Speed", &speed, 0.1f)) {
2716 if (ImGui::CollapsingHeader(
"Shaders")) {
2717 bool sksl =
params.fGrContextOptions.fShaderCacheStrategy ==
2720#if defined(SK_VULKAN)
2721 const bool isVulkan = fBackendType == sk_app::Window::kVulkan_BackendType;
2723 const bool isVulkan =
false;
2728 static bool gLoadPending =
false;
2730 fCachedShaders.
clear();
2737 CachedShader& entry(fCachedShaders.
push_back());
2741 entry.fKeyString =
hash.finish().toHexString();
2742 entry.fKeyDescription = description;
2751#if defined(SK_GRAPHITE)
2757 const skgpu::graphite::GraphicsPipeline::PipelineInfo& pipelineInfo =
2758 pipeline->getPipelineInfo();
2762 dict->
lookup(pipelineInfo.fPaintID);
2764 CachedShader& entry(fCachedShaders.
push_back());
2765 entry.fKey =
nullptr;
2766 entry.fKeyString =
SkStringPrintf(
"#%-3d RenderStep: %u, Paint: ",
2768 pipelineInfo.fRenderStepID);
2769 entry.fKeyString.append(paintKey.
toString(dict,
true));
2773 pipelineInfo.fSkSLVertexShader;
2775 pipelineInfo.fSkSLFragmentShader;
2779 pipelineInfo.fNativeVertexShader;
2781 pipelineInfo.fNativeFragmentShader;
2791 gLoadPending =
false;
2793#if defined(SK_VULKAN)
2794 if (isVulkan && !sksl) {
2796 spvtools::SpirvTools
tools(SPV_ENV_VULKAN_1_0);
2797 for (
auto& entry : fCachedShaders) {
2799 const std::string& spirv(entry.fShader[
i]);
2801 tools.Disassemble((
const uint32_t*)spirv.c_str(), spirv.size() / 4,
2803 entry.fShader[
i].assign(disasm);
2810 for (
auto& entry : fCachedShaders) {
2820 bool doView = ImGui::Button(
"View"); ImGui::SameLine();
2821 bool doApply =
false;
2822 bool doDump =
false;
2825 doApply = ImGui::Button(
"Apply Changes"); ImGui::SameLine();
2826 doDump = ImGui::Button(
"Dump SkSL to resources/sksl/");
2828 int newOptLevel = fOptLevel;
2829 ImGui::RadioButton(
"SkSL", &newOptLevel, kShaderOptLevel_Source);
2831 ImGui::RadioButton(
"Compile", &newOptLevel, kShaderOptLevel_Compile);
2833 ImGui::RadioButton(
"Optimize", &newOptLevel, kShaderOptLevel_Optimize);
2835 ImGui::RadioButton(
"Inline", &newOptLevel, kShaderOptLevel_Inline);
2839 static bool sDoDeferredView =
false;
2840 if (doView || doDump || newOptLevel != fOptLevel) {
2841 sksl = doDump || (newOptLevel == kShaderOptLevel_Source);
2842 fOptLevel = (ShaderOptLevel)newOptLevel;
2843 switch (fOptLevel) {
2844 case kShaderOptLevel_Source:
2848 case kShaderOptLevel_Compile:
2852 case kShaderOptLevel_Optimize:
2856 case kShaderOptLevel_Inline:
2862 params.fGrContextOptions.fShaderCacheStrategy =
2865 displayParamsChanged =
true;
2867 fDeferredActions.
push_back([doDump,
this]() {
2869 fPersistentCache.
reset();
2870 sDoDeferredView =
true;
2875 this->dumpShadersToResources();
2881 ImGui::BeginChild(
"##ScrollingRegion");
2882 for (
auto& entry : fCachedShaders) {
2883 bool inTreeNode = ImGui::TreeNode(entry.fKeyString.c_str());
2884 bool hovered = ImGui::IsItemHovered();
2885 if (hovered != entry.fHovered) {
2887 entry.fHovered = hovered;
2891 auto stringBox = [](
const char* label, std::string* str) {
2894 ImVec2 boxSize(-1.0f, ImGui::GetTextLineHeight() *
std::min(
lines, 30));
2895 ImGui::InputTextMultiline(label, str, boxSize);
2897 if (ImGui::TreeNode(
"Key")) {
2898 ImGui::TextWrapped(
"%s", entry.fKeyDescription.c_str());
2908 if (doView || sDoDeferredView) {
2909 fPersistentCache.
reset();
2911 ctx->
priv().
getGpu()->resetShaderCacheForTesting();
2913#if defined(SK_GRAPHITE)
2918 gLoadPending =
true;
2919 sDoDeferredView =
false;
2924 if (isVulkan && !sksl) {
2927 if (ctx && doApply) {
2928 fPersistentCache.
reset();
2929 ctx->
priv().
getGpu()->resetShaderCacheForTesting();
2930 for (
auto& entry : fCachedShaders) {
2932 if (entry.fHovered) {
2936 switch (entry.fShaderType) {
2957 fPersistentCache.
store(*entry.fKey, *
data, entry.fKeyDescription);
2964 if (displayParamsChanged || uiParamsChanged) {
2966 if (displayParamsChanged) {
2970 this->updateTitle();
2977 ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
2978 ImGui::Begin(
"Shader Errors",
nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
2983 ImGui::TextWrapped(
"%4i\t%s\n", lineNumber, lineText);
2990 if (fShowZoomWindow && fLastImage) {
2991 ImGui::SetNextWindowSize(ImVec2(200, 200), ImGuiCond_FirstUseEver);
2992 if (ImGui::Begin(
"Zoom", &fShowZoomWindow)) {
2993 static int zoomFactor = 8;
2994 if (ImGui::Button(
"<<")) {
2995 zoomFactor =
std::max(zoomFactor / 2, 4);
2997 ImGui::SameLine(); ImGui::Text(
"%2d", zoomFactor); ImGui::SameLine();
2998 if (ImGui::Button(
">>")) {
2999 zoomFactor =
std::min(zoomFactor * 2, 32);
3002 if (!fZoomWindowFixed) {
3003 ImVec2 mousePos = ImGui::GetMousePos();
3004 fZoomWindowLocation =
SkPoint::Make(mousePos.x, mousePos.y);
3010 ImVec2 avail = ImGui::GetContentRegionAvail();
3014 bool didGraphiteRead =
false;
3016#if defined(GRAPHITE_TEST_UTILS)
3021 didGraphiteRead = fLastImage->readPixelsGraphite(fWindow->
graphiteRecorder(),
3025 pixel = *pixels.
addr32();
3027 ImGui::Text(
"(X, Y): %d, %d RGBA: %X %X %X %X",
3041 ImGui::Text(
"(X, Y): %d, %d RGBA: %X %X %X %X",
3046 if (!didGraphiteRead) {
3048 ImGui::Text(
"Failed to readPixels");
3055 c->
scale(zoomFactor, zoomFactor);
3056 c->
translate(avail.x * 0.5f / zoomFactor -
x - 0.5f,
3057 avail.y * 0.5f / zoomFactor -
y - 0.5f);
3069 if (fShowHistogramWindow && fLastImage) {
3070 ImGui::SetNextWindowSize(ImVec2(450, 500));
3071 ImGui::SetNextWindowBgAlpha(0.5f);
3072 if (ImGui::Begin(
"Color Histogram (R,G,B)", &fShowHistogramWindow)) {
3078 info.minRowBytes(), 0, 0)) {
3079 std::vector<float> r(256), g(256),
b(256);
3080 for (
int y = 0;
y <
info.height(); ++
y) {
3081 for (
int x = 0;
x <
info.width(); ++
x) {
3082 const auto pmc = *pixmap.
addr32(
x,
y);
3089 ImGui::PushItemWidth(-1);
3090 ImGui::PlotHistogram(
"R", r.data(), r.size(), 0,
nullptr,
3091 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3092 ImGui::PlotHistogram(
"G", g.data(), g.size(), 0,
nullptr,
3093 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3094 ImGui::PlotHistogram(
"B",
b.data(),
b.size(), 0,
nullptr,
3095 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3096 ImGui::PopItemWidth();
3104void Viewer::dumpShadersToResources() {
3107 std::vector<const CachedShader*> shaders;
3108 shaders.reserve(fCachedShaders.size());
3109 for (
const CachedShader& shader : fCachedShaders) {
3110 shaders.push_back(&shader);
3113 std::sort(shaders.begin(), shaders.end(), [](
const CachedShader*
a,
const CachedShader*
b) {
3114 return std::tie(a->fShader[kFragment_GrShaderType], a->fShader[kVertex_GrShaderType]) <
3115 std::tie(b->fShader[kFragment_GrShaderType], b->fShader[kVertex_GrShaderType]);
3121 fSlides[fCurrentSlide]->getName().c_str());
3128 for (
const auto& entry : shaders) {
3155 actionsToRun.swap(fDeferredActions);
3157 for (
const auto& fn : actionsToRun) {
3163 bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer.
nanos());
3166 ImGuiIO& io = ImGui::GetIO();
3171 if (animateWantsInval || fStatsLayer.
getActive() || fRefresh ||
3172 io.MetricsActiveWindows > 1 || io.MetricsRenderWindows > 0) {
3177template <
typename OptionsFunc>
3179 OptionsFunc&& optionsFunc) {
3187 optionsFunc(writer);
3195void Viewer::updateUIState() {
3205 writer.beginArray();
3210 for(
const auto& slide : fSlides) {
3228 writer.appendS32(0);
3230 if (sk_app::Window::kRaster_BackendType == fBackendType) {
3234 for (
int msaa : {4, 8, 16}) {
3241 GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
3244 auto ctx = fWindow->directContext();
3249#if defined(SK_GANESH)
3250 if (fWindow->sampleCount() > 1 || FLAGS_dmsaa) {
3251 const auto* caps = ctx->priv().caps();
3252 if (skgpu::ganesh::AtlasPathRenderer::IsSupported(ctx)) {
3253 writer.appendString(gGaneshPathRendererNames[GpuPathRenderers::kAtlas]);
3260 if (1 == fWindow->sampleCount()) {
3261 writer.appendString(gGaneshPathRendererNames[GpuPathRenderers::kSmall]);
3272 for (
const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
3273 writer.appendString(softkey);
3283 const SkString cstring(
static_cast<const char*
>(
data->data()),
data->size());
3285 fWindow->setUIState(cstring.c_str());
3294 for (
int i = 0;
i < fSlides.size(); ++
i) {
3295 if (fSlides[
i]->getName().
equals(stateValue)) {
3296 this->setCurrentSlide(
i);
3306 if (fBackendType !=
i) {
3307 fBackendType = backendType;
3308 for(
auto& slide : fSlides) {
3309 slide->gpuTeardown();
3319 int sampleCount = atoi(stateValue.
c_str());
3320 if (sampleCount !=
params.fMSAASampleCount) {
3321 params.fMSAASampleCount = sampleCount;
3324 this->updateTitle();
3325 this->updateUIState();
3330 if (pair.second == stateValue.
c_str()) {
3331 if (
params.fGrContextOptions.fGpuPathRenderers != pair.first) {
3332 params.fGrContextOptions.fGpuPathRenderers = pair.first;
3335 this->updateTitle();
3336 this->updateUIState();
3344 this->updateUIState();
3360 if (fSlides[fCurrentSlide]->
onChar(c)) {
3364 return fCommands.
onChar(c, modifiers);
static SkM44 inv(const SkM44 &m)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
void initializeEventTracingForTools(const char *traceFlag)
for(const auto glyph :glyphs)
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static const int kGrShaderTypeCount
static sk_sp< Effect > Create()
void SetResourcePath(const char *resource)
SkString GetResourcePath(const char *resource)
sk_sp< SkBlender > GetRuntimeBlendForBlendMode(SkBlendMode mode)
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
#define SkASSERT_RELEASE(cond)
#define SkDEBUGFAILF(fmt,...)
#define SkGetPackedB32(packed)
#define SkGetPackedR32(packed)
#define SkGetPackedA32(packed)
#define SkGetPackedG32(packed)
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
@ kRGBA_F16Norm_SkColorType
pixel with half floats in [0,1] for red, green, blue, alpha;
constexpr SkColor SK_ColorMAGENTA
constexpr SkColor SK_ColorRED
constexpr SkColor SK_ColorGREEN
constexpr SkColor SK_ColorWHITE
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
@ kNormal
glyph outlines modified to improve constrast
@ kNone
glyph outlines unchanged
@ kSlight
minimal modification to improve constrast
@ kFull
modifies glyph outlines for maximum constrast
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static SkImage_Base * as_IB(SkImage *image)
bool sk_mkdir(const char *path)
FILE * sk_fopen(const char path[], SkFILE_Flags)
size_t sk_fwrite(const void *buffer, size_t byteCount, FILE *)
bool sk_exists(const char *path, SkFILE_Flags=(SkFILE_Flags) 0)
static std::vector< SkPDFIndirectReference > sort(const THashSet< SkPDFIndirectReference > &src)
static uint32_t hash(const SkShaderBase::GradientInfo &v)
bool equals(SkDrawable *a, SkDrawable *b)
#define SkScalarRoundToInt(x)
#define SkScalarCeilToInt(x)
bool SkStrEndsWith(const char string[], const char suffixStr[])
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
@ kUnknown_SkPixelGeometry
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
void SkTQSort(T *begin, T *end, const C &lessThan)
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Slide *(*)() SlideFactory
static SkColorSpacePrimaries gSrgbPrimaries
static void WriteStateObject(SkJSONWriter &writer, const char *name, const char *value, OptionsFunc &&optionsFunc)
static std::map< GpuPathRenderers, std::string > gGaneshPathRendererNames
static const char kSoftkeyHint[]
static void ImGui_Primaries(SkColorSpacePrimaries *primaries, SkPaint *gamutPaint)
static const char kName[]
static const char kValue[]
static SkColorSpacePrimaries gAdobePrimaries
static SkSerialProcs serial_procs_using_png()
static DEFINE_string(slide, "", "Start on this sample.")
static CapturingShaderErrorHandler gShaderErrorHandler
const char * get_backend_string(sk_app::Window::BackendType type)
static sk_sp< SkData > base64_string_to_data(const std::string &s)
static std::string build_metal_highlight_shader(const std::string &inShader)
static Window::BackendType backend_type_for_window(Window::BackendType backendType)
static DEFINE_bool(list, false, "List samples?")
static bool primaries_equal(const SkColorSpacePrimaries &a, const SkColorSpacePrimaries &b)
static bool ImGui_DragLocation(SkPoint *pt)
static const char kOptions[]
static bool ImGui_DragQuad(SkPoint *pts)
static DEFINE_int_2(threads, j, -1, "Run threadsafe tests on a threadpool with this many extra threads, " "defaulting to one extra thread per core.")
static SkColorSpacePrimaries gRec2020Primaries
static sk_sp< SkData > data_from_file(FILE *fp)
static std::string build_glsl_highlight_shader(const GrShaderCaps &shaderCaps)
static const char kMSAAStateName[]
static SkColorSpacePrimaries gP3Primaries
static bool is_graphite_backend_type(sk_app::Window::BackendType type)
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".")
static const char kPathRendererStateName[]
static std::vector< sk_sp< SkImage > > find_data_uri_images(sk_sp< SkData > data)
struct NamedPrimaries gNamedPrimaries[]
static const char kRefreshStateName[]
static const char kBackendStateName[]
static sk_app::Window::BackendType get_backend_type(const char *str)
static std::string build_sksl_highlight_shader()
static const char kSlideStateName[]
static DEFINE_int(msaa, 1, "Number of subpixel samples. 0 for no HW antialiasing.")
static const char kSoftkeyStateName[]
static void draw(SkCanvas *canvas, SkRect &target, int x, int y)
void setSpeed(float speed)
static sk_sp< BisectSlide > Create(const char filepath[])
void compileError(const char *shader, const char *errors) override
TArray< SkString > fErrors
TArray< SkString > fShaders
static bool ShouldSkip(const SkTDArray< const char * > &strings, const char *name)
static void Parse(int argc, const char *const *argv)
const GrCaps * caps() const
const GrShaderCaps * shaderCaps() const
SK_API int maxSurfaceSampleCountForColorType(SkColorType colorType) const
GrDirectContextPriv priv()
void setScaleFactor(float scaleFactor)
void skiaWidget(const ImVec2 &size, SkiaWidgetFunc func)
void onDrawGlyphRunList(const sktext::GlyphRunList &glyphRunList, const SkPaint &paint) override
bool filterFont(SkTCopyOnFirstWrite< SkFont > *font) const
Viewer::SkFontFields * fFontOverrides
Viewer::SkPaintFields * fPaintOverrides
const SkTextBlob * filterTextBlob(const SkPaint &paint, const SkTextBlob *blob, sk_sp< SkTextBlob > *cache)
void onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint) override
bool onFilter(SkPaint &paint) const override
OveridePaintFilterCanvas(SkCanvas *canvas, SkPaint *paint, Viewer::SkPaintFields *pfields, SkFont *font, Viewer::SkFontFields *ffields)
void alloc(const SkImageInfo &)
bool getProps(SkSurfaceProps *props) const
void drawRect(const SkRect &rect, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void translate(SkScalar dx, SkScalar dy)
void clear(SkColor color)
void restoreToCount(int saveCount)
void scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
void drawPicture(const SkPicture *picture)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
static sk_sp< SkColorSpace > MakeRGB(const skcms_TransferFunction &transferFn, const skcms_Matrix3x3 &toXYZ)
static sk_sp< SkData > MakeUninitialized(size_t length)
sk_sp< SkData > detachAsData()
bool isBaselineSnap() const
void setSubpixel(bool subpixel)
void setScaleX(SkScalar scaleX)
void setLinearMetrics(bool linearMetrics)
void setBaselineSnap(bool baselineSnap)
void setEdging(Edging edging)
SkFontHinting getHinting() const
void setSize(SkScalar textSize)
bool isForceAutoHinting() const
bool isLinearMetrics() const
bool isEmbeddedBitmaps() const
SkScalar getScaleX() const
SkScalar getSkewX() const
void setSkewX(SkScalar skewX)
void setForceAutoHinting(bool forceAutoHinting)
sk_sp< SkTypeface > refTypeface() const
void setHinting(SkFontHinting hintingLevel)
@ kAntiAlias
may have transparent pixels on glyph edges
@ kAlias
no transparent pixels on glyph edges
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
void setEmbolden(bool embolden)
void setEmbeddedBitmaps(bool embeddedBitmaps)
static OpenTypeSVGDecoderFactory SetOpenTypeSVGDecoderFactory(OpenTypeSVGDecoderFactory)
bool readPixels(GrDirectContext *context, const SkImageInfo &dstInfo, void *dstPixels, size_t dstRowBytes, int srcX, int srcY, CachingHint cachingHint=kAllow_CachingHint) const
void appendS32(int32_t value)
void appendNString(char const (&value)[N])
void beginArray(const char *name=nullptr, bool multiline=true)
void beginObject(const char *name=nullptr, bool multiline=true)
void appendCString(const char *value)
void appendString(const char *value, size_t size)
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
@ kStart_ScaleToFit
scales and aligns to left and top
static SkString Join(const char *rootPath, const char *relativePath)
static SkString Basename(const char *fullPath)
void onDrawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint) override
void onDrawGlyphRunList(const sktext::GlyphRunList &, const SkPaint &) override
SkScalar getStrokeMiter() const
@ kDefault_Cap
equivalent to kButt_Cap
void setStyle(Style style)
void setColor(SkColor color)
void setStrokeMiter(SkScalar miter)
sk_sp< SkShader > refShader() const
void setAntiAlias(bool aa)
sk_sp< SkImageFilter > refImageFilter() const
void setDither(bool dither)
void setStrokeCap(Cap cap)
SkBlendMode getBlendMode_or(SkBlendMode defaultMode) const
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
void setStrokeJoin(Join join)
sk_sp< SkColorFilter > refColorFilter() const
SkColor4f getColor4f() const
void setShader(sk_sp< SkShader > shader)
SkScalar getStrokeWidth() const
@ kDefault_Join
equivalent to kMiter_Join
sk_sp< SkMaskFilter > refMaskFilter() const
sk_sp< SkPathEffect > refPathEffect() const
Join getStrokeJoin() const
void setStrokeWidth(SkScalar width)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
sk_sp< SkData > serialize(const SkSerialProcs *procs=nullptr) const
static sk_sp< SkPicture > MakeFromData(const SkData *data, const SkDeserialProcs *procs=nullptr)
const uint32_t * addr32() const
void * writable_addr() const
static std::unique_ptr< SkOpenTypeSVGDecoder > Make(const uint8_t *svg, size_t svgLength)
bool equals(const SkString &) const
void append(const char text[])
const char * c_str() const
@ kUseDeviceIndependentFonts_Flag
SkPixelGeometry pixelGeometry() const
sk_sp< SkImage > makeImageSnapshot()
@ kHorizontal_Positioning
Timer addTimer(const char *label, SkColor color, SkColor labelColor=0)
void setDisplayScale(float scale)
void setTransLimit(const SkRect &contentRect, const SkRect &windowRect, const SkMatrix &preTouchM)
void touchEnd(void *owner)
bool isFling(SkPoint *dir)
void touchBegin(void *owner, float x, float y)
void touchMoved(void *owner, float x, float y)
const SkMatrix & localM()
const SkMatrix & globalM() const
void updateZoom(float scale, float startX, float startY, float lastX, float lastY)
bool onChar(SkUnichar c, skui::ModifierKey modifiers) override
static GrContextOptions::ShaderErrorHandler * ShaderErrorHandler()
bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers) override
bool onTouch(intptr_t owner, skui::InputState state, float x, float y) override
void onBackendCreated() override
bool onMouseWheel(float delta, int x, int y, skui::ModifierKey) override
bool onPinch(skui::InputState state, float scale, float x, float y) override
void onResize(int width, int height) override
Viewer(int argc, char **argv, void *platformData)
void onUIStateChanged(const SkString &stateName, const SkString &stateValue) override
void onPaint(SkSurface *) override
bool onFling(skui::InputState state) override
bool onMouse(int x, int y, skui::InputState state, skui::ModifierKey modifiers) override
void attach(Window *window)
void drawHelp(SkCanvas *canvas)
bool onChar(SkUnichar, skui::ModifierKey modifiers)
bool onKey(skui::Key key, skui::InputState state, skui::ModifierKey modifiers)
void addCommand(SkUnichar c, const char *group, const char *description, std::function< void(void)> function)
bool onSoftkey(const SkString &softkey)
void setActive(bool active)
virtual const DisplayParams & getRequestedDisplayParams()
virtual bool scaleContentToFit() const
skgpu::graphite::Context * graphiteContext() const
void pushLayer(Layer *layer)
virtual void setRequestedDisplayParams(const DisplayParams &, bool allowReattach=true)
virtual bool attach(BackendType)=0
GrDirectContext * directContext() const
virtual void setTitle(const char *)=0
virtual float scaleFactor() const
skgpu::graphite::Recorder * graphiteRecorder() const
void store(const SkData &key, const SkData &data, const SkString &description) override
void reset(T *ptr=nullptr)
static bool IsSupported(GrRecordingContext *)
static bool IsSupported(const GrCaps &)
const GlobalCache * globalCache() const
const ShaderCodeDictionary * shaderCodeDictionary() const
SkString toString(const ShaderCodeDictionary *dict, bool includeData) const
PaintParamsKey lookup(UniquePaintParamsID) const SK_EXCLUDES(fSpinLock)
sk_sp< SkTextBlob > makeBlob() const
const EmbeddedViewParams * params
FlutterSemanticsFlag flag
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Dart_NativeFunction function
static float max(float r, float g, float b)
static float min(float r, float g, float b)
std::array< MockImage, 3 > images
void RegisterAllAvailable()
void SetCtxOptions(struct GrContextOptions *)
sk_sp< SkData > PackCachedShaders(SkFourByteTag shaderType, const std::string shaders[], const SkSL::Program::Interface interfaces[], int numInterfaces, const ShaderMetadata *meta)
bool UnpackCachedShaders(SkReadBuffer *reader, std::string shaders[], SkSL::Program::Interface interfaces[], int numInterfaces, ShaderMetadata *meta)
SkFourByteTag GetType(SkReadBuffer *reader)
SK_API sk_sp< SkImage > DeferredFromEncodedData(sk_sp< SkData > encoded, std::optional< SkAlphaType > alphaType=std::nullopt)
static constexpr skcms_TransferFunction k2Dot2
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
sk_sp< const SkImage > image
sk_sp< const SkPicture > picture
SkSamplingOptions sampling
std::string void appendf(std::string *str, const char *fmt,...) SK_PRINTF_LIKE(2
std::string PrettyPrint(const std::string &string)
void VisitLineByLine(const std::string &text, const std::function< void(int lineNumber, const char *lineText)> &visitFn)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library name
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets dir
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
font
Font Metadata and Metrics.
SK_API void FlushAndSubmit(sk_sp< SkSurface >)
void Flush(sk_sp< SkSurface > surface)
std::function< std::unique_ptr< skiagm::GM >()> GMFactory
SkSamplingOptions(SkFilterMode::kLinear))
def filtered(names, to_skip)
PersistentCache * fPersistentCache
ShaderErrorHandler * fShaderErrorHandler
bool fSupportBilerpFromGlyphAtlas
ShaderCacheStrategy fShaderCacheStrategy
skia_private::STArray< 4, ImVec2, true > fScreenPoints
void dragPoint(SkPoint *p, bool tooltip=false, ImU32 color=0xFFFFFFFF)
void fillColor(ImU32 color)
SkColorSpacePrimaries * fPrimaries
static Error Decode(const void *src, size_t srcLength, void *dst, size_t *dstLength)
bool toXYZD50(skcms_Matrix3x3 *toXYZD50) const
constexpr int32_t width() const
constexpr int32_t height() const
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
SkPaintTitleUpdater(SkString *title)
void append(const char *s)
static constexpr SkPoint Make(float x, float y)
void set(float x, float y)
constexpr float y() const
constexpr float x() const
static SkRect Make(const SkISize &size)
static SkRect MakeIWH(int w, int h)
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
constexpr float height() const
constexpr float width() const
static constexpr SkRect MakeWH(float w, float h)
const char * fVersionDeclString
bool fUsesPrecisionModifiers
SkSerialImageProc fImageProc
SkScalar * pos
storage for glyph positions in run
char * utf8text
storage for text UTF-8 code units in run
SkGlyphID * glyphs
storage for glyph indexes in run
uint32_t * clusters
storage for glyph clusters (index of UTF-8 code unit)
SkSurfacePropsFields fSurfaceProps
bool overridesSomething() const
bool overridesSomething() const
PathRendererStrategy fPathRendererStrategy
SkSurfaceProps fSurfaceProps
GrContextOptions fGrContextOptions
bool fCreateProtectedNativeBackend
std::shared_ptr< const fml::Mapping > data