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
175Application* Application::Create(
int argc,
char** argv,
void* platformData) {
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
".");
255#if defined(SK_BUILD_FOR_ANDROID)
256# define PATH_PREFIX "/data/local/tmp/"
258# define PATH_PREFIX ""
268static DEFINE_string(svgs,
"",
"Directory to read SVGs from, or a single SVG file.");
270static DEFINE_string(rives,
"",
"Directory to read RIVs from, or a single .riv file.");
273 "Run threadsafe tests on a threadpool with this many extra threads, "
274 "defaulting to one extra thread per core.");
278static DEFINE_bool(offscreen,
false,
"Force rendering to an offscreen surface.");
279static DEFINE_bool(stats,
false,
"Display stats overlay on startup.");
280static DEFINE_bool(createProtected,
false,
"Create a protected native backend (e.g., in EGL).");
283static_assert(
false,
"viewer requires GL backend for raster.")
287#if defined(SK_GRAPHITE)
290 case sk_app::Window::kGraphiteDawn_BackendType:
293 case sk_app::Window::kGraphiteMetal_BackendType:
296 case sk_app::Window::kGraphiteVulkan_BackendType:
306#if defined(SK_GRAPHITE)
311 case Strategy::kDefault:
313 case Strategy::kComputeAnalyticAA:
314 return "GPU Compute AA (Analytic)";
315 case Strategy::kComputeMSAA16:
316 return "GPU Compute AA (16xMSAA)";
317 case Strategy::kComputeMSAA8:
318 return "GPU Compute AA (8xMSAA)";
319 case Strategy::kRasterAA:
320 return "CPU Raster AA";
321 case Strategy::kTessellation:
322 return "Tessellation";
329 if (0 == strcmp(str,
"default")) {
330 return Strategy::kDefault;
331 }
else if (0 == strcmp(str,
"raster")) {
332 return Strategy::kRasterAA;
333#ifdef SK_ENABLE_VELLO_SHADERS
334 }
else if (0 == strcmp(str,
"compute-analytic")) {
335 return Strategy::kComputeAnalyticAA;
336 }
else if (0 == strcmp(str,
"compute-msaa16")) {
337 return Strategy::kComputeMSAA16;
338 }
else if (0 == strcmp(str,
"compute-msaa8")) {
339 return Strategy::kComputeMSAA8;
341 }
else if (0 == strcmp(str,
"tessellation")) {
342 return Strategy::kTessellation;
344 SkDebugf(
"Unknown path renderer strategy type, %s, defaulting to default.", str);
345 return Strategy::kDefault;
352 case sk_app::Window::kNativeGL_BackendType:
return "OpenGL";
353#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
354 case sk_app::Window::kANGLE_BackendType:
return "ANGLE";
357#if defined(SK_GRAPHITE)
358 case sk_app::Window::kGraphiteDawn_BackendType:
return "Dawn (Graphite)";
362 case sk_app::Window::kVulkan_BackendType:
return "Vulkan";
363#if defined(SK_GRAPHITE)
364 case sk_app::Window::kGraphiteVulkan_BackendType:
return "Vulkan (Graphite)";
368 case sk_app::Window::kMetal_BackendType:
return "Metal";
369#if defined(SK_GRAPHITE)
370 case sk_app::Window::kGraphiteMetal_BackendType:
return "Metal (Graphite)";
374 case sk_app::Window::kDirect3D_BackendType:
return "Direct3D";
384#if defined(SK_GRAPHITE)
385 if (0 == strcmp(str,
"grdawn")) {
386 return sk_app::Window::kGraphiteDawn_BackendType;
391 if (0 == strcmp(str,
"vk")) {
392 return sk_app::Window::kVulkan_BackendType;
394#if defined(SK_GRAPHITE)
395 if (0 == strcmp(str,
"grvk")) {
396 return sk_app::Window::kGraphiteVulkan_BackendType;
400#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
401 if (0 == strcmp(str,
"angle")) {
402 return sk_app::Window::kANGLE_BackendType;
406 if (0 == strcmp(str,
"mtl")) {
407 return sk_app::Window::kMetal_BackendType;
409#if defined(SK_GRAPHITE)
410 if (0 == strcmp(str,
"grmtl")) {
411 return sk_app::Window::kGraphiteMetal_BackendType;
416 if (0 == strcmp(str,
"d3d")) {
417 return sk_app::Window::kDirect3D_BackendType;
421 if (0 == strcmp(str,
"gl")) {
422 return sk_app::Window::kNativeGL_BackendType;
423 }
else if (0 == strcmp(str,
"sw")) {
426 SkDebugf(
"Unknown backend type, %s, defaulting to sw.", str);
477 canvas->
clear(0xffff11ff);
490static const char kON[] =
"ON";
497 , fShowSlideDimensions(false)
498 , fShowImGuiDebugWindow(false)
499 , fShowSlidePicker(false)
500 , fShowImGuiTestWindow(false)
501 , fShowHistogramWindow(false)
502 , fShowZoomWindow(false)
503 , fZoomWindowFixed(false)
504 , fZoomWindowLocation{0.0f, 0.0f}
505 , fLastImage(nullptr)
508 , fColorMode(ColorMode::kLegacy)
512 , fApplyBackingScale(
true)
515 , fOffset{0.5f, 0.5f}
516 , fGestureDevice(GestureDevice::
kNone)
518 , fDrawTileBoundaries(false)
519 , fTileScale{0.25f, 0.25f}
520 , fPerspectiveMode(kPerspective_Off)
523#if defined(SK_ENABLE_SVG)
535 SkDebugf(
"Command line arguments: ");
536 for (
int i = 1; i < argc; ++i) {
542#ifdef SK_BUILD_FOR_ANDROID
550 fWindow = Window::CreateNativeWindow(platformData);
567#if defined(SK_GRAPHITE)
568 displayParams.fGraphiteContextOptions.fPriv.fPathRendererStrategy =
569 get_path_renderer_strategy_type(FLAGS_pathstrategy[0]);
573 fRefresh = FLAGS_redraw;
585 fCommands.
attach(fWindow);
591 fCommands.
addCommand(
' ',
"GUI",
"Toggle Debug GUI", [
this]() {
592 this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
596 fCommands.
addCommand(
'/',
"GUI",
"Jump to slide picker", [
this]() {
597 this->fShowImGuiDebugWindow =
true;
598 this->fShowSlidePicker =
true;
602 fCommands.
addCommand(skui::Key::kBack,
"Backspace",
"GUI",
"Jump to slide picker", [
this]() {
603 this->fShowImGuiDebugWindow =
true;
604 this->fShowSlidePicker =
true;
607 fCommands.
addCommand(
'g',
"GUI",
"Toggle GUI Demo", [
this]() {
608 this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
611 fCommands.
addCommand(
'z',
"GUI",
"Toggle zoom window", [
this]() {
612 this->fShowZoomWindow = !this->fShowZoomWindow;
615 fCommands.
addCommand(
'Z',
"GUI",
"Toggle zoom window state", [
this]() {
616 this->fZoomWindowFixed = !this->fZoomWindowFixed;
619 fCommands.
addCommand(
'v',
"Swapchain",
"Toggle vsync on/off", [
this]() {
626 fCommands.
addCommand(
'V',
"Swapchain",
"Toggle delayed acquire on/off (Metal only)", [
this]() {
633 fCommands.
addCommand(
'r',
"Redraw",
"Toggle redraw", [
this]() {
634 fRefresh = !fRefresh;
637 fCommands.
addCommand(
's',
"Overlays",
"Toggle stats display", [
this]() {
641 fCommands.
addCommand(
'0',
"Overlays",
"Reset stats", [
this]() {
646 fCommands.
addCommand(
'C',
"GUI",
"Toggle color histogram", [
this]() {
647 this->fShowHistogramWindow = !this->fShowHistogramWindow;
650 fCommands.
addCommand(
'c',
"Modes",
"Cycle color mode", [
this]() {
651 switch (fColorMode) {
652 case ColorMode::kLegacy:
653 this->setColorMode(ColorMode::kColorManaged8888);
655 case ColorMode::kColorManaged8888:
656 this->setColorMode(ColorMode::kColorManagedF16);
658 case ColorMode::kColorManagedF16:
659 this->setColorMode(ColorMode::kColorManagedF16Norm);
661 case ColorMode::kColorManagedF16Norm:
662 this->setColorMode(ColorMode::kLegacy);
666 fCommands.
addCommand(
'w',
"Modes",
"Toggle wireframe", [
this]() {
672 fCommands.
addCommand(
'w',
"Modes",
"Toggle reduced shaders", [
this]() {
675 !
params.fGrContextOptions.fReducedShaderVariations;
679 fCommands.
addCommand(skui::Key::kRight,
"Right",
"Navigation",
"Next slide", [
this]() {
680 this->setCurrentSlide(fCurrentSlide < fSlides.
size() - 1 ? fCurrentSlide + 1 : 0);
682 fCommands.
addCommand(skui::Key::kLeft,
"Left",
"Navigation",
"Previous slide", [
this]() {
683 this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.
size() - 1);
685 fCommands.
addCommand(skui::Key::kUp,
"Up",
"Transform",
"Zoom in", [
this]() {
686 this->changeZoomLevel(1.f / 32.f);
689 fCommands.
addCommand(skui::Key::kDown,
"Down",
"Transform",
"Zoom out", [
this]() {
690 this->changeZoomLevel(-1.f / 32.f);
693 fCommands.
addCommand(
'd',
"Modes",
"Change rendering backend", [
this]() {
697#if defined(SK_BUILD_FOR_UNIX) && defined(SK_VULKAN)
698 if (newBackend == sk_app::Window::kVulkan_BackendType) {
701 }
else if (fBackendType == sk_app::Window::kVulkan_BackendType) {
702 newBackend = sk_app::Window::kVulkan_BackendType;
705 this->setBackend(newBackend);
707 fCommands.
addCommand(
'K',
"IO",
"Save slide to SKP", [
this]() {
711 fCommands.
addCommand(
'&',
"Overlays",
"Show slide dimensios", [
this]() {
712 fShowSlideDimensions = !fShowSlideDimensions;
715 fCommands.
addCommand(
'G',
"Modes",
"Geometry", [
this]() {
723 switch (
params.fSurfaceProps.pixelGeometry()) {
746 fCommands.
addCommand(
'H',
"Font",
"Hinting mode", [
this]() {
770 fCommands.
addCommand(
'D',
"Modes",
"DFT", [
this]() {
779 fCommands.
addCommand(
'L',
"Font",
"Subpixel Antialias Mode", [
this]() {
793 fFontOverrides.
fEdging =
false;
800 fCommands.
addCommand(
'S',
"Font",
"Subpixel Position Mode", [
this]() {
814 fCommands.
addCommand(
'B',
"Font",
"Baseline Snapping", [
this]() {
828 fCommands.
addCommand(
'p',
"Transform",
"Toggle Perspective Mode", [
this]() {
829 fPerspectiveMode = (kPerspective_Real == fPerspectiveMode) ? kPerspective_Fake
834 fCommands.
addCommand(
'P',
"Transform",
"Toggle Perspective", [
this]() {
835 fPerspectiveMode = (kPerspective_Off == fPerspectiveMode) ? kPerspective_Real
840 fCommands.
addCommand(
'a',
"Transform",
"Toggle Animation", [
this]() {
843 fCommands.
addCommand(
'u',
"GUI",
"Zoom UI", [
this]() {
848 fCommands.
addCommand(
'$',
"ViaSerialize",
"Toggle ViaSerialize", [
this]() {
849 fDrawViaSerialize = !fDrawViaSerialize;
860 fPerspectivePoints[0].
set(0, 0);
861 fPerspectivePoints[1].
set(1, 0);
862 fPerspectivePoints[2].
set(0, 1);
863 fPerspectivePoints[3].
set(1, 1);
873 this->setCurrentSlide(this->startupSlide());
879 while (
size_t bytesRead = fread(buf, 1, 4096, fp)) {
880 stream.write(buf, bytesRead);
882 return stream.detachAsData();
892 void* rawData = decodedData->writable_data();
901 std::string str(
reinterpret_cast<const char*
>(data->data()), data->size());
902 std::regex re(
"data:image/png;base64,([a-zA-Z0-9+/=]+)");
903 std::sregex_iterator images_begin(str.begin(), str.end(), re);
904 std::sregex_iterator images_end;
905 std::vector<sk_sp<SkImage>>
images;
907 for (
auto iter = images_begin; iter != images_end; ++iter) {
908 const std::smatch&
match = *iter;
922void Viewer::initSlides() {
924 static const struct {
925 const char* fExtension;
926 const char* fDirName;
928 const SlideMaker fFactory;
929 } gExternalSlidesInfo[] = {
930 {
".mskp",
"mskp-dir", FLAGS_mskps,
932 return sk_make_sp<MSKPSlide>(
name, path);}
934 {
".skp",
"skp-dir", FLAGS_skps,
936 return sk_make_sp<SKPSlide>(
name, path);}
938 {
".jpg",
"jpg-dir", FLAGS_jpgs,
940 return sk_make_sp<ImageSlide>(
name, path);}
942 {
".jxl",
"jxl-dir", FLAGS_jxls,
944 return sk_make_sp<ImageSlide>(
name, path);}
946#if defined(SK_ENABLE_SKOTTIE)
947 {
".json",
"skottie-dir", FLAGS_lotties,
949 return sk_make_sp<SkottieSlide>(
name, path);}
953#if defined(SK_ENABLE_SVG)
954 {
".svg",
"svg-dir", FLAGS_svgs,
956 return sk_make_sp<SvgSlide>(
name, path);}
968 if (
auto slide = fact(
name, path)) {
974 if (!FLAGS_file.isEmpty()) {
979 if (
file.equals(
"stdin")) {
985 char imageID =
'A' + fSlides.
size();
989 if (!fSlides.
empty()) {
990 fShowZoomWindow =
true;
996 for (
const auto& sinfo : gExternalSlidesInfo) {
997 if (
file.endsWith(sinfo.fExtension)) {
1003 fprintf(stderr,
"Unsupported file type \"%s\"\n",
file.c_str());
1005 fprintf(stderr,
"Cannot read \"%s\"\n",
file.c_str());
1012 if (!FLAGS_bisect.isEmpty()) {
1015 if (FLAGS_bisect.size() >= 2) {
1016 for (
const char* ch = FLAGS_bisect[1]; *ch; ++ch) {
1017 bisect->onChar(*ch);
1025 int firstGM = fSlides.
size();
1027 std::unique_ptr<skiagm::GM> gm = gmFactory();
1029 auto slide = sk_make_sp<GMSlide>(std::move(gm));
1037 std::sort(fSlides.
begin() + firstGM, fSlides.
end(), orderBySlideName);
1039 int firstRegisteredSlide = fSlides.
size();
1049 std::sort(fSlides.
begin() + firstRegisteredSlide, fSlides.
end(), orderBySlideName);
1053 auto slide = sk_make_sp<SkSLSlide>();
1061 auto slide = sk_make_sp<SkSLDebuggerSlide>();
1067 for (
const auto&
info : gExternalSlidesInfo) {
1077 while (it.next(&
name)) {
1080 if (sortedFilenames.
size()) {
1083 return strcmp(a.c_str(), b.c_str()) < 0;
1086 for (
const SkString& filename : sortedFilenames) {
1091 if (!dirSlides.
empty()) {
1094 std::move(dirSlides)));
1100 if (fSlides.
empty()) {
1101 auto slide = sk_make_sp<NullSlide>();
1108 for(
auto& slide : fSlides) {
1136void Viewer::updateTitle() {
1145 title.append(fSlides[fCurrentSlide]->getName());
1147 if (fDrawViaSerialize) {
1148 title.append(
" <serialize>");
1152 auto paintFlag = [
this, &paintTitle](
bool SkPaintFields::*
flag,
1153 bool (
SkPaint::* isFlag)() const,
1154 const char* on, const char* off)
1156 if (fPaintOverrides.*
flag) {
1157 paintTitle.append((fPaint.*isFlag)() ? on : off);
1161 auto fontFlag = [
this, &paintTitle](
bool SkFontFields::*
flag, bool (
SkFont::* isFlag)() const,
1162 const char* on, const char* off)
1164 if (fFontOverrides.*
flag) {
1165 paintTitle.append((fFont.*isFlag)() ? on : off);
1173 "Force Autohint",
"No Force Autohint");
1177 "Linear Metrics",
"Non-Linear Metrics");
1179 "Bitmap Text",
"No Bitmap Text");
1185 paintTitle.append(
"Alias Text");
1188 paintTitle.append(
"Antialias Text");
1191 paintTitle.append(
"Subpixel Antialias Text");
1199 paintTitle.append(
"No Hinting");
1202 paintTitle.append(
"Slight Hinting");
1205 paintTitle.append(
"Normal Hinting");
1208 paintTitle.append(
"Full Hinting");
1214 switch (fColorMode) {
1215 case ColorMode::kLegacy:
1216 title.append(
" Legacy 8888");
1218 case ColorMode::kColorManaged8888:
1219 title.append(
" ColorManaged 8888");
1221 case ColorMode::kColorManagedF16:
1222 title.append(
" ColorManaged F16");
1224 case ColorMode::kColorManagedF16Norm:
1225 title.append(
" ColorManaged F16 Norm");
1229 if (ColorMode::kLegacy != fColorMode) {
1230 int curPrimaries = -1;
1237 title.appendf(
" %s Gamma %f",
1239 fColorSpaceTransferFn.g);
1244 switch (
params.fSurfaceProps.pixelGeometry()) {
1246 title.append(
" Flat");
1249 title.append(
" RGB");
1252 title.append(
" BGR");
1255 title.append(
" RGBV");
1258 title.append(
" BGRV");
1263 if (
params.fSurfaceProps.isUseDeviceIndependentFonts()) {
1264 title.append(
" DFT");
1271 title.appendf(
" MSAA: %i", msaa);
1276#if defined(SK_GRAPHITE)
1279 .fGraphiteContextOptions.fPriv.fPathRendererStrategy;
1281 title.appendf(
" [Path renderer strategy: %s]",
1282 get_path_renderer_strategy_string(strategy));
1293 if (kPerspective_Real == fPerspectiveMode) {
1294 title.append(
" Perspective (Real)");
1295 }
else if (kPerspective_Fake == fPerspectiveMode) {
1296 title.append(
" Perspective (Fake)");
1302int Viewer::startupSlide()
const {
1304 if (!FLAGS_slide.isEmpty()) {
1306 for (
int i = 0; i <
count; i++) {
1307 if (fSlides[i]->getName().
equals(FLAGS_slide[0])) {
1312 fprintf(stderr,
"Unknown slide \"%s\"\n", FLAGS_slide[0]);
1319void Viewer::listNames()
const {
1321 for (
const auto& slide : fSlides) {
1322 SkDebugf(
" %s\n", slide->getName().c_str());
1326void Viewer::setCurrentSlide(
int slide) {
1329 if (slide == fCurrentSlide) {
1333 if (fCurrentSlide >= 0) {
1334 fSlides[fCurrentSlide]->unload();
1338 if (fApplyBackingScale) {
1343 fCurrentSlide = slide;
1344 this->setupCurrentSlide();
1347SkISize Viewer::currentSlideSize()
const {
1348 if (
auto size = fSlides[fCurrentSlide]->getDimensions(); !
size.isEmpty()) {
1354void Viewer::setupCurrentSlide() {
1355 if (fCurrentSlide >= 0) {
1358 fDefaultMatrix.
reset();
1365 if (windowRect.
width() > 0 && windowRect.
height() > 0) {
1372 fGesture.
setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
1374 this->updateTitle();
1375 this->updateUIState();
1383#define MAX_ZOOM_LEVEL 8.0f
1384#define MIN_ZOOM_LEVEL -8.0f
1386void Viewer::changeZoomLevel(
float delta) {
1387 fZoomLevel += delta;
1389 this->preTouchMatrixChanged();
1392void Viewer::preTouchMatrixChanged() {
1396 fGesture.
setTransLimit(slideBounds, windowRect, this->computePreTouchMatrix());
1399SkMatrix Viewer::computePerspectiveMatrix() {
1401 SkPoint orthoPts[4] = { { 0, 0 }, {
w, 0 }, { 0,
h }, {
w,
h } };
1403 { fPerspectivePoints[0].
fX *
w, fPerspectivePoints[0].
fY *
h },
1404 { fPerspectivePoints[1].
fX *
w, fPerspectivePoints[1].
fY *
h },
1405 { fPerspectivePoints[2].
fX *
w, fPerspectivePoints[2].
fY *
h },
1406 { fPerspectivePoints[3].
fX *
w, fPerspectivePoints[3].
fY *
h }
1409 m.setPolyToPoly(orthoPts, perspPts, 4);
1413SkMatrix Viewer::computePreTouchMatrix() {
1416 SkScalar zoomScale = exp(fZoomLevel);
1417 if (fApplyBackingScale) {
1420 m.preTranslate((fOffset.
x() - 0.5f) * 2.0f, (fOffset.
y() - 0.5f) * 2.0f);
1421 m.preScale(zoomScale, zoomScale);
1423 const SkISize slideSize = this->currentSlideSize();
1424 m.preRotate(fRotation, slideSize.
width() * 0.5f, slideSize.
height() * 0.5f);
1426 if (kPerspective_Real == fPerspectiveMode) {
1427 SkMatrix persp = this->computePerspectiveMatrix();
1428 m.postConcat(persp);
1437 m.preConcat(this->computePreTouchMatrix());
1442 fPersistentCache.
reset();
1443 fCachedShaders.
clear();
1444 fBackendType = backendType;
1447 for(
auto& slide : fSlides) {
1448 slide->gpuTeardown();
1453#if defined(SK_BUILD_FOR_WIN)
1458 fWindow = Window::CreateNativeWindow(
nullptr);
1461 fCommands.
attach(fWindow);
1478void Viewer::setColorMode(ColorMode colorMode) {
1479 fColorMode = colorMode;
1480 this->updateTitle();
1499 bool blobWillChange =
false;
1502 bool shouldDraw = this->
filterFont(&filteredFont);
1503 if (it.font() != *filteredFont || !shouldDraw) {
1504 blobWillChange =
true;
1508 if (!blobWillChange) {
1515 bool shouldDraw = this->
filterFont(&filteredFont);
1520 SkFont font = *filteredFont;
1524 ? builder.allocRunText(font, it.glyphCount(), it.offset().x(),it.offset().y(),
1527 ? builder.allocRunTextPosH(font, it.glyphCount(), it.offset().y(),
1530 ? builder.allocRunTextPos(font, it.glyphCount(), it.textSize())
1532 ? builder.allocRunTextRSXform(font, it.glyphCount(), it.textSize())
1534 uint32_t glyphCount = it.glyphCount();
1536 size_t glyphSize =
sizeof(
decltype(*it.glyphs()));
1537 memcpy(runBuffer.
glyphs, it.glyphs(), glyphCount * glyphSize);
1540 size_t posSize =
sizeof(
decltype(*it.pos()));
1541 unsigned posPerGlyph = it.scalarsPerGlyph();
1542 memcpy(runBuffer.
pos, it.pos(), glyphCount * posPerGlyph * posSize);
1545 size_t textSize =
sizeof(
decltype(*it.text()));
1546 uint32_t textCount = it.textSize();
1547 memcpy(runBuffer.
utf8text, it.text(), textCount * textSize);
1549 if (it.clusters()) {
1550 size_t clusterSize =
sizeof(
decltype(*it.clusters()));
1551 memcpy(runBuffer.
clusters, it.clusters(), glyphCount * clusterSize);
1554 *cache = builder.make();
1555 return cache->get();
1575 builder.blobToGlyphRunList(*cache, glyphRunList.
origin());
1655 if (std::optional<SkBlendMode> mode =
paint.asBlendMode()) {
1685 if (fCurrentSlide < 0) {
1698 if (ColorMode::kLegacy != fColorMode) {
1707 fSlides[fCurrentSlide]->draw(recorderCanvas);
1717 switch (fColorMode) {
1718 case ColorMode::kLegacy:
1719 case ColorMode::kColorManaged8888:
1722 case ColorMode::kColorManagedF16:
1725 case ColorMode::kColorManagedF16Norm:
1736 if (kPerspective_Fake == fPerspectiveMode ||
1738 fShowHistogramWindow ||
1739 Window::kRaster_BackendType == fBackendType ||
1740 colorSpace !=
nullptr ||
1747 offscreenSurface = Window::kRaster_BackendType == this->fBackendType
1751 slideSurface = offscreenSurface.
get();
1752 slideCanvas = offscreenSurface->getCanvas();
1756 SkCanvas* recorderRestoreCanvas =
nullptr;
1757 if (fDrawViaSerialize) {
1758 recorderRestoreCanvas = slideCanvas;
1769 for (
int y = 0;
y < fWindow->
height();
y += tileH) {
1770 for (
int x = 0;
x < fWindow->
width();
x += tileW) {
1773 fSlides[fCurrentSlide]->draw(slideCanvas);
1778 if (fDrawTileBoundaries) {
1782 for (
int y = 0;
y < fWindow->
height();
y += tileH) {
1783 for (
int x = 0;
x < fWindow->
width();
x += tileW) {
1789 slideCanvas->
concat(this->computeMatrix());
1790 if (kPerspective_Real == fPerspectiveMode) {
1795 &fPaint, &fPaintOverrides,
1796 &fFont, &fFontOverrides);
1797 fSlides[fCurrentSlide]->draw(&filterCanvas);
1799 fSlides[fCurrentSlide]->draw(slideCanvas);
1805 if (recorderRestoreCanvas) {
1809 slideCanvas = recorderRestoreCanvas;
1819 if (offscreenSurface) {
1820 fLastImage = offscreenSurface->makeImageSnapshot();
1826 int prePerspectiveCount = canvas->
save();
1827 if (kPerspective_Fake == fPerspectiveMode) {
1830 canvas->
concat(this->computePerspectiveMatrix());
1836 if (fShowSlideDimensions) {
1839 canvas->
concat(this->computeMatrix());
1842 paint.setColor(0x40FFFF00);
1848 this->setupCurrentSlide();
1863 direct->performDeferredCleanup(std::chrono::seconds(10));
1868 if (fCurrentSlide >= 0) {
1870 if (fApplyBackingScale) {
1877SkPoint Viewer::mapEvent(
float x,
float y) {
1878 const auto m = this->computeMatrix();
1883 return inv.mapXY(
x,
y);
1887 if (GestureDevice::kMouse == fGestureDevice) {
1891 const auto slidePt = this->mapEvent(
x,
y);
1897 void* castedOwner =
reinterpret_cast<void*
>(owner);
1901#if defined(SK_BUILD_FOR_IOS)
1908 this->setCurrentSlide(fCurrentSlide < fSlides.
size() - 1 ?
1909 fCurrentSlide + 1 : 0);
1911 this->setCurrentSlide(fCurrentSlide > 0 ?
1912 fCurrentSlide - 1 : fSlides.
size() - 1);
1934 fGestureDevice = fGesture.
isBeingTouched() ? GestureDevice::kTouch : GestureDevice::kNone;
1940 if (GestureDevice::kTouch == fGestureDevice) {
1944 const auto slidePt = this->mapEvent(
x,
y);
1945 if (fSlides[fCurrentSlide]->
onMouse(slidePt.x(), slidePt.y(),
state, modifiers)) {
1968 fGestureDevice = fGesture.
isBeingTouched() ? GestureDevice::kMouse : GestureDevice::kNone;
1990 this->setCurrentSlide(fCurrentSlide > 0 ? fCurrentSlide - 1 : fSlides.
size() - 1);
1993 this->setCurrentSlide(fCurrentSlide < fSlides.
size() - 1 ? fCurrentSlide + 1 : 0);
2025 dc.
fDrawList->AddImage(gamutPaint, dc.fPos,
2026 ImVec2(dc.fPos.x + dc.fSize.x, dc.fPos.y + dc.fSize.y),
2027 ImVec2(242, 61), ImVec2(1897, 1922));
2029 dc.dragPoint((
SkPoint*)(&primaries->
fRX),
true, 0xFF000040);
2030 dc.dragPoint((
SkPoint*)(&primaries->
fGX),
true, 0xFF004000);
2031 dc.dragPoint((
SkPoint*)(&primaries->
fBX),
true, 0xFF400000);
2032 dc.dragPoint((
SkPoint*)(&primaries->
fWX),
true);
2033 dc.fDrawList->AddPolyline(dc.fScreenPoints.begin(), 3, 0xFFFFFFFF,
true, 1.5f);
2047 for (
int i = 0; i < 4; ++i) {
2060 return std::string(
"void main() { sk_FragColor = half4(1, 0, 1, 0.5); }");
2066 size_t pos = inShader.rfind(
"return _out;\n");
2067 if (
pos == std::string::npos) {
2071 std::string replacementShader = inShader;
2072 replacementShader.insert(
pos,
"_out.sk_FragColor = float4(1.0, 0.0, 1.0, 0.5); ");
2073 return replacementShader;
2078 std::string highlight = versionDecl ? versionDecl :
"";
2080 highlight.append(
"precision mediump float;\n");
2083 "void main() { sk_FragColor = vec4(1, 0, 1, 0.5); }");
2087void Viewer::drawImGui() {
2089 if (fShowImGuiTestWindow) {
2090 ImGui::ShowDemoWindow(&fShowImGuiTestWindow);
2093 if (fShowImGuiDebugWindow) {
2096 ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
2098 bool displayParamsChanged =
false;
2099 bool uiParamsChanged =
false;
2102 if (ImGui::Begin(
"Tools", &fShowImGuiDebugWindow,
2103 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
2104 if (ImGui::CollapsingHeader(
"Backend")) {
2105 int newBackend =
static_cast<int>(fBackendType);
2108 ImGui::RadioButton(
"OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
2109#if SK_ANGLE && (defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC))
2111 ImGui::RadioButton(
"ANGLE", &newBackend, sk_app::Window::kANGLE_BackendType);
2114#if defined(SK_GRAPHITE)
2116 ImGui::RadioButton(
"Dawn (Graphite)", &newBackend,
2117 sk_app::Window::kGraphiteDawn_BackendType);
2120#if defined(SK_VULKAN) && !defined(SK_BUILD_FOR_MAC)
2122 ImGui::RadioButton(
"Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);
2123#if defined(SK_GRAPHITE)
2125 ImGui::RadioButton(
"Vulkan (Graphite)", &newBackend,
2126 sk_app::Window::kGraphiteVulkan_BackendType);
2129#if defined(SK_METAL)
2131 ImGui::RadioButton(
"Metal", &newBackend, sk_app::Window::kMetal_BackendType);
2132#if defined(SK_GRAPHITE)
2134 ImGui::RadioButton(
"Metal (Graphite)", &newBackend,
2135 sk_app::Window::kGraphiteMetal_BackendType);
2138#if defined(SK_DIRECT3D)
2140 ImGui::RadioButton(
"Direct3D", &newBackend, sk_app::Window::kDirect3D_BackendType);
2142 if (newBackend != fBackendType) {
2143 fDeferredActions.
push_back([newBackend,
this]() {
2149 bool* wire = &
params.fGrContextOptions.fWireframeMode;
2150 if (ImGui::Checkbox(
"Wireframe Mode", wire)) {
2151 displayParamsChanged =
true;
2154 bool* reducedShaders = &
params.fGrContextOptions.fReducedShaderVariations;
2155 if (ImGui::Checkbox(
"Reduced shaders", reducedShaders)) {
2156 displayParamsChanged =
true;
2167 ImGui::Text(
"MSAA: ");
2169 for (
int curMSAA = 1; curMSAA <= maxMSAA; curMSAA *= 2) {
2177 &sampleCount, curMSAA);
2181 if (sampleCount !=
params.fMSAASampleCount) {
2182 params.fMSAASampleCount = sampleCount;
2183 displayParamsChanged =
true;
2187 int pixelGeometryIdx = 0;
2189 pixelGeometryIdx =
params.fSurfaceProps.pixelGeometry() + 1;
2191 if (ImGui::Combo(
"Pixel Geometry", &pixelGeometryIdx,
2192 "Default\0Flat\0RGB\0BGR\0RGBV\0BGRV\0\0"))
2195 if (pixelGeometryIdx == 0) {
2201 SkPixelGeometry pixelGeometry = SkTo<SkPixelGeometry>(pixelGeometryIdx - 1);
2204 displayParamsChanged =
true;
2207 bool useDFT =
params.fSurfaceProps.isUseDeviceIndependentFonts();
2208 if (ImGui::Checkbox(
"DFT", &useDFT)) {
2217 displayParamsChanged =
true;
2220 if (ImGui::TreeNode(
"Path Renderers")) {
2223#if defined(SK_GRAPHITE)
2226 &
params.fGraphiteContextOptions.fPriv;
2229 if (ImGui::RadioButton(get_path_renderer_strategy_string(
s),
2233 displayParamsChanged =
true;
2238 prsButton(PathRendererStrategy::kDefault);
2241 PathRendererStrategy::kComputeAnalyticAA,
2242 PathRendererStrategy::kComputeMSAA16,
2243 PathRendererStrategy::kComputeMSAA8,
2244 PathRendererStrategy::kRasterAA,
2245 PathRendererStrategy::kTessellation,
2247 for (
size_t i = 0; i < std::size(strategies); ++i) {
2248 if (gctx->
priv().supportsPathRendererStrategy(strategies[i])) {
2249 prsButton(strategies[i]);
2258 if (
x !=
params.fGrContextOptions.fGpuPathRenderers) {
2259 params.fGrContextOptions.fGpuPathRenderers =
x;
2260 displayParamsChanged =
true;
2266#if defined(SK_GANESH)
2268 const auto* caps = ctx->
priv().
caps();
2283 ImGui::RadioButton(
"Software",
true);
2289 if (ImGui::CollapsingHeader(
"Tiling")) {
2290 ImGui::Checkbox(
"Enable", &fTiled);
2291 ImGui::Checkbox(
"Draw Boundaries", &fDrawTileBoundaries);
2292 ImGui::SliderFloat(
"Horizontal", &fTileScale.
fWidth, 0.1f, 1.0f);
2293 ImGui::SliderFloat(
"Vertical", &fTileScale.
fHeight, 0.1f, 1.0f);
2296 if (ImGui::CollapsingHeader(
"Transform")) {
2297 if (ImGui::Checkbox(
"Apply Backing Scale", &fApplyBackingScale)) {
2298 this->preTouchMatrixChanged();
2302 uiParamsChanged =
true;
2305 float zoom = fZoomLevel;
2308 this->preTouchMatrixChanged();
2309 uiParamsChanged =
true;
2311 float deg = fRotation;
2312 if (ImGui::SliderFloat(
"Rotate", °, -30, 360,
"%.3f deg")) {
2314 this->preTouchMatrixChanged();
2315 uiParamsChanged =
true;
2317 if (ImGui::CollapsingHeader(
"Subpixel offset", ImGuiTreeNodeFlags_NoTreePushOnOpen)) {
2319 this->preTouchMatrixChanged();
2320 uiParamsChanged =
true;
2322 }
else if (fOffset !=
SkVector{0.5f, 0.5f}) {
2323 this->preTouchMatrixChanged();
2324 uiParamsChanged =
true;
2325 fOffset = {0.5f, 0.5f};
2327 int perspectiveMode =
static_cast<int>(fPerspectiveMode);
2328 if (ImGui::Combo(
"Perspective", &perspectiveMode,
"Off\0Real\0Fake\0\0")) {
2329 fPerspectiveMode =
static_cast<PerspectiveMode
>(perspectiveMode);
2330 this->preTouchMatrixChanged();
2331 uiParamsChanged =
true;
2333 if (perspectiveMode != kPerspective_Off &&
ImGui_DragQuad(fPerspectivePoints)) {
2334 this->preTouchMatrixChanged();
2335 uiParamsChanged =
true;
2339 if (ImGui::CollapsingHeader(
"Paint")) {
2340 auto paintFlag = [
this, &uiParamsChanged](
const char* label,
const char* items,
2341 bool SkPaintFields::*
flag,
2342 bool (
SkPaint::* isFlag)() const,
2343 void (
SkPaint::* setFlag)(bool) )
2346 if (fPaintOverrides.*
flag) {
2347 itemIndex = (fPaint.*isFlag)() ? 2 : 1;
2349 if (ImGui::Combo(label, &itemIndex, items)) {
2350 if (itemIndex == 0) {
2351 fPaintOverrides.*
flag =
false;
2353 fPaintOverrides.*
flag =
true;
2354 (fPaint.*setFlag)(itemIndex == 2);
2356 uiParamsChanged =
true;
2360 paintFlag(
"Antialias",
2361 "Default\0No AA\0AA\0\0",
2366 "Default\0No Dither\0Dither\0\0",
2371 if (fPaintOverrides.
fStyle) {
2372 styleIdx = SkTo<int>(fPaint.
getStyle()) + 1;
2374 if (ImGui::Combo(
"Style", &styleIdx,
2375 "Default\0Fill\0Stroke\0Stroke and Fill\0\0"))
2377 if (styleIdx == 0) {
2378 fPaintOverrides.
fStyle =
false;
2381 fPaint.
setStyle(SkTo<SkPaint::Style>(styleIdx - 1));
2382 fPaintOverrides.
fStyle =
true;
2384 uiParamsChanged =
true;
2389 ImGui::Checkbox(
"Override Stroke Width", &fPaintOverrides.
fStrokeWidth);
2392 if (ImGui::SliderFloat(
"Stroke Width", &
width, 0, 20)) {
2394 uiParamsChanged =
true;
2398 ImGui::Checkbox(
"Override Miter Limit", &fPaintOverrides.
fMiterLimit);
2401 if (ImGui::SliderFloat(
"Miter Limit", &miterLimit, 0, 20)) {
2403 uiParamsChanged =
true;
2411 if (ImGui::Combo(
"Cap Type", &capIdx,
2412 "Default\0Butt\0Round\0Square\0\0"))
2421 uiParamsChanged =
true;
2428 if (ImGui::Combo(
"Join Type", &joinIdx,
2429 "Default\0Miter\0Round\0Bevel\0\0"))
2438 uiParamsChanged =
true;
2442 if (ImGui::CollapsingHeader(
"Font")) {
2445 hintingIdx = SkTo<int>(fFont.
getHinting()) + 1;
2447 if (ImGui::Combo(
"Hinting", &hintingIdx,
2448 "Default\0None\0Slight\0Normal\0Full\0\0"))
2450 if (hintingIdx == 0) {
2454 fFont.
setHinting(SkTo<SkFontHinting>(hintingIdx - 1));
2457 uiParamsChanged =
true;
2460 auto fontFlag = [
this, &uiParamsChanged](
const char* label,
const char* items,
2461 bool SkFontFields::*
flag,
2462 bool (
SkFont::* isFlag)() const,
2463 void (
SkFont::* setFlag)(bool) )
2466 if (fFontOverrides.*
flag) {
2467 itemIndex = (fFont.*isFlag)() ? 2 : 1;
2469 if (ImGui::Combo(label, &itemIndex, items)) {
2470 if (itemIndex == 0) {
2471 fFontOverrides.*
flag =
false;
2473 fFontOverrides.*
flag =
true;
2474 (fFont.*setFlag)(itemIndex == 2);
2476 uiParamsChanged =
true;
2480 fontFlag(
"Fake Bold Glyphs",
2481 "Default\0No Fake Bold\0Fake Bold\0\0",
2485 fontFlag(
"Baseline Snapping",
2486 "Default\0No Baseline Snapping\0Baseline Snapping\0\0",
2490 fontFlag(
"Linear Text",
2491 "Default\0No Linear Text\0Linear Text\0\0",
2495 fontFlag(
"Subpixel Position Glyphs",
2496 "Default\0Pixel Text\0Subpixel Text\0\0",
2500 fontFlag(
"Embedded Bitmap Text",
2501 "Default\0No Embedded Bitmaps\0Embedded Bitmaps\0\0",
2505 fontFlag(
"Force Auto-Hinting",
2506 "Default\0No Force Auto-Hinting\0Force Auto-Hinting\0\0",
2512 edgingIdx = SkTo<int>(fFont.
getEdging()) + 1;
2514 if (ImGui::Combo(
"Edging", &edgingIdx,
2515 "Default\0Alias\0Antialias\0Subpixel Antialias\0\0"))
2517 if (edgingIdx == 0) {
2518 fFontOverrides.
fEdging =
false;
2521 fFont.
setEdging(SkTo<SkFont::Edging>(edgingIdx-1));
2522 fFontOverrides.
fEdging =
true;
2524 uiParamsChanged =
true;
2527 ImGui::Checkbox(
"Override Size", &fFontOverrides.
fSize);
2528 if (fFontOverrides.
fSize) {
2529 ImGui::DragFloat2(
"TextRange", fFontOverrides.
fSizeRange,
2530 0.001f, -10.0f, 300.0f,
"%.6f", ImGuiSliderFlags_Logarithmic);
2531 float textSize = fFont.
getSize();
2532 if (ImGui::DragFloat(
"TextSize", &textSize, 0.001f,
2535 "%.6f", ImGuiSliderFlags_Logarithmic))
2538 uiParamsChanged =
true;
2542 ImGui::Checkbox(
"Override ScaleX", &fFontOverrides.
fScaleX);
2547 uiParamsChanged =
true;
2551 ImGui::Checkbox(
"Override SkewX", &fFontOverrides.
fSkewX);
2552 if (fFontOverrides.
fSkewX) {
2556 uiParamsChanged =
true;
2563 if (fSlides[fCurrentSlide]->onGetControls(&controls)) {
2564 if (ImGui::CollapsingHeader(
"Current Slide")) {
2574 if (ImGui::SliderFloat(
name, &val[0], val[1], val[2])) {
2581 if (ImGui::Checkbox(
name, &val)) {
2586 fSlides[fCurrentSlide]->onSetControls(controls);
2591 if (fShowSlidePicker) {
2592 ImGui::SetNextTreeNodeOpen(
true);
2594 if (ImGui::CollapsingHeader(
"Slide")) {
2595 static ImGuiTextFilter filter;
2596 static ImVector<const char*> filteredSlideNames;
2597 static ImVector<int> filteredSlideIndices;
2599 if (fShowSlidePicker) {
2600 ImGui::SetKeyboardFocusHere();
2601 fShowSlidePicker =
false;
2605 filteredSlideNames.clear();
2606 filteredSlideIndices.clear();
2607 int filteredIndex = 0;
2608 for (
int i = 0; i < fSlides.
size(); ++i) {
2609 const char* slideName = fSlides[i]->getName().c_str();
2610 if (filter.PassFilter(slideName) || i == fCurrentSlide) {
2611 if (i == fCurrentSlide) {
2612 filteredIndex = filteredSlideIndices.
size();
2614 filteredSlideNames.push_back(slideName);
2615 filteredSlideIndices.push_back(i);
2619 if (ImGui::ListBox(
"", &filteredIndex, filteredSlideNames.begin(),
2620 filteredSlideNames.size(), 20)) {
2621 this->setCurrentSlide(filteredSlideIndices[filteredIndex]);
2625 if (ImGui::CollapsingHeader(
"Color Mode")) {
2626 ColorMode newMode = fColorMode;
2627 auto cmButton = [&](ColorMode
mode,
const char* label) {
2628 if (ImGui::RadioButton(label, mode == fColorMode)) {
2633 cmButton(ColorMode::kLegacy,
"Legacy 8888");
2634 cmButton(ColorMode::kColorManaged8888,
"Color Managed 8888");
2635 cmButton(ColorMode::kColorManagedF16,
"Color Managed F16");
2636 cmButton(ColorMode::kColorManagedF16Norm,
"Color Managed F16 Norm");
2638 if (newMode != fColorMode) {
2639 this->setColorMode(newMode);
2643 int primariesIdx = 4;
2652 ImGui::SliderFloat(
"Gamma", &fColorSpaceTransferFn.
g, 0.5f, 3.5f);
2654 if (ImGui::Combo(
"Primaries", &primariesIdx,
2655 "sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
2656 if (primariesIdx >= 0 && primariesIdx <= 3) {
2661 if (ImGui::Button(
"Spin")) {
2662 float rx = fColorSpacePrimaries.
fRX,
2663 ry = fColorSpacePrimaries.
fRY;
2664 fColorSpacePrimaries.
fRX = fColorSpacePrimaries.
fGX;
2665 fColorSpacePrimaries.
fRY = fColorSpacePrimaries.
fGY;
2666 fColorSpacePrimaries.
fGX = fColorSpacePrimaries.
fBX;
2667 fColorSpacePrimaries.
fGY = fColorSpacePrimaries.
fBY;
2668 fColorSpacePrimaries.
fBX = rx;
2669 fColorSpacePrimaries.
fBY = ry;
2676 if (ImGui::CollapsingHeader(
"Animation")) {
2678 if (ImGui::Checkbox(
"Pause", &isPaused)) {
2682 float speed = fAnimTimer.
getSpeed();
2683 if (ImGui::DragFloat(
"Speed", &speed, 0.1f)) {
2688 if (ImGui::CollapsingHeader(
"Shaders")) {
2689 bool sksl =
params.fGrContextOptions.fShaderCacheStrategy ==
2692#if defined(SK_VULKAN)
2693 const bool isVulkan = fBackendType == sk_app::Window::kVulkan_BackendType;
2695 const bool isVulkan =
false;
2700 static bool gLoadPending =
false;
2702 fCachedShaders.
clear();
2709 CachedShader& entry(fCachedShaders.
push_back());
2713 entry.fKeyString =
hash.finish().toHexString();
2714 entry.fKeyDescription = description;
2723#if defined(SK_GRAPHITE)
2729 const skgpu::graphite::GraphicsPipeline::PipelineInfo& pipelineInfo =
2730 pipeline->getPipelineInfo();
2734 dict->
lookup(pipelineInfo.fPaintID);
2736 CachedShader& entry(fCachedShaders.
push_back());
2737 entry.fKey =
nullptr;
2738 entry.fKeyString =
SkStringPrintf(
"#%-3d RenderStep: %u, Paint: ",
2740 pipelineInfo.fRenderStepID);
2741 entry.fKeyString.append(paintKey.
toString(dict));
2745 pipelineInfo.fSkSLVertexShader;
2747 pipelineInfo.fSkSLFragmentShader;
2751 pipelineInfo.fNativeVertexShader;
2753 pipelineInfo.fNativeFragmentShader;
2763 gLoadPending =
false;
2765#if defined(SK_VULKAN)
2766 if (isVulkan && !sksl) {
2768 spvtools::SpirvTools
tools(SPV_ENV_VULKAN_1_0);
2769 for (
auto& entry : fCachedShaders) {
2771 const std::string& spirv(entry.fShader[i]);
2773 tools.Disassemble((
const uint32_t*)spirv.c_str(), spirv.size() / 4,
2775 entry.fShader[i].assign(disasm);
2782 for (
auto& entry : fCachedShaders) {
2792 bool doView = ImGui::Button(
"View"); ImGui::SameLine();
2793 bool doApply =
false;
2794 bool doDump =
false;
2797 doApply = ImGui::Button(
"Apply Changes"); ImGui::SameLine();
2798 doDump = ImGui::Button(
"Dump SkSL to resources/sksl/");
2800 int newOptLevel = fOptLevel;
2801 ImGui::RadioButton(
"SkSL", &newOptLevel, kShaderOptLevel_Source);
2803 ImGui::RadioButton(
"Compile", &newOptLevel, kShaderOptLevel_Compile);
2805 ImGui::RadioButton(
"Optimize", &newOptLevel, kShaderOptLevel_Optimize);
2807 ImGui::RadioButton(
"Inline", &newOptLevel, kShaderOptLevel_Inline);
2811 static bool sDoDeferredView =
false;
2812 if (doView || doDump || newOptLevel != fOptLevel) {
2813 sksl = doDump || (newOptLevel == kShaderOptLevel_Source);
2814 fOptLevel = (ShaderOptLevel)newOptLevel;
2815 switch (fOptLevel) {
2816 case kShaderOptLevel_Source:
2817 Compiler::EnableOptimizer(OverrideFlag::kOff);
2818 Compiler::EnableInliner(OverrideFlag::kOff);
2820 case kShaderOptLevel_Compile:
2821 Compiler::EnableOptimizer(OverrideFlag::kOff);
2822 Compiler::EnableInliner(OverrideFlag::kOff);
2824 case kShaderOptLevel_Optimize:
2825 Compiler::EnableOptimizer(OverrideFlag::kOn);
2826 Compiler::EnableInliner(OverrideFlag::kOff);
2828 case kShaderOptLevel_Inline:
2829 Compiler::EnableOptimizer(OverrideFlag::kOn);
2830 Compiler::EnableInliner(OverrideFlag::kOn);
2834 params.fGrContextOptions.fShaderCacheStrategy =
2837 displayParamsChanged =
true;
2839 fDeferredActions.
push_back([doDump,
this]() {
2841 fPersistentCache.
reset();
2842 sDoDeferredView =
true;
2847 this->dumpShadersToResources();
2853 ImGui::BeginChild(
"##ScrollingRegion");
2854 for (
auto& entry : fCachedShaders) {
2855 bool inTreeNode = ImGui::TreeNode(entry.fKeyString.c_str());
2856 bool hovered = ImGui::IsItemHovered();
2857 if (hovered != entry.fHovered) {
2859 entry.fHovered = hovered;
2863 auto stringBox = [](
const char* label, std::string* str) {
2865 int lines = std::count(str->begin(), str->end(),
'\n') + 2;
2866 ImVec2 boxSize(-1.0f, ImGui::GetTextLineHeight() * std::min(lines, 30));
2867 ImGui::InputTextMultiline(label, str, boxSize);
2869 if (ImGui::TreeNode(
"Key")) {
2870 ImGui::TextWrapped(
"%s", entry.fKeyDescription.c_str());
2880 if (doView || sDoDeferredView) {
2881 fPersistentCache.
reset();
2883 ctx->
priv().
getGpu()->resetShaderCacheForTesting();
2885#if defined(SK_GRAPHITE)
2890 gLoadPending =
true;
2891 sDoDeferredView =
false;
2896 if (isVulkan && !sksl) {
2899 if (ctx && doApply) {
2900 fPersistentCache.
reset();
2901 ctx->
priv().
getGpu()->resetShaderCacheForTesting();
2902 for (
auto& entry : fCachedShaders) {
2904 if (entry.fHovered) {
2908 switch (entry.fShaderType) {
2929 fPersistentCache.
store(*entry.fKey, *data, entry.fKeyDescription);
2936 if (displayParamsChanged || uiParamsChanged) {
2938 if (displayParamsChanged) {
2942 this->updateTitle();
2949 ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
2950 ImGui::Begin(
"Shader Errors",
nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
2955 ImGui::TextWrapped(
"%4i\t%s\n", lineNumber, lineText);
2962 if (fShowZoomWindow && fLastImage) {
2963 ImGui::SetNextWindowSize(ImVec2(200, 200), ImGuiCond_FirstUseEver);
2964 if (ImGui::Begin(
"Zoom", &fShowZoomWindow)) {
2965 static int zoomFactor = 8;
2966 if (ImGui::Button(
"<<")) {
2967 zoomFactor = std::max(zoomFactor / 2, 4);
2969 ImGui::SameLine(); ImGui::Text(
"%2d", zoomFactor); ImGui::SameLine();
2970 if (ImGui::Button(
">>")) {
2971 zoomFactor = std::min(zoomFactor * 2, 32);
2974 if (!fZoomWindowFixed) {
2975 ImVec2 mousePos = ImGui::GetMousePos();
2976 fZoomWindowLocation =
SkPoint::Make(mousePos.x, mousePos.y);
2982 ImVec2 avail = ImGui::GetContentRegionAvail();
2986 bool didGraphiteRead =
false;
2988#if defined(GRAPHITE_TEST_UTILS)
2993 didGraphiteRead = fLastImage->readPixelsGraphite(fWindow->
graphiteRecorder(),
2997 pixel = *pixels.
addr32();
2999 ImGui::Text(
"(X, Y): %d, %d RGBA: %X %X %X %X",
3013 ImGui::Text(
"(X, Y): %d, %d RGBA: %X %X %X %X",
3018 if (!didGraphiteRead) {
3020 ImGui::Text(
"Failed to readPixels");
3027 c->
scale(zoomFactor, zoomFactor);
3028 c->
translate(avail.x * 0.5f / zoomFactor -
x - 0.5f,
3029 avail.y * 0.5f / zoomFactor -
y - 0.5f);
3041 if (fShowHistogramWindow && fLastImage) {
3042 ImGui::SetNextWindowSize(ImVec2(450, 500));
3043 ImGui::SetNextWindowBgAlpha(0.5f);
3044 if (ImGui::Begin(
"Color Histogram (R,G,B)", &fShowHistogramWindow)) {
3050 info.minRowBytes(), 0, 0)) {
3051 std::vector<float> r(256), g(256),
b(256);
3052 for (
int y = 0;
y <
info.height(); ++
y) {
3053 for (
int x = 0;
x <
info.width(); ++
x) {
3054 const auto pmc = *pixmap.
addr32(
x,
y);
3061 ImGui::PushItemWidth(-1);
3062 ImGui::PlotHistogram(
"R", r.data(), r.size(), 0,
nullptr,
3063 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3064 ImGui::PlotHistogram(
"G", g.data(), g.size(), 0,
nullptr,
3065 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3066 ImGui::PlotHistogram(
"B",
b.data(),
b.size(), 0,
nullptr,
3067 FLT_MAX, FLT_MAX, ImVec2(0, 150));
3068 ImGui::PopItemWidth();
3076void Viewer::dumpShadersToResources() {
3079 std::vector<const CachedShader*> shaders;
3080 shaders.reserve(fCachedShaders.
size());
3081 for (
const CachedShader& shader : fCachedShaders) {
3082 shaders.push_back(&shader);
3085 std::sort(shaders.begin(), shaders.end(), [](
const CachedShader*
a,
const CachedShader*
b) {
3086 return std::tie(a->fShader[kFragment_GrShaderType], a->fShader[kVertex_GrShaderType]) <
3087 std::tie(b->fShader[kFragment_GrShaderType], b->fShader[kVertex_GrShaderType]);
3093 fSlides[fCurrentSlide]->getName().c_str());
3100 for (
const auto& entry : shaders) {
3126 TArray<std::function<void()>> actionsToRun;
3127 actionsToRun.
swap(fDeferredActions);
3129 for (
const auto& fn : actionsToRun) {
3135 bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer.
nanos());
3138 ImGuiIO& io = ImGui::GetIO();
3143 if (animateWantsInval || fStatsLayer.
getActive() || fRefresh ||
3144 io.MetricsActiveWindows > 1 || io.MetricsRenderWindows > 0) {
3149template <
typename OptionsFunc>
3151 OptionsFunc&& optionsFunc) {
3159 optionsFunc(writer);
3167void Viewer::updateUIState() {
3177 writer.beginArray();
3182 for(
const auto& slide : fSlides) {
3200 writer.appendS32(0);
3202 if (sk_app::Window::kRaster_BackendType == fBackendType) {
3206 for (
int msaa : {4, 8, 16}) {
3213 GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
3216 auto ctx = fWindow->directContext();
3221#if defined(SK_GANESH)
3222 if (fWindow->sampleCount() > 1 || FLAGS_dmsaa) {
3223 const auto* caps = ctx->priv().caps();
3224 if (skgpu::ganesh::AtlasPathRenderer::IsSupported(ctx)) {
3225 writer.appendString(gGaneshPathRendererNames[GpuPathRenderers::kAtlas]);
3232 if (1 == fWindow->sampleCount()) {
3233 writer.appendString(gGaneshPathRendererNames[GpuPathRenderers::kSmall]);
3244 for (
const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
3255 const SkString cstring(
static_cast<const char*
>(
data->data()),
data->size());
3257 fWindow->setUIState(cstring.c_str());
3266 for (
int i = 0; i < fSlides.
size(); ++i) {
3267 if (fSlides[i]->getName().
equals(stateValue)) {
3268 this->setCurrentSlide(i);
3278 if (fBackendType != i) {
3279 fBackendType = backendType;
3280 for(
auto& slide : fSlides) {
3281 slide->gpuTeardown();
3291 int sampleCount = atoi(stateValue.
c_str());
3292 if (sampleCount !=
params.fMSAASampleCount) {
3293 params.fMSAASampleCount = sampleCount;
3296 this->updateTitle();
3297 this->updateUIState();
3302 if (pair.second == stateValue.
c_str()) {
3303 if (
params.fGrContextOptions.fGpuPathRenderers != pair.first) {
3307 this->updateTitle();
3308 this->updateUIState();
3316 this->updateUIState();
3332 if (fSlides[fCurrentSlide]->
onChar(c)) {
3336 return fCommands.
onChar(c, modifiers);
static SkM44 inv(const SkM44 &m)
#define DEFINE_bool(name, defaultValue, helpString)
#define DEFINE_int(name, defaultValue, helpString)
#define DEFINE_string2(name, shortName, defaultValue, helpString)
#define DEFINE_int_2(name, shortName, defaultValue, helpString)
#define DEFINE_string(name, defaultValue, helpString)
static bool match(const char *needle, const char *haystack)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
void initializeEventTracingForTools(const char *traceFlag)
static const int kGrShaderTypeCount
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 SkAssertResult(cond)
#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 uint32_t hash(const SkShaderBase::GradientInfo &v)
static bool equals(T *a, T *b)
#define SkScalarRoundToInt(x)
#define SkScalarCeilToInt(x)
SK_API SkString static SkString SkStringPrintf()
bool SkStrEndsWith(const char string[], const char suffixStr[])
@ 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 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 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 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 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 const char kSoftkeyStateName[]
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 draw(SkCanvas *canvas) override
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)
bool write(const void *buffer, size_t size) final
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
@ kHorizontal_Positioning
virtual void gpuTeardown()
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) const
PaintParamsKey lookup(UniquePaintParamsID) const SK_EXCLUDES(fSpinLock)
void resize(size_t count)
sk_sp< SkTextBlob > makeBlob() const
const EmbeddedViewParams * params
FlutterSemanticsFlag flag
FlutterSemanticsFlag flags
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
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)
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
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
void FlushAndSubmit(SkSurface *surface)
std::function< std::unique_ptr< skiagm::GM >()> GMFactory
sk_tools::Registry< GMFactory > GMRegistry
for(int row=0;row< height;++row)
PersistentCache * fPersistentCache
ShaderErrorHandler * fShaderErrorHandler
bool fSupportBilerpFromGlyphAtlas
bool fReducedShaderVariations
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
bool fDelayDrawableAcquisition
SkSurfaceProps fSurfaceProps
GrContextOptions fGrContextOptions
bool fCreateProtectedNativeBackend