From ef4df93e06f19f526c1f3699237fd0e0f8b61413 Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Mon, 21 Sep 2015 15:45:09 -0700 Subject: [PATCH 1/2] SkPicture tracing to file follows same path as rendering into the OpenGL context --- sky/compositor/paint_context.cc | 34 +++++++++++++++++++++++ sky/compositor/paint_context.h | 21 ++++++++------- sky/shell/gpu/rasterizer.cc | 48 ++++++++++++++------------------- sky/shell/ios/sky_surface.mm | 39 +++++++++++---------------- sky/shell/shell_view.cc | 6 ----- sky/shell/shell_view.h | 2 -- sky/shell/tracing_controller.cc | 24 ++++++++++++----- sky/shell/tracing_controller.h | 10 ++++++- sky/shell/ui/engine.cc | 3 --- sky/shell/ui/engine.h | 2 -- 10 files changed, 106 insertions(+), 83 deletions(-) diff --git a/sky/compositor/paint_context.cc b/sky/compositor/paint_context.cc index 15178d68f44..1247a585fe7 100644 --- a/sky/compositor/paint_context.cc +++ b/sky/compositor/paint_context.cc @@ -5,6 +5,7 @@ #include "sky/compositor/paint_context.h" #include "base/logging.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "services/sky/compositor/picture_serializer.h" namespace sky { namespace compositor { @@ -55,6 +56,39 @@ PaintContext::ScopedFrame PaintContext::AcquireFrame(SkCanvas& canvas) { return ScopedFrame(*this, canvas); } +PaintContext::ScopedFrame PaintContext::AcquireFrame( + const std::string& trace_file_name) { + return ScopedFrame(*this, trace_file_name); +} + +PaintContext::ScopedFrame::ScopedFrame(PaintContext& context, SkCanvas& canvas) + : context_(context), canvas_(&canvas) { + context_.beginFrame(*this); +}; + +PaintContext::ScopedFrame::ScopedFrame(ScopedFrame&& frame) = default; + +PaintContext::ScopedFrame::ScopedFrame(PaintContext& context, + const std::string& trace_file_name) + : context_(context), + trace_file_name_(trace_file_name), + trace_recorder_(new SkPictureRecorder()) { + trace_recorder_->beginRecording( + SkRect::MakeWH(SK_ScalarInfinity, SK_ScalarInfinity)); + canvas_ = trace_recorder_->getRecordingCanvas(); + DCHECK(canvas_); + context_.beginFrame(*this); +}; + +PaintContext::ScopedFrame::~ScopedFrame() { + context_.endFrame(*this); + + if (trace_file_name_.length() > 0) { + auto picture = trace_recorder_->endRecordingAsPicture(); + SerializePicture(trace_file_name_.c_str(), picture); + } +} + PaintContext::~PaintContext() { } diff --git a/sky/compositor/paint_context.h b/sky/compositor/paint_context.h index f7cd8c858ac..7f3fc0ffe92 100644 --- a/sky/compositor/paint_context.h +++ b/sky/compositor/paint_context.h @@ -10,6 +10,7 @@ #include "sky/compositor/compositor_options.h" #include "sky/compositor/instrumentation.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" namespace sky { namespace compositor { @@ -18,23 +19,21 @@ class PaintContext { public: class ScopedFrame { public: - SkCanvas& canvas() { return canvas_; } + SkCanvas& canvas() { return *canvas_; } - ScopedFrame(ScopedFrame&& frame) = default; + ScopedFrame(ScopedFrame&& frame); - ~ScopedFrame() { context_.endFrame(*this); } + ~ScopedFrame(); private: PaintContext& context_; - SkCanvas& canvas_; + SkCanvas* canvas_; + std::string trace_file_name_; + std::unique_ptr trace_recorder_; - ScopedFrame() = delete; + ScopedFrame(PaintContext& context, SkCanvas& canvas); - ScopedFrame(PaintContext& context, SkCanvas& canvas) - : context_(context), canvas_(canvas) { - DCHECK(&canvas) << "The frame requries a valid canvas"; - context_.beginFrame(*this); - }; + ScopedFrame(PaintContext& context, const std::string& trace_file_name); friend class PaintContext; @@ -48,6 +47,8 @@ class PaintContext { ScopedFrame AcquireFrame(SkCanvas& canvas); + ScopedFrame AcquireFrame(const std::string& trace_file_name); + private: CompositorOptions options_; diff --git a/sky/shell/gpu/rasterizer.cc b/sky/shell/gpu/rasterizer.cc index 1f3e876bd94..58ac621d938 100644 --- a/sky/shell/gpu/rasterizer.cc +++ b/sky/shell/gpu/rasterizer.cc @@ -12,40 +12,24 @@ #include "sky/shell/gpu/ganesh_context.h" #include "sky/shell/gpu/ganesh_surface.h" #include "sky/shell/gpu/picture_serializer.h" +#include "sky/shell/shell.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPicture.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" +#include "mojo/public/cpp/system/data_pipe.h" // Set this value to 1 to serialize the layer tree to disk. #define SERIALIZE_LAYER_TREE 0 namespace sky { namespace shell { -namespace { - -#if SERIALIZE_LAYER_TREE - -void SketchySerializeLayerTree(const char* path, - compositor::LayerTree* layer_tree) { - const auto& layers = - static_cast(layer_tree->root_layer()) - ->layers(); - if (layers.empty()) - return; - SerializePicture( - path, static_cast(layers[0].get())->picture()); -} - -#endif - -} // namespace Rasterizer::Rasterizer() - : share_group_(new gfx::GLShareGroup()), - weak_factory_(this) {} + : share_group_(new gfx::GLShareGroup()), weak_factory_(this) { +} Rasterizer::~Rasterizer() { } @@ -55,8 +39,8 @@ base::WeakPtr Rasterizer::GetWeakPtr() { } void Rasterizer::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) { - surface_ = gfx::GLSurface::CreateViewGLSurface(widget, - gfx::SurfaceConfiguration()); + surface_ = + gfx::GLSurface::CreateViewGLSurface(widget, gfx::SurfaceConfiguration()); CHECK(surface_) << "GLSurface required."; } @@ -72,6 +56,8 @@ void Rasterizer::Draw(scoped_ptr layer_tree) { if (surface_->GetSize() != size) surface_->Resize(size); + // Use the canvas from the Ganesh Surface to render the current frame into + EnsureGLContext(); CHECK(context_->MakeCurrent(surface_.get())); EnsureGaneshSurface(surface_->GetBackingFrameBufferObject(), size); @@ -79,16 +65,22 @@ void Rasterizer::Draw(scoped_ptr layer_tree) { canvas->clear(SK_ColorBLACK); { - auto frame = paint_context_.AcquireFrame(*canvas); + sky::compositor::PaintContext::ScopedFrame frame = + paint_context_.AcquireFrame(*canvas); layer_tree->root_layer()->Paint(frame); } canvas->flush(); surface_->SwapBuffers(); -#if SERIALIZE_LAYER_TREE - SketchySerializeLayerTree("/data/data/org.domokit.sky.shell/cache/layer0.skp", - layer_tree.get()); -#endif + // Optionally, if the user has specified tracing the current scene to a file, + // acquire another frame and draw into it to obtain an SkPicture to serialize + + auto options = Shell::Shared().tracing_controller().picture_tracing_options(); + if (options.first) { + sky::compositor::PaintContext::ScopedFrame to_file_frame = + paint_context_.AcquireFrame(options.second); + layer_tree->root_layer()->Paint(to_file_frame); + } } void Rasterizer::OnOutputSurfaceDestroyed() { @@ -118,7 +110,7 @@ void Rasterizer::EnsureGaneshSurface(intptr_t window_fbo, const gfx::Size& size) { if (!ganesh_surface_ || ganesh_surface_->size() != size) ganesh_surface_.reset( - new GaneshSurface(window_fbo, ganesh_context_.get(), size)); + new GaneshSurface(window_fbo, ganesh_context_.get(), size)); } } // namespace shell diff --git a/sky/shell/ios/sky_surface.mm b/sky/shell/ios/sky_surface.mm index 9264ebbc879..d41843fd2cd 100644 --- a/sky/shell/ios/sky_surface.mm +++ b/sky/shell/ios/sky_surface.mm @@ -55,9 +55,24 @@ static inline int64 InputEventTimestampFromNSTimeInterval( #endif } +static std::string SkPictureTracingPath() { + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, + NSUserDomainMask, YES); + + char* temp = reinterpret_cast(calloc(256, sizeof(char))); + snprintf(temp, 256, "%s/layers.skp", [paths.firstObject UTF8String]); + std::string path(temp); + free(temp); + + return path; +} + -(instancetype) initWithShellView:(sky::shell::ShellView *) shellView { self = [super init]; if (self) { + sky::shell::Shell::Shared().tracing_controller().set_picture_tracing_path( + SkPictureTracingPath()); + _shell_view.reset(shellView); self.multipleTouchEnabled = YES; } @@ -254,27 +269,3 @@ static inline int64 InputEventTimestampFromNSTimeInterval( } @end - -void SaveFrameToSkPicture() { - @autoreleasepool { - NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, - NSUserDomainMask, YES); - NSString* basePath = paths.firstObject; - - if (basePath.length == 0) { - return; - } - - NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; - [formatter setDateFormat:@"HH_mm_ss"]; - NSString* dateString = [formatter stringFromDate:[NSDate date]]; - [formatter release]; - - NSString* path = - [NSString stringWithFormat:@"%@/%@.trace.skp", basePath, dateString]; - - base::FilePath filePath(path.UTF8String); - sky::shell::Shell::Shared().tracing_controller().SaveFrameToSkPicture( - filePath); - } -} diff --git a/sky/shell/shell_view.cc b/sky/shell/shell_view.cc index 09942f26fe5..1a8e1b32d64 100644 --- a/sky/shell/shell_view.cc +++ b/sky/shell/shell_view.cc @@ -63,11 +63,5 @@ void ShellView::StopDartTracing( base::Passed(&producer))); } -void ShellView::SaveFrameToSkPicture(base::FilePath& destination) { - shell_.ui_task_runner()->PostTask( - FROM_HERE, base::Bind(&Engine::SaveFrameToSkPicture, - engine_->GetWeakPtr(), destination)); -} - } // namespace shell } // namespace sky diff --git a/sky/shell/shell_view.h b/sky/shell/shell_view.h index ac3472f8851..4231cf79d54 100644 --- a/sky/shell/shell_view.h +++ b/sky/shell/shell_view.h @@ -27,8 +27,6 @@ class ShellView { void StartDartTracing(); void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer); - void SaveFrameToSkPicture(base::FilePath& destination); - private: void CreateEngine(); void CreatePlatformView(); diff --git a/sky/shell/tracing_controller.cc b/sky/shell/tracing_controller.cc index 84bcf163689..5c0cfd48095 100644 --- a/sky/shell/tracing_controller.cc +++ b/sky/shell/tracing_controller.cc @@ -17,7 +17,8 @@ const char kBaseTraceStart[] = "{\"traceEvents\":["; const char kBaseTraceEnd[] = "]}"; const char kSentinel[] = "\0"; -TracingController::TracingController() : view_(nullptr) {} +TracingController::TracingController() + : view_(nullptr), picture_tracing_enabled_(false) {} TracingController::~TracingController() {} @@ -108,12 +109,6 @@ void TracingController::OnBaseTraceChunk( } } -void TracingController::SaveFrameToSkPicture(base::FilePath& destination) { - if (view_ != nullptr) { - view_->SaveFrameToSkPicture(destination); - } -} - void TracingController::RegisterShellView(ShellView* view) { view_ = view; } @@ -122,5 +117,20 @@ void TracingController::UnregisterShellView(ShellView* view) { view_ = nullptr; } +TracingController::SkPictureTracingOptions +TracingController::picture_tracing_options() const { + return SkPictureTracingOptions( + picture_tracing_path_.length() == 0 ? false : picture_tracing_enabled_, + picture_tracing_path_); +} + +void TracingController::set_picture_tracing_path(const std::string& path) { + picture_tracing_path_ = path; +} + +void TracingController::set_picture_tracing_enabled(bool enabled) { + picture_tracing_enabled_ = enabled; +} + } // namespace shell } // namespace sky diff --git a/sky/shell/tracing_controller.h b/sky/shell/tracing_controller.h index e0a591d34ba..96c6281fdd5 100644 --- a/sky/shell/tracing_controller.h +++ b/sky/shell/tracing_controller.h @@ -35,7 +35,13 @@ class TracingController : public mojo::common::DataPipeDrainer::Client { // be merged before viewing in the trace viewer void StopTracing(const base::FilePath& path); - void SaveFrameToSkPicture(base::FilePath& destination); + using SkPictureTracingOptions = + std::pair; + SkPictureTracingOptions picture_tracing_options() const; + + void set_picture_tracing_path(const std::string& path); + + void set_picture_tracing_enabled(bool enabled); private: std::unique_ptr drainer_; @@ -44,6 +50,8 @@ class TracingController : public mojo::common::DataPipeDrainer::Client { // the ability to host multiple shell views, references to each must be stored // instead and trace data from each serialized to the output trace. ShellView* view_; + std::string picture_tracing_path_; + bool picture_tracing_enabled_; void StartDartTracing(); void StartBaseTracing(); diff --git a/sky/shell/ui/engine.cc b/sky/shell/ui/engine.cc index 29c134beb83..06b06bb010f 100644 --- a/sky/shell/ui/engine.cc +++ b/sky/shell/ui/engine.cc @@ -264,8 +264,5 @@ void Engine::StopDartTracing(mojo::ScopedDataPipeProducerHandle producer) { sky_view_->StopDartTracing(producer.Pass()); } -void Engine::SaveFrameToSkPicture(const base::FilePath& destination) { -} - } // namespace shell } // namespace sky diff --git a/sky/shell/ui/engine.h b/sky/shell/ui/engine.h index 438fa2f9232..33592e6dc01 100644 --- a/sky/shell/ui/engine.h +++ b/sky/shell/ui/engine.h @@ -60,8 +60,6 @@ class Engine : public UIDelegate, void StartDartTracing(); void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer); - void SaveFrameToSkPicture(const base::FilePath& destination); - private: // UIDelegate implementation: void ConnectToEngine(mojo::InterfaceRequest request) override; From 0a2984c95901ad9768ab0aaeaff52837516ca4ca Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Mon, 21 Sep 2015 15:46:39 -0700 Subject: [PATCH 2/2] Remove the SERIALIZE_LAYER_TREE macro --- sky/shell/gpu/rasterizer.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sky/shell/gpu/rasterizer.cc b/sky/shell/gpu/rasterizer.cc index 58ac621d938..c04be105dca 100644 --- a/sky/shell/gpu/rasterizer.cc +++ b/sky/shell/gpu/rasterizer.cc @@ -21,9 +21,6 @@ #include "ui/gl/gl_surface.h" #include "mojo/public/cpp/system/data_pipe.h" -// Set this value to 1 to serialize the layer tree to disk. -#define SERIALIZE_LAYER_TREE 0 - namespace sky { namespace shell {