2016-04-06 13:08:59 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
#include "Viewer.h"
|
2016-04-06 13:08:59 +00:00
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
#include "GMSlide.h"
|
2016-06-13 19:26:45 +00:00
|
|
|
#include "ImageSlide.h"
|
2016-11-29 21:35:19 +00:00
|
|
|
#include "Resources.h"
|
2016-06-16 16:52:35 +00:00
|
|
|
#include "SampleSlide.h"
|
2016-04-08 14:24:09 +00:00
|
|
|
#include "SKPSlide.h"
|
|
|
|
|
2017-02-28 00:00:53 +00:00
|
|
|
#include "GrContext.h"
|
2016-10-14 13:12:53 +00:00
|
|
|
#include "SkATrace.h"
|
2016-04-06 13:08:59 +00:00
|
|
|
#include "SkCanvas.h"
|
2017-02-24 14:49:14 +00:00
|
|
|
#include "SkColorSpace_Base.h"
|
2017-03-15 14:24:55 +00:00
|
|
|
#include "SkColorSpaceXformCanvas.h"
|
2016-10-18 19:33:53 +00:00
|
|
|
#include "SkCommandLineFlags.h"
|
2017-02-22 19:00:42 +00:00
|
|
|
#include "SkCommonFlagsPathRenderer.h"
|
2016-06-16 21:10:34 +00:00
|
|
|
#include "SkDashPathEffect.h"
|
2016-10-14 13:12:53 +00:00
|
|
|
#include "SkGraphics.h"
|
2017-02-08 15:47:28 +00:00
|
|
|
#include "SkImagePriv.h"
|
2016-06-13 19:26:45 +00:00
|
|
|
#include "SkMetaData.h"
|
2017-02-28 00:00:53 +00:00
|
|
|
#include "SkOnce.h"
|
2016-04-08 14:24:09 +00:00
|
|
|
#include "SkOSFile.h"
|
2016-11-07 23:05:29 +00:00
|
|
|
#include "SkOSPath.h"
|
2016-04-08 14:24:09 +00:00
|
|
|
#include "SkRandom.h"
|
|
|
|
#include "SkStream.h"
|
2016-06-16 21:10:34 +00:00
|
|
|
#include "SkSurface.h"
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
#include "SkSwizzle.h"
|
2017-02-10 22:05:14 +00:00
|
|
|
#include "SkTaskGroup.h"
|
2016-07-06 21:11:32 +00:00
|
|
|
#include "SkTime.h"
|
2017-04-03 15:11:09 +00:00
|
|
|
#include "SkVertices.h"
|
2016-04-06 13:08:59 +00:00
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
#include "imgui.h"
|
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
#include <stdlib.h>
|
2017-02-28 00:00:53 +00:00
|
|
|
#include <map>
|
2017-02-24 23:04:47 +00:00
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
using namespace sk_app;
|
|
|
|
|
2017-02-28 00:00:53 +00:00
|
|
|
using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
|
|
|
|
static std::map<GpuPathRenderers, std::string> gPathRendererNames;
|
|
|
|
|
2016-04-06 13:08:59 +00:00
|
|
|
Application* Application::Create(int argc, char** argv, void* platformData) {
|
2016-05-04 20:49:13 +00:00
|
|
|
return new Viewer(argc, argv, platformData);
|
2016-04-06 13:08:59 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 20:22:53 +00:00
|
|
|
static void on_backend_created_func(void* userData) {
|
|
|
|
Viewer* vv = reinterpret_cast<Viewer*>(userData);
|
|
|
|
|
|
|
|
return vv->onBackendCreated();
|
|
|
|
}
|
|
|
|
|
2016-04-06 13:08:59 +00:00
|
|
|
static void on_paint_handler(SkCanvas* canvas, void* userData) {
|
2016-05-04 20:49:13 +00:00
|
|
|
Viewer* vv = reinterpret_cast<Viewer*>(userData);
|
2016-04-06 13:08:59 +00:00
|
|
|
|
|
|
|
return vv->onPaint(canvas);
|
|
|
|
}
|
|
|
|
|
2016-06-06 15:48:47 +00:00
|
|
|
static bool on_touch_handler(intptr_t owner, Window::InputState state, float x, float y, void* userData)
|
2016-05-17 19:44:20 +00:00
|
|
|
{
|
|
|
|
Viewer* viewer = reinterpret_cast<Viewer*>(userData);
|
|
|
|
|
|
|
|
return viewer->onTouch(owner, state, x, y);
|
|
|
|
}
|
|
|
|
|
2016-05-27 15:52:52 +00:00
|
|
|
static void on_ui_state_changed_handler(const SkString& stateName, const SkString& stateValue, void* userData) {
|
|
|
|
Viewer* viewer = reinterpret_cast<Viewer*>(userData);
|
|
|
|
|
|
|
|
return viewer->onUIStateChanged(stateName, stateValue);
|
|
|
|
}
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
static bool on_mouse_handler(int x, int y, Window::InputState state, uint32_t modifiers,
|
|
|
|
void* userData) {
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.MousePos.x = static_cast<float>(x);
|
|
|
|
io.MousePos.y = static_cast<float>(y);
|
|
|
|
if (Window::kDown_InputState == state) {
|
|
|
|
io.MouseDown[0] = true;
|
|
|
|
} else if (Window::kUp_InputState == state) {
|
|
|
|
io.MouseDown[0] = false;
|
|
|
|
}
|
2017-05-04 18:00:59 +00:00
|
|
|
if (io.WantCaptureMouse) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
Viewer* viewer = reinterpret_cast<Viewer*>(userData);
|
|
|
|
return viewer->onMouse(x, y, state, modifiers);
|
|
|
|
}
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool on_mouse_wheel_handler(float delta, uint32_t modifiers, void* userData) {
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.MouseWheel += delta;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool on_key_handler(Window::Key key, Window::InputState state, uint32_t modifiers,
|
|
|
|
void* userData) {
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.KeysDown[static_cast<int>(key)] = (Window::kDown_InputState == state);
|
|
|
|
|
|
|
|
if (io.WantCaptureKeyboard) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
Viewer* viewer = reinterpret_cast<Viewer*>(userData);
|
|
|
|
return viewer->onKey(key, state, modifiers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool on_char_handler(SkUnichar c, uint32_t modifiers, void* userData) {
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
if (io.WantTextInput) {
|
|
|
|
if (c > 0 && c < 0x10000) {
|
|
|
|
io.AddInputCharacter(c);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
Viewer* viewer = reinterpret_cast<Viewer*>(userData);
|
|
|
|
return viewer->onChar(c, modifiers);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_bool2(fullscreen, f, true, "Run fullscreen.");
|
2016-10-18 18:42:44 +00:00
|
|
|
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_string2(match, m, nullptr,
|
2016-04-08 14:24:09 +00:00
|
|
|
"[~][^]substring[$] [...] of bench name to run.\n"
|
|
|
|
"Multiple matches may be separated by spaces.\n"
|
|
|
|
"~ causes a matching bench to always be skipped\n"
|
|
|
|
"^ requires the start of the bench to match\n"
|
|
|
|
"$ requires the end of the bench to match\n"
|
|
|
|
"^ and $ requires an exact match\n"
|
|
|
|
"If a bench does not match any list entry,\n"
|
|
|
|
"it is skipped unless some list entry starts with ~");
|
2016-07-26 19:56:32 +00:00
|
|
|
|
2017-02-14 20:16:46 +00:00
|
|
|
DEFINE_string(slide, "", "Start on this sample.");
|
|
|
|
DEFINE_bool(list, false, "List samples?");
|
|
|
|
|
2016-07-26 19:56:32 +00:00
|
|
|
#ifdef SK_VULKAN
|
2016-07-27 21:29:18 +00:00
|
|
|
# define BACKENDS_STR "\"sw\", \"gl\", and \"vk\""
|
2016-07-26 19:56:32 +00:00
|
|
|
#else
|
|
|
|
# define BACKENDS_STR "\"sw\" and \"gl\""
|
|
|
|
#endif
|
|
|
|
|
2016-06-09 19:02:34 +00:00
|
|
|
#ifdef SK_BUILD_FOR_ANDROID
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_string(skps, "/data/local/tmp/skia", "Directory to read skps from.");
|
|
|
|
static DEFINE_string(jpgs, "/data/local/tmp/skia", "Directory to read jpgs from.");
|
2016-06-09 19:02:34 +00:00
|
|
|
#else
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_string(skps, "skps", "Directory to read skps from.");
|
|
|
|
static DEFINE_string(jpgs, "jpgs", "Directory to read jpgs from.");
|
2016-06-09 19:02:34 +00:00
|
|
|
#endif
|
2016-04-08 14:24:09 +00:00
|
|
|
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_string2(backend, b, "sw", "Backend to use. Allowed values are " BACKENDS_STR ".");
|
2016-07-26 19:56:32 +00:00
|
|
|
|
2016-10-18 19:33:53 +00:00
|
|
|
static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android.");
|
2016-10-14 13:12:53 +00:00
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
DEFINE_int32(msaa, 0, "Number of subpixel samples. 0 for no HW antialiasing.");
|
2017-02-22 19:00:42 +00:00
|
|
|
DEFINE_pathrenderer_flag;
|
|
|
|
|
2017-03-08 19:03:56 +00:00
|
|
|
DEFINE_bool(instancedRendering, false, "Enable instanced rendering on GPU backends.");
|
|
|
|
|
2016-05-20 13:01:06 +00:00
|
|
|
const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
|
2017-02-24 23:04:47 +00:00
|
|
|
"OpenGL",
|
2016-06-17 16:29:14 +00:00
|
|
|
#ifdef SK_VULKAN
|
2017-02-24 23:04:47 +00:00
|
|
|
"Vulkan",
|
2016-06-17 16:29:14 +00:00
|
|
|
#endif
|
2017-02-24 23:04:47 +00:00
|
|
|
"Raster"
|
2016-05-20 13:01:06 +00:00
|
|
|
};
|
|
|
|
|
2016-07-26 19:56:32 +00:00
|
|
|
static sk_app::Window::BackendType get_backend_type(const char* str) {
|
|
|
|
#ifdef SK_VULKAN
|
|
|
|
if (0 == strcmp(str, "vk")) {
|
|
|
|
return sk_app::Window::kVulkan_BackendType;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
if (0 == strcmp(str, "gl")) {
|
|
|
|
return sk_app::Window::kNativeGL_BackendType;
|
|
|
|
} else if (0 == strcmp(str, "sw")) {
|
|
|
|
return sk_app::Window::kRaster_BackendType;
|
|
|
|
} else {
|
|
|
|
SkDebugf("Unknown backend type, %s, defaulting to sw.", str);
|
|
|
|
return sk_app::Window::kRaster_BackendType;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-24 14:49:14 +00:00
|
|
|
static SkColorSpacePrimaries gSrgbPrimaries = {
|
|
|
|
0.64f, 0.33f,
|
|
|
|
0.30f, 0.60f,
|
|
|
|
0.15f, 0.06f,
|
|
|
|
0.3127f, 0.3290f };
|
|
|
|
|
|
|
|
static SkColorSpacePrimaries gAdobePrimaries = {
|
|
|
|
0.64f, 0.33f,
|
|
|
|
0.21f, 0.71f,
|
|
|
|
0.15f, 0.06f,
|
|
|
|
0.3127f, 0.3290f };
|
|
|
|
|
|
|
|
static SkColorSpacePrimaries gP3Primaries = {
|
|
|
|
0.680f, 0.320f,
|
|
|
|
0.265f, 0.690f,
|
|
|
|
0.150f, 0.060f,
|
|
|
|
0.3127f, 0.3290f };
|
|
|
|
|
|
|
|
static SkColorSpacePrimaries gRec2020Primaries = {
|
|
|
|
0.708f, 0.292f,
|
|
|
|
0.170f, 0.797f,
|
|
|
|
0.131f, 0.046f,
|
|
|
|
0.3127f, 0.3290f };
|
|
|
|
|
|
|
|
struct NamedPrimaries {
|
|
|
|
const char* fName;
|
|
|
|
SkColorSpacePrimaries* fPrimaries;
|
|
|
|
} gNamedPrimaries[] = {
|
|
|
|
{ "sRGB", &gSrgbPrimaries },
|
|
|
|
{ "AdobeRGB", &gAdobePrimaries },
|
|
|
|
{ "P3", &gP3Primaries },
|
|
|
|
{ "Rec. 2020", &gRec2020Primaries },
|
|
|
|
};
|
|
|
|
|
|
|
|
static bool primaries_equal(const SkColorSpacePrimaries& a, const SkColorSpacePrimaries& b) {
|
|
|
|
return memcmp(&a, &b, sizeof(SkColorSpacePrimaries)) == 0;
|
|
|
|
}
|
|
|
|
|
2016-05-27 15:52:52 +00:00
|
|
|
const char* kName = "name";
|
|
|
|
const char* kValue = "value";
|
|
|
|
const char* kOptions = "options";
|
|
|
|
const char* kSlideStateName = "Slide";
|
|
|
|
const char* kBackendStateName = "Backend";
|
2017-02-24 23:04:47 +00:00
|
|
|
const char* kMSAAStateName = "MSAA";
|
2017-02-28 00:00:53 +00:00
|
|
|
const char* kPathRendererStateName = "Path renderer";
|
2017-03-07 20:16:34 +00:00
|
|
|
const char* kInstancedRenderingStateName = "Instanced rendering";
|
2016-06-03 15:47:23 +00:00
|
|
|
const char* kSoftkeyStateName = "Softkey";
|
|
|
|
const char* kSoftkeyHint = "Please select a softkey";
|
2016-06-07 13:57:40 +00:00
|
|
|
const char* kFpsStateName = "FPS";
|
2016-06-13 19:26:45 +00:00
|
|
|
const char* kON = "ON";
|
|
|
|
const char* kOFF = "OFF";
|
2016-07-06 21:11:32 +00:00
|
|
|
const char* kRefreshStateName = "Refresh";
|
2016-05-27 15:52:52 +00:00
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
Viewer::Viewer(int argc, char** argv, void* platformData)
|
2016-04-08 19:51:45 +00:00
|
|
|
: fCurrentMeasurement(0)
|
|
|
|
, fDisplayStats(false)
|
2016-07-06 21:11:32 +00:00
|
|
|
, fRefresh(false)
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
, fShowImGuiDebugWindow(false)
|
|
|
|
, fShowImGuiTestWindow(false)
|
2017-02-13 14:39:57 +00:00
|
|
|
, fShowZoomWindow(false)
|
|
|
|
, fLastImage(nullptr)
|
2016-06-17 16:29:14 +00:00
|
|
|
, fBackendType(sk_app::Window::kNativeGL_BackendType)
|
2017-03-06 16:47:26 +00:00
|
|
|
, fColorMode(ColorMode::kLegacy)
|
2017-02-24 14:49:14 +00:00
|
|
|
, fColorSpacePrimaries(gSrgbPrimaries)
|
2016-04-11 15:30:40 +00:00
|
|
|
, fZoomCenterX(0.0f)
|
|
|
|
, fZoomCenterY(0.0f)
|
|
|
|
, fZoomLevel(0.0f)
|
|
|
|
, fZoomScale(SK_Scalar1)
|
2016-04-08 19:51:45 +00:00
|
|
|
{
|
2017-02-10 22:05:14 +00:00
|
|
|
static SkTaskGroup::Enabler kTaskGroupEnabler;
|
2016-10-14 13:12:53 +00:00
|
|
|
SkGraphics::Init();
|
2017-02-28 00:00:53 +00:00
|
|
|
|
|
|
|
static SkOnce initPathRendererNames;
|
|
|
|
initPathRendererNames([]() {
|
|
|
|
gPathRendererNames[GpuPathRenderers::kAll] = "Default Ganesh Behavior (best path renderer)";
|
|
|
|
gPathRendererNames[GpuPathRenderers::kStencilAndCover] = "NV_path_rendering";
|
|
|
|
gPathRendererNames[GpuPathRenderers::kMSAA] = "Sample shading";
|
2017-03-16 12:45:39 +00:00
|
|
|
gPathRendererNames[GpuPathRenderers::kSmall] = "Small paths (cached sdf or alpha masks)";
|
2017-03-01 19:59:05 +00:00
|
|
|
gPathRendererNames[GpuPathRenderers::kTessellating] = "Tessellating";
|
2017-02-28 00:00:53 +00:00
|
|
|
gPathRendererNames[GpuPathRenderers::kDefault] = "Original Ganesh path renderer";
|
|
|
|
gPathRendererNames[GpuPathRenderers::kNone] = "Software masks";
|
|
|
|
});
|
|
|
|
|
2017-02-09 17:10:20 +00:00
|
|
|
memset(fPaintTimes, 0, sizeof(fPaintTimes));
|
|
|
|
memset(fFlushTimes, 0, sizeof(fFlushTimes));
|
|
|
|
memset(fAnimateTimes, 0, sizeof(fAnimateTimes));
|
2016-04-06 13:08:59 +00:00
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
SkDebugf("Command line arguments: ");
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
SkDebugf("%s ", argv[i]);
|
|
|
|
}
|
|
|
|
SkDebugf("\n");
|
|
|
|
|
|
|
|
SkCommandLineFlags::Parse(argc, argv);
|
2016-11-29 21:35:19 +00:00
|
|
|
#ifdef SK_BUILD_FOR_ANDROID
|
|
|
|
SetResourcePath("/data/local/tmp/skia");
|
|
|
|
#endif
|
2016-04-08 14:24:09 +00:00
|
|
|
|
2016-10-14 13:12:53 +00:00
|
|
|
if (FLAGS_atrace) {
|
|
|
|
SkEventTracer::SetInstance(new SkATrace());
|
|
|
|
}
|
|
|
|
|
2016-07-26 19:56:32 +00:00
|
|
|
fBackendType = get_backend_type(FLAGS_backend[0]);
|
2016-04-06 13:08:59 +00:00
|
|
|
fWindow = Window::CreateNativeWindow(platformData);
|
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
DisplayParams displayParams;
|
|
|
|
displayParams.fMSAASampleCount = FLAGS_msaa;
|
2017-03-08 19:03:56 +00:00
|
|
|
displayParams.fGrContextOptions.fEnableInstancedRendering = FLAGS_instancedRendering;
|
2017-02-28 00:00:53 +00:00
|
|
|
displayParams.fGrContextOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
|
2017-02-24 23:04:47 +00:00
|
|
|
fWindow->setRequestedDisplayParams(displayParams);
|
|
|
|
|
2016-04-06 13:08:59 +00:00
|
|
|
// register callbacks
|
2016-05-10 13:50:49 +00:00
|
|
|
fCommands.attach(fWindow);
|
2017-02-24 20:22:53 +00:00
|
|
|
fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
|
2016-04-06 13:08:59 +00:00
|
|
|
fWindow->registerPaintFunc(on_paint_handler, this);
|
2016-05-17 19:44:20 +00:00
|
|
|
fWindow->registerTouchFunc(on_touch_handler, this);
|
2016-05-27 15:52:52 +00:00
|
|
|
fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
fWindow->registerMouseFunc(on_mouse_handler, this);
|
|
|
|
fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
|
|
|
|
fWindow->registerKeyFunc(on_key_handler, this);
|
|
|
|
fWindow->registerCharFunc(on_char_handler, this);
|
2016-04-06 13:08:59 +00:00
|
|
|
|
2016-05-10 13:50:49 +00:00
|
|
|
// add key-bindings
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
fCommands.addCommand(' ', "GUI", "Toggle Debug GUI", [this]() {
|
|
|
|
this->fShowImGuiDebugWindow = !this->fShowImGuiDebugWindow;
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
|
|
|
fCommands.addCommand('g', "GUI", "Toggle GUI Demo", [this]() {
|
|
|
|
this->fShowImGuiTestWindow = !this->fShowImGuiTestWindow;
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
2017-02-13 14:39:57 +00:00
|
|
|
fCommands.addCommand('z', "GUI", "Toggle zoom window", [this]() {
|
|
|
|
this->fShowZoomWindow = !this->fShowZoomWindow;
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
2016-05-10 13:50:49 +00:00
|
|
|
fCommands.addCommand('s', "Overlays", "Toggle stats display", [this]() {
|
|
|
|
this->fDisplayStats = !this->fDisplayStats;
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
2017-02-08 15:47:28 +00:00
|
|
|
fCommands.addCommand('c', "Modes", "Cycle color mode", [this]() {
|
2017-03-06 16:47:26 +00:00
|
|
|
switch (fColorMode) {
|
|
|
|
case ColorMode::kLegacy:
|
|
|
|
this->setColorMode(ColorMode::kColorManagedSRGB8888_NonLinearBlending);
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
|
|
|
|
this->setColorMode(ColorMode::kColorManagedSRGB8888);
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedSRGB8888:
|
|
|
|
this->setColorMode(ColorMode::kColorManagedLinearF16);
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedLinearF16:
|
|
|
|
this->setColorMode(ColorMode::kLegacy);
|
|
|
|
break;
|
2017-02-08 15:47:28 +00:00
|
|
|
}
|
2016-05-10 13:50:49 +00:00
|
|
|
});
|
|
|
|
fCommands.addCommand(Window::Key::kRight, "Right", "Navigation", "Next slide", [this]() {
|
|
|
|
int previousSlide = fCurrentSlide;
|
|
|
|
fCurrentSlide++;
|
|
|
|
if (fCurrentSlide >= fSlides.count()) {
|
|
|
|
fCurrentSlide = 0;
|
|
|
|
}
|
|
|
|
this->setupCurrentSlide(previousSlide);
|
|
|
|
});
|
|
|
|
fCommands.addCommand(Window::Key::kLeft, "Left", "Navigation", "Previous slide", [this]() {
|
|
|
|
int previousSlide = fCurrentSlide;
|
|
|
|
fCurrentSlide--;
|
|
|
|
if (fCurrentSlide < 0) {
|
|
|
|
fCurrentSlide = fSlides.count() - 1;
|
|
|
|
}
|
|
|
|
this->setupCurrentSlide(previousSlide);
|
|
|
|
});
|
|
|
|
fCommands.addCommand(Window::Key::kUp, "Up", "Transform", "Zoom in", [this]() {
|
|
|
|
this->changeZoomLevel(1.f / 32.f);
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
|
|
|
fCommands.addCommand(Window::Key::kDown, "Down", "Transform", "Zoom out", [this]() {
|
|
|
|
this->changeZoomLevel(-1.f / 32.f);
|
|
|
|
fWindow->inval();
|
|
|
|
});
|
2016-05-20 13:01:06 +00:00
|
|
|
fCommands.addCommand('d', "Modes", "Change rendering backend", [this]() {
|
2017-02-28 20:45:01 +00:00
|
|
|
sk_app::Window::BackendType newBackend = fBackendType;
|
2017-01-05 18:50:49 +00:00
|
|
|
#if defined(SK_BUILD_FOR_WIN) || defined(SK_BUILD_FOR_MAC)
|
2016-07-27 21:29:18 +00:00
|
|
|
if (sk_app::Window::kRaster_BackendType == fBackendType) {
|
2017-02-28 20:45:01 +00:00
|
|
|
newBackend = sk_app::Window::kNativeGL_BackendType;
|
2016-07-27 21:29:18 +00:00
|
|
|
#ifdef SK_VULKAN
|
|
|
|
} else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
|
2017-02-28 20:45:01 +00:00
|
|
|
newBackend = sk_app::Window::kVulkan_BackendType;
|
2016-07-27 21:29:18 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
2017-02-28 20:45:01 +00:00
|
|
|
newBackend = sk_app::Window::kRaster_BackendType;
|
2016-07-27 21:29:18 +00:00
|
|
|
}
|
2017-01-05 18:50:49 +00:00
|
|
|
#elif defined(SK_BUILD_FOR_UNIX)
|
|
|
|
// Switching to and from Vulkan is problematic on Linux so disabled for now
|
|
|
|
if (sk_app::Window::kRaster_BackendType == fBackendType) {
|
2017-02-28 20:45:01 +00:00
|
|
|
newBackend = sk_app::Window::kNativeGL_BackendType;
|
2017-01-05 18:50:49 +00:00
|
|
|
} else if (sk_app::Window::kNativeGL_BackendType == fBackendType) {
|
2017-02-28 20:45:01 +00:00
|
|
|
newBackend = sk_app::Window::kRaster_BackendType;
|
2017-01-05 18:50:49 +00:00
|
|
|
}
|
|
|
|
#endif
|
2016-05-20 13:01:06 +00:00
|
|
|
|
2017-02-28 20:45:01 +00:00
|
|
|
this->setBackend(newBackend);
|
2016-05-20 13:01:06 +00:00
|
|
|
});
|
2016-05-10 13:50:49 +00:00
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
// set up slides
|
|
|
|
this->initSlides();
|
2017-02-14 20:16:46 +00:00
|
|
|
this->setStartupSlide();
|
|
|
|
if (FLAGS_list) {
|
|
|
|
this->listNames();
|
|
|
|
}
|
2016-04-08 14:24:09 +00:00
|
|
|
|
2016-04-21 14:59:44 +00:00
|
|
|
fAnimTimer.run();
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
// ImGui initialization:
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.DisplaySize.x = static_cast<float>(fWindow->width());
|
|
|
|
io.DisplaySize.y = static_cast<float>(fWindow->height());
|
|
|
|
|
|
|
|
// Keymap...
|
|
|
|
io.KeyMap[ImGuiKey_Tab] = (int)Window::Key::kTab;
|
|
|
|
io.KeyMap[ImGuiKey_LeftArrow] = (int)Window::Key::kLeft;
|
|
|
|
io.KeyMap[ImGuiKey_RightArrow] = (int)Window::Key::kRight;
|
|
|
|
io.KeyMap[ImGuiKey_UpArrow] = (int)Window::Key::kUp;
|
|
|
|
io.KeyMap[ImGuiKey_DownArrow] = (int)Window::Key::kDown;
|
|
|
|
io.KeyMap[ImGuiKey_PageUp] = (int)Window::Key::kPageUp;
|
|
|
|
io.KeyMap[ImGuiKey_PageDown] = (int)Window::Key::kPageDown;
|
|
|
|
io.KeyMap[ImGuiKey_Home] = (int)Window::Key::kHome;
|
|
|
|
io.KeyMap[ImGuiKey_End] = (int)Window::Key::kEnd;
|
|
|
|
io.KeyMap[ImGuiKey_Delete] = (int)Window::Key::kDelete;
|
|
|
|
io.KeyMap[ImGuiKey_Backspace] = (int)Window::Key::kBack;
|
|
|
|
io.KeyMap[ImGuiKey_Enter] = (int)Window::Key::kOK;
|
|
|
|
io.KeyMap[ImGuiKey_Escape] = (int)Window::Key::kEscape;
|
|
|
|
io.KeyMap[ImGuiKey_A] = (int)Window::Key::kA;
|
|
|
|
io.KeyMap[ImGuiKey_C] = (int)Window::Key::kC;
|
|
|
|
io.KeyMap[ImGuiKey_V] = (int)Window::Key::kV;
|
|
|
|
io.KeyMap[ImGuiKey_X] = (int)Window::Key::kX;
|
|
|
|
io.KeyMap[ImGuiKey_Y] = (int)Window::Key::kY;
|
|
|
|
io.KeyMap[ImGuiKey_Z] = (int)Window::Key::kZ;
|
|
|
|
|
|
|
|
int w, h;
|
|
|
|
unsigned char* pixels;
|
|
|
|
io.Fonts->GetTexDataAsAlpha8(&pixels, &w, &h);
|
|
|
|
SkImageInfo info = SkImageInfo::MakeA8(w, h);
|
|
|
|
SkPixmap pmap(info, pixels, info.minRowBytes());
|
2017-02-13 14:39:57 +00:00
|
|
|
SkMatrix localMatrix = SkMatrix::MakeScale(1.0f / w, 1.0f / h);
|
|
|
|
auto fontImage = SkImage::MakeFromRaster(pmap, nullptr, nullptr);
|
2017-04-28 15:12:19 +00:00
|
|
|
auto fontShader = fontImage->makeShader(&localMatrix);
|
2017-02-13 14:39:57 +00:00
|
|
|
fImGuiFontPaint.setShader(fontShader);
|
|
|
|
fImGuiFontPaint.setColor(SK_ColorWHITE);
|
|
|
|
fImGuiFontPaint.setFilterQuality(kLow_SkFilterQuality);
|
|
|
|
io.Fonts->TexID = &fImGuiFontPaint;
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
|
2017-02-24 14:49:14 +00:00
|
|
|
auto gamutImage = GetResourceAsImage("gamut.png");
|
|
|
|
if (gamutImage) {
|
2017-04-28 15:12:19 +00:00
|
|
|
fImGuiGamutPaint.setShader(gamutImage->makeShader());
|
2017-02-24 14:49:14 +00:00
|
|
|
}
|
|
|
|
fImGuiGamutPaint.setColor(SK_ColorWHITE);
|
|
|
|
fImGuiGamutPaint.setFilterQuality(kLow_SkFilterQuality);
|
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
fWindow->attach(fBackendType);
|
2016-04-08 14:24:09 +00:00
|
|
|
}
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
void Viewer::initSlides() {
|
2016-06-07 13:57:40 +00:00
|
|
|
fAllSlideNames = Json::Value(Json::arrayValue);
|
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
const skiagm::GMRegistry* gms(skiagm::GMRegistry::Head());
|
|
|
|
while (gms) {
|
2016-11-03 18:40:50 +00:00
|
|
|
std::unique_ptr<skiagm::GM> gm(gms->factory()(nullptr));
|
2016-04-08 14:24:09 +00:00
|
|
|
|
|
|
|
if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, gm->getName())) {
|
|
|
|
sk_sp<Slide> slide(new GMSlide(gm.release()));
|
|
|
|
fSlides.push_back(slide);
|
|
|
|
}
|
|
|
|
|
|
|
|
gms = gms->next();
|
|
|
|
}
|
|
|
|
|
|
|
|
// reverse array
|
|
|
|
for (int i = 0; i < fSlides.count()/2; ++i) {
|
|
|
|
sk_sp<Slide> temp = fSlides[i];
|
|
|
|
fSlides[i] = fSlides[fSlides.count() - i - 1];
|
|
|
|
fSlides[fSlides.count() - i - 1] = temp;
|
|
|
|
}
|
|
|
|
|
2016-06-16 16:52:35 +00:00
|
|
|
// samples
|
|
|
|
const SkViewRegister* reg = SkViewRegister::Head();
|
|
|
|
while (reg) {
|
|
|
|
sk_sp<Slide> slide(new SampleSlide(reg->factory()));
|
2016-07-12 16:07:33 +00:00
|
|
|
if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, slide->getName().c_str())) {
|
|
|
|
fSlides.push_back(slide);
|
|
|
|
}
|
2016-06-16 16:52:35 +00:00
|
|
|
reg = reg->next();
|
|
|
|
}
|
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
// SKPs
|
|
|
|
for (int i = 0; i < FLAGS_skps.count(); i++) {
|
|
|
|
if (SkStrEndsWith(FLAGS_skps[i], ".skp")) {
|
2016-04-08 19:51:45 +00:00
|
|
|
if (SkCommandLineFlags::ShouldSkip(FLAGS_match, FLAGS_skps[i])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-04-08 14:24:09 +00:00
|
|
|
SkString path(FLAGS_skps[i]);
|
2016-04-08 19:51:45 +00:00
|
|
|
sk_sp<SKPSlide> slide(new SKPSlide(SkOSPath::Basename(path.c_str()), path));
|
2016-04-08 14:24:09 +00:00
|
|
|
if (slide) {
|
|
|
|
fSlides.push_back(slide);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SkOSFile::Iter it(FLAGS_skps[i], ".skp");
|
2016-04-08 19:51:45 +00:00
|
|
|
SkString skpName;
|
|
|
|
while (it.next(&skpName)) {
|
|
|
|
if (SkCommandLineFlags::ShouldSkip(FLAGS_match, skpName.c_str())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkString path = SkOSPath::Join(FLAGS_skps[i], skpName.c_str());
|
|
|
|
sk_sp<SKPSlide> slide(new SKPSlide(skpName, path));
|
2016-04-08 14:24:09 +00:00
|
|
|
if (slide) {
|
|
|
|
fSlides.push_back(slide);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-13 19:26:45 +00:00
|
|
|
|
|
|
|
// JPGs
|
|
|
|
for (int i = 0; i < FLAGS_jpgs.count(); i++) {
|
|
|
|
SkOSFile::Iter it(FLAGS_jpgs[i], ".jpg");
|
|
|
|
SkString jpgName;
|
|
|
|
while (it.next(&jpgName)) {
|
2016-07-12 16:07:33 +00:00
|
|
|
if (SkCommandLineFlags::ShouldSkip(FLAGS_match, jpgName.c_str())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-06-13 19:26:45 +00:00
|
|
|
SkString path = SkOSPath::Join(FLAGS_jpgs[i], jpgName.c_str());
|
|
|
|
sk_sp<ImageSlide> slide(new ImageSlide(jpgName, path));
|
|
|
|
if (slide) {
|
|
|
|
fSlides.push_back(slide);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-08 14:24:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
Viewer::~Viewer() {
|
2016-04-06 13:08:59 +00:00
|
|
|
fWindow->detach();
|
|
|
|
delete fWindow;
|
|
|
|
}
|
|
|
|
|
2016-05-06 20:28:57 +00:00
|
|
|
void Viewer::updateTitle() {
|
2017-02-24 23:04:47 +00:00
|
|
|
if (!fWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fWindow->sampleCount() < 0) {
|
|
|
|
return; // Surface hasn't been created yet.
|
|
|
|
}
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
SkString title("Viewer: ");
|
2016-04-08 19:51:45 +00:00
|
|
|
title.append(fSlides[fCurrentSlide]->getName());
|
2016-06-16 20:03:24 +00:00
|
|
|
|
2017-03-06 16:47:26 +00:00
|
|
|
switch (fColorMode) {
|
|
|
|
case ColorMode::kLegacy:
|
|
|
|
title.append(" Legacy 8888");
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedSRGB8888_NonLinearBlending:
|
|
|
|
title.append(" ColorManaged 8888 (Nonlinear blending)");
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedSRGB8888:
|
|
|
|
title.append(" ColorManaged 8888");
|
|
|
|
break;
|
|
|
|
case ColorMode::kColorManagedLinearF16:
|
|
|
|
title.append(" ColorManaged F16");
|
|
|
|
break;
|
|
|
|
}
|
2017-02-24 14:49:14 +00:00
|
|
|
|
2017-03-06 16:47:26 +00:00
|
|
|
if (ColorMode::kLegacy != fColorMode) {
|
2017-02-24 14:49:14 +00:00
|
|
|
int curPrimaries = -1;
|
|
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(gNamedPrimaries); ++i) {
|
|
|
|
if (primaries_equal(*gNamedPrimaries[i].fPrimaries, fColorSpacePrimaries)) {
|
|
|
|
curPrimaries = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
title.appendf(" %s", curPrimaries >= 0 ? gNamedPrimaries[curPrimaries].fName : "Custom");
|
2016-05-06 20:28:57 +00:00
|
|
|
}
|
2017-02-08 15:47:28 +00:00
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
title.append(" [");
|
2016-05-20 13:01:06 +00:00
|
|
|
title.append(kBackendTypeStrings[fBackendType]);
|
2017-02-24 23:04:47 +00:00
|
|
|
if (int msaa = fWindow->sampleCount()) {
|
|
|
|
title.appendf(" MSAA: %i", msaa);
|
|
|
|
}
|
|
|
|
title.append("]");
|
2017-02-28 00:00:53 +00:00
|
|
|
|
|
|
|
GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
|
|
|
|
if (GpuPathRenderers::kAll != pr) {
|
|
|
|
title.appendf(" [Path renderer: %s]", gPathRendererNames[pr].c_str());
|
|
|
|
}
|
|
|
|
|
2016-05-06 20:28:57 +00:00
|
|
|
fWindow->setTitle(title.c_str());
|
|
|
|
}
|
|
|
|
|
2017-02-14 20:16:46 +00:00
|
|
|
void Viewer::setStartupSlide() {
|
|
|
|
|
|
|
|
if (!FLAGS_slide.isEmpty()) {
|
|
|
|
int count = fSlides.count();
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
if (fSlides[i]->getName().equals(FLAGS_slide[0])) {
|
|
|
|
fCurrentSlide = i;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(stderr, "Unknown slide \"%s\"\n", FLAGS_slide[0]);
|
|
|
|
this->listNames();
|
|
|
|
}
|
|
|
|
|
|
|
|
fCurrentSlide = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Viewer::listNames() {
|
|
|
|
int count = fSlides.count();
|
|
|
|
SkDebugf("All Slides:\n");
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
SkDebugf(" %s\n", fSlides[i]->getName().c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-06 20:28:57 +00:00
|
|
|
void Viewer::setupCurrentSlide(int previousSlide) {
|
2016-05-27 15:52:52 +00:00
|
|
|
if (fCurrentSlide == previousSlide) {
|
|
|
|
return; // no change; do nothing
|
|
|
|
}
|
2016-06-13 19:26:45 +00:00
|
|
|
// prepare dimensions for image slides
|
2016-06-16 16:52:35 +00:00
|
|
|
fSlides[fCurrentSlide]->load(SkIntToScalar(fWindow->width()), SkIntToScalar(fWindow->height()));
|
2016-06-13 19:26:45 +00:00
|
|
|
|
2016-05-20 14:32:19 +00:00
|
|
|
fGesture.reset();
|
|
|
|
fDefaultMatrix.reset();
|
|
|
|
fDefaultMatrixInv.reset();
|
|
|
|
|
|
|
|
if (fWindow->supportsContentRect() && fWindow->scaleContentToFit()) {
|
|
|
|
const SkRect contentRect = fWindow->getContentRect();
|
|
|
|
const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
|
|
|
|
const SkRect slideBounds = SkRect::MakeIWH(slideSize.width(), slideSize.height());
|
|
|
|
if (contentRect.width() > 0 && contentRect.height() > 0) {
|
|
|
|
fDefaultMatrix.setRectToRect(slideBounds, contentRect, SkMatrix::kStart_ScaleToFit);
|
2016-05-20 18:41:01 +00:00
|
|
|
SkAssertResult(fDefaultMatrix.invert(&fDefaultMatrixInv));
|
2016-05-20 14:32:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fWindow->supportsContentRect()) {
|
|
|
|
const SkISize slideSize = fSlides[fCurrentSlide]->getDimensions();
|
|
|
|
SkRect windowRect = fWindow->getContentRect();
|
|
|
|
fDefaultMatrixInv.mapRect(&windowRect);
|
2016-06-01 16:39:15 +00:00
|
|
|
fGesture.setTransLimit(SkRect::MakeWH(SkIntToScalar(slideSize.width()),
|
|
|
|
SkIntToScalar(slideSize.height())),
|
|
|
|
windowRect);
|
2016-05-20 14:32:19 +00:00
|
|
|
}
|
|
|
|
|
2016-05-06 20:28:57 +00:00
|
|
|
this->updateTitle();
|
2016-05-27 15:52:52 +00:00
|
|
|
this->updateUIState();
|
2016-04-08 19:51:45 +00:00
|
|
|
if (previousSlide >= 0) {
|
|
|
|
fSlides[previousSlide]->unload();
|
|
|
|
}
|
|
|
|
fWindow->inval();
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MAX_ZOOM_LEVEL 8
|
|
|
|
#define MIN_ZOOM_LEVEL -8
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
void Viewer::changeZoomLevel(float delta) {
|
2016-04-08 19:51:45 +00:00
|
|
|
fZoomLevel += delta;
|
|
|
|
if (fZoomLevel > 0) {
|
|
|
|
fZoomLevel = SkMinScalar(fZoomLevel, MAX_ZOOM_LEVEL);
|
|
|
|
fZoomScale = fZoomLevel + SK_Scalar1;
|
|
|
|
} else if (fZoomLevel < 0) {
|
|
|
|
fZoomLevel = SkMaxScalar(fZoomLevel, MIN_ZOOM_LEVEL);
|
|
|
|
fZoomScale = SK_Scalar1 / (SK_Scalar1 - fZoomLevel);
|
|
|
|
} else {
|
|
|
|
fZoomScale = SK_Scalar1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-17 19:44:20 +00:00
|
|
|
SkMatrix Viewer::computeMatrix() {
|
2016-04-08 19:51:45 +00:00
|
|
|
SkMatrix m;
|
|
|
|
m.reset();
|
|
|
|
|
|
|
|
if (fZoomLevel) {
|
|
|
|
SkPoint center;
|
|
|
|
//m = this->getLocalMatrix();//.invert(&m);
|
|
|
|
m.mapXY(fZoomCenterX, fZoomCenterY, ¢er);
|
|
|
|
SkScalar cx = center.fX;
|
|
|
|
SkScalar cy = center.fY;
|
|
|
|
|
|
|
|
m.setTranslate(-cx, -cy);
|
|
|
|
m.postScale(fZoomScale, fZoomScale);
|
|
|
|
m.postTranslate(cx, cy);
|
|
|
|
}
|
|
|
|
|
2016-05-17 19:44:20 +00:00
|
|
|
m.preConcat(fGesture.localM());
|
|
|
|
m.preConcat(fGesture.globalM());
|
2016-04-08 19:51:45 +00:00
|
|
|
|
2016-05-17 19:44:20 +00:00
|
|
|
return m;
|
2016-04-08 19:51:45 +00:00
|
|
|
}
|
|
|
|
|
2017-02-28 20:45:01 +00:00
|
|
|
void Viewer::setBackend(sk_app::Window::BackendType backendType) {
|
|
|
|
fBackendType = backendType;
|
|
|
|
|
|
|
|
fWindow->detach();
|
|
|
|
|
|
|
|
#if defined(SK_BUILD_FOR_WIN) && defined(SK_VULKAN)
|
|
|
|
// Switching from OpenGL to Vulkan in the same window is problematic at this point on
|
|
|
|
// Windows, so we just delete the window and recreate it.
|
|
|
|
if (sk_app::Window::kVulkan_BackendType == fBackendType) {
|
2017-05-02 20:15:53 +00:00
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
2017-02-28 20:45:01 +00:00
|
|
|
delete fWindow;
|
|
|
|
fWindow = Window::CreateNativeWindow(nullptr);
|
|
|
|
|
|
|
|
// re-register callbacks
|
|
|
|
fCommands.attach(fWindow);
|
|
|
|
fWindow->registerBackendCreatedFunc(on_backend_created_func, this);
|
|
|
|
fWindow->registerPaintFunc(on_paint_handler, this);
|
|
|
|
fWindow->registerTouchFunc(on_touch_handler, this);
|
|
|
|
fWindow->registerUIStateChangedFunc(on_ui_state_changed_handler, this);
|
|
|
|
fWindow->registerMouseFunc(on_mouse_handler, this);
|
|
|
|
fWindow->registerMouseWheelFunc(on_mouse_wheel_handler, this);
|
|
|
|
fWindow->registerKeyFunc(on_key_handler, this);
|
|
|
|
fWindow->registerCharFunc(on_char_handler, this);
|
2017-05-02 20:15:53 +00:00
|
|
|
fWindow->setRequestedDisplayParams(params);
|
2017-02-28 20:45:01 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
fWindow->attach(fBackendType);
|
|
|
|
}
|
|
|
|
|
2017-03-06 16:47:26 +00:00
|
|
|
void Viewer::setColorMode(ColorMode colorMode) {
|
|
|
|
fColorMode = colorMode;
|
2016-06-13 19:26:45 +00:00
|
|
|
|
2017-02-08 15:47:28 +00:00
|
|
|
// When we're in color managed mode, we tag our window surface as sRGB. If we've switched into
|
2017-03-15 14:24:55 +00:00
|
|
|
// or out of legacy/nonlinear mode, we need to update our window configuration.
|
2017-02-24 23:04:47 +00:00
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
2017-03-06 16:47:26 +00:00
|
|
|
bool wasInLegacy = !SkToBool(params.fColorSpace);
|
2017-03-15 14:24:55 +00:00
|
|
|
bool wantLegacy = (ColorMode::kLegacy == fColorMode) ||
|
|
|
|
(ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode);
|
2017-03-06 16:47:26 +00:00
|
|
|
if (wasInLegacy != wantLegacy) {
|
|
|
|
params.fColorSpace = wantLegacy ? nullptr : SkColorSpace::MakeSRGB();
|
2017-02-24 23:04:47 +00:00
|
|
|
fWindow->setRequestedDisplayParams(params);
|
2017-02-08 15:47:28 +00:00
|
|
|
}
|
2016-04-21 14:59:44 +00:00
|
|
|
|
2017-02-08 15:47:28 +00:00
|
|
|
this->updateTitle();
|
|
|
|
fWindow->inval();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Viewer::drawSlide(SkCanvas* canvas) {
|
2017-02-22 20:21:11 +00:00
|
|
|
SkAutoCanvasRestore autorestore(canvas, false);
|
|
|
|
|
2016-04-21 14:59:44 +00:00
|
|
|
if (fWindow->supportsContentRect()) {
|
|
|
|
SkRect contentRect = fWindow->getContentRect();
|
|
|
|
canvas->clipRect(contentRect);
|
|
|
|
canvas->translate(contentRect.fLeft, contentRect.fTop);
|
|
|
|
}
|
|
|
|
|
2017-02-08 15:47:28 +00:00
|
|
|
// By default, we render directly into the window's surface/canvas
|
|
|
|
SkCanvas* slideCanvas = canvas;
|
2017-02-13 14:39:57 +00:00
|
|
|
fLastImage.reset();
|
2016-04-08 19:51:45 +00:00
|
|
|
|
2017-03-15 14:24:55 +00:00
|
|
|
// If we're in any of the color managed modes, construct the color space we're going to use
|
|
|
|
sk_sp<SkColorSpace> cs = nullptr;
|
|
|
|
if (ColorMode::kLegacy != fColorMode) {
|
|
|
|
auto transferFn = (ColorMode::kColorManagedLinearF16 == fColorMode)
|
|
|
|
? SkColorSpace::kLinear_RenderTargetGamma : SkColorSpace::kSRGB_RenderTargetGamma;
|
|
|
|
SkMatrix44 toXYZ;
|
|
|
|
SkAssertResult(fColorSpacePrimaries.toXYZD50(&toXYZ));
|
|
|
|
cs = SkColorSpace::MakeRGB(transferFn, toXYZ);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we're in F16, or we're zooming, or we're in color correct 8888 and the gamut isn't sRGB,
|
2017-03-06 16:47:26 +00:00
|
|
|
// we need to render offscreen
|
2017-02-08 15:47:28 +00:00
|
|
|
sk_sp<SkSurface> offscreenSurface = nullptr;
|
2017-03-06 16:47:26 +00:00
|
|
|
if (ColorMode::kColorManagedLinearF16 == fColorMode ||
|
|
|
|
fShowZoomWindow ||
|
2017-03-15 14:24:55 +00:00
|
|
|
(ColorMode::kColorManagedSRGB8888 == fColorMode &&
|
|
|
|
!primaries_equal(fColorSpacePrimaries, gSrgbPrimaries))) {
|
|
|
|
|
2017-03-06 16:47:26 +00:00
|
|
|
SkColorType colorType = (ColorMode::kColorManagedLinearF16 == fColorMode)
|
|
|
|
? kRGBA_F16_SkColorType : kN32_SkColorType;
|
2017-03-15 14:24:55 +00:00
|
|
|
// In nonlinear blending mode, we actually use a legacy off-screen canvas, and wrap it
|
|
|
|
// with a special canvas (below) that has the color space attached
|
|
|
|
sk_sp<SkColorSpace> offscreenColorSpace =
|
|
|
|
(ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) ? nullptr : cs;
|
2017-03-06 16:47:26 +00:00
|
|
|
SkImageInfo info = SkImageInfo::Make(fWindow->width(), fWindow->height(), colorType,
|
2017-03-15 14:24:55 +00:00
|
|
|
kPremul_SkAlphaType, std::move(offscreenColorSpace));
|
2017-02-08 15:47:28 +00:00
|
|
|
offscreenSurface = canvas->makeSurface(info);
|
|
|
|
slideCanvas = offscreenSurface->getCanvas();
|
2016-06-16 21:10:34 +00:00
|
|
|
}
|
|
|
|
|
2017-03-15 14:24:55 +00:00
|
|
|
std::unique_ptr<SkCanvas> xformCanvas = nullptr;
|
|
|
|
if (ColorMode::kColorManagedSRGB8888_NonLinearBlending == fColorMode) {
|
|
|
|
xformCanvas = SkCreateColorSpaceXformCanvas(slideCanvas, cs);
|
|
|
|
slideCanvas = xformCanvas.get();
|
|
|
|
}
|
|
|
|
|
2017-02-22 20:21:11 +00:00
|
|
|
int count = slideCanvas->save();
|
2017-02-08 15:47:28 +00:00
|
|
|
slideCanvas->clear(SK_ColorWHITE);
|
|
|
|
slideCanvas->concat(fDefaultMatrix);
|
|
|
|
slideCanvas->concat(computeMatrix());
|
2017-02-09 17:10:20 +00:00
|
|
|
// Time the painting logic of the slide
|
|
|
|
double startTime = SkTime::GetMSecs();
|
2017-02-08 15:47:28 +00:00
|
|
|
fSlides[fCurrentSlide]->draw(slideCanvas);
|
2017-02-09 17:10:20 +00:00
|
|
|
fPaintTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
|
2017-02-22 20:21:11 +00:00
|
|
|
slideCanvas->restoreToCount(count);
|
2017-02-09 17:10:20 +00:00
|
|
|
|
|
|
|
// Force a flush so we can time that, too
|
|
|
|
startTime = SkTime::GetMSecs();
|
|
|
|
slideCanvas->flush();
|
|
|
|
fFlushTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
|
2017-02-08 15:47:28 +00:00
|
|
|
|
|
|
|
// If we rendered offscreen, snap an image and push the results to the window's canvas
|
|
|
|
if (offscreenSurface) {
|
2017-02-13 14:39:57 +00:00
|
|
|
fLastImage = offscreenSurface->makeImageSnapshot();
|
2017-02-08 15:47:28 +00:00
|
|
|
|
|
|
|
// Tag the image with the sRGB gamut, so no further color space conversion happens
|
2017-03-15 14:24:55 +00:00
|
|
|
sk_sp<SkColorSpace> srgb = (ColorMode::kColorManagedLinearF16 == fColorMode)
|
2017-02-08 15:47:28 +00:00
|
|
|
? SkColorSpace::MakeSRGBLinear() : SkColorSpace::MakeSRGB();
|
2017-03-15 14:24:55 +00:00
|
|
|
auto retaggedImage = SkImageMakeRasterCopyAndAssignColorSpace(fLastImage.get(), srgb.get());
|
2017-02-22 20:21:11 +00:00
|
|
|
SkPaint paint;
|
|
|
|
paint.setBlendMode(SkBlendMode::kSrc);
|
|
|
|
canvas->drawImage(retaggedImage, 0, 0, &paint);
|
2016-06-16 21:10:34 +00:00
|
|
|
}
|
2016-06-13 19:26:45 +00:00
|
|
|
}
|
|
|
|
|
2017-02-24 20:22:53 +00:00
|
|
|
void Viewer::onBackendCreated() {
|
|
|
|
this->updateTitle();
|
|
|
|
this->updateUIState();
|
|
|
|
this->setupCurrentSlide(-1);
|
|
|
|
fWindow->show();
|
|
|
|
fWindow->inval();
|
|
|
|
}
|
2017-02-14 20:16:46 +00:00
|
|
|
|
2017-02-24 20:22:53 +00:00
|
|
|
void Viewer::onPaint(SkCanvas* canvas) {
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
// Update ImGui input
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
io.DeltaTime = 1.0f / 60.0f;
|
|
|
|
io.DisplaySize.x = static_cast<float>(fWindow->width());
|
|
|
|
io.DisplaySize.y = static_cast<float>(fWindow->height());
|
|
|
|
|
|
|
|
io.KeyAlt = io.KeysDown[static_cast<int>(Window::Key::kOption)];
|
|
|
|
io.KeyCtrl = io.KeysDown[static_cast<int>(Window::Key::kCtrl)];
|
|
|
|
io.KeyShift = io.KeysDown[static_cast<int>(Window::Key::kShift)];
|
|
|
|
|
|
|
|
ImGui::NewFrame();
|
|
|
|
|
2017-02-08 15:47:28 +00:00
|
|
|
drawSlide(canvas);
|
2016-04-07 18:09:51 +00:00
|
|
|
|
2017-02-09 17:10:20 +00:00
|
|
|
// Advance our timing bookkeeping
|
|
|
|
fCurrentMeasurement = (fCurrentMeasurement + 1) & (kMeasurementCount - 1);
|
|
|
|
SkASSERT(fCurrentMeasurement < kMeasurementCount);
|
|
|
|
|
|
|
|
// Draw any overlays or UI that we don't want timed
|
2016-04-08 19:51:45 +00:00
|
|
|
if (fDisplayStats) {
|
|
|
|
drawStats(canvas);
|
|
|
|
}
|
2016-05-10 13:50:49 +00:00
|
|
|
fCommands.drawHelp(canvas);
|
2016-07-06 21:11:32 +00:00
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
drawImGui(canvas);
|
|
|
|
|
2017-02-09 17:10:20 +00:00
|
|
|
// Update the FPS
|
|
|
|
updateUIState();
|
2016-04-07 18:09:51 +00:00
|
|
|
}
|
|
|
|
|
2016-06-06 15:48:47 +00:00
|
|
|
bool Viewer::onTouch(intptr_t owner, Window::InputState state, float x, float y) {
|
2016-05-17 19:44:20 +00:00
|
|
|
void* castedOwner = reinterpret_cast<void*>(owner);
|
2016-05-20 14:32:19 +00:00
|
|
|
SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
|
2016-05-17 19:44:20 +00:00
|
|
|
switch (state) {
|
|
|
|
case Window::kUp_InputState: {
|
|
|
|
fGesture.touchEnd(castedOwner);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Window::kDown_InputState: {
|
2016-05-20 14:32:19 +00:00
|
|
|
fGesture.touchBegin(castedOwner, touchPoint.fX, touchPoint.fY);
|
2016-05-17 19:44:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Window::kMove_InputState: {
|
2016-05-20 14:32:19 +00:00
|
|
|
fGesture.touchMoved(castedOwner, touchPoint.fX, touchPoint.fY);
|
2016-05-17 19:44:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fWindow->inval();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-04 18:00:59 +00:00
|
|
|
bool Viewer::onMouse(float x, float y, Window::InputState state, uint32_t modifiers) {
|
|
|
|
|
|
|
|
SkPoint touchPoint = fDefaultMatrixInv.mapXY(x, y);
|
|
|
|
switch (state) {
|
|
|
|
case Window::kUp_InputState: {
|
|
|
|
fGesture.touchEnd(nullptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Window::kDown_InputState: {
|
|
|
|
fGesture.touchBegin(nullptr, touchPoint.fX, touchPoint.fY);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Window::kMove_InputState: {
|
|
|
|
fGesture.touchMoved(nullptr, touchPoint.fX, touchPoint.fY);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fWindow->inval();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-05-04 20:49:13 +00:00
|
|
|
void Viewer::drawStats(SkCanvas* canvas) {
|
2016-04-07 18:09:51 +00:00
|
|
|
static const float kPixelPerMS = 2.0f;
|
|
|
|
static const int kDisplayWidth = 130;
|
|
|
|
static const int kDisplayHeight = 100;
|
|
|
|
static const int kDisplayPadding = 10;
|
|
|
|
static const int kGraphPadding = 3;
|
|
|
|
static const SkScalar kBaseMS = 1000.f / 60.f; // ms/frame to hit 60 fps
|
|
|
|
|
2017-02-22 18:21:42 +00:00
|
|
|
SkISize canvasSize = canvas->getBaseLayerSize();
|
2016-04-07 18:09:51 +00:00
|
|
|
SkRect rect = SkRect::MakeXYWH(SkIntToScalar(canvasSize.fWidth-kDisplayWidth-kDisplayPadding),
|
|
|
|
SkIntToScalar(kDisplayPadding),
|
|
|
|
SkIntToScalar(kDisplayWidth), SkIntToScalar(kDisplayHeight));
|
|
|
|
SkPaint paint;
|
|
|
|
canvas->save();
|
|
|
|
|
2016-04-21 14:59:44 +00:00
|
|
|
if (fWindow->supportsContentRect()) {
|
|
|
|
SkRect contentRect = fWindow->getContentRect();
|
|
|
|
canvas->clipRect(contentRect);
|
|
|
|
canvas->translate(contentRect.fLeft, contentRect.fTop);
|
|
|
|
}
|
|
|
|
|
2016-04-07 18:09:51 +00:00
|
|
|
canvas->clipRect(rect);
|
|
|
|
paint.setColor(SK_ColorBLACK);
|
|
|
|
canvas->drawRect(rect, paint);
|
|
|
|
// draw the 16ms line
|
|
|
|
paint.setColor(SK_ColorLTGRAY);
|
|
|
|
canvas->drawLine(rect.fLeft, rect.fBottom - kBaseMS*kPixelPerMS,
|
|
|
|
rect.fRight, rect.fBottom - kBaseMS*kPixelPerMS, paint);
|
|
|
|
paint.setColor(SK_ColorRED);
|
|
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
|
|
canvas->drawRect(rect, paint);
|
|
|
|
|
|
|
|
int x = SkScalarTruncToInt(rect.fLeft) + kGraphPadding;
|
|
|
|
const int xStep = 2;
|
|
|
|
int i = fCurrentMeasurement;
|
|
|
|
do {
|
2017-02-09 17:10:20 +00:00
|
|
|
// Round to nearest values
|
|
|
|
int animateHeight = (int)(fAnimateTimes[i] * kPixelPerMS + 0.5);
|
|
|
|
int paintHeight = (int)(fPaintTimes[i] * kPixelPerMS + 0.5);
|
|
|
|
int flushHeight = (int)(fFlushTimes[i] * kPixelPerMS + 0.5);
|
|
|
|
int startY = SkScalarTruncToInt(rect.fBottom);
|
|
|
|
int endY = startY - flushHeight;
|
|
|
|
paint.setColor(SK_ColorRED);
|
|
|
|
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
|
|
|
|
SkIntToScalar(x), SkIntToScalar(endY), paint);
|
|
|
|
startY = endY;
|
|
|
|
endY = startY - paintHeight;
|
|
|
|
paint.setColor(SK_ColorGREEN);
|
|
|
|
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
|
|
|
|
SkIntToScalar(x), SkIntToScalar(endY), paint);
|
|
|
|
startY = endY;
|
|
|
|
endY = startY - animateHeight;
|
|
|
|
paint.setColor(SK_ColorMAGENTA);
|
2016-04-07 18:09:51 +00:00
|
|
|
canvas->drawLine(SkIntToScalar(x), SkIntToScalar(startY),
|
|
|
|
SkIntToScalar(x), SkIntToScalar(endY), paint);
|
|
|
|
i++;
|
|
|
|
i &= (kMeasurementCount - 1); // fast mod
|
|
|
|
x += xStep;
|
|
|
|
} while (i != fCurrentMeasurement);
|
2016-04-06 13:08:59 +00:00
|
|
|
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
|
2017-02-24 14:49:14 +00:00
|
|
|
static ImVec2 ImGui_DragPrimary(const char* label, float* x, float* y,
|
|
|
|
const ImVec2& pos, const ImVec2& size) {
|
|
|
|
// Transform primaries ([0, 0] - [0.8, 0.9]) to screen coords (including Y-flip)
|
|
|
|
ImVec2 center(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);
|
|
|
|
|
|
|
|
// Invisible 10x10 button
|
|
|
|
ImGui::SetCursorScreenPos(ImVec2(center.x - 5, center.y - 5));
|
|
|
|
ImGui::InvisibleButton(label, ImVec2(10, 10));
|
|
|
|
|
|
|
|
if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) {
|
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
// Normalized mouse position, relative to our gamut box
|
|
|
|
ImVec2 mousePosXY((io.MousePos.x - pos.x) / size.x, (io.MousePos.y - pos.y) / size.y);
|
|
|
|
// Clamp to edge of box, convert back to primary scale
|
|
|
|
*x = SkTPin(mousePosXY.x, 0.0f, 1.0f) * 0.8f;
|
|
|
|
*y = SkTPin(1 - mousePosXY.y, 0.0f, 1.0f) * 0.9f;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ImGui::IsItemHovered()) {
|
|
|
|
ImGui::SetTooltip("x: %.3f\ny: %.3f", *x, *y);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return screen coordinates for the caller. We could just return center here, but we'd have
|
|
|
|
// one frame of lag during drag.
|
|
|
|
return ImVec2(pos.x + (*x / 0.8f) * size.x, pos.y + (1.0f - (*y / 0.9f)) * size.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ImGui_Primaries(SkColorSpacePrimaries* primaries, SkPaint* gamutPaint) {
|
|
|
|
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
|
|
|
|
|
|
|
// The gamut image covers a (0.8 x 0.9) shaped region, so fit our image/canvas to the available
|
|
|
|
// width, and scale the height to maintain aspect ratio.
|
|
|
|
float canvasWidth = SkTMax(ImGui::GetContentRegionAvailWidth(), 50.0f);
|
|
|
|
ImVec2 size = ImVec2(canvasWidth, canvasWidth * (0.9f / 0.8f));
|
|
|
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
|
|
|
|
|
|
|
// Background image. Only draw a subset of the image, to avoid the regions less than zero.
|
|
|
|
// Simplifes re-mapping math, clipping behavior, and increases resolution in the useful area.
|
|
|
|
// Magic numbers are pixel locations of the origin and upper-right corner.
|
|
|
|
drawList->AddImage(gamutPaint, pos, ImVec2(pos.x + size.x, pos.y + size.y),
|
|
|
|
ImVec2(242, 61), ImVec2(1897, 1922));
|
|
|
|
ImVec2 endPos = ImGui::GetCursorPos();
|
|
|
|
|
|
|
|
// Primary markers
|
|
|
|
ImVec2 r = ImGui_DragPrimary("R", &primaries->fRX, &primaries->fRY, pos, size);
|
|
|
|
ImVec2 g = ImGui_DragPrimary("G", &primaries->fGX, &primaries->fGY, pos, size);
|
|
|
|
ImVec2 b = ImGui_DragPrimary("B", &primaries->fBX, &primaries->fBY, pos, size);
|
|
|
|
ImVec2 w = ImGui_DragPrimary("W", &primaries->fWX, &primaries->fWY, pos, size);
|
|
|
|
|
|
|
|
// Gamut triangle
|
|
|
|
drawList->AddCircle(r, 5.0f, 0xFF000040);
|
|
|
|
drawList->AddCircle(g, 5.0f, 0xFF004000);
|
|
|
|
drawList->AddCircle(b, 5.0f, 0xFF400000);
|
|
|
|
drawList->AddCircle(w, 5.0f, 0xFFFFFFFF);
|
|
|
|
drawList->AddTriangle(r, g, b, 0xFFFFFFFF);
|
|
|
|
|
|
|
|
// Re-position cursor immediate after the diagram for subsequent controls
|
|
|
|
ImGui::SetCursorPos(endPos);
|
|
|
|
}
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
void Viewer::drawImGui(SkCanvas* canvas) {
|
|
|
|
// Support drawing the ImGui demo window. Superfluous, but gives a good idea of what's possible
|
|
|
|
if (fShowImGuiTestWindow) {
|
|
|
|
ImGui::ShowTestWindow(&fShowImGuiTestWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fShowImGuiDebugWindow) {
|
2017-02-24 14:49:14 +00:00
|
|
|
// We have some dynamic content that sizes to fill available size. If the scroll bar isn't
|
|
|
|
// always visible, we can end up in a layout feedback loop.
|
|
|
|
ImGui::SetNextWindowSize(ImVec2(400, 400), ImGuiSetCond_FirstUseEver);
|
2017-03-07 20:16:34 +00:00
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
|
|
|
bool paramsChanged = false;
|
2017-02-24 14:49:14 +00:00
|
|
|
if (ImGui::Begin("Tools", &fShowImGuiDebugWindow,
|
|
|
|
ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
|
2017-02-28 20:45:01 +00:00
|
|
|
if (ImGui::CollapsingHeader("Backend")) {
|
|
|
|
int newBackend = static_cast<int>(fBackendType);
|
|
|
|
ImGui::RadioButton("Raster", &newBackend, sk_app::Window::kRaster_BackendType);
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("OpenGL", &newBackend, sk_app::Window::kNativeGL_BackendType);
|
|
|
|
#if defined(SK_VULKAN)
|
|
|
|
ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("Vulkan", &newBackend, sk_app::Window::kVulkan_BackendType);
|
|
|
|
#endif
|
|
|
|
if (newBackend != fBackendType) {
|
|
|
|
fDeferredActions.push_back([=]() {
|
|
|
|
this->setBackend(static_cast<sk_app::Window::BackendType>(newBackend));
|
|
|
|
});
|
|
|
|
}
|
2017-03-01 19:59:05 +00:00
|
|
|
|
2017-03-07 20:16:34 +00:00
|
|
|
const GrContext* ctx = fWindow->getGrContext();
|
|
|
|
bool* inst = ¶ms.fGrContextOptions.fEnableInstancedRendering;
|
|
|
|
if (ctx && ImGui::Checkbox("Instanced Rendering", inst)) {
|
|
|
|
paramsChanged = true;
|
|
|
|
}
|
2017-05-02 20:15:53 +00:00
|
|
|
bool* wire = ¶ms.fGrContextOptions.fWireframeMode;
|
|
|
|
if (ctx && ImGui::Checkbox("Wireframe Mode", wire)) {
|
|
|
|
paramsChanged = true;
|
|
|
|
}
|
2017-03-07 20:16:34 +00:00
|
|
|
|
2017-03-08 22:10:24 +00:00
|
|
|
if (ctx) {
|
|
|
|
int sampleCount = fWindow->sampleCount();
|
|
|
|
ImGui::Text("MSAA: "); ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("0", &sampleCount, 0); ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("4", &sampleCount, 4); ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("8", &sampleCount, 8); ImGui::SameLine();
|
|
|
|
ImGui::RadioButton("16", &sampleCount, 16);
|
|
|
|
|
|
|
|
if (sampleCount != params.fMSAASampleCount) {
|
|
|
|
params.fMSAASampleCount = sampleCount;
|
|
|
|
paramsChanged = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-01 19:59:05 +00:00
|
|
|
if (ImGui::TreeNode("Path Renderers")) {
|
|
|
|
GpuPathRenderers prevPr = params.fGrContextOptions.fGpuPathRenderers;
|
|
|
|
auto prButton = [&](GpuPathRenderers x) {
|
|
|
|
if (ImGui::RadioButton(gPathRendererNames[x].c_str(), prevPr == x)) {
|
2017-03-07 20:16:34 +00:00
|
|
|
if (x != params.fGrContextOptions.fGpuPathRenderers) {
|
|
|
|
params.fGrContextOptions.fGpuPathRenderers = x;
|
|
|
|
paramsChanged = true;
|
|
|
|
}
|
2017-03-01 19:59:05 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!ctx) {
|
|
|
|
ImGui::RadioButton("Software", true);
|
|
|
|
} else if (fWindow->sampleCount()) {
|
|
|
|
prButton(GpuPathRenderers::kAll);
|
|
|
|
if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
|
|
|
|
prButton(GpuPathRenderers::kStencilAndCover);
|
|
|
|
}
|
|
|
|
if (ctx->caps()->sampleShadingSupport()) {
|
|
|
|
prButton(GpuPathRenderers::kMSAA);
|
|
|
|
}
|
|
|
|
prButton(GpuPathRenderers::kTessellating);
|
|
|
|
prButton(GpuPathRenderers::kDefault);
|
|
|
|
prButton(GpuPathRenderers::kNone);
|
|
|
|
} else {
|
|
|
|
prButton(GpuPathRenderers::kAll);
|
2017-03-16 12:45:39 +00:00
|
|
|
prButton(GpuPathRenderers::kSmall);
|
2017-03-01 19:59:05 +00:00
|
|
|
prButton(GpuPathRenderers::kTessellating);
|
|
|
|
prButton(GpuPathRenderers::kNone);
|
|
|
|
}
|
|
|
|
ImGui::TreePop();
|
|
|
|
}
|
2017-02-28 20:45:01 +00:00
|
|
|
}
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
if (ImGui::CollapsingHeader("Slide")) {
|
|
|
|
static ImGuiTextFilter filter;
|
|
|
|
filter.Draw();
|
|
|
|
int previousSlide = fCurrentSlide;
|
|
|
|
fCurrentSlide = 0;
|
|
|
|
for (auto slide : fSlides) {
|
|
|
|
if (filter.PassFilter(slide->getName().c_str())) {
|
|
|
|
ImGui::BulletText("%s", slide->getName().c_str());
|
|
|
|
if (ImGui::IsItemClicked()) {
|
|
|
|
setupCurrentSlide(previousSlide);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++fCurrentSlide;
|
|
|
|
}
|
|
|
|
if (fCurrentSlide >= fSlides.count()) {
|
|
|
|
fCurrentSlide = previousSlide;
|
|
|
|
}
|
|
|
|
}
|
2017-02-24 14:49:14 +00:00
|
|
|
|
|
|
|
if (ImGui::CollapsingHeader("Color Mode")) {
|
2017-03-06 16:47:26 +00:00
|
|
|
ColorMode newMode = fColorMode;
|
|
|
|
auto cmButton = [&](ColorMode mode, const char* label) {
|
|
|
|
if (ImGui::RadioButton(label, mode == fColorMode)) {
|
|
|
|
newMode = mode;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
cmButton(ColorMode::kLegacy, "Legacy 8888");
|
|
|
|
cmButton(ColorMode::kColorManagedSRGB8888_NonLinearBlending,
|
|
|
|
"Color Managed 8888 (Nonlinear blending)");
|
|
|
|
cmButton(ColorMode::kColorManagedSRGB8888, "Color Managed 8888");
|
|
|
|
cmButton(ColorMode::kColorManagedLinearF16, "Color Managed F16");
|
|
|
|
|
|
|
|
if (newMode != fColorMode) {
|
2017-02-24 16:57:23 +00:00
|
|
|
// It isn't safe to switch color mode now (in the middle of painting). We might
|
|
|
|
// tear down the back-end, etc... Defer this change until the next onIdle.
|
|
|
|
fDeferredActions.push_back([=]() {
|
2017-03-06 16:47:26 +00:00
|
|
|
this->setColorMode(newMode);
|
2017-02-24 16:57:23 +00:00
|
|
|
});
|
2017-02-24 14:49:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Pick from common gamuts:
|
|
|
|
int primariesIdx = 4; // Default: Custom
|
|
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(gNamedPrimaries); ++i) {
|
|
|
|
if (primaries_equal(*gNamedPrimaries[i].fPrimaries, fColorSpacePrimaries)) {
|
|
|
|
primariesIdx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ImGui::Combo("Primaries", &primariesIdx,
|
|
|
|
"sRGB\0AdobeRGB\0P3\0Rec. 2020\0Custom\0\0")) {
|
|
|
|
if (primariesIdx >= 0 && primariesIdx <= 3) {
|
|
|
|
fColorSpacePrimaries = *gNamedPrimaries[primariesIdx].fPrimaries;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allow direct editing of gamut
|
|
|
|
ImGui_Primaries(&fColorSpacePrimaries, &fImGuiGamutPaint);
|
|
|
|
}
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
}
|
2017-03-07 20:16:34 +00:00
|
|
|
if (paramsChanged) {
|
|
|
|
fDeferredActions.push_back([=]() {
|
|
|
|
fWindow->setRequestedDisplayParams(params);
|
|
|
|
fWindow->inval();
|
|
|
|
this->updateTitle();
|
|
|
|
});
|
|
|
|
}
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
2017-02-13 14:39:57 +00:00
|
|
|
SkPaint zoomImagePaint;
|
|
|
|
if (fShowZoomWindow && fLastImage) {
|
|
|
|
if (ImGui::Begin("Zoom", &fShowZoomWindow, ImVec2(200, 200))) {
|
|
|
|
static int zoomFactor = 4;
|
|
|
|
ImGui::SliderInt("Scale", &zoomFactor, 1, 16);
|
|
|
|
|
2017-04-28 15:12:19 +00:00
|
|
|
zoomImagePaint.setShader(fLastImage->makeShader());
|
2017-02-13 14:39:57 +00:00
|
|
|
zoomImagePaint.setColor(SK_ColorWHITE);
|
|
|
|
|
|
|
|
// Zoom by shrinking the corner UVs towards the mouse cursor
|
|
|
|
ImVec2 mousePos = ImGui::GetMousePos();
|
|
|
|
ImVec2 avail = ImGui::GetContentRegionAvail();
|
|
|
|
|
|
|
|
ImVec2 zoomHalfExtents = ImVec2((avail.x * 0.5f) / zoomFactor,
|
|
|
|
(avail.y * 0.5f) / zoomFactor);
|
|
|
|
ImGui::Image(&zoomImagePaint, avail,
|
|
|
|
ImVec2(mousePos.x - zoomHalfExtents.x, mousePos.y - zoomHalfExtents.y),
|
|
|
|
ImVec2(mousePos.x + zoomHalfExtents.x, mousePos.y + zoomHalfExtents.y));
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::End();
|
|
|
|
}
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
// This causes ImGui to rebuild vertex/index data based on all immediate-mode commands
|
|
|
|
// (widgets, etc...) that have been issued
|
|
|
|
ImGui::Render();
|
|
|
|
|
|
|
|
// Then we fetch the most recent data, and convert it so we can render with Skia
|
|
|
|
const ImDrawData* drawData = ImGui::GetDrawData();
|
|
|
|
SkTDArray<SkPoint> pos;
|
|
|
|
SkTDArray<SkPoint> uv;
|
|
|
|
SkTDArray<SkColor> color;
|
|
|
|
|
|
|
|
for (int i = 0; i < drawData->CmdListsCount; ++i) {
|
|
|
|
const ImDrawList* drawList = drawData->CmdLists[i];
|
|
|
|
|
|
|
|
// De-interleave all vertex data (sigh), convert to Skia types
|
|
|
|
pos.rewind(); uv.rewind(); color.rewind();
|
|
|
|
for (int i = 0; i < drawList->VtxBuffer.size(); ++i) {
|
|
|
|
const ImDrawVert& vert = drawList->VtxBuffer[i];
|
|
|
|
pos.push(SkPoint::Make(vert.pos.x, vert.pos.y));
|
|
|
|
uv.push(SkPoint::Make(vert.uv.x, vert.uv.y));
|
|
|
|
color.push(vert.col);
|
|
|
|
}
|
|
|
|
// ImGui colors are RGBA
|
|
|
|
SkSwapRB(color.begin(), color.begin(), color.count());
|
|
|
|
|
|
|
|
int indexOffset = 0;
|
|
|
|
|
|
|
|
// Draw everything with canvas.drawVertices...
|
|
|
|
for (int j = 0; j < drawList->CmdBuffer.size(); ++j) {
|
|
|
|
const ImDrawCmd* drawCmd = &drawList->CmdBuffer[j];
|
|
|
|
|
|
|
|
// TODO: Find min/max index for each draw, so we know how many vertices (sigh)
|
|
|
|
if (drawCmd->UserCallback) {
|
|
|
|
drawCmd->UserCallback(drawList, drawCmd);
|
|
|
|
} else {
|
2017-02-13 14:39:57 +00:00
|
|
|
SkPaint* paint = static_cast<SkPaint*>(drawCmd->TextureId);
|
|
|
|
SkASSERT(paint);
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
canvas->save();
|
|
|
|
canvas->clipRect(SkRect::MakeLTRB(drawCmd->ClipRect.x, drawCmd->ClipRect.y,
|
|
|
|
drawCmd->ClipRect.z, drawCmd->ClipRect.w));
|
2017-04-03 15:11:09 +00:00
|
|
|
canvas->drawVertices(SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode,
|
|
|
|
drawList->VtxBuffer.size(), pos.begin(),
|
|
|
|
uv.begin(), color.begin(),
|
|
|
|
drawCmd->ElemCount,
|
|
|
|
drawList->IdxBuffer.begin() + indexOffset),
|
|
|
|
SkBlendMode::kModulate, *paint);
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
indexOffset += drawCmd->ElemCount;
|
|
|
|
canvas->restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-06 21:11:32 +00:00
|
|
|
void Viewer::onIdle() {
|
2017-02-24 16:57:23 +00:00
|
|
|
for (int i = 0; i < fDeferredActions.count(); ++i) {
|
|
|
|
fDeferredActions[i]();
|
|
|
|
}
|
|
|
|
fDeferredActions.reset();
|
|
|
|
|
2017-02-09 17:10:20 +00:00
|
|
|
double startTime = SkTime::GetMSecs();
|
2016-04-08 19:51:45 +00:00
|
|
|
fAnimTimer.updateTime();
|
2017-02-09 17:10:20 +00:00
|
|
|
bool animateWantsInval = fSlides[fCurrentSlide]->animate(fAnimTimer);
|
|
|
|
fAnimateTimes[fCurrentMeasurement] = SkTime::GetMSecs() - startTime;
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
ImGuiIO& io = ImGui::GetIO();
|
|
|
|
if (animateWantsInval || fDisplayStats || fRefresh || io.MetricsActiveWindows) {
|
2016-04-08 19:51:45 +00:00
|
|
|
fWindow->inval();
|
|
|
|
}
|
2016-04-06 13:08:59 +00:00
|
|
|
}
|
2016-05-27 15:52:52 +00:00
|
|
|
|
|
|
|
void Viewer::updateUIState() {
|
2017-02-24 23:04:47 +00:00
|
|
|
if (!fWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fWindow->sampleCount() < 0) {
|
|
|
|
return; // Surface hasn't been created yet.
|
|
|
|
}
|
|
|
|
|
2016-06-03 15:47:23 +00:00
|
|
|
// Slide state
|
2016-05-27 15:52:52 +00:00
|
|
|
Json::Value slideState(Json::objectValue);
|
|
|
|
slideState[kName] = kSlideStateName;
|
|
|
|
slideState[kValue] = fSlides[fCurrentSlide]->getName().c_str();
|
2016-06-07 13:57:40 +00:00
|
|
|
if (fAllSlideNames.size() == 0) {
|
|
|
|
for(auto slide : fSlides) {
|
|
|
|
fAllSlideNames.append(Json::Value(slide->getName().c_str()));
|
|
|
|
}
|
2016-05-27 15:52:52 +00:00
|
|
|
}
|
2016-06-07 13:57:40 +00:00
|
|
|
slideState[kOptions] = fAllSlideNames;
|
2016-05-27 15:52:52 +00:00
|
|
|
|
2016-06-03 15:47:23 +00:00
|
|
|
// Backend state
|
2016-05-27 15:52:52 +00:00
|
|
|
Json::Value backendState(Json::objectValue);
|
|
|
|
backendState[kName] = kBackendStateName;
|
2016-06-02 19:16:25 +00:00
|
|
|
backendState[kValue] = kBackendTypeStrings[fBackendType];
|
2016-05-27 15:52:52 +00:00
|
|
|
backendState[kOptions] = Json::Value(Json::arrayValue);
|
2016-06-03 15:47:23 +00:00
|
|
|
for (auto str : kBackendTypeStrings) {
|
2016-06-02 19:16:25 +00:00
|
|
|
backendState[kOptions].append(Json::Value(str));
|
|
|
|
}
|
2016-05-27 15:52:52 +00:00
|
|
|
|
2017-02-24 23:04:47 +00:00
|
|
|
// MSAA state
|
|
|
|
Json::Value msaaState(Json::objectValue);
|
|
|
|
msaaState[kName] = kMSAAStateName;
|
|
|
|
msaaState[kValue] = fWindow->sampleCount();
|
|
|
|
msaaState[kOptions] = Json::Value(Json::arrayValue);
|
|
|
|
if (sk_app::Window::kRaster_BackendType == fBackendType) {
|
|
|
|
msaaState[kOptions].append(Json::Value(0));
|
|
|
|
} else {
|
|
|
|
for (int msaa : {0, 4, 8, 16}) {
|
|
|
|
msaaState[kOptions].append(Json::Value(msaa));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-28 00:00:53 +00:00
|
|
|
// Path renderer state
|
|
|
|
GpuPathRenderers pr = fWindow->getRequestedDisplayParams().fGrContextOptions.fGpuPathRenderers;
|
|
|
|
Json::Value prState(Json::objectValue);
|
|
|
|
prState[kName] = kPathRendererStateName;
|
|
|
|
prState[kValue] = gPathRendererNames[pr];
|
|
|
|
prState[kOptions] = Json::Value(Json::arrayValue);
|
|
|
|
const GrContext* ctx = fWindow->getGrContext();
|
|
|
|
if (!ctx) {
|
|
|
|
prState[kOptions].append("Software");
|
|
|
|
} else if (fWindow->sampleCount()) {
|
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
|
|
|
|
if (ctx->caps()->shaderCaps()->pathRenderingSupport()) {
|
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kStencilAndCover]);
|
|
|
|
}
|
|
|
|
if (ctx->caps()->sampleShadingSupport()) {
|
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kMSAA]);
|
|
|
|
}
|
2017-03-01 19:59:05 +00:00
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
|
2017-02-28 00:00:53 +00:00
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kDefault]);
|
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
|
|
|
|
} else {
|
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kAll]);
|
2017-03-16 12:45:39 +00:00
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kSmall]);
|
2017-03-01 19:59:05 +00:00
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kTessellating]);
|
2017-02-28 00:00:53 +00:00
|
|
|
prState[kOptions].append(gPathRendererNames[GpuPathRenderers::kNone]);
|
|
|
|
}
|
|
|
|
|
2017-03-07 20:16:34 +00:00
|
|
|
// Instanced rendering state
|
|
|
|
Json::Value instState(Json::objectValue);
|
|
|
|
instState[kName] = kInstancedRenderingStateName;
|
|
|
|
if (ctx) {
|
|
|
|
if (fWindow->getRequestedDisplayParams().fGrContextOptions.fEnableInstancedRendering) {
|
|
|
|
instState[kValue] = kON;
|
|
|
|
} else {
|
|
|
|
instState[kValue] = kOFF;
|
|
|
|
}
|
|
|
|
instState[kOptions] = Json::Value(Json::arrayValue);
|
|
|
|
instState[kOptions].append(kOFF);
|
|
|
|
instState[kOptions].append(kON);
|
|
|
|
}
|
|
|
|
|
2016-06-03 15:47:23 +00:00
|
|
|
// Softkey state
|
|
|
|
Json::Value softkeyState(Json::objectValue);
|
|
|
|
softkeyState[kName] = kSoftkeyStateName;
|
|
|
|
softkeyState[kValue] = kSoftkeyHint;
|
|
|
|
softkeyState[kOptions] = Json::Value(Json::arrayValue);
|
|
|
|
softkeyState[kOptions].append(kSoftkeyHint);
|
|
|
|
for (const auto& softkey : fCommands.getCommandsAsSoftkeys()) {
|
|
|
|
softkeyState[kOptions].append(Json::Value(softkey.c_str()));
|
|
|
|
}
|
|
|
|
|
2016-06-07 13:57:40 +00:00
|
|
|
// FPS state
|
|
|
|
Json::Value fpsState(Json::objectValue);
|
|
|
|
fpsState[kName] = kFpsStateName;
|
2017-02-09 17:10:20 +00:00
|
|
|
int idx = (fCurrentMeasurement + (kMeasurementCount - 1)) & (kMeasurementCount - 1);
|
|
|
|
fpsState[kValue] = SkStringPrintf("%8.3lf ms\n\nA %8.3lf\nP %8.3lf\nF%8.3lf",
|
|
|
|
fAnimateTimes[idx] + fPaintTimes[idx] + fFlushTimes[idx],
|
|
|
|
fAnimateTimes[idx],
|
|
|
|
fPaintTimes[idx],
|
|
|
|
fFlushTimes[idx]).c_str();
|
2016-06-07 13:57:40 +00:00
|
|
|
fpsState[kOptions] = Json::Value(Json::arrayValue);
|
|
|
|
|
2016-05-27 15:52:52 +00:00
|
|
|
Json::Value state(Json::arrayValue);
|
|
|
|
state.append(slideState);
|
|
|
|
state.append(backendState);
|
2017-02-24 23:04:47 +00:00
|
|
|
state.append(msaaState);
|
2017-02-28 00:00:53 +00:00
|
|
|
state.append(prState);
|
2017-03-07 20:16:34 +00:00
|
|
|
state.append(instState);
|
2016-06-03 15:47:23 +00:00
|
|
|
state.append(softkeyState);
|
2016-06-07 13:57:40 +00:00
|
|
|
state.append(fpsState);
|
2016-05-27 15:52:52 +00:00
|
|
|
|
|
|
|
fWindow->setUIState(state);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Viewer::onUIStateChanged(const SkString& stateName, const SkString& stateValue) {
|
2016-06-02 19:16:25 +00:00
|
|
|
// For those who will add more features to handle the state change in this function:
|
|
|
|
// After the change, please call updateUIState no notify the frontend (e.g., Android app).
|
|
|
|
// For example, after slide change, updateUIState is called inside setupCurrentSlide;
|
|
|
|
// after backend change, updateUIState is called in this function.
|
2016-05-27 15:52:52 +00:00
|
|
|
if (stateName.equals(kSlideStateName)) {
|
|
|
|
int previousSlide = fCurrentSlide;
|
|
|
|
fCurrentSlide = 0;
|
|
|
|
for(auto slide : fSlides) {
|
|
|
|
if (slide->getName().equals(stateValue)) {
|
2017-03-07 20:16:34 +00:00
|
|
|
this->setupCurrentSlide(previousSlide);
|
2016-05-27 15:52:52 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
fCurrentSlide++;
|
|
|
|
}
|
|
|
|
if (fCurrentSlide >= fSlides.count()) {
|
|
|
|
fCurrentSlide = previousSlide;
|
|
|
|
SkDebugf("Slide not found: %s", stateValue.c_str());
|
|
|
|
}
|
2016-06-02 19:16:25 +00:00
|
|
|
} else if (stateName.equals(kBackendStateName)) {
|
|
|
|
for (int i = 0; i < sk_app::Window::kBackendTypeCount; i++) {
|
|
|
|
if (stateValue.equals(kBackendTypeStrings[i])) {
|
|
|
|
if (fBackendType != i) {
|
|
|
|
fBackendType = (sk_app::Window::BackendType)i;
|
|
|
|
fWindow->detach();
|
2017-02-24 23:04:47 +00:00
|
|
|
fWindow->attach(fBackendType);
|
2016-06-02 19:16:25 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-02-24 23:04:47 +00:00
|
|
|
} else if (stateName.equals(kMSAAStateName)) {
|
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
|
|
|
int sampleCount = atoi(stateValue.c_str());
|
|
|
|
if (sampleCount != params.fMSAASampleCount) {
|
|
|
|
params.fMSAASampleCount = sampleCount;
|
|
|
|
fWindow->setRequestedDisplayParams(params);
|
|
|
|
fWindow->inval();
|
2017-03-07 20:16:34 +00:00
|
|
|
this->updateTitle();
|
|
|
|
this->updateUIState();
|
2017-02-28 00:00:53 +00:00
|
|
|
}
|
|
|
|
} else if (stateName.equals(kPathRendererStateName)) {
|
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
|
|
|
for (const auto& pair : gPathRendererNames) {
|
|
|
|
if (pair.second == stateValue.c_str()) {
|
|
|
|
if (params.fGrContextOptions.fGpuPathRenderers != pair.first) {
|
|
|
|
params.fGrContextOptions.fGpuPathRenderers = pair.first;
|
|
|
|
fWindow->setRequestedDisplayParams(params);
|
|
|
|
fWindow->inval();
|
2017-03-07 20:16:34 +00:00
|
|
|
this->updateTitle();
|
|
|
|
this->updateUIState();
|
2017-02-28 00:00:53 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2017-02-24 23:04:47 +00:00
|
|
|
}
|
2017-03-07 20:16:34 +00:00
|
|
|
} else if (stateName.equals(kInstancedRenderingStateName)) {
|
|
|
|
DisplayParams params = fWindow->getRequestedDisplayParams();
|
|
|
|
bool value = !strcmp(stateValue.c_str(), kON);
|
|
|
|
if (params.fGrContextOptions.fEnableInstancedRendering != value) {
|
|
|
|
params.fGrContextOptions.fEnableInstancedRendering = value;
|
|
|
|
fWindow->setRequestedDisplayParams(params);
|
|
|
|
fWindow->inval();
|
|
|
|
this->updateTitle();
|
|
|
|
this->updateUIState();
|
|
|
|
}
|
2016-06-03 15:47:23 +00:00
|
|
|
} else if (stateName.equals(kSoftkeyStateName)) {
|
|
|
|
if (!stateValue.equals(kSoftkeyHint)) {
|
|
|
|
fCommands.onSoftkey(stateValue);
|
2017-03-07 20:16:34 +00:00
|
|
|
this->updateUIState(); // This is still needed to reset the value to kSoftkeyHint
|
2016-06-03 15:47:23 +00:00
|
|
|
}
|
2016-07-06 21:11:32 +00:00
|
|
|
} else if (stateName.equals(kRefreshStateName)) {
|
|
|
|
// This state is actually NOT in the UI state.
|
|
|
|
// We use this to allow Android to quickly set bool fRefresh.
|
|
|
|
fRefresh = stateValue.equals(kON);
|
2016-05-27 15:52:52 +00:00
|
|
|
} else {
|
|
|
|
SkDebugf("Unknown stateName: %s", stateName.c_str());
|
|
|
|
}
|
|
|
|
}
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
|
|
|
|
bool Viewer::onKey(sk_app::Window::Key key, sk_app::Window::InputState state, uint32_t modifiers) {
|
|
|
|
return fCommands.onKey(key, state, modifiers);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Viewer::onChar(SkUnichar c, uint32_t modifiers) {
|
2017-02-14 20:16:46 +00:00
|
|
|
if (fSlides[fCurrentSlide]->onChar(c)) {
|
|
|
|
fWindow->inval();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
Integrate the ImGui library with viewer
Code and docs are at: https://github.com/ocornut/imgui
ImGui is an open source immediate mode GUI library that's
lightweight and fairly simply to integrate. Widget functions
return their state, and the library emits vertex and index
data to render everything. It's got a huge set of built-in
widgets and really robust layout control.
For the initial integration, I had to fix up event handling
in the viewer's app framework (to get mouse wheel and more
keys, etc...).
The new viewer 'Debug' window is toggled with the space bar.
For this change, I've added one feature to that window: the
slide picker. It's got a list of all slides, with filtering
support, and the ability to click to switch slides.
I also included the ImGui 'Demo' window (toggled with 'g').
This is nicely laid out, and includes examples of pretty
much everything the library can do. It also serves as good
documentation - find something that looks like what you want,
and then go look at the corresponding code (all of it is in
imgui_demo.cpp).
I have other CLs with other features (like directly editing
the primaries of the working color space), but I wanted to
land this chunk first, then start adding more features.
Other than adding new debugging features, there are few
more outstanding work items:
1) Raster doesn't render the GUI correctly, due to non-
invertible pos -> UV matrices. Florin is working on that.
2) Touch inputs aren't being routed yet, so the GUI isn't
usable on Android yet. Might also be tough to work with,
given the size.
3) ImGui has clipboard integration (that's why it wants
the C, X, and V keys), but we need to wire it up to the
OS' clipboard functions.
4) Draw commands can carry a void* payload to support
drawing images (using whatever mechanism the engine has).
I'd like to set that up (probably using SkImage*), which
makes it really easy to add visualization of off-screen
images in GMs, etc...
BUG=skia:
Change-Id: Iac2a63e37228d33141cb55b7e4d60bf11b7e9ae1
Reviewed-on: https://skia-review.googlesource.com/7702
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2017-02-10 18:36:16 +00:00
|
|
|
return fCommands.onChar(c, modifiers);
|
|
|
|
}
|