summaryrefslogtreecommitdiffstats
path: root/gfx/2d/DrawingJob.h
blob: a384dabda754f49d2aea9177e8fe0cc95c79b211 (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * 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_GFX_COMMANDBUFFER_H_
#define MOZILLA_GFX_COMMANDBUFFER_H_

#include <stdint.h>

#include "mozilla/RefPtr.h"
#include "mozilla/Assertions.h"
#include "mozilla/gfx/Matrix.h"
#include "mozilla/gfx/JobScheduler.h"
#include "mozilla/gfx/IterableArena.h"
#include "mozilla/RefCounted.h"
#include "DrawCommand.h"

namespace mozilla {
namespace gfx {

class DrawingCommand;
class PrintCommand;
class SignalCommand;
class DrawingJob;
class WaitCommand;

class SyncObject;
class MultiThreadedJobQueue;

class DrawTarget;

class DrawingJobBuilder;
class CommandBufferBuilder;

/// Contains a sequence of immutable drawing commands that are typically used by
/// several DrawingJobs.
///
/// CommandBuffer objects are built using CommandBufferBuilder.
class CommandBuffer : public external::AtomicRefCounted<CommandBuffer>
{
public:
  MOZ_DECLARE_REFCOUNTED_TYPENAME(CommandBuffer)

  ~CommandBuffer();

  const DrawingCommand* GetDrawingCommand(ptrdiff_t aId);

protected:
  explicit CommandBuffer(size_t aSize = 256)
  : mStorage(IterableArena::GROWABLE, aSize)
  {}

  IterableArena mStorage;
  friend class CommandBufferBuilder;
};

/// Generates CommandBuffer objects.
///
/// The builder is a separate object to ensure that commands are not added to a
/// submitted CommandBuffer.
class CommandBufferBuilder
{
public:
  void BeginCommandBuffer(size_t aBufferSize = 256);

  already_AddRefed<CommandBuffer> EndCommandBuffer();

  /// Build the CommandBuffer, command after command.
  /// This must be used between BeginCommandBuffer and EndCommandBuffer.
  template<typename T, typename... Args>
  ptrdiff_t AddCommand(Args&&... aArgs)
  {
    static_assert(IsBaseOf<DrawingCommand, T>::value,
                  "T must derive from DrawingCommand");
    return mCommands->mStorage.Alloc<T>(Forward<Args>(aArgs)...);
  }

  bool HasCommands() const { return !!mCommands; }

protected:
  RefPtr<CommandBuffer> mCommands;
};

/// Stores multiple commands to be executed sequencially.
class DrawingJob : public Job {
public:
  ~DrawingJob();

  virtual JobStatus Run() override;

protected:
  DrawingJob(DrawTarget* aTarget,
              IntPoint aOffset,
              SyncObject* aStart,
              SyncObject* aCompletion,
              WorkerThread* aPinToWorker = nullptr);

  /// Runs the tasks's destructors and resets the buffer.
  void Clear();

  std::vector<ptrdiff_t> mCommandOffsets;
  RefPtr<CommandBuffer> mCommandBuffer;
  uint32_t mCursor;

  RefPtr<DrawTarget> mDrawTarget;
  IntPoint mOffset;

  friend class DrawingJobBuilder;
};

/// Generates DrawingJob objects.
///
/// The builder is a separate object to ensure that commands are not added to a
/// submitted DrawingJob.
class DrawingJobBuilder {
public:
  DrawingJobBuilder();

  ~DrawingJobBuilder();

  /// Allocates a DrawingJob.
  ///
  /// call this method before starting to add commands.
  void BeginDrawingJob(DrawTarget* aTarget, IntPoint aOffset,
                        SyncObject* aStart = nullptr);

  /// Build the DrawingJob, command after command.
  /// This must be used between BeginDrawingJob and EndDrawingJob.
  void AddCommand(ptrdiff_t offset)
  {
    mCommandOffsets.push_back(offset);
  }

  /// Finalizes and returns the drawing task.
  ///
  /// If aCompletion is not null, the sync object will be signaled after the
  /// task buffer is destroyed (and after the destructor of the tasks have run).
  /// In most cases this means after the completion of all tasks in the task buffer,
  /// but also when the task buffer is destroyed due to an error.
  DrawingJob* EndDrawingJob(CommandBuffer* aCmdBuffer,
                              SyncObject* aCompletion = nullptr,
                              WorkerThread* aPinToWorker = nullptr);

  /// Returns true between BeginDrawingJob and EndDrawingJob, false otherwise.
  bool HasDrawingJob() const { return !!mDrawTarget; }

protected:
  std::vector<ptrdiff_t> mCommandOffsets;
  RefPtr<DrawTarget> mDrawTarget;
  IntPoint mOffset;
  RefPtr<SyncObject> mStart;
};

} // namespace
} // namespace

#endif