summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ScreenshotGrabber.h
blob: a2dfc2a0851e2c57439ab7c94a97c087ea739ce9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_layers_ScreenshotGrabber_h
#define mozilla_layers_ScreenshotGrabber_h

#include "nsISupportsImpl.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"

namespace mozilla {
namespace layers {

namespace profiler_screenshots {
class Window;
class RenderSource;
class DownscaleTarget;
class AsyncReadbackBuffer;

class ScreenshotGrabberImpl;
}  // namespace profiler_screenshots

/**
 * Used by various renderers / layer managers to grab snapshots from the window
 * and submit them to the Gecko profiler.
 * Doesn't do any work if the profiler is not running or the "screenshots"
 * feature is not enabled.
 * Screenshots are scaled down to fit within a fixed size, and read back to
 * main memory using async readback. Scaling is done in multiple scale-by-0.5x
 * steps using DownscaleTarget::CopyFrom, and readback is done using
 * AsyncReadbackBuffers.
 */
class ScreenshotGrabber final {
 public:
  ScreenshotGrabber();
  ~ScreenshotGrabber();

  // Scale the contents of aWindow's current render target into an
  // appropriately sized DownscaleTarget and read its contents into an
  // AsyncReadbackBuffer. The AsyncReadbackBuffer is not mapped into main
  // memory until the second call to MaybeProcessQueue() after this call to
  // MaybeGrabScreenshot().
  void MaybeGrabScreenshot(profiler_screenshots::Window& aWindow,
                           const gfx::IntSize& aWindowSize);

  // Map the contents of any outstanding AsyncReadbackBuffers from previous
  // composites into main memory and submit each screenshot to the profiler.
  void MaybeProcessQueue();

  // Insert a special profiler marker for a composite that didn't do any actual
  // compositing, so that the profiler knows why no screenshot was taken for
  // this frame.
  void NotifyEmptyFrame();

  // Destroy all Window-related resources that this class is holding on to.
  void Destroy();

 private:
  // non-null while ProfilerScreenshots::IsEnabled() returns true
  UniquePtr<profiler_screenshots::ScreenshotGrabberImpl> mImpl;
};

// Interface definitions.

namespace profiler_screenshots {

class Window {
 public:
  virtual already_AddRefed<RenderSource> GetWindowContents(
      const gfx::IntSize& aWindowSize) = 0;
  virtual already_AddRefed<DownscaleTarget> CreateDownscaleTarget(
      const gfx::IntSize& aSize) = 0;
  virtual already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer(
      const gfx::IntSize& aSize) = 0;

 protected:
  virtual ~Window() {}
};

class RenderSource {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RenderSource)

  const auto& Size() const { return mSize; }

 protected:
  explicit RenderSource(const gfx::IntSize& aSize) : mSize(aSize) {}
  virtual ~RenderSource() {}

  const gfx::IntSize mSize;
};

class DownscaleTarget {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DownscaleTarget)

  virtual already_AddRefed<RenderSource> AsRenderSource() = 0;

  const auto& Size() const { return mSize; }
  virtual bool DownscaleFrom(RenderSource* aSource,
                             const gfx::IntRect& aSourceRect,
                             const gfx::IntRect& aDestRect) = 0;

 protected:
  explicit DownscaleTarget(const gfx::IntSize& aSize) : mSize(aSize) {}
  virtual ~DownscaleTarget() {}

  const gfx::IntSize mSize;
};

class AsyncReadbackBuffer {
 public:
  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(
      mozilla::layers::profiler_screenshots::AsyncReadbackBuffer)

  const auto& Size() const { return mSize; }
  virtual void CopyFrom(RenderSource* aSource) = 0;
  virtual bool MapAndCopyInto(gfx::DataSourceSurface* aSurface,
                              const gfx::IntSize& aReadSize) = 0;

 protected:
  explicit AsyncReadbackBuffer(const gfx::IntSize& aSize) : mSize(aSize) {}
  virtual ~AsyncReadbackBuffer() {}

  const gfx::IntSize mSize;
};

}  // namespace profiler_screenshots

}  // namespace layers
}  // namespace mozilla

#endif  // mozilla_layers_ScreenshotGrabber_h