File: buffer_queue.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (213 lines) | stat: -rw-r--r-- 9,252 bytes parent folder | download | duplicates (6)
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_BUFFER_QUEUE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_BUFFER_QUEUE_H_

#include <stddef.h>

#include <memory>
#include <optional>
#include <vector>

#include "base/containers/circular_deque.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/timer/elapsed_timer.h"
#include "components/viz/common/resources/shared_image_format.h"
#include "components/viz/service/display/render_pass_alpha_type.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"

namespace viz {

class SkiaOutputSurface;

// Encapsulates a queue of buffers for compositing backed by SharedImages.
// Double/triple/N-buffering is configured by specifying |number_of_buffers| at
// construction, or by calling EnsureMinNumberOfBuffers().
class VIZ_SERVICE_EXPORT BufferQueue {
 public:
  // Creates a BufferQueue that allocates SharedImage buffers using |sii|.
  // Buffers are not allocated until Reshape() is called. |number_of_buffers|
  // specifies the number of buffers that will be allocated, and can be
  // increased by calling EnsureMinNumberOfBuffers() when
  // |supports_dynamic_frame_buffer_allocation| capability is true.
  BufferQueue(SkiaOutputSurface* skia_output_surface,
              gpu::SurfaceHandle surface_handle,
              size_t number_of_buffers,
              bool is_protected = false);

  BufferQueue(const BufferQueue&) = delete;
  BufferQueue& operator=(const BufferQueue&) = delete;

  ~BufferQueue();

  // Returns the SharedImage backed by the current buffer (i.e., the render
  // target for compositing).
  gpu::Mailbox GetCurrentBuffer();

  // Returns a mailbox to be used for overlay testing. This will be the last
  // swapped buffer if one exists, or another buffer in the queue if not. This
  // will return a zero-mailbox if DestroyBuffers() has been called and buffers
  // have not been recreated since.
  gpu::Mailbox GetLastSwappedBuffer();

  // Returns a rectangle whose contents may have changed since the current
  // buffer was last submitted and needs to be redrawn. For partial swap,
  // only the contents outside this rectangle can be considered valid and do not
  // need to be redrawn.
  gfx::Rect CurrentBufferDamage() const;

  // Called by the user of this object to indicate that the buffer currently
  // marked for drawing should be moved to the list of in-flight buffers.
  // |damage| represents the rectangle containing the damaged area since the
  // last SwapBuffers.
  void SwapBuffers(const gfx::Rect& damage);

  // Called by the user of this object to indicate that a previous request to
  // swap buffers has completed. This allows us to correctly keep track of the
  // state of the buffers. If `did_present` was true, the buffer currently
  // marked as being displayed will now marked as available, and the next buffer
  // marked as in-flight will now be marked as displayed. Otherwise, next
  // in-flight will be marked as available and displayed will be unchanged.
  void SwapBuffersComplete(bool did_present);

  // Called when SwapBuffers is skipped this frame. Damages allocated buffers,
  // but does not advance |in_flight_buffers_| or |current_buffer_|. We don't
  // clear the damage on |current_buffer_| because it hasn't been displayed yet.
  // SwapBuffersComplete() must not be called for skipped swap.
  void SwapBuffersSkipped(const gfx::Rect& damage);

  // If |size| or |color_space| correspond to a change of state, frees all
  // the buffers and reallocatess |number_of_buffers_| buffers. Otherwise, it's
  // a no-op. Returns true if there was a change of state, false otherwise.
  bool Reshape(const gfx::Size& size,
               const gfx::ColorSpace& color_space,
               RenderPassAlphaType alpha_type,
               SharedImageFormat format);

  // Sets the number of frame buffers to use when
  // |supports_dynamic_frame_buffer_allocation| is true, and allocates those
  // buffers if necessary. If |n| <= |number_of_buffers_| this is a no-op.
  void EnsureMinNumberOfBuffers(size_t n);

  // Free all buffers and allocate |number_of_buffers_| new ones.
  // Note: SwapBuffersComplete() calls are still expected for all current
  // in-flight buffers, but they've been free'd so they won't be moved to
  // |available_buffers_|.
  void RecreateBuffers();

  // Destroys all allocated buffers. This should be used when the renderer knows
  // these buffers will no longer be needed, e.g. when delegating to the system
  // compositor.
  // Buffers will only be recreated the next time GetCurrentBuffer() is called.
  // NOTE: This should not be used on platforms that use buffers for
  // overlay testing because GetLastSwappedBuffer() will not recreate the
  // buffers.
  void DestroyBuffers();

  // Indicates buffer contents can be purged, aka their contents deleted if
  // memory is needed. For each completed swap one buffer will be marked
  // purgeable.
  //
  // NOTE: This should only be used when buffers are not currently needed, eg.
  // when delegating to system compositor, and if the platform support purgeable
  // shared images.
  void SetBuffersPurgeable();

 private:
  friend class BufferQueueTest;
  friend class BufferQueueMockedSharedImageInterfaceTest;
  FRIEND_TEST_ALL_PREFIXES(BufferQueueTest, AllocateFails);
  FRIEND_TEST_ALL_PREFIXES(BufferQueueMockedSharedImageInterfaceTest,
                           AllocateFails);

  struct VIZ_SERVICE_EXPORT AllocatedBuffer {
    AllocatedBuffer(const gpu::Mailbox& mailbox, const gfx::Rect& rect);
    ~AllocatedBuffer();

    bool purgeable = false;
    gpu::Mailbox mailbox;
    gfx::Rect damage;  // This is the damage for this frame from the previous.
  };

  // Frees all buffers that have been allocated, and destroys their shared
  // images.
  void FreeAllBuffers();

  // Free |buffer| and destroy its shared image.
  void FreeBuffer(std::unique_ptr<AllocatedBuffer> buffer);

  // Sets `buffer`s shared image as `purgeable` and returns true if the value
  // changed.
  bool SetBufferPurgeable(AllocatedBuffer& buffer, bool purgeable);

  // Unions |damage| to all allocated buffers except |current_buffer_| which
  // hasn't been displayed yet.
  void UpdateBufferDamage(const gfx::Rect& damage);

  // Allocates |n| buffers and pushes them into |available_buffers_|.
  void AllocateBuffers(size_t n);

  // Return a buffer that is available to be drawn into.
  std::unique_ptr<AllocatedBuffer> GetNextBuffer();

  // If |buffers_destroyed_| = true, this will create |number_of_buffers_|
  // buffers with the settings last set by Reshape().
  void RecreateBuffersIfDestroyed();

  // Used to create and destroy shared images.
  const raw_ptr<SkiaOutputSurface> skia_output_surface_;
  // Used when creating shared images.
  gpu::SurfaceHandle surface_handle_;
  // The number of buffers that should be allocated when Reshape() is called.
  size_t number_of_buffers_ = 0;

  // The size of all allocated buffers.
  gfx::Size size_;
  // The color space of all allocated buffers.
  gfx::ColorSpace color_space_;
  // The alpha type of all allocated buffers.
  RenderPassAlphaType alpha_type_ = RenderPassAlphaType::kPremul;
  // The format of all allocated buffers. The |format_| is optional to prevent
  // use of uninitialized values.
  std::optional<SharedImageFormat> format_;

  // This buffer is currently bound. This may be nullptr if no buffer has
  // been bound.
  std::unique_ptr<AllocatedBuffer> current_buffer_;
  // The buffer currently on the screen, if any.
  std::unique_ptr<AllocatedBuffer> displayed_buffer_;
  // These are free for use, and are not nullptr.
  base::circular_deque<std::unique_ptr<AllocatedBuffer>> available_buffers_;
  // These have been swapped but are not displayed yet. Entries of this deque
  // may be nullptr, if they represent frames that have been destroyed, or
  // frames where SwapBuffers() was called without calling GetCurrentBuffer().
  base::circular_deque<std::unique_ptr<AllocatedBuffer>> in_flight_buffers_;

  // When the buffers are not being used due to delegated compositing.
  bool buffers_can_be_purged_ = false;

  // Whether the buffers have been destroyed and are not yet recreated. If true,
  // don't allocate buffers when you normally would. They will be recreated on
  // demand the next time GetNextBuffer() is called.
  bool buffers_destroyed_ = false;
  // Started when DestroyBuffers() destroys all buffers, and reported the next
  // time RecreateBuffersIfDestroyed() is called. The timer will be reset after
  // reporting.
  // Used to see how often we destroy buffers and recreate them very soon, which
  // we want to be rare.
  std::optional<base::ElapsedTimer> destroyed_timer_;
  // Whether or not to allocate these buffers as protected buffers.
  bool is_protected_ = false;
};

}  // namespace viz

#endif  // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_BUFFER_QUEUE_H_