| Index: content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
|
| diff --git a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
|
| index 98fb73f9b0806fc70ab5f93c965a41e7daae2a19..0380c9789e785ce71af8d0979c3590c9019730d2 100644
|
| --- a/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
|
| +++ b/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
|
| @@ -6,6 +6,11 @@
|
|
|
| #include <utility>
|
|
|
| +#include "base/barrier_closure.h"
|
| +#include "base/base64.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/trace_event/trace_event.h"
|
| #include "cc/output/output_surface_client.h"
|
| #include "cc/output/output_surface_frame.h"
|
| #include "components/display_compositor/buffer_queue.h"
|
| @@ -15,8 +20,88 @@
|
| #include "gpu/GLES2/gl2extchromium.h"
|
| #include "gpu/command_buffer/client/gles2_interface.h"
|
| #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/gfx/codec/png_codec.h"
|
| +#include "ui/gfx/skia_util.h"
|
|
|
| namespace content {
|
| +namespace {
|
| +
|
| +// How frequently to do a readback of the framebuffer and overlay textures
|
| +// when tracing is turned on.
|
| +const size_t kSnapshotInterval = 60;
|
| +
|
| +class Snapshot : public base::trace_event::ConvertableToTraceFormat {
|
| + public:
|
| + explicit Snapshot(base::TimeTicks vsync_time) : vsync_time_(vsync_time) {}
|
| +
|
| + // base::trace_event::ConvertableToTraceFormat implementation.
|
| + void AppendAsTraceFormat(std::string* out) const override {
|
| + *out += "{";
|
| + // Add framebuffer or the first overlay texture as screenshot if available.
|
| + const SkBitmap& bitmap = overlay_texture_bitmaps_.empty()
|
| + ? framebuffer_bitmap_
|
| + : overlay_texture_bitmaps_.front();
|
| + if (!bitmap.isNull()) {
|
| + std::vector<unsigned char> png_data;
|
| + bool png_ok = gfx::PNGCodec::Encode(
|
| + static_cast<unsigned char*>(bitmap.getPixels()),
|
| + gfx::PNGCodec::FORMAT_RGBA, gfx::SkISizeToSize(bitmap.dimensions()),
|
| + bitmap.rowBytes(), false, std::vector<gfx::PNGCodec::Comment>(),
|
| + &png_data);
|
| + DCHECK(png_ok);
|
| +
|
| + base::StringPiece base64_input(
|
| + reinterpret_cast<const char*>(&png_data[0]), png_data.size());
|
| + std::string base64_output;
|
| + Base64Encode(base64_input, &base64_output);
|
| +
|
| + *out += "\"screenshot\":\"" + base64_output + "\",";
|
| + }
|
| + *out += "\"vsyncTime\":" +
|
| + base::Uint64ToString(vsync_time_.ToInternalValue()) + ",";
|
| + uint64_t elapsed_time =
|
| + (base::TimeTicks::Now() - vsync_time_).ToInternalValue();
|
| + *out += "\"vsyncJsTime\":" +
|
| + base::Uint64ToString(
|
| + static_cast<uint64_t>(base::Time::Now().ToJsTime() *
|
| + base::Time::kMicrosecondsPerMillisecond) -
|
| + elapsed_time) +
|
| + ",";
|
| + *out += "\"overlayTextures\":\"" +
|
| + base::SizeTToString(overlay_texture_bitmaps_.size()) + "\"";
|
| + *out += "}";
|
| + }
|
| +
|
| + SkBitmap& framebuffer_bitmap() { return framebuffer_bitmap_; }
|
| + std::vector<SkBitmap>& overlay_texture_bitmaps() {
|
| + return overlay_texture_bitmaps_;
|
| + }
|
| +
|
| + private:
|
| + const base::TimeTicks vsync_time_;
|
| + SkBitmap framebuffer_bitmap_;
|
| + std::vector<SkBitmap> overlay_texture_bitmaps_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Snapshot);
|
| +};
|
| +
|
| +void CallbackForwader(const base::Closure& callback, bool result) {
|
| + callback.Run();
|
| +}
|
| +
|
| +void SaveSnapshot(
|
| + void* id,
|
| + std::unique_ptr<base::trace_event::ConvertableToTraceFormat> snapshot,
|
| + base::TimeTicks page_flip_time) {
|
| + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug.outputsurface"),
|
| + "SaveSnapshot");
|
| + TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP(
|
| + TRACE_DISABLED_BY_DEFAULT("cc.debug.outputsurface"), "cc::OutputSurface",
|
| + id, page_flip_time, std::move(snapshot));
|
| +}
|
| +
|
| +} // namespace
|
|
|
| GpuSurfacelessBrowserCompositorOutputSurface::
|
| GpuSurfacelessBrowserCompositorOutputSurface(
|
| @@ -51,10 +136,17 @@ GpuSurfacelessBrowserCompositorOutputSurface::
|
| context_provider_->ContextGL(), target, internalformat, format,
|
| gl_helper_.get(), gpu_memory_buffer_manager_, surface_handle));
|
| buffer_queue_->Initialize();
|
| +
|
| + TRACE_EVENT_OBJECT_CREATED_WITH_ID(
|
| + TRACE_DISABLED_BY_DEFAULT("cc.debug.outputsurface"), "cc::OutputSurface",
|
| + this);
|
| }
|
|
|
| GpuSurfacelessBrowserCompositorOutputSurface::
|
| ~GpuSurfacelessBrowserCompositorOutputSurface() {
|
| + TRACE_EVENT_OBJECT_DELETED_WITH_ID(
|
| + TRACE_DISABLED_BY_DEFAULT("cc.debug.outputsurface"), "cc::OutputSurface",
|
| + this);
|
| }
|
|
|
| bool GpuSurfacelessBrowserCompositorOutputSurface::IsDisplayedAsOverlayPlane()
|
| @@ -113,6 +205,30 @@ void GpuSurfacelessBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
|
| buffer_queue_->RecreateBuffers();
|
| force_swap = true;
|
| }
|
| + bool is_tracing;
|
| + TRACE_EVENT_CATEGORY_GROUP_ENABLED(
|
| + TRACE_DISABLED_BY_DEFAULT("cc.debug.outputsurface"), &is_tracing);
|
| + // Create a snapshot of the previous frame now that we've received an ack
|
| + // for the new frame. |last_timebase_| is the page flip time for the
|
| + // previous frame.
|
| + if (is_tracing && !(++swap_count_ % kSnapshotInterval)) {
|
| + // |last_vsync_timebase_| should contain an accurate vsync time stamp for
|
| + // the previous frame at this time.
|
| + Snapshot* snapshot = new Snapshot(last_vsync_timebase_);
|
| + std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
|
| + scoped_snapshot(snapshot);
|
| + base::Closure save_snaphost_callback =
|
| + base::Bind(&SaveSnapshot, this, base::Passed(&scoped_snapshot),
|
| + last_vsync_timebase_);
|
| + base::Closure barrier_closure =
|
| + base::BarrierClosure(2, save_snaphost_callback);
|
| + buffer_queue_->ReadbackDisplayedFramebuffer(
|
| + &snapshot->framebuffer_bitmap(),
|
| + base::Bind(&CallbackForwader, barrier_closure));
|
| + client_->ReadbackSwappedOverlayTextures(
|
| + &snapshot->overlay_texture_bitmaps(),
|
| + base::Bind(&CallbackForwader, barrier_closure));
|
| + }
|
| buffer_queue_->PageFlipComplete();
|
| GpuBrowserCompositorOutputSurface::OnGpuSwapBuffersCompleted(
|
| latency_info, result, params_mac);
|
|
|