Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/layers/ContentClient.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef MOZILLA_GFX_CONTENTCLIENT_H
8
#define MOZILLA_GFX_CONTENTCLIENT_H
9
10
#include <stdint.h>                     // for uint32_t
11
#include "RotatedBuffer.h"              // for RotatedBuffer, etc
12
#include "gfxTypes.h"
13
#include "gfxPlatform.h"                // for gfxPlatform
14
#include "mozilla/Assertions.h"         // for MOZ_CRASH
15
#include "mozilla/Attributes.h"         // for override
16
#include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
17
#include "mozilla/gfx/Point.h"          // for IntSize
18
#include "mozilla/layers/CompositableClient.h"  // for CompositableClient
19
#include "mozilla/layers/CompositableForwarder.h"
20
#include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
21
#include "mozilla/layers/ISurfaceAllocator.h"
22
#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
23
#include "mozilla/layers/LayersTypes.h"  // for TextureDumpMode
24
#include "mozilla/layers/TextureClient.h"  // for TextureClient
25
#include "mozilla/layers/PaintThread.h"  // for PaintTask
26
#include "mozilla/Maybe.h"              // for Maybe
27
#include "mozilla/mozalloc.h"           // for operator delete
28
#include "mozilla/UniquePtr.h"          // for UniquePtr
29
#include "ReadbackProcessor.h"          // For ReadbackProcessor::Update
30
#include "nsCOMPtr.h"                   // for already_AddRefed
31
#include "nsPoint.h"                    // for nsIntPoint
32
#include "nsRect.h"                     // for mozilla::gfx::IntRect
33
#include "nsRegion.h"                   // for nsIntRegion
34
#include "nsTArray.h"                   // for nsTArray
35
36
namespace mozilla {
37
namespace gfx {
38
class DrawTarget;
39
} // namespace gfx
40
41
namespace layers {
42
43
class PaintedLayer;
44
45
/**
46
 * A compositable client for PaintedLayers. These are different to Image/Canvas
47
 * clients due to sending a valid region across IPC and because we do a lot more
48
 * optimisation work, encapsulated in RotatedBuffers.
49
 *
50
 * We use content clients for OMTC and non-OMTC, basic rendering so that
51
 * BasicPaintedLayer has only one interface to deal with. We support single and
52
 * double buffered flavours. For tiled layers, we do not use a ContentClient
53
 * although we do have a ContentHost, and we do use texture clients and texture
54
 * hosts.
55
 *
56
 * The interface presented by ContentClient is used by the BasicPaintedLayer
57
 * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer
58
 * which is different (the OMTC one does a little more).
59
 */
60
class ContentClient : public CompositableClient
61
{
62
public:
63
  typedef gfxContentType ContentType;
64
65
  /**
66
   * Creates, configures, and returns a new content client. If necessary, a
67
   * message will be sent to the compositor to create a corresponding content
68
   * host.
69
   */
70
  static already_AddRefed<ContentClient> CreateContentClient(CompositableForwarder* aFwd);
71
72
  /**
73
   * Controls the size of the backing buffer of this.
74
   * - SizedToVisibleBounds: the backing buffer is exactly the same
75
   *   size as the bounds of PaintedLayer's visible region
76
   * - ContainsVisibleBounds: the backing buffer is large enough to
77
   *   fit visible bounds.  May be larger.
78
   */
79
  enum BufferSizePolicy {
80
    SizedToVisibleBounds,
81
    ContainsVisibleBounds
82
  };
83
84
  explicit ContentClient(CompositableForwarder* aForwarder,
85
                         BufferSizePolicy aBufferSizePolicy)
86
  : CompositableClient(aForwarder)
87
  , mBufferSizePolicy(aBufferSizePolicy)
88
0
  {}
89
  virtual ~ContentClient()
90
0
  {}
91
92
  virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
93
94
  virtual void Clear();
95
96
  /**
97
   * This is returned by BeginPaint. The caller should draw into mTarget.
98
   * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated
99
   * by ContentClient and must be redrawn on the screen.
100
   * mRegionToInvalidate is set when the buffer has changed from
101
   * opaque to transparent or vice versa, since the details of rendering can
102
   * depend on the buffer type.
103
   */
104
  struct PaintState {
105
    PaintState()
106
      : mRegionToDraw()
107
      , mRegionToInvalidate()
108
      , mMode(SurfaceMode::SURFACE_NONE)
109
      , mClip(DrawRegionClip::NONE)
110
      , mContentType(gfxContentType::SENTINEL)
111
      , mAsyncPaint(false)
112
      , mAsyncTask(nullptr)
113
0
    {}
114
115
    nsIntRegion mRegionToDraw;
116
    nsIntRegion mRegionToInvalidate;
117
    SurfaceMode mMode;
118
    DrawRegionClip mClip;
119
    gfxContentType mContentType;
120
    bool mAsyncPaint;
121
    UniquePtr<PaintTask> mAsyncTask;
122
  };
123
124
  enum {
125
    PAINT_WILL_RESAMPLE = 0x01,
126
    PAINT_NO_ROTATION = 0x02,
127
    PAINT_CAN_DRAW_ROTATED = 0x04,
128
    PAINT_ASYNC = 0x08,
129
  };
130
131
  /**
132
   * Start a drawing operation. This returns a PaintState describing what
133
   * needs to be drawn to bring the buffer up to date in the visible region.
134
   * This queries aLayer to get the currently valid and visible regions.
135
   * The returned mTarget may be null if mRegionToDraw is empty.
136
   * Otherwise it must not be null.
137
   * mRegionToInvalidate will contain mRegionToDraw.
138
   * @param aFlags when PAINT_WILL_RESAMPLE is passed, this indicates that
139
   * buffer will be resampled when rendering (i.e the effective transform
140
   * combined with the scale for the resolution is not just an integer
141
   * translation). This will disable buffer rotation (since we don't want
142
   * to resample across the rotation boundary) and will ensure that we
143
   * make the entire buffer contents valid (since we don't want to sample
144
   * invalid pixels outside the visible region, if the visible region doesn't
145
   * fill the buffer bounds).
146
   * PAINT_CAN_DRAW_ROTATED can be passed if the caller supports drawing
147
   * rotated content that crosses the physical buffer boundary. The caller
148
   * will need to call BorrowDrawTargetForPainting multiple times to achieve
149
   * this.
150
   */
151
  virtual PaintState BeginPaint(PaintedLayer* aLayer, uint32_t aFlags);
152
  virtual void EndPaint(PaintState& aPaintState, nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr);
153
154
  /**
155
   * Fetch a DrawTarget for rendering. The DrawTarget remains owned by
156
   * this. See notes on BorrowDrawTargetForQuadrantUpdate.
157
   * May return null. If the return value is non-null, it must be
158
   * 'un-borrowed' using ReturnDrawTarget.
159
   *
160
   * If PAINT_CAN_DRAW_ROTATED was specified for BeginPaint, then the caller
161
   * must call this function repeatedly (with an iterator) until it returns
162
   * nullptr. The caller should draw the mDrawRegion of the iterator instead
163
   * of mRegionToDraw in the PaintState.
164
   *
165
   * @param aPaintState Paint state data returned by a call to BeginPaint
166
   * @param aIter Paint state iterator. Only required if PAINT_CAN_DRAW_ROTATED
167
   * was specified to BeginPaint.
168
   */
169
  virtual gfx::DrawTarget* BorrowDrawTargetForPainting(
170
    PaintState& aPaintState,
171
    RotatedBuffer::DrawIterator* aIter = nullptr);
172
173
  void ReturnDrawTarget(gfx::DrawTarget*& aReturned);
174
175
  enum {
176
    BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
177
                                  // component alpha.
178
  };
179
180
protected:
181
  struct BufferDecision {
182
    nsIntRegion mNeededRegion;
183
    nsIntRegion mValidRegion;
184
    gfx::IntRect mBufferRect;
185
    SurfaceMode mBufferMode;
186
    gfxContentType mBufferContentType;
187
    bool mCanReuseBuffer;
188
    bool mCanKeepBufferContents;
189
  };
190
191
  /**
192
   * Decide whether we can keep our current buffer and its contents,
193
   * and return a struct containing the regions to paint, invalidate,
194
   * the new buffer rect, surface mode, and content type.
195
   */
196
  BufferDecision CalculateBufferForPaint(PaintedLayer* aLayer,
197
                                         uint32_t aFlags);
198
199
  static bool ValidBufferSize(BufferSizePolicy aPolicy,
200
                              const gfx::IntSize& aBufferSize,
201
                              const gfx::IntSize& aVisibleBoundsSize);
202
203
  /**
204
   * Any actions that should be performed at the last moment before we begin
205
   * rendering the next frame. I.e., after we calculate what we will draw,
206
   * but before we rotate the buffer and possibly create new buffers.
207
   * aRegionToDraw is the region which is guaranteed to be overwritten when
208
   * drawing the next frame.
209
   */
210
0
  virtual void FinalizeFrame(PaintState& aPaintState) {
211
0
  }
212
213
  virtual RefPtr<RotatedBuffer> GetFrontBuffer() const
214
0
  {
215
0
    return mBuffer;
216
0
  }
217
218
  /**
219
   * Create a new rotated buffer for the specified content type, buffer rect,
220
   * and buffer flags.
221
   */
222
  virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType,
223
                                             const gfx::IntRect& aRect,
224
                                             uint32_t aFlags) = 0;
225
226
  RefPtr<RotatedBuffer> mBuffer;
227
  BufferSizePolicy      mBufferSizePolicy;
228
};
229
230
// Thin wrapper around DrawTargetRotatedBuffer, for on-mtc
231
class ContentClientBasic final : public ContentClient
232
{
233
public:
234
  explicit ContentClientBasic(gfx::BackendType aBackend);
235
236
  void DrawTo(PaintedLayer* aLayer,
237
              gfx::DrawTarget* aTarget,
238
              float aOpacity,
239
              gfx::CompositionOp aOp,
240
              gfx::SourceSurface* aMask,
241
              const gfx::Matrix* aMaskTransform);
242
243
  virtual TextureInfo GetTextureInfo() const override
244
0
  {
245
0
    MOZ_CRASH("GFX: Should not be called on non-remote ContentClient");
246
0
  }
247
248
protected:
249
  virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType,
250
                                             const gfx::IntRect& aRect,
251
                                             uint32_t aFlags) override;
252
253
private:
254
  gfx::BackendType mBackend;
255
};
256
257
/**
258
 * A ContentClient backed by a RemoteRotatedBuffer.
259
 *
260
 * When using a ContentClientRemoteBuffer, SurfaceDescriptors are created on
261
 * the rendering side and destroyed on the compositing side. They are only
262
 * passed from one side to the other when the TextureClient/Hosts are created.
263
 * *Ownership* of the SurfaceDescriptor moves from the rendering side to the
264
 * compositing side with the create message (send from CreateBuffer) which
265
 * tells the compositor that TextureClients have been created and that the
266
 * compositor should assign the corresponding TextureHosts to our corresponding
267
 * ContentHost.
268
 *
269
 * If the size or type of our buffer(s) change(s), then we simply destroy and
270
 * create them.
271
 */
272
class ContentClientRemoteBuffer : public ContentClient
273
{
274
public:
275
  explicit ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
276
    : ContentClient(aForwarder, ContainsVisibleBounds)
277
    , mIsNewBuffer(false)
278
0
  {}
279
280
  virtual void Dump(std::stringstream& aStream,
281
                    const char* aPrefix="",
282
                    bool aDumpHtml=false,
283
                    TextureDumpMode aCompress=TextureDumpMode::Compress) override;
284
285
  virtual void EndPaint(PaintState& aPaintState, nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr) override;
286
287
  virtual void Updated(const nsIntRegion& aRegionToDraw,
288
                       const nsIntRegion& aVisibleRegion);
289
290
  virtual TextureFlags ExtraTextureFlags() const
291
0
  {
292
0
    return TextureFlags::IMMEDIATE_UPLOAD;
293
0
  }
294
295
protected:
296
  /**
297
   * Called when we have been updated and should swap references to our
298
   * buffers.
299
   */
300
0
  virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {}
301
302
  virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
303
                                       const nsIntRegion& aVisibleRegion);
304
305
  virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType,
306
                                             const gfx::IntRect& aRect,
307
                                             uint32_t aFlags) override;
308
309
  RefPtr<RotatedBuffer> CreateBufferInternal(const gfx::IntRect& aRect,
310
                                             gfx::SurfaceFormat aFormat,
311
                                             TextureFlags aFlags);
312
313
  RemoteRotatedBuffer* GetRemoteBuffer() const
314
0
  {
315
0
    return static_cast<RemoteRotatedBuffer*>(mBuffer.get());
316
0
  }
317
318
  bool mIsNewBuffer;
319
};
320
321
/**
322
 * A double buffered ContentClientRemoteBuffer. mBuffer is the back buffer, which
323
 * we draw into. mFrontBuffer is the front buffer which we may read from, but
324
 * not write to, when the compositor does not have the 'soft' lock.
325
 *
326
 * The ContentHost keeps a reference to both corresponding texture hosts, in
327
 * response to our UpdateTextureRegion message, the compositor swaps its
328
 * references.
329
 */
330
class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
331
{
332
public:
333
  explicit ContentClientDoubleBuffered(CompositableForwarder* aFwd)
334
    : ContentClientRemoteBuffer(aFwd)
335
    , mFrontAndBackBufferDiffer(false)
336
0
  {}
337
338
0
  virtual ~ContentClientDoubleBuffered() {}
339
340
  virtual void Dump(std::stringstream& aStream,
341
                    const char* aPrefix="",
342
                    bool aDumpHtml=false,
343
                    TextureDumpMode aCompress=TextureDumpMode::Compress) override;
344
345
  virtual void Clear() override;
346
347
  virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
348
349
  virtual PaintState BeginPaint(PaintedLayer* aLayer, uint32_t aFlags) override;
350
351
  virtual void FinalizeFrame(PaintState& aPaintState) override;
352
353
  virtual RefPtr<RotatedBuffer> GetFrontBuffer() const override
354
0
  {
355
0
    return mFrontBuffer;
356
0
  }
357
358
  virtual TextureInfo GetTextureInfo() const override
359
0
  {
360
0
    return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags);
361
0
  }
362
363
private:
364
  void EnsureBackBufferIfFrontBuffer();
365
366
  RefPtr<RemoteRotatedBuffer> mFrontBuffer;
367
  nsIntRegion mFrontUpdatedRegion;
368
  bool mFrontAndBackBufferDiffer;
369
};
370
371
/**
372
 * A single buffered ContentClientRemoteBuffer. We have a single
373
 * TextureClient/Host which we update and then send a message to the
374
 * compositor that we are done updating. It is not safe for the compositor
375
 * to use the corresponding TextureHost's memory directly, it must upload
376
 * it to video memory of some kind. We are free to modify the TextureClient
377
 * once we receive reply from the compositor.
378
 */
379
class ContentClientSingleBuffered : public ContentClientRemoteBuffer
380
{
381
public:
382
  explicit ContentClientSingleBuffered(CompositableForwarder* aFwd)
383
    : ContentClientRemoteBuffer(aFwd)
384
0
  {
385
0
  }
386
0
  virtual ~ContentClientSingleBuffered() {}
387
388
  virtual TextureInfo GetTextureInfo() const override
389
0
  {
390
0
    return TextureInfo(CompositableType::CONTENT_SINGLE, mTextureFlags | ExtraTextureFlags());
391
0
  }
392
};
393
394
} // namespace layers
395
} // namespace mozilla
396
397
#endif